1use std::{fmt, rc::Rc};
2
3use crate::ctx::{Ctx, WaitersRef};
4use crate::{Service, ServiceFactory, util::BoxFuture};
5
6pub struct BoxService<St, Req, Res, Err> {
10 inner: Rc<dyn ServiceObj<St, Req, Res = Res, Error = Err>>,
11}
12
13pub fn service<S, St, Req, Res, Err>(service: S) -> BoxService<St, Req, Res, Err>
15where
16 S: Service<St, Req, Res = Res, Error = Err> + 'static,
17{
18 BoxService::new(service)
19}
20
21impl<St, Req, Res, Err> BoxService<St, Req, Res, Err> {
22 pub fn new<S>(service: S) -> Self
24 where
25 S: Service<St, Req, Res = Res, Error = Err> + 'static,
26 {
27 BoxService {
28 inner: Rc::new(service),
29 }
30 }
31}
32
33impl<St, Req, Res, Err> Clone for BoxService<St, Req, Res, Err> {
34 fn clone(&self) -> Self {
35 Self {
36 inner: self.inner.clone(),
37 }
38 }
39}
40
41impl<St, Req, Res, Err> fmt::Debug for BoxService<St, Req, Res, Err> {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.debug_struct("BoxService").finish()
44 }
45}
46
47impl<St, Req, Res, Err> Service<St, Req> for BoxService<St, Req, Res, Err> {
48 type Res = Res;
49 type Error = Err;
50
51 #[inline]
52 async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Self::Error> {
53 let (idx, waiters, st) = ctx.inner();
54 self.inner.ready(idx, waiters, st).await
55 }
56
57 #[inline]
58 async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<Res, Err> {
59 let (idx, waiters, st) = ctx.inner();
60 self.inner.call(req, idx, waiters, st).await
61 }
62
63 #[inline]
64 async fn shutdown(&self, ctx: Ctx<'_, Self, St>) {
65 let (idx, waiters, st) = ctx.inner();
66 self.inner.shutdown(idx, waiters, st).await;
67 }
68}
69
70trait ServiceObj<St, Req> {
71 type Res;
72 type Error;
73
74 fn ready<'a>(
75 &'a self,
76 i: u32,
77 w: &'a WaitersRef,
78 s: &'a St,
79 ) -> BoxFuture<'a, Result<(), Self::Error>>;
80
81 fn call<'a>(
82 &'a self,
83 r: Req,
84 i: u32,
85 w: &'a WaitersRef,
86 s: &'a St,
87 ) -> BoxFuture<'a, Result<Self::Res, Self::Error>>
88 where
89 Req: 'a;
90
91 fn shutdown<'a>(&'a self, idx: u32, waiters: &'a WaitersRef, st: &'a St) -> BoxFuture<'a, ()>
92 where
93 St: 'a,
94 Req: 'a;
95}
96
97impl<S, St, Req> ServiceObj<St, Req> for S
98where
99 S: Service<St, Req>,
100{
101 type Res = S::Res;
102 type Error = S::Error;
103
104 #[inline]
105 fn ready<'a>(
106 &'a self,
107 idx: u32,
108 waiters: &'a WaitersRef,
109 st: &'a St,
110 ) -> BoxFuture<'a, Result<(), Self::Error>> {
111 Box::pin(async move { Ctx::<'a, S, St>::new(idx, waiters, st).ready(self).await })
112 }
113
114 #[inline]
115 fn call<'a>(
116 &'a self,
117 req: Req,
118 idx: u32,
119 waiters: &'a WaitersRef,
120 st: &'a St,
121 ) -> BoxFuture<'a, Result<S::Res, S::Error>>
122 where
123 Req: 'a,
124 {
125 Box::pin(async move {
126 Ctx::<'a, S, St>::new(idx, waiters, st)
127 .call_nowait(self, req)
128 .await
129 })
130 }
131
132 #[inline]
133 fn shutdown<'a>(&'a self, idx: u32, waiters: &'a WaitersRef, st: &'a St) -> BoxFuture<'a, ()>
134 where
135 St: 'a,
136 Req: 'a,
137 {
138 Box::pin(async move { Ctx::<'a, S, St>::new(idx, waiters, st).shutdown(self).await })
139 }
140}
141
142pub struct BoxServiceFactory<St, Req, Res, Err, InitErr> {
146 inner: Rc<dyn ServiceFactoryObj<St, Req, Res = Res, Error = Err, InitErr = InitErr>>,
147}
148
149pub fn factory<Sf, St, Req>(
151 factory: Sf,
152) -> BoxServiceFactory<St, Req, Sf::Res, Sf::Error, Sf::InitError>
153where
154 Sf: ServiceFactory<St, Req> + 'static,
155 St: 'static,
156 Req: 'static,
157{
158 BoxServiceFactory::new(factory)
159}
160
161impl<St, Req, Res, Err, InitErr> BoxServiceFactory<St, Req, Res, Err, InitErr>
162where
163 St: 'static,
164 Req: 'static,
165{
166 pub fn new<Sf>(factory: Sf) -> Self
168 where
169 Sf: ServiceFactory<St, Req, Res = Res, Error = Err, InitError = InitErr> + 'static,
170 St: 'static,
171 Req: 'static,
172 {
173 Self {
174 inner: Rc::new(factory),
175 }
176 }
177}
178
179impl<St, Req, Res, Err, InitErr> ServiceFactory<St, Req>
180 for BoxServiceFactory<St, Req, Res, Err, InitErr>
181where
182 Req: 'static,
183{
184 type Res = Res;
185 type Error = Err;
186
187 type Service = BoxService<St, Req, Res, Err>;
188 type InitError = InitErr;
189
190 #[inline]
191 async fn create(&self, st: &St) -> Result<Self::Service, Self::InitError> {
192 self.inner.create(st).await
193 }
194}
195
196impl<St, Req, Res, Err, InitErr> Clone for BoxServiceFactory<St, Req, Res, Err, InitErr> {
197 fn clone(&self) -> Self {
198 Self {
199 inner: self.inner.clone(),
200 }
201 }
202}
203
204impl<St, Req, Res, Err, InitErr> fmt::Debug for BoxServiceFactory<St, Req, Res, Err, InitErr> {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 f.debug_struct("BoxServiceFactory").finish()
207 }
208}
209
210trait ServiceFactoryObj<St, Req> {
211 type Res;
212 type Error;
213 type InitErr;
214
215 fn create<'a>(
216 &'a self,
217 st: &'a St,
218 ) -> BoxFuture<'a, Result<BoxService<St, Req, Self::Res, Self::Error>, Self::InitErr>>
219 where
220 Req: 'a;
221}
222
223impl<Sf, St, Req> ServiceFactoryObj<St, Req> for Sf
224where
225 St: 'static,
226 Req: 'static,
227 Sf: ServiceFactory<St, Req> + 'static,
228{
229 type Res = Sf::Res;
230 type Error = Sf::Error;
231 type InitErr = Sf::InitError;
232
233 #[inline]
234 fn create<'a>(
235 &'a self,
236 st: &'a St,
237 ) -> BoxFuture<'a, Result<BoxService<St, Req, Self::Res, Self::Error>, Self::InitErr>>
238 where
239 Req: 'a,
240 {
241 let fut = ServiceFactory::create(self, st);
242 Box::pin(async move { fut.await.map(service) })
243 }
244}