requiem_service/
boxed.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use futures_util::future::FutureExt;
6
7use crate::{Service, ServiceFactory};
8
9pub type BoxFuture<I, E> = Pin<Box<dyn Future<Output = Result<I, E>>>>;
10
11pub type BoxService<Req, Res, Err> =
12    Box<dyn Service<Request = Req, Response = Res, Error = Err, Future = BoxFuture<Res, Err>>>;
13
14pub struct BoxServiceFactory<C, Req, Res, Err, InitErr>(Inner<C, Req, Res, Err, InitErr>);
15
16/// Create boxed service factory
17pub fn factory<T>(
18    factory: T,
19) -> BoxServiceFactory<T::Config, T::Request, T::Response, T::Error, T::InitError>
20where
21    T: ServiceFactory + 'static,
22    T::Request: 'static,
23    T::Response: 'static,
24    T::Service: 'static,
25    T::Future: 'static,
26    T::Error: 'static,
27    T::InitError: 'static,
28{
29    BoxServiceFactory(Box::new(FactoryWrapper {
30        factory,
31        _t: std::marker::PhantomData,
32    }))
33}
34
35/// Create boxed service
36pub fn service<T>(service: T) -> BoxService<T::Request, T::Response, T::Error>
37where
38    T: Service + 'static,
39    T::Future: 'static,
40{
41    Box::new(ServiceWrapper(service))
42}
43
44type Inner<C, Req, Res, Err, InitErr> = Box<
45    dyn ServiceFactory<
46        Config = C,
47        Request = Req,
48        Response = Res,
49        Error = Err,
50        InitError = InitErr,
51        Service = BoxService<Req, Res, Err>,
52        Future = BoxFuture<BoxService<Req, Res, Err>, InitErr>,
53    >,
54>;
55
56impl<C, Req, Res, Err, InitErr> ServiceFactory for BoxServiceFactory<C, Req, Res, Err, InitErr>
57where
58    Req: 'static,
59    Res: 'static,
60    Err: 'static,
61    InitErr: 'static,
62{
63    type Request = Req;
64    type Response = Res;
65    type Error = Err;
66    type InitError = InitErr;
67    type Config = C;
68    type Service = BoxService<Req, Res, Err>;
69
70    type Future = BoxFuture<Self::Service, InitErr>;
71
72    fn new_service(&self, cfg: C) -> Self::Future {
73        self.0.new_service(cfg)
74    }
75}
76
77struct FactoryWrapper<C, T: ServiceFactory> {
78    factory: T,
79    _t: std::marker::PhantomData<C>,
80}
81
82impl<C, T, Req, Res, Err, InitErr> ServiceFactory for FactoryWrapper<C, T>
83where
84    Req: 'static,
85    Res: 'static,
86    Err: 'static,
87    InitErr: 'static,
88    T: ServiceFactory<
89        Config = C,
90        Request = Req,
91        Response = Res,
92        Error = Err,
93        InitError = InitErr,
94    >,
95    T::Future: 'static,
96    T::Service: 'static,
97    <T::Service as Service>::Future: 'static,
98{
99    type Request = Req;
100    type Response = Res;
101    type Error = Err;
102    type InitError = InitErr;
103    type Config = C;
104    type Service = BoxService<Req, Res, Err>;
105    type Future = BoxFuture<Self::Service, Self::InitError>;
106
107    fn new_service(&self, cfg: C) -> Self::Future {
108        Box::pin(
109            self.factory
110                .new_service(cfg)
111                .map(|res| res.map(ServiceWrapper::boxed)),
112        )
113    }
114}
115
116struct ServiceWrapper<T: Service>(T);
117
118impl<T> ServiceWrapper<T>
119where
120    T: Service + 'static,
121    T::Future: 'static,
122{
123    fn boxed(service: T) -> BoxService<T::Request, T::Response, T::Error> {
124        Box::new(ServiceWrapper(service))
125    }
126}
127
128impl<T, Req, Res, Err> Service for ServiceWrapper<T>
129where
130    T: Service<Request = Req, Response = Res, Error = Err>,
131    T::Future: 'static,
132{
133    type Request = Req;
134    type Response = Res;
135    type Error = Err;
136    type Future = BoxFuture<Res, Err>;
137
138    fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
139        self.0.poll_ready(ctx)
140    }
141
142    fn call(&mut self, req: Self::Request) -> Self::Future {
143        Box::pin(self.0.call(req))
144    }
145}