1#![allow(clippy::type_complexity)]
2use std::{fmt, marker::PhantomData};
3
4use crate::and_then::{AndThen, AndThenFactory};
5use crate::apply::{Apply, ApplyFactory};
6use crate::ctx::ServiceCtx;
7use crate::map::{Map, MapFactory};
8use crate::map_err::{MapErr, MapErrFactory};
9use crate::map_init_err::MapInitErr;
10use crate::middleware::{ApplyMiddleware, Middleware};
11use crate::then::{Then, ThenFactory};
12use crate::{IntoService, IntoServiceFactory, Pipeline, Service, ServiceFactory};
13
14pub fn chain<Svc, Req, F>(service: F) -> ServiceChain<Svc, Req>
16where
17 Svc: Service<Req>,
18 F: IntoService<Svc, Req>,
19{
20 ServiceChain {
21 service: service.into_service(),
22 _t: PhantomData,
23 }
24}
25
26pub fn chain_factory<Fac, Req, C, F>(factory: F) -> ServiceChainFactory<Fac, Req, C>
28where
29 Fac: ServiceFactory<Req, C>,
30 F: IntoServiceFactory<Fac, Req, C>,
31{
32 ServiceChainFactory {
33 factory: factory.into_factory(),
34 _t: PhantomData,
35 }
36}
37
38pub struct ServiceChain<Svc, Req> {
40 service: Svc,
41 _t: PhantomData<Req>,
42}
43
44impl<Svc: Service<Req>, Req> ServiceChain<Svc, Req> {
45 pub fn and_then<Next, F>(self, service: F) -> ServiceChain<AndThen<Svc, Next>, Req>
55 where
56 Self: Sized,
57 F: IntoService<Next, Svc::Response>,
58 Next: Service<Svc::Response, Error = Svc::Error>,
59 {
60 ServiceChain {
61 service: AndThen::new(self.service, service.into_service()),
62 _t: PhantomData,
63 }
64 }
65
66 pub fn then<Next, F>(self, service: F) -> ServiceChain<Then<Svc, Next>, Req>
72 where
73 Self: Sized,
74 F: IntoService<Next, Result<Svc::Response, Svc::Error>>,
75 Next: Service<Result<Svc::Response, Svc::Error>, Error = Svc::Error>,
76 {
77 ServiceChain {
78 service: Then::new(self.service, service.into_service()),
79 _t: PhantomData,
80 }
81 }
82
83 pub fn map<F, Res>(self, f: F) -> ServiceChain<Map<Svc, F, Req, Res>, Req>
93 where
94 Self: Sized,
95 F: Fn(Svc::Response) -> Res,
96 {
97 ServiceChain {
98 service: Map::new(self.service, f),
99 _t: PhantomData,
100 }
101 }
102
103 pub fn map_err<F, Err>(self, f: F) -> ServiceChain<MapErr<Svc, F, Err>, Req>
112 where
113 Self: Sized,
114 F: Fn(Svc::Error) -> Err,
115 {
116 ServiceChain {
117 service: MapErr::new(self.service, f),
118 _t: PhantomData,
119 }
120 }
121
122 pub fn apply_fn<F, In, Out, Err>(
126 self,
127 f: F,
128 ) -> ServiceChain<Apply<Svc, Req, F, In, Out, Err>, In>
129 where
130 F: AsyncFn(In, &Pipeline<Svc>) -> Result<Out, Err>,
131 Svc: Service<Req>,
132 Err: From<Svc::Error>,
133 {
134 crate::apply_fn(self.service, f)
135 }
136
137 pub fn into_pipeline(self) -> Pipeline<Svc> {
139 Pipeline::new(self.service)
140 }
141}
142
143impl<Svc, Req> Clone for ServiceChain<Svc, Req>
144where
145 Svc: Clone,
146{
147 fn clone(&self) -> Self {
148 ServiceChain {
149 service: self.service.clone(),
150 _t: PhantomData,
151 }
152 }
153}
154
155impl<Svc, Req> fmt::Debug for ServiceChain<Svc, Req>
156where
157 Svc: fmt::Debug,
158{
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 f.debug_struct("ServiceChain")
161 .field("service", &self.service)
162 .finish()
163 }
164}
165
166impl<Svc: Service<Req>, Req> Service<Req> for ServiceChain<Svc, Req> {
167 type Response = Svc::Response;
168 type Error = Svc::Error;
169
170 crate::forward_poll!(service);
171 crate::forward_ready!(service);
172 crate::forward_shutdown!(service);
173
174 #[inline]
175 async fn call(
176 &self,
177 req: Req,
178 ctx: ServiceCtx<'_, Self>,
179 ) -> Result<Self::Response, Self::Error> {
180 ctx.call(&self.service, req).await
181 }
182}
183
184pub struct ServiceChainFactory<Fac, Req, C = ()> {
186 pub(crate) factory: Fac,
187 pub(crate) _t: PhantomData<(Req, C)>,
188}
189
190impl<Fac: ServiceFactory<Req, C>, Req, C> ServiceChainFactory<Fac, Req, C> {
191 pub fn and_then<F, U>(
193 self,
194 factory: F,
195 ) -> ServiceChainFactory<AndThenFactory<Fac, U>, Req, C>
196 where
197 Self: Sized,
198 F: IntoServiceFactory<U, Fac::Response, C>,
199 U: ServiceFactory<Fac::Response, C, Error = Fac::Error, InitError = Fac::InitError>,
200 {
201 ServiceChainFactory {
202 factory: AndThenFactory::new(self.factory, factory.into_factory()),
203 _t: PhantomData,
204 }
205 }
206
207 pub fn apply<U>(self, tr: U) -> ServiceChainFactory<ApplyMiddleware<U, Fac, C>, Req, C>
211 where
212 U: Middleware<Fac::Service, C>,
213 {
214 crate::apply(tr, self.factory)
215 }
216
217 pub fn apply_fn<F, In, Out, Err>(
221 self,
222 f: F,
223 ) -> ServiceChainFactory<ApplyFactory<Fac, Req, C, F, In, Out, Err>, In, C>
224 where
225 F: AsyncFn(In, &Pipeline<Fac::Service>) -> Result<Out, Err> + Clone,
226 Fac: ServiceFactory<Req, C>,
227 Err: From<Fac::Error>,
228 {
229 crate::apply_fn_factory(self.factory, f)
230 }
231
232 pub fn then<F, U>(self, factory: F) -> ServiceChainFactory<ThenFactory<Fac, U>, Req, C>
239 where
240 Self: Sized,
241 C: Clone,
242 F: IntoServiceFactory<U, Result<Fac::Response, Fac::Error>, C>,
243 U: ServiceFactory<
244 Result<Fac::Response, Fac::Error>,
245 C,
246 Error = Fac::Error,
247 InitError = Fac::InitError,
248 >,
249 {
250 ServiceChainFactory {
251 factory: ThenFactory::new(self.factory, factory.into_factory()),
252 _t: PhantomData,
253 }
254 }
255
256 pub fn map<F, Res>(
259 self,
260 f: F,
261 ) -> ServiceChainFactory<MapFactory<Fac, F, Req, Res, C>, Req, C>
262 where
263 Self: Sized,
264 F: Fn(Fac::Response) -> Res + Clone,
265 {
266 ServiceChainFactory {
267 factory: MapFactory::new(self.factory, f),
268 _t: PhantomData,
269 }
270 }
271
272 pub fn map_err<F, E>(
274 self,
275 f: F,
276 ) -> ServiceChainFactory<MapErrFactory<Fac, Req, C, F, E>, Req, C>
277 where
278 Self: Sized,
279 F: Fn(Fac::Error) -> E + Clone,
280 {
281 ServiceChainFactory {
282 factory: MapErrFactory::new(self.factory, f),
283 _t: PhantomData,
284 }
285 }
286
287 pub fn map_init_err<F, E>(
289 self,
290 f: F,
291 ) -> ServiceChainFactory<MapInitErr<Fac, Req, C, F, E>, Req, C>
292 where
293 Self: Sized,
294 F: Fn(Fac::InitError) -> E + Clone,
295 {
296 ServiceChainFactory {
297 factory: MapInitErr::new(self.factory, f),
298 _t: PhantomData,
299 }
300 }
301
302 pub async fn pipeline(&self, cfg: C) -> Result<Pipeline<Fac::Service>, Fac::InitError>
304 where
305 Self: Sized,
306 {
307 Ok(Pipeline::new(self.factory.create(cfg).await?))
308 }
309}
310
311impl<Fac, R, C> Clone for ServiceChainFactory<Fac, R, C>
312where
313 Fac: Clone,
314{
315 fn clone(&self) -> Self {
316 ServiceChainFactory {
317 factory: self.factory.clone(),
318 _t: PhantomData,
319 }
320 }
321}
322
323impl<Fac, R, C> fmt::Debug for ServiceChainFactory<Fac, R, C>
324where
325 Fac: fmt::Debug,
326{
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 f.debug_struct("ServiceChainFactory")
329 .field("factory", &self.factory)
330 .finish()
331 }
332}
333
334impl<Fac: ServiceFactory<Req, C>, Req, C> ServiceFactory<Req, C>
335 for ServiceChainFactory<Fac, Req, C>
336{
337 type Response = Fac::Response;
338 type Error = Fac::Error;
339 type Service = Fac::Service;
340 type InitError = Fac::InitError;
341
342 #[inline]
343 async fn create(&self, cfg: C) -> Result<Self::Service, Self::InitError> {
344 self.factory.create(cfg).await
345 }
346}