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( Box< dyn CloneService>> + Send + Sync, >, ); impl BoxCloneSyncService { /// Create a new `BoxCloneSyncService`. pub fn new(inner: S) -> Self where S: Service + 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() -> LayerFn Self> where S: Service + Clone + Send + Sync + 'static, S::Future: Send + 'static, { layer_fn(Self::new) } } impl Service for BoxCloneSyncService { type Response = U; type Error = E; type Future = BoxFuture<'static, Result>; #[inline] fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.0.poll_ready(cx) } #[inline] fn call(&mut self, request: T) -> Self::Future { self.0.call(request) } } impl Clone for BoxCloneSyncService { fn clone(&self) -> Self { Self(self.0.clone_box()) } } trait CloneService: Service { fn clone_box( &self, ) -> Box< dyn CloneService + Send + Sync, >; } impl CloneService for T where T: Service + Send + Sync + Clone + 'static, { fn clone_box( &self, ) -> Box< dyn CloneService + Send + Sync, > { Box::new(self.clone()) } } impl fmt::Debug for BoxCloneSyncService { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("BoxCloneSyncService").finish() } }