1use alloc::{boxed::Box, rc::Rc};
4use core::{future::Future, pin::Pin};
5
6use paste::paste;
7
8use crate::{Service, ServiceFactory};
9
10pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
12
13macro_rules! service_object {
14 ($name: ident, $type: tt, $fn_name: ident) => {
15 paste! {
16 #[doc = "Type alias for service trait object using `" $type "`."]
17 pub type $name<Req, Res, Err> = $type<
18 dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>,
19 >;
20
21 #[doc = "Wraps service as a trait object using [`" $name "`]."]
22 pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error>
23 where
24 S: Service<Req> + 'static,
25 Req: 'static,
26 S::Future: 'static,
27 {
28 $type::new(ServiceWrapper::new(service))
29 }
30 }
31 };
32}
33
34service_object!(BoxService, Box, service);
35service_object!(RcService, Rc, rc_service);
36
37struct ServiceWrapper<S> {
38 inner: S,
39}
40
41impl<S> ServiceWrapper<S> {
42 fn new(inner: S) -> Self {
43 Self { inner }
44 }
45}
46
47impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
48where
49 S: Service<Req, Response = Res, Error = Err>,
50 S::Future: 'static,
51{
52 type Response = Res;
53 type Error = Err;
54 type Future = BoxFuture<Result<Res, Err>>;
55
56 crate::forward_ready!(inner);
57
58 fn call(&self, req: Req) -> Self::Future {
59 Box::pin(self.inner.call(req))
60 }
61}
62
63pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
65
66pub fn factory<SF, Req>(
68 factory: SF,
69) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError>
70where
71 SF: ServiceFactory<Req> + 'static,
72 Req: 'static,
73 SF::Response: 'static,
74 SF::Service: 'static,
75 SF::Future: 'static,
76 SF::Error: 'static,
77 SF::InitError: 'static,
78{
79 BoxServiceFactory(Box::new(FactoryWrapper(factory)))
80}
81
82type Inner<C, Req, Res, Err, InitErr> = Box<
83 dyn ServiceFactory<
84 Req,
85 Config = C,
86 Response = Res,
87 Error = Err,
88 InitError = InitErr,
89 Service = BoxService<Req, Res, Err>,
90 Future = BoxFuture<Result<BoxService<Req, Res, Err>, InitErr>>,
91 >,
92>;
93
94impl<C, Req, Res, Err, InitErr> ServiceFactory<Req>
95 for BoxServiceFactory<C, Req, Res, Err, InitErr>
96where
97 Req: 'static,
98 Res: 'static,
99 Err: 'static,
100 InitErr: 'static,
101{
102 type Response = Res;
103 type Error = Err;
104 type Config = C;
105 type Service = BoxService<Req, Res, Err>;
106 type InitError = InitErr;
107
108 type Future = BoxFuture<Result<Self::Service, InitErr>>;
109
110 fn new_service(&self, cfg: C) -> Self::Future {
111 self.0.new_service(cfg)
112 }
113}
114
115struct FactoryWrapper<SF>(SF);
116
117impl<SF, Req, Cfg, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<SF>
118where
119 Req: 'static,
120 Res: 'static,
121 Err: 'static,
122 InitErr: 'static,
123 SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err, InitError = InitErr>,
124 SF::Future: 'static,
125 SF::Service: 'static,
126 <SF::Service as Service<Req>>::Future: 'static,
127{
128 type Response = Res;
129 type Error = Err;
130 type Config = Cfg;
131 type Service = BoxService<Req, Res, Err>;
132 type InitError = InitErr;
133 type Future = BoxFuture<Result<Self::Service, Self::InitError>>;
134
135 fn new_service(&self, cfg: Cfg) -> Self::Future {
136 let f = self.0.new_service(cfg);
137 Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as _) })
138 }
139}