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>
165where
166 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
167{
168 f: F,
169 _t: PhantomData<(Req,)>,
170}
171
172impl<F, Req, Res, Err> FnServiceFactory<F, Req, Res, Err>
173where
174 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
175{
176 fn new(f: F) -> Self {
177 FnServiceFactory { f, _t: PhantomData }
178 }
179}
180
181impl<F, Req, Res, Err> Clone for FnServiceFactory<F, Req, Res, Err>
182where
183 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
184{
185 #[inline]
186 fn clone(&self) -> Self {
187 Self {
188 f: self.f.clone(),
189 _t: PhantomData,
190 }
191 }
192}
193
194impl<F, Req, Res, Err> fmt::Debug for FnServiceFactory<F, Req, Res, Err>
195where
196 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
197{
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 f.debug_struct("FnServiceFactory")
200 .field("f", &std::any::type_name::<F>())
201 .finish()
202 }
203}
204
205impl<F, St, Req, Res, Err> ServiceFactory<St, Req> for FnServiceFactory<F, Req, Res, Err>
206where
207 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
208{
209 type Res = Res;
210 type Error = Err;
211
212 type Service = FnService<F, Req, Res, Err>;
213 type InitError = Infallible;
214
215 #[inline]
216 async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
217 Ok(FnService {
218 f: self.f.clone(),
219 _t: PhantomData,
220 })
221 }
222}
223
224impl<St, F, Req, Res, Err> IntoServiceFactory<FnServiceFactory<F, Req, Res, Err>, St, Req> for F
225where
226 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
227{
228 #[inline]
229 fn into_factory(self) -> FnServiceFactory<F, Req, Res, Err> {
230 FnServiceFactory::new(self)
231 }
232}
233
234pub struct FnServiceStFactory<F, St, Req, Res, Err>
238where
239 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
240{
241 f: F,
242 ph: PhantomData<(St, Req, Res, Err)>,
243}
244
245impl<F, St, Req, Res, Err> Clone for FnServiceStFactory<F, St, Req, Res, Err>
246where
247 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
248{
249 #[inline]
250 fn clone(&self) -> Self {
251 Self {
252 f: self.f.clone(),
253 ph: PhantomData,
254 }
255 }
256}
257
258impl<F, St, Req, Res, Err> fmt::Debug for FnServiceStFactory<F, St, Req, Res, Err>
259where
260 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
261{
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 f.debug_struct("FnServiceStFactory")
264 .field("f", &std::any::type_name::<F>())
265 .finish()
266 }
267}
268
269impl<F, St, Req, Res, Err> ServiceFactory<St, Req> for FnServiceStFactory<F, St, Req, Res, Err>
270where
271 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
272{
273 type Res = Res;
274 type Error = Err;
275
276 type Service = FnServiceSt<F, St, Req, Res, Err>;
277 type InitError = Infallible;
278
279 #[inline]
280 async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
281 Ok(FnServiceSt {
282 f: self.f.clone(),
283 _t: PhantomData,
284 })
285 }
286}
287
288impl<F, St, Req, Res, Err> IntoServiceFactory<FnServiceStFactory<F, St, Req, Res, Err>, St, Req>
289 for F
290where
291 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
292{
293 #[inline]
294 fn into_factory(self) -> FnServiceStFactory<F, St, Req, Res, Err> {
295 FnServiceStFactory {
296 f: self,
297 ph: PhantomData,
298 }
299 }
300}
301
302#[inline]
305pub fn fn_factory<F, S, St, Req, Err>(f: F) -> FnFactory<F, S, St, Req, Err>
335where
336 F: AsyncFn(&St) -> Result<S, Err>,
337 S: Service<St, Req>,
338{
339 FnFactory { f, _t: PhantomData }
340}
341
342pub struct FnFactory<F, S, St, Req, Err>
344where
345 F: AsyncFn(&St) -> Result<S, Err>,
346 S: Service<St, Req>,
347{
348 f: F,
349 _t: PhantomData<(S, St, Req, Err)>,
350}
351
352impl<F, S, St, Req, Err> ServiceFactory<St, Req> for FnFactory<F, S, St, Req, Err>
353where
354 F: AsyncFn(&St) -> Result<S, Err>,
355 S: Service<St, Req>,
356{
357 type Res = S::Res;
358 type Error = S::Error;
359
360 type Service = S;
361 type InitError = Err;
362
363 #[inline]
364 async fn create(&self, st: &St) -> Result<Self::Service, Self::InitError> {
365 (self.f)(st).await
366 }
367}
368
369impl<F, S, St, Req, Err> Clone for FnFactory<F, S, St, Req, Err>
370where
371 F: AsyncFn(&St) -> Result<S, Err> + Clone,
372 S: Service<St, Req>,
373{
374 #[inline]
375 fn clone(&self) -> Self {
376 FnFactory {
377 f: self.f.clone(),
378 _t: PhantomData,
379 }
380 }
381}
382
383impl<F, S, St, Req, Err> fmt::Debug for FnFactory<F, S, St, Req, Err>
384where
385 F: AsyncFn(&St) -> Result<S, Err>,
386 S: Service<St, Req>,
387{
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 f.debug_struct("FnFactory")
390 .field("f", &std::any::type_name::<F>())
391 .finish()
392 }
393}
394
395impl<F, S, St, Req, Err> IntoServiceFactory<FnFactory<F, S, St, Req, Err>, St, Req> for F
396where
397 F: AsyncFn(&St) -> Result<S, Err>,
398 S: Service<St, Req>,
399{
400 #[inline]
401 fn into_factory(self) -> FnFactory<F, S, St, Req, Err> {
402 FnFactory {
403 f: self,
404 _t: PhantomData,
405 }
406 }
407}
408
409#[cfg(test)]
410mod tests {
411 use ntex::util::lazy;
412 use std::task::Poll;
413
414 use super::*;
415 use crate::{Pipeline, factory};
416
417 #[ntex::test]
418 async fn test_fn_service() {
419 let new_srv = factory(fn_service(async |()| Ok::<_, ()>("srv")).clone());
420 let _ = format!("{new_srv:?}");
421
422 let srv = Pipeline::new((), new_srv.create(&()).await.unwrap());
423 let res = srv.call(()).await;
424 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
425 assert!(res.is_ok());
426 assert_eq!(res.unwrap(), "srv");
427 let _ = format!("{srv:?}");
428
429 let new_srv = fn_service(async |()| Ok::<_, ()>("srv"));
430 let srv = Pipeline::new((), new_srv.clone());
431 let res = srv.call(()).await;
432 assert!(res.is_ok());
433 assert_eq!(res.unwrap(), "srv");
434 let _ = format!("{srv:?}");
435
436 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
437 }
438
439 #[ntex::test]
440 async fn test_fn_service_comp() {
441 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
442 let _ = format!("{new_srv:?}");
443
444 let srv = Pipeline::new((), factory(new_srv).create(&()).await.unwrap());
445 let res = srv.call(()).await;
446 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
447 assert!(res.is_ok());
448 assert_eq!(res.unwrap(), "srv");
449 let _ = format!("{srv:?}");
450
451 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
452 let srv = Pipeline::new((), new_srv.clone());
453 let res = srv.call(()).await;
454 assert!(res.is_ok());
455 assert_eq!(res.unwrap(), "srv");
456 let _ = format!("{srv:?}");
457
458 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
459 }
460
461 #[ntex::test]
462 async fn test_fn_service_service() {
463 let srv = Pipeline::new(
464 (),
465 factory(fn_service(async |()| Ok::<_, ()>("srv")).clone())
466 .create(&())
467 .await
468 .unwrap()
469 .clone(),
470 );
471
472 let res = srv.call(()).await;
473 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
474 assert!(res.is_ok());
475 assert_eq!(res.unwrap(), "srv");
476 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
477 }
478
479 #[ntex::test]
480 async fn test_fn_factory() {
481 let new_srv = factory(fn_factory(async move |cfg: &usize| {
482 let cfg = *cfg;
483 Ok::<_, ()>(fn_service(async move |()| Ok::<_, ()>(("srv", cfg))))
484 }))
485 .clone();
486
487 let srv = Pipeline::new(1, new_srv.create(&1).await.unwrap());
488 let res = srv.call(()).await;
489 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
490 assert!(res.is_ok());
491 assert_eq!(res.unwrap(), ("srv", 1));
492 }
493
494 #[ntex::test]
495 async fn test_fn_service_st() {
496 let new_srv = factory(async |(): &(), ()| Ok::<_, ()>("srv")).clone();
497 let _ = format!("{new_srv:?}");
498
499 let srv = Pipeline::new((), new_srv.create(&()).await.unwrap());
500 let res = srv.call(()).await;
501 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
502 assert!(res.is_ok());
503 assert_eq!(res.unwrap(), "srv");
504 let _ = format!("{srv:?}");
505
506 let new_srv = fn_service(async |()| Ok::<_, ()>("srv"));
507 let srv = Pipeline::new((), new_srv.clone());
508 let res = srv.call(()).await;
509 assert!(res.is_ok());
510 assert_eq!(res.unwrap(), "srv");
511 let _ = format!("{srv:?}");
512
513 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
514 }
515}