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