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`] trait object. pub struct UnsyncBoxService { inner: Box>>, } /// A boxed [`Future`] trait object. /// /// This type alias represents a boxed future that is *not* [`Send`] and must /// remain on the current thread. type UnsyncBoxFuture = Pin>>>; #[derive(Debug)] struct UnsyncBoxed { inner: S, } impl UnsyncBoxService { #[allow(missing_docs)] pub fn new(inner: S) -> Self where S: Service + 'static, S::Future: 'static, { let inner = Box::new(UnsyncBoxed { inner }); UnsyncBoxService { inner } } /// Returns a [`Layer`] for wrapping a [`Service`] in an [`UnsyncBoxService`] middleware. /// /// [`Layer`]: crate::Layer pub fn layer() -> LayerFn Self> where S: Service + 'static, S::Future: 'static, { layer_fn(Self::new) } } impl Service for UnsyncBoxService { type Response = U; type Error = E; type Future = UnsyncBoxFuture; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, request: T) -> UnsyncBoxFuture { self.inner.call(request) } } impl fmt::Debug for UnsyncBoxService { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("UnsyncBoxService").finish() } } impl Service for UnsyncBoxed where S: Service + 'static, S::Future: 'static, { type Response = S::Response; type Error = S::Error; type Future = Pin>>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, request: Request) -> Self::Future { Box::pin(self.inner.call(request)) } }