1 use tower_layer::{layer_fn, LayerFn}; 2 use tower_service::Service; 3 4 use std::fmt; 5 use std::{ 6 future::Future, 7 pin::Pin, 8 task::{Context, Poll}, 9 }; 10 11 /// A boxed [`Service`] trait object. 12 pub struct UnsyncBoxService<T, U, E> { 13 inner: Box<dyn Service<T, Response = U, Error = E, Future = UnsyncBoxFuture<U, E>>>, 14 } 15 16 /// A boxed [`Future`] trait object. 17 /// 18 /// This type alias represents a boxed future that is *not* [`Send`] and must 19 /// remain on the current thread. 20 type UnsyncBoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>>>>; 21 22 #[derive(Debug)] 23 struct UnsyncBoxed<S> { 24 inner: S, 25 } 26 27 impl<T, U, E> UnsyncBoxService<T, U, E> { 28 #[allow(missing_docs)] new<S>(inner: S) -> Self where S: Service<T, Response = U, Error = E> + 'static, S::Future: 'static,29 pub fn new<S>(inner: S) -> Self 30 where 31 S: Service<T, Response = U, Error = E> + 'static, 32 S::Future: 'static, 33 { 34 let inner = Box::new(UnsyncBoxed { inner }); 35 UnsyncBoxService { inner } 36 } 37 38 /// Returns a [`Layer`] for wrapping a [`Service`] in an [`UnsyncBoxService`] middleware. 39 /// 40 /// [`Layer`]: crate::Layer layer<S>() -> LayerFn<fn(S) -> Self> where S: Service<T, Response = U, Error = E> + 'static, S::Future: 'static,41 pub fn layer<S>() -> LayerFn<fn(S) -> Self> 42 where 43 S: Service<T, Response = U, Error = E> + 'static, 44 S::Future: 'static, 45 { 46 layer_fn(Self::new) 47 } 48 } 49 50 impl<T, U, E> Service<T> for UnsyncBoxService<T, U, E> { 51 type Response = U; 52 type Error = E; 53 type Future = UnsyncBoxFuture<U, E>; 54 poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>>55 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { 56 self.inner.poll_ready(cx) 57 } 58 call(&mut self, request: T) -> UnsyncBoxFuture<U, E>59 fn call(&mut self, request: T) -> UnsyncBoxFuture<U, E> { 60 self.inner.call(request) 61 } 62 } 63 64 impl<T, U, E> fmt::Debug for UnsyncBoxService<T, U, E> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result65 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 66 fmt.debug_struct("UnsyncBoxService").finish() 67 } 68 } 69 70 impl<S, Request> Service<Request> for UnsyncBoxed<S> 71 where 72 S: Service<Request> + 'static, 73 S::Future: 'static, 74 { 75 type Response = S::Response; 76 type Error = S::Error; 77 type Future = Pin<Box<dyn Future<Output = Result<S::Response, S::Error>>>>; 78 poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>79 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { 80 self.inner.poll_ready(cx) 81 } 82 call(&mut self, request: Request) -> Self::Future83 fn call(&mut self, request: Request) -> Self::Future { 84 Box::pin(self.inner.call(request)) 85 } 86 } 87