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
16pub 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
35pub 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}