tower/util/boxed/
unsync.rs

1use tower_layer::{layer_fn, LayerFn};
2use tower_service::Service;
3
4use std::fmt;
5use std::{
6    future::Future,
7    pin::Pin,
8    task::{Context, Poll},
9};
10
11/// A boxed [`Service`] trait object.
12pub 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.
20type UnsyncBoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>>>>;
21
22#[derive(Debug)]
23struct UnsyncBoxed<S> {
24    inner: S,
25}
26
27impl<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::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
50impl<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(request)
61    }
62}
63
64impl<T, U, E> fmt::Debug for UnsyncBoxService<T, U, E> {
65    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
66        fmt.debug_struct("UnsyncBoxService").finish()
67    }
68}
69
70impl<S, Request> Service<Request> for UnsyncBoxed<S>
71where
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(request))
85    }
86}