1use std::{convert::Infallible, fmt, marker::PhantomData};
2
3use crate::{Ctx, IntoService, IntoServiceFactory, Service, ServiceFactory};
4
5#[inline]
7pub fn fn_service<F, Req, Res, Err>(f: F) -> FnService<F, Req, Res, Err>
8where
9 F: AsyncFn(Req) -> Result<Res, Err>,
10{
11 FnService { f, _t: PhantomData }
12}
13
14#[inline]
18pub fn fn_service_st<F, St, Req, Res, Err>(f: F) -> FnServiceSt<F, St, Req, Res, Err>
19where
20 F: AsyncFn(&St, Req) -> Result<Res, Err>,
21{
22 FnServiceSt { f, _t: PhantomData }
23}
24
25pub struct FnService<F, Req, Res, Err> {
29 f: F,
30 _t: PhantomData<(Req, Res, Err)>,
31}
32
33impl<F, Req, Res, Err> Clone for FnService<F, Req, Res, Err>
34where
35 F: Clone,
36{
37 fn clone(&self) -> Self {
38 Self {
39 f: self.f.clone(),
40 _t: PhantomData,
41 }
42 }
43}
44
45impl<F, Req, Res, Err> fmt::Debug for FnService<F, Req, Res, Err> {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 f.debug_struct("FnService")
48 .field("f", &std::any::type_name::<F>())
49 .finish()
50 }
51}
52
53impl<F, St, Req, Res, Err> Service<St, Req> for FnService<F, Req, Res, Err>
54where
55 F: AsyncFn(Req) -> Result<Res, Err>,
56{
57 type Res = Res;
58 type Error = Err;
59
60 #[inline]
61 async fn call(&self, req: Req, _: Ctx<'_, Self, St>) -> Result<Res, Err> {
62 (self.f)(req).await
63 }
64}
65
66impl<F, St, Req, Res, Err> IntoServiceFactory<FnServiceFactory<F, Req, Res, Err>, St, Req>
67 for FnService<F, Req, Res, Err>
68where
69 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
70{
71 #[inline]
72 fn into_factory(self) -> FnServiceFactory<F, Req, Res, Err> {
73 FnServiceFactory {
74 f: self.f,
75 _t: PhantomData,
76 }
77 }
78}
79
80impl<F, St, Req, Res, Err> IntoService<FnService<F, Req, Res, Err>, St, Req> for F
81where
82 F: AsyncFn(Req) -> Result<Res, Err>,
83{
84 #[inline]
85 fn into_service(self) -> FnService<F, Req, Res, Err> {
86 FnService {
87 f: self,
88 _t: PhantomData,
89 }
90 }
91}
92
93pub struct FnServiceSt<F, St, Req, Res, Err> {
97 f: F,
98 _t: PhantomData<(St, Req, Res, Err)>,
99}
100
101impl<F, St, Req, Res, Err> Clone for FnServiceSt<F, St, Req, Res, Err>
102where
103 F: Clone,
104{
105 fn clone(&self) -> Self {
106 Self {
107 f: self.f.clone(),
108 _t: PhantomData,
109 }
110 }
111}
112
113impl<F, St, Req, Res, Err> fmt::Debug for FnServiceSt<F, St, Req, Res, Err> {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 f.debug_struct("FnServiceSt")
116 .field("f", &std::any::type_name::<F>())
117 .finish()
118 }
119}
120
121impl<F, St, Req, Res, Err> Service<St, Req> for FnServiceSt<F, St, Req, Res, Err>
122where
123 F: AsyncFn(&St, Req) -> Result<Res, Err>,
124{
125 type Res = Res;
126 type Error = Err;
127
128 #[inline]
129 async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<Res, Err> {
130 (self.f)(ctx.st(), req).await
131 }
132}
133
134impl<F, St, Req, Res, Err> IntoServiceFactory<FnServiceStFactory<F, St, Req, Res, Err>, St, Req>
135 for FnServiceSt<F, St, Req, Res, Err>
136where
137 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
138{
139 #[inline]
140 fn into_factory(self) -> FnServiceStFactory<F, St, Req, Res, Err> {
141 FnServiceStFactory {
142 f: self.f,
143 ph: PhantomData,
144 }
145 }
146}
147
148impl<F, St, Req, Res, Err> IntoService<FnServiceSt<F, St, Req, Res, Err>, St, Req> for F
149where
150 F: AsyncFn(&St, Req) -> Result<Res, Err>,
151{
152 #[inline]
153 fn into_service(self) -> FnServiceSt<F, St, Req, Res, Err> {
154 FnServiceSt {
155 f: self,
156 _t: PhantomData,
157 }
158 }
159}
160
161pub struct FnServiceFactory<F, Req, Res, Err>
164where
165 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
166{
167 f: F,
168 _t: PhantomData<(Req,)>,
169}
170
171impl<F, Req, Res, Err> FnServiceFactory<F, Req, Res, Err>
172where
173 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
174{
175 fn new(f: F) -> Self {
176 FnServiceFactory { f, _t: PhantomData }
177 }
178}
179
180impl<F, Req, Res, Err> Clone for FnServiceFactory<F, Req, Res, Err>
181where
182 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
183{
184 #[inline]
185 fn clone(&self) -> Self {
186 Self {
187 f: self.f.clone(),
188 _t: PhantomData,
189 }
190 }
191}
192
193impl<F, Req, Res, Err> fmt::Debug for FnServiceFactory<F, Req, Res, Err>
194where
195 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
196{
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 f.debug_struct("FnServiceFactory")
199 .field("f", &std::any::type_name::<F>())
200 .finish()
201 }
202}
203
204impl<F, St, Req, Res, Err> ServiceFactory<St, Req> for FnServiceFactory<F, Req, Res, Err>
205where
206 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
207{
208 type Res = Res;
209 type Error = Err;
210
211 type Service = FnService<F, Req, Res, Err>;
212 type InitError = Infallible;
213
214 #[inline]
215 async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
216 Ok(FnService {
217 f: self.f.clone(),
218 _t: PhantomData,
219 })
220 }
221}
222
223impl<St, F, Req, Res, Err> IntoServiceFactory<FnServiceFactory<F, Req, Res, Err>, St, Req> for F
224where
225 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
226{
227 #[inline]
228 fn into_factory(self) -> FnServiceFactory<F, Req, Res, Err> {
229 FnServiceFactory::new(self)
230 }
231}
232
233pub struct FnServiceStFactory<F, St, Req, Res, Err>
236where
237 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
238{
239 f: F,
240 ph: PhantomData<(St, Req, Res, Err)>,
241}
242
243impl<F, St, Req, Res, Err> FnServiceStFactory<F, St, Req, Res, Err>
244where
245 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
246{
247 fn new(f: F) -> Self {
248 FnServiceStFactory { f, ph: PhantomData }
249 }
250}
251
252impl<F, St, Req, Res, Err> Clone for FnServiceStFactory<F, St, Req, Res, Err>
253where
254 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
255{
256 #[inline]
257 fn clone(&self) -> Self {
258 Self {
259 f: self.f.clone(),
260 ph: PhantomData,
261 }
262 }
263}
264
265impl<F, St, Req, Res, Err> fmt::Debug for FnServiceStFactory<F, St, Req, Res, Err>
266where
267 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
268{
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 f.debug_struct("FnServiceStFactory")
271 .field("f", &std::any::type_name::<F>())
272 .finish()
273 }
274}
275
276impl<F, St, Req, Res, Err> ServiceFactory<St, Req> for FnServiceStFactory<F, St, Req, Res, Err>
277where
278 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
279{
280 type Res = Res;
281 type Error = Err;
282
283 type Service = FnServiceSt<F, St, Req, Res, Err>;
284 type InitError = Infallible;
285
286 #[inline]
287 async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
288 Ok(FnServiceSt {
289 f: self.f.clone(),
290 _t: PhantomData,
291 })
292 }
293}
294
295impl<F, St, Req, Res, Err> IntoServiceFactory<FnServiceStFactory<F, St, Req, Res, Err>, St, Req>
296 for F
297where
298 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
299{
300 #[inline]
301 fn into_factory(self) -> FnServiceStFactory<F, St, Req, Res, Err> {
302 FnServiceStFactory::new(self)
303 }
304}
305
306#[inline]
309pub fn fn_factory<F, S, St, Req, Err>(f: F) -> FnFactory<F, S, St, Req, Err>
340where
341 F: AsyncFn(&St) -> Result<S, Err>,
342 S: Service<St, Req>,
343{
344 FnFactory { f, _t: PhantomData }
345}
346
347pub struct FnFactory<F, S, St, Req, Err>
349where
350 F: AsyncFn(&St) -> Result<S, Err>,
351 S: Service<St, Req>,
352{
353 f: F,
354 _t: PhantomData<(S, St, Req, Err)>,
355}
356
357impl<F, S, St, Req, Err> ServiceFactory<St, Req> for FnFactory<F, S, St, Req, Err>
358where
359 F: AsyncFn(&St) -> Result<S, Err>,
360 S: Service<St, Req>,
361{
362 type Res = S::Res;
363 type Error = S::Error;
364
365 type Service = S;
366 type InitError = Err;
367
368 #[inline]
369 async fn create(&self, st: &St) -> Result<Self::Service, Self::InitError> {
370 (self.f)(st).await
371 }
372}
373
374impl<F, S, St, Req, Err> Clone for FnFactory<F, S, St, Req, Err>
375where
376 F: AsyncFn(&St) -> Result<S, Err> + Clone,
377 S: Service<St, Req>,
378{
379 #[inline]
380 fn clone(&self) -> Self {
381 FnFactory {
382 f: self.f.clone(),
383 _t: PhantomData,
384 }
385 }
386}
387
388impl<F, S, St, Req, Err> fmt::Debug for FnFactory<F, S, St, Req, Err>
389where
390 F: AsyncFn(&St) -> Result<S, Err>,
391 S: Service<St, Req>,
392{
393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
394 f.debug_struct("FnFactory")
395 .field("f", &std::any::type_name::<F>())
396 .finish()
397 }
398}
399
400impl<F, S, St, Req, Err> IntoServiceFactory<FnFactory<F, S, St, Req, Err>, St, Req> for F
401where
402 F: AsyncFn(&St) -> Result<S, Err>,
403 S: Service<St, Req>,
404{
405 #[inline]
406 fn into_factory(self) -> FnFactory<F, S, St, Req, Err> {
407 FnFactory {
408 f: self,
409 _t: PhantomData,
410 }
411 }
412}
413
414#[cfg(test)]
415mod tests {
416 use ntex::util::lazy;
417 use std::task::Poll;
418
419 use super::*;
420 use crate::{Pipeline, factory};
421
422 #[ntex::test]
423 async fn test_fn_service() {
424 let new_srv = factory(fn_service(async |()| Ok::<_, ()>("srv")).clone());
425 let _ = format!("{new_srv:?}");
426
427 let srv = Pipeline::new((), new_srv.create(&()).await.unwrap());
428 let res = srv.call(()).await;
429 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
430 assert!(res.is_ok());
431 assert_eq!(res.unwrap(), "srv");
432 let _ = format!("{srv:?}");
433
434 let new_srv = fn_service(async |()| Ok::<_, ()>("srv"));
435 let srv = Pipeline::new((), new_srv.clone());
436 let res = srv.call(()).await;
437 assert!(res.is_ok());
438 assert_eq!(res.unwrap(), "srv");
439 let _ = format!("{srv:?}");
440
441 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
442 }
443
444 #[ntex::test]
445 async fn test_fn_service_comp() {
446 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
447 let _ = format!("{new_srv:?}");
448
449 let srv = Pipeline::new((), factory(new_srv).create(&()).await.unwrap());
450 let res = srv.call(()).await;
451 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
452 assert!(res.is_ok());
453 assert_eq!(res.unwrap(), "srv");
454 let _ = format!("{srv:?}");
455
456 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
457 let srv = Pipeline::new((), new_srv.clone());
458 let res = srv.call(()).await;
459 assert!(res.is_ok());
460 assert_eq!(res.unwrap(), "srv");
461 let _ = format!("{srv:?}");
462
463 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
464 }
465
466 #[ntex::test]
467 async fn test_fn_service_service() {
468 let srv = Pipeline::new(
469 (),
470 factory(fn_service(async |()| Ok::<_, ()>("srv")).clone())
471 .create(&())
472 .await
473 .unwrap()
474 .clone(),
475 );
476
477 let res = srv.call(()).await;
478 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
479 assert!(res.is_ok());
480 assert_eq!(res.unwrap(), "srv");
481 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
482 }
483
484 #[ntex::test]
485 async fn test_fn_service_with_config() {
486 let new_srv = factory(fn_factory(async move |cfg: &usize| {
487 let cfg = *cfg;
488 Ok::<_, ()>(fn_service(async move |()| Ok::<_, ()>(("srv", cfg))))
489 }))
490 .clone();
491
492 let srv = Pipeline::new(1, new_srv.create(&1).await.unwrap());
493 let res = srv.call(()).await;
494 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
495 assert!(res.is_ok());
496 assert_eq!(res.unwrap(), ("srv", 1));
497 }
498}