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)] |
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> = 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 |
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 | |
55 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { |
56 | self.inner.poll_ready(cx) |
57 | } |
58 | |
59 | fn call(&mut self, request: T) -> UnsyncBoxFuture<U, E> { |
60 | self.inner.call(req:request) |
61 | } |
62 | } |
63 | |
64 | impl<T, U, E> fmt::Debug for UnsyncBoxService<T, U, E> { |
65 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
66 | fmt.debug_struct(name:"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 | |
79 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
80 | self.inner.poll_ready(cx) |
81 | } |
82 | |
83 | fn call(&mut self, request: Request) -> Self::Future { |
84 | Box::pin(self.inner.call(req:request)) |
85 | } |
86 | } |
87 | |