use crate::ServiceExt; use tower_layer::{layer_fn, LayerFn}; use tower_service::Service; use std::fmt; use std::{ future::Future, pin::Pin, task::{Context, Poll}, }; /// A boxed `Service + Send` trait object. /// /// [`BoxService`] turns a service into a trait object, allowing the response /// future type to be dynamic. This type requires both the service and the /// response future to be [`Send`]. /// /// If you need a boxed [`Service`] that implements [`Clone`] consider using /// [`BoxCloneService`](crate::util::BoxCloneService). /// /// See module level documentation for more details. pub struct BoxService { inner: Box> + Send>, } /// A boxed `Future + Send` trait object. /// /// This type alias represents a boxed future that is [`Send`] and can be moved /// across threads. type BoxFuture = Pin> + Send>>; impl BoxService { #[allow(missing_docs)] pub fn new(inner: S) -> Self where S: Service + Send + 'static, S::Future: Send + 'static, { let inner = Box::new(inner.map_future(|f: S::Future| Box::pin(f) as _)); BoxService { inner } } /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxService`] /// middleware. /// /// [`Layer`]: crate::Layer pub fn layer() -> LayerFn Self> where S: Service + Send + 'static, S::Future: Send + 'static, { layer_fn(Self::new) } } impl Service for BoxService { type Response = U; type Error = E; type Future = BoxFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, request: T) -> BoxFuture { self.inner.call(request) } } impl fmt::Debug for BoxService { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("BoxService").finish() } }