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`] boxed [`Service`]. /// /// [`BoxCloneService`] turns a service into a trait object, allowing the /// response future type to be dynamic, and allowing the service to be cloned. /// /// This is similar to [`BoxService`](super::BoxService) except the resulting /// service implements [`Clone`]. /// /// # Example /// /// ``` /// use tower::{Service, ServiceBuilder, BoxError, util::BoxCloneService}; /// use std::time::Duration; /// # /// # struct Request; /// # struct Response; /// # impl Response { /// # fn new() -> Self { Self } /// # } /// /// // This service has a complex type that is hard to name /// let service = ServiceBuilder::new() /// .map_request(|req| { /// println!("received request"); /// req /// }) /// .map_response(|res| { /// println!("response produced"); /// res /// }) /// .load_shed() /// .concurrency_limit(64) /// .timeout(Duration::from_secs(10)) /// .service_fn(|req: Request| async { /// Ok::<_, BoxError>(Response::new()) /// }); /// # let service = assert_service(service); /// /// // `BoxCloneService` will erase the type so it's nameable /// let service: BoxCloneService = BoxCloneService::new(service); /// # let service = assert_service(service); /// /// // And we can still clone the service /// let cloned_service = service.clone(); /// # /// # fn assert_service(svc: S) -> S /// # where S: Service { svc } /// ``` pub struct BoxCloneService( Box< dyn CloneService>> + Send, >, ); impl BoxCloneService { /// Create a new `BoxCloneService`. pub fn new(inner: S) -> Self where S: Service + Clone + Send + 'static, S::Future: Send + 'static, { let inner = inner.map_future(|f| Box::pin(f) as _); BoxCloneService(Box::new(inner)) } /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxCloneService`] /// middleware. /// /// [`Layer`]: crate::Layer pub fn layer() -> LayerFn Self> where S: Service + Clone + Send + 'static, S::Future: Send + 'static, { layer_fn(Self::new) } } impl Service for BoxCloneService { 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 BoxCloneService { fn clone(&self) -> Self { Self(self.0.clone_box()) } } trait CloneService: Service { fn clone_box( &self, ) -> Box< dyn CloneService + Send, >; } impl CloneService for T where T: Service + Send + Clone + 'static, { fn clone_box( &self, ) -> Box + Send> { Box::new(self.clone()) } } impl fmt::Debug for BoxCloneService { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("BoxCloneService").finish() } }