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