Skip to main content

motore/service/
tower_adapter.rs

1//! This module provides the Adapter trait, which is used to convert a Motore service into a Tower
2//! service and vice versa.
3//!
4//! Take `TowerAdapter` for example: it will be automatically implemented for any type that
5//! implements `Motore::Service`. Thus, you can use `.tower(f)` method with a closure parameters
6//! passed in to convert a Motore service into a Tower service.
7//!
8//! # Example
9//!
10//! ```rust, ignore
11//! // Convert a Motore service into a Tower service
12//! let tower_service = motore_service.tower(|tower_req| { cx, motore_req });
13//!
14//! // Convert a Tower service into a Motore service
15//! let motore_service = tower_service.motore(|cx, motore_req| { tower_req });
16//! ```
17
18use std::{
19    fmt,
20    marker::PhantomData,
21    task::{Context, Poll},
22};
23
24#[cfg(feature = "service_send")]
25use futures::future::BoxFuture;
26#[cfg(not(feature = "service_send"))]
27use futures::future::LocalBoxFuture;
28use futures::{Future, FutureExt};
29
30use crate::Service;
31
32impl<T: ?Sized, Cx, MotoreReq, TowerReq> TowerAdapter<Cx, MotoreReq, TowerReq> for T where
33    T: Service<Cx, MotoreReq>
34{
35}
36
37#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
38pub trait TowerAdapter<Cx, MotoreReq, TowerReq>: Service<Cx, MotoreReq> {
39    fn tower<F>(self, f: F) -> Tower<Self, F, Cx, MotoreReq>
40    where
41        F: FnOnce(TowerReq) -> (Cx, MotoreReq),
42        Self: Sized,
43    {
44        Tower::new(self, f)
45    }
46}
47
48#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
49pub struct Tower<S, F, Cx, MotoreReq> {
50    inner: S,
51    f: F,
52    _phantom: PhantomData<fn(Cx, MotoreReq)>,
53}
54
55impl<S, F, Cx, MotoreReq> Tower<S, F, Cx, MotoreReq> {
56    pub fn new(inner: S, f: F) -> Self {
57        Self {
58            inner,
59            f,
60            _phantom: PhantomData,
61        }
62    }
63}
64
65#[cfg(feature = "service_send")]
66impl<S, F, Cx, MotoreReq, TowerReq> tower::Service<TowerReq> for Tower<S, F, Cx, MotoreReq>
67where
68    S: Service<Cx, MotoreReq> + Clone + 'static + Send,
69    F: FnOnce(TowerReq) -> (Cx, MotoreReq) + Clone,
70    MotoreReq: 'static + Send,
71    Cx: 'static + Send,
72{
73    type Response = S::Response;
74
75    type Error = S::Error;
76
77    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
78
79    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
80        Poll::Ready(Ok(()))
81    }
82
83    fn call(&mut self, req: TowerReq) -> Self::Future {
84        let inner = self.inner.clone();
85        let (mut cx, r) = (self.f.clone())(req);
86        async move { inner.call(&mut cx, r).await }.boxed()
87    }
88}
89
90#[cfg(not(feature = "service_send"))]
91impl<S, F, Cx, MotoreReq, TowerReq> tower::Service<TowerReq> for Tower<S, F, Cx, MotoreReq>
92where
93    S: Service<Cx, MotoreReq> + Clone + 'static,
94    F: FnOnce(TowerReq) -> (Cx, MotoreReq) + Clone,
95    MotoreReq: 'static,
96    Cx: 'static,
97{
98    type Response = S::Response;
99
100    type Error = S::Error;
101
102    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
103
104    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
105        Poll::Ready(Ok(()))
106    }
107
108    fn call(&mut self, req: TowerReq) -> Self::Future {
109        let inner = self.inner.clone();
110        let (mut cx, r) = (self.f.clone())(req);
111        async move { inner.call(&mut cx, r).await }.boxed_local()
112    }
113}
114
115impl<S, F, Cx, MotoreReq> Clone for Tower<S, F, Cx, MotoreReq>
116where
117    S: Clone,
118    F: Clone,
119{
120    fn clone(&self) -> Self {
121        Self {
122            inner: self.inner.clone(),
123            f: self.f.clone(),
124            _phantom: PhantomData,
125        }
126    }
127}
128
129impl<S, F, Cx, MotoreReq> fmt::Debug for Tower<S, F, Cx, MotoreReq>
130where
131    S: fmt::Debug,
132{
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        f.debug_struct("Tower")
135            .field("inner", &self.inner)
136            .field("f", &format_args!("{}", std::any::type_name::<F>()))
137            .finish()
138    }
139}
140
141impl<T: ?Sized, Cx, MotoreReq, TowerReq> MotoreAdapter<Cx, MotoreReq, TowerReq> for T where
142    T: tower::Service<TowerReq>
143{
144}
145
146#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
147pub trait MotoreAdapter<Cx, MotoreReq, TowerReq>: tower::Service<TowerReq> {
148    fn motore<F>(self, f: F) -> Motore<Self, F>
149    where
150        F: FnOnce(&mut Cx, MotoreReq) -> TowerReq,
151        Self: Sized,
152    {
153        Motore::new(self, f)
154    }
155}
156
157#[derive(Clone)]
158#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
159pub struct Motore<S, F> {
160    inner: S,
161    f: F,
162}
163
164impl<S, F> Motore<S, F> {
165    pub fn new(inner: S, f: F) -> Self {
166        Self { inner, f }
167    }
168}
169
170impl<S, F, Cx, MotoreReq, TowerReq> Service<Cx, MotoreReq> for Motore<S, F>
171where
172    S: tower::Service<TowerReq> + Clone,
173    for<'cx> <S as tower::Service<TowerReq>>::Future: Send + 'cx,
174    F: FnOnce(&mut Cx, MotoreReq) -> TowerReq + Clone,
175{
176    type Response = S::Response;
177
178    type Error = S::Error;
179
180    #[cfg(feature = "service_send")]
181    fn call(
182        &self,
183        cx: &mut Cx,
184        req: MotoreReq,
185    ) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send {
186        self.inner.clone().call((self.f.clone())(cx, req))
187    }
188
189    #[cfg(not(feature = "service_send"))]
190    fn call(
191        &self,
192        cx: &mut Cx,
193        req: MotoreReq,
194    ) -> impl Future<Output = Result<Self::Response, Self::Error>> {
195        self.inner.clone().call((self.f.clone())(cx, req))
196    }
197}
198
199impl<S, F> fmt::Debug for Motore<S, F>
200where
201    S: fmt::Debug,
202{
203    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204        f.debug_struct("Motore")
205            .field("inner", &self.inner)
206            .field("f", &format_args!("{}", std::any::type_name::<F>()))
207            .finish()
208    }
209}