async_svc/
boxed.rs

1use std::{
2    future::Future,
3    marker::PhantomData,
4    pin::Pin,
5    task::{Context, Poll},
6};
7
8use pin_project::pin_project;
9
10use crate::Svc;
11
12pub type BoxFut<Res> = Pin<Box<dyn Future<Output = Res>>>;
13pub type BoxSvc<Req, Res> = Pin<Box<dyn Svc<Req, Res = Res, Fut = BoxFut<Res>>>>;
14
15impl<Req, Res> Svc<Req> for BoxSvc<Req, Res> {
16    type Res = Res;
17    type Fut = BoxFut<Res>;
18
19    fn poll_ready(mut self: Pin<&mut Self>, cx: Context<'_>) -> Poll<()> {
20        self.as_mut().poll_ready(cx)
21    }
22
23    fn exec(mut self: Pin<&mut Self>, req: Req) -> Self::Fut {
24        self.as_mut().exec(req)
25    }
26}
27
28pub fn box_svc<S, Req>(svc: S) -> BoxSvc<Req, S::Res>
29where
30    S: Svc<Req> + 'static,
31    Req: 'static,
32{
33    Box::pin(SvcWrapper::new(svc))
34}
35
36#[pin_project]
37struct SvcWrapper<S: Svc<Req>, Req> {
38    #[pin]
39    svc: S,
40    _req: PhantomData<Req>,
41}
42
43impl<S: Svc<Req>, Req> SvcWrapper<S, Req> {
44    fn new(svc: S) -> Self {
45        Self {
46            svc,
47            _req: PhantomData,
48        }
49    }
50}
51
52impl<S, Req> Svc<Req> for SvcWrapper<S, Req>
53where
54    S: Svc<Req>,
55    S::Fut: 'static,
56{
57    type Res = S::Res;
58    type Fut = BoxFut<S::Res>;
59
60    fn poll_ready(self: Pin<&mut Self>, cx: Context<'_>) -> Poll<()> {
61        let this = self.project();
62        this.svc.poll_ready(cx)
63    }
64
65    fn exec(self: Pin<&mut Self>, req: Req) -> Self::Fut {
66        let this = self.project();
67        Box::pin(this.svc.exec(req))
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use std::{cell::RefCell, rc::Rc};
74
75    use super::*;
76    use crate::FnSvc;
77
78    #[tokio::test]
79    async fn test_boxed() {
80        let sum = Rc::new(RefCell::new(0));
81        let sum2 = Rc::clone(&sum);
82        let running_sum = move |n: u64| {
83            let sum = Rc::clone(&sum2);
84            Box::pin(async move {
85                *sum.borrow_mut() += n;
86                *sum.borrow()
87            })
88        };
89
90        let svc = FnSvc::new(running_sum);
91        let mut boxed_srv = box_svc(svc);
92
93        let res = boxed_srv.as_mut().exec(20).await;
94        assert_eq!(res, 20);
95
96        let res = boxed_srv.as_mut().exec(14).await;
97        assert_eq!(res, 34);
98    }
99}