| 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<T, U, E> { |
| inner: Box<dyn Service<T, Response = U, Error = E, Future = BoxFuture<U, E>> + 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<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send>>; |
| |
| impl<T, U, E> BoxService<T, U, E> { |
| #[allow(missing_docs)] |
| pub fn new<S>(inner: S) -> Self |
| where |
| S: Service<T, Response = U, Error = E> + 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<S>() -> LayerFn<fn(S) -> Self> |
| where |
| S: Service<T, Response = U, Error = E> + Send + 'static, |
| S::Future: Send + 'static, |
| { |
| layer_fn(Self::new) |
| } |
| } |
| |
| impl<T, U, E> Service<T> for BoxService<T, U, E> { |
| type Response = U; |
| type Error = E; |
| type Future = BoxFuture<U, E>; |
| |
| fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { |
| self.inner.poll_ready(cx) |
| } |
| |
| fn call(&mut self, request: T) -> BoxFuture<U, E> { |
| self.inner.call(request) |
| } |
| } |
| |
| impl<T, U, E> fmt::Debug for BoxService<T, U, E> { |
| fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| fmt.debug_struct("BoxService").finish() |
| } |
| } |