1 | use crate::ServiceExt; |
2 | use tower_layer::{layer_fn, LayerFn}; |
3 | use tower_service::Service; |
4 | |
5 | use sync_wrapper::SyncWrapper; |
6 | |
7 | use std::fmt; |
8 | use std::{ |
9 | future::Future, |
10 | pin::Pin, |
11 | task::{Context, Poll}, |
12 | }; |
13 | |
14 | /// A boxed `Service + Send` trait object. |
15 | /// |
16 | /// [`BoxService`] turns a service into a trait object, allowing the response |
17 | /// future type to be dynamic. This type requires both the service and the |
18 | /// response future to be [`Send`]. |
19 | /// |
20 | /// If you need a boxed [`Service`] that implements [`Clone`] consider using |
21 | /// [`BoxCloneService`](crate::util::BoxCloneService). |
22 | /// |
23 | /// Dynamically dispatched [`Service`] objects allow for erasing the underlying |
24 | /// [`Service`] type and using the `Service` instances as opaque handles. This can |
25 | /// be useful when the service instance cannot be explicitly named for whatever |
26 | /// reason. |
27 | /// |
28 | /// # Examples |
29 | /// |
30 | /// ``` |
31 | /// use futures_util::future::ready; |
32 | /// # use tower_service::Service; |
33 | /// # use tower::util::{BoxService, service_fn}; |
34 | /// // Respond to requests using a closure, but closures cannot be named... |
35 | /// # pub fn main() { |
36 | /// let svc = service_fn(|mut request: String| { |
37 | /// request.push_str(" response" ); |
38 | /// ready(Ok(request)) |
39 | /// }); |
40 | /// |
41 | /// let service: BoxService<String, String, ()> = BoxService::new(svc); |
42 | /// # drop(service); |
43 | /// } |
44 | /// ``` |
45 | /// |
46 | /// [`Service`]: crate::Service |
47 | /// [`Rc`]: std::rc::Rc |
48 | pub struct BoxService<T, U, E> { |
49 | inner: |
50 | SyncWrapper<Box<dyn Service<T, Response = U, Error = E, Future = BoxFuture<U, E>> + Send>>, |
51 | } |
52 | |
53 | /// A boxed `Future + Send` trait object. |
54 | /// |
55 | /// This type alias represents a boxed future that is [`Send`] and can be moved |
56 | /// across threads. |
57 | type BoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send>>; |
58 | |
59 | impl<T, U, E> BoxService<T, U, E> { |
60 | #[allow (missing_docs)] |
61 | pub fn new<S>(inner: S) -> Self |
62 | where |
63 | S: Service<T, Response = U, Error = E> + Send + 'static, |
64 | S::Future: Send + 'static, |
65 | { |
66 | // rust can't infer the type |
67 | let inner: Box<dyn Service<T, Response = U, Error = E, Future = BoxFuture<U, E>> + Send> = |
68 | Box::new(inner.map_future(|f: S::Future| Box::pin(f) as _)); |
69 | let inner = SyncWrapper::new(inner); |
70 | BoxService { inner } |
71 | } |
72 | |
73 | /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxService`] |
74 | /// middleware. |
75 | /// |
76 | /// [`Layer`]: crate::Layer |
77 | pub fn layer<S>() -> LayerFn<fn(S) -> Self> |
78 | where |
79 | S: Service<T, Response = U, Error = E> + Send + 'static, |
80 | S::Future: Send + 'static, |
81 | { |
82 | layer_fn(Self::new) |
83 | } |
84 | } |
85 | |
86 | impl<T, U, E> Service<T> for BoxService<T, U, E> { |
87 | type Response = U; |
88 | type Error = E; |
89 | type Future = BoxFuture<U, E>; |
90 | |
91 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> { |
92 | self.inner.get_mut().poll_ready(cx) |
93 | } |
94 | |
95 | fn call(&mut self, request: T) -> BoxFuture<U, E> { |
96 | self.inner.get_mut().call(req:request) |
97 | } |
98 | } |
99 | |
100 | impl<T, U, E> fmt::Debug for BoxService<T, U, E> { |
101 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
102 | fmt.debug_struct(name:"BoxService" ).finish() |
103 | } |
104 | } |
105 | |
106 | #[test ] |
107 | fn is_sync() { |
108 | fn assert_sync<T: Sync>() {} |
109 | |
110 | assert_sync::<BoxService<(), (), ()>>(); |
111 | } |
112 | |