diff options
Diffstat (limited to 'vendor/tower/src/util/boxed_clone_sync.rs')
| -rw-r--r-- | vendor/tower/src/util/boxed_clone_sync.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/vendor/tower/src/util/boxed_clone_sync.rs b/vendor/tower/src/util/boxed_clone_sync.rs new file mode 100644 index 00000000..d62e8ff2 --- /dev/null +++ b/vendor/tower/src/util/boxed_clone_sync.rs @@ -0,0 +1,101 @@ +use super::ServiceExt; +use futures_util::future::BoxFuture; +use std::{ + fmt, + task::{Context, Poll}, +}; +use tower_layer::{layer_fn, LayerFn}; +use tower_service::Service; + +/// A [`Clone`] + [`Send`] + [`Sync`] boxed [`Service`]. +/// +/// [`BoxCloneSyncService`] turns a service into a trait object, allowing the +/// response future type to be dynamic, and allowing the service to be cloned and shared. +/// +/// This is similar to [`BoxCloneService`](super::BoxCloneService) except the resulting +/// service implements [`Sync`]. +/// ``` +pub struct BoxCloneSyncService<T, U, E>( + Box< + dyn CloneService<T, Response = U, Error = E, Future = BoxFuture<'static, Result<U, E>>> + + Send + + Sync, + >, +); + +impl<T, U, E> BoxCloneSyncService<T, U, E> { + /// Create a new `BoxCloneSyncService`. + pub fn new<S>(inner: S) -> Self + where + S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static, + S::Future: Send + 'static, + { + let inner = inner.map_future(|f| Box::pin(f) as _); + BoxCloneSyncService(Box::new(inner)) + } + + /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxCloneSyncService`] + /// middleware. + /// + /// [`Layer`]: crate::Layer + pub fn layer<S>() -> LayerFn<fn(S) -> Self> + where + S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static, + S::Future: Send + 'static, + { + layer_fn(Self::new) + } +} + +impl<T, U, E> Service<T> for BoxCloneSyncService<T, U, E> { + type Response = U; + type Error = E; + type Future = BoxFuture<'static, Result<U, E>>; + + #[inline] + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { + self.0.poll_ready(cx) + } + + #[inline] + fn call(&mut self, request: T) -> Self::Future { + self.0.call(request) + } +} + +impl<T, U, E> Clone for BoxCloneSyncService<T, U, E> { + fn clone(&self) -> Self { + Self(self.0.clone_box()) + } +} + +trait CloneService<R>: Service<R> { + fn clone_box( + &self, + ) -> Box< + dyn CloneService<R, Response = Self::Response, Error = Self::Error, Future = Self::Future> + + Send + + Sync, + >; +} + +impl<R, T> CloneService<R> for T +where + T: Service<R> + Send + Sync + Clone + 'static, +{ + fn clone_box( + &self, + ) -> Box< + dyn CloneService<R, Response = T::Response, Error = T::Error, Future = T::Future> + + Send + + Sync, + > { + Box::new(self.clone()) + } +} + +impl<T, U, E> fmt::Debug for BoxCloneSyncService<T, U, E> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BoxCloneSyncService").finish() + } +} |
