tower/util/
boxed_clone_sync.rs

1use super::ServiceExt;
2use futures_util::future::BoxFuture;
3use std::{
4    fmt,
5    task::{Context, Poll},
6};
7use tower_layer::{layer_fn, LayerFn};
8use tower_service::Service;
9
10/// A [`Clone`] + [`Send`] + [`Sync`] boxed [`Service`].
11///
12/// [`BoxCloneSyncService`] turns a service into a trait object, allowing the
13/// response future type to be dynamic, and allowing the service to be cloned and shared.
14///
15/// This is similar to [`BoxCloneService`](super::BoxCloneService) except the resulting
16/// service implements [`Sync`].
17pub struct BoxCloneSyncService<T, U, E>(
18    Box<
19        dyn CloneService<T, Response = U, Error = E, Future = BoxFuture<'static, Result<U, E>>>
20            + Send
21            + Sync,
22    >,
23);
24
25impl<T, U, E> BoxCloneSyncService<T, U, E> {
26    /// Create a new `BoxCloneSyncService`.
27    pub fn new<S>(inner: S) -> Self
28    where
29        S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
30        S::Future: Send + 'static,
31    {
32        let inner = inner.map_future(|f| Box::pin(f) as _);
33        BoxCloneSyncService(Box::new(inner))
34    }
35
36    /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxCloneSyncService`]
37    /// middleware.
38    ///
39    /// [`Layer`]: crate::Layer
40    pub fn layer<S>() -> LayerFn<fn(S) -> Self>
41    where
42        S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
43        S::Future: Send + 'static,
44    {
45        layer_fn(Self::new)
46    }
47}
48
49impl<T, U, E> Service<T> for BoxCloneSyncService<T, U, E> {
50    type Response = U;
51    type Error = E;
52    type Future = BoxFuture<'static, Result<U, E>>;
53
54    #[inline]
55    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
56        self.0.poll_ready(cx)
57    }
58
59    #[inline]
60    fn call(&mut self, request: T) -> Self::Future {
61        self.0.call(request)
62    }
63}
64
65impl<T, U, E> Clone for BoxCloneSyncService<T, U, E> {
66    fn clone(&self) -> Self {
67        Self(self.0.clone_box())
68    }
69}
70
71trait CloneService<R>: Service<R> {
72    fn clone_box(
73        &self,
74    ) -> Box<
75        dyn CloneService<R, Response = Self::Response, Error = Self::Error, Future = Self::Future>
76            + Send
77            + Sync,
78    >;
79}
80
81impl<R, T> CloneService<R> for T
82where
83    T: Service<R> + Send + Sync + Clone + 'static,
84{
85    fn clone_box(
86        &self,
87    ) -> Box<
88        dyn CloneService<R, Response = T::Response, Error = T::Error, Future = T::Future>
89            + Send
90            + Sync,
91    > {
92        Box::new(self.clone())
93    }
94}
95
96impl<T, U, E> fmt::Debug for BoxCloneSyncService<T, U, E> {
97    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
98        fmt.debug_struct("BoxCloneSyncService").finish()
99    }
100}