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
25#[inline]
26pub fn fn_factory<St, F, Srv, Err>(f: F) -> FnServiceNoConfig<St, F, Srv, Err>
62where
63 F: AsyncFn() -> Result<Srv, Err>,
64{
65 FnServiceNoConfig::new(f)
66}
67
68#[inline]
69pub fn fn_factory_with_config<St, F, Cfg, Srv, Req, Err>(
100 f: F,
101) -> FnServiceConfig<St, F, Cfg, Srv, Req, Err>
102where
103 F: AsyncFn(&Cfg) -> Result<Srv, Err>,
104{
105 FnServiceConfig { f, _t: PhantomData }
106}
107
108pub struct FnService<F, Req, Res, Err> {
110 f: F,
111 _t: PhantomData<(Req, Res, Err)>,
112}
113
114impl<F, Req, Res, Err> Clone for FnService<F, Req, Res, Err>
115where
116 F: Clone,
117{
118 fn clone(&self) -> Self {
119 Self {
120 f: self.f.clone(),
121 _t: PhantomData,
122 }
123 }
124}
125
126impl<F, Req, Res, Err> fmt::Debug for FnService<F, Req, Res, Err> {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 f.debug_struct("FnService")
129 .field("f", &std::any::type_name::<F>())
130 .finish()
131 }
132}
133
134impl<F, St, Req, Res, Err> Service<St, Req> for FnService<F, Req, Res, Err>
135where
136 F: AsyncFn(Req) -> Result<Res, Err>,
137{
138 type Res = Res;
139 type Error = Err;
140
141 #[inline]
142 async fn call(&self, req: Req, _: Ctx<'_, Self, St>) -> Result<Res, Err> {
143 (self.f)(req).await
144 }
145}
146
147impl<F, St, Req, Res, Err, Cfg>
148 IntoServiceFactory<FnServiceFactory<F, Req, Res, Err, Cfg>, St, Req, Cfg>
149 for FnService<F, Req, Res, Err>
150where
151 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
152{
153 #[inline]
154 fn into_factory(self) -> FnServiceFactory<F, Req, Res, Err, Cfg> {
155 FnServiceFactory {
156 f: self.f,
157 _t: PhantomData,
158 }
159 }
160}
161
162impl<F, St, Req, Res, Err> IntoService<FnService<F, Req, Res, Err>, St, Req> for F
163where
164 F: AsyncFn(Req) -> Result<Res, Err>,
165{
166 #[inline]
167 fn into_service(self) -> FnService<F, Req, Res, Err> {
168 FnService {
169 f: self,
170 _t: PhantomData,
171 }
172 }
173}
174
175pub struct FnServiceSt<F, St, Req, Res, Err> {
179 f: F,
180 _t: PhantomData<(St, Req, Res, Err)>,
181}
182
183impl<F, St, Req, Res, Err> Clone for FnServiceSt<F, St, Req, Res, Err>
184where
185 F: Clone,
186{
187 fn clone(&self) -> Self {
188 Self {
189 f: self.f.clone(),
190 _t: PhantomData,
191 }
192 }
193}
194
195impl<F, St, Req, Res, Err> fmt::Debug for FnServiceSt<F, St, Req, Res, Err> {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 f.debug_struct("FnServiceSt")
198 .field("f", &std::any::type_name::<F>())
199 .finish()
200 }
201}
202
203impl<F, St, Req, Res, Err> Service<St, Req> for FnServiceSt<F, St, Req, Res, Err>
204where
205 F: AsyncFn(&St, Req) -> Result<Res, Err>,
206{
207 type Res = Res;
208 type Error = Err;
209
210 #[inline]
211 async fn call(&self, req: Req, ctx: Ctx<'_, Self, St>) -> Result<Res, Err> {
212 (self.f)(ctx.st(), req).await
213 }
214}
215
216impl<F, St, Req, Res, Err, Cfg>
217 IntoServiceFactory<FnServiceStFactory<F, St, Req, Res, Err>, St, Req, Cfg>
218 for FnServiceSt<F, St, Req, Res, Err>
219where
220 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
221{
222 #[inline]
223 fn into_factory(self) -> FnServiceStFactory<F, St, Req, Res, Err> {
224 FnServiceStFactory {
225 f: self.f,
226 ph: PhantomData,
227 }
228 }
229}
230
231impl<F, St, Req, Res, Err> IntoService<FnServiceSt<F, St, Req, Res, Err>, St, Req> for F
232where
233 F: AsyncFn(&St, Req) -> Result<Res, Err>,
234{
235 #[inline]
236 fn into_service(self) -> FnServiceSt<F, St, Req, Res, Err> {
237 FnServiceSt {
238 f: self,
239 _t: PhantomData,
240 }
241 }
242}
243
244pub struct FnServiceFactory<F, Req, Res, Err, Cfg>
247where
248 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
249{
250 f: F,
251 _t: PhantomData<(Req, Cfg)>,
252}
253
254impl<F, Req, Res, Err, Cfg> FnServiceFactory<F, Req, Res, Err, Cfg>
255where
256 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
257{
258 fn new(f: F) -> Self {
259 FnServiceFactory { f, _t: PhantomData }
260 }
261}
262
263impl<F, Req, Res, Err, Cfg> Clone for FnServiceFactory<F, Req, Res, Err, Cfg>
264where
265 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
266{
267 #[inline]
268 fn clone(&self) -> Self {
269 Self {
270 f: self.f.clone(),
271 _t: PhantomData,
272 }
273 }
274}
275
276impl<F, Req, Res, Err, Cfg> fmt::Debug for FnServiceFactory<F, Req, Res, Err, Cfg>
277where
278 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
279{
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 f.debug_struct("FnServiceFactory")
282 .field("f", &std::any::type_name::<F>())
283 .finish()
284 }
285}
286
287impl<F, St, Req, Res, Err, Cfg> ServiceFactory<St, Req, Cfg>
288 for FnServiceFactory<F, Req, Res, Err, Cfg>
289where
290 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
291{
292 type Res = Res;
293 type Error = Err;
294
295 type Service = FnService<F, Req, Res, Err>;
296 type InitError = Infallible;
297
298 #[inline]
299 async fn create(&self, _: &Cfg) -> Result<Self::Service, Self::InitError> {
300 Ok(FnService {
301 f: self.f.clone(),
302 _t: PhantomData,
303 })
304 }
305}
306
307impl<St, F, Req, Res, Err, Cfg>
308 IntoServiceFactory<FnServiceFactory<F, Req, Res, Err, Cfg>, St, Req, Cfg> for F
309where
310 F: AsyncFn(Req) -> Result<Res, Err> + Clone,
311{
312 #[inline]
313 fn into_factory(self) -> FnServiceFactory<F, Req, Res, Err, Cfg> {
314 FnServiceFactory::new(self)
315 }
316}
317
318pub struct FnServiceStFactory<F, St, Req, Res, Err>
321where
322 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
323{
324 f: F,
325 ph: PhantomData<(St, Req, Res, Err)>,
326}
327
328impl<F, St, Req, Res, Err> FnServiceStFactory<F, St, Req, Res, Err>
329where
330 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
331{
332 fn new(f: F) -> Self {
333 FnServiceStFactory { f, ph: PhantomData }
334 }
335}
336
337impl<F, St, Req, Res, Err> Clone for FnServiceStFactory<F, St, Req, Res, Err>
338where
339 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
340{
341 #[inline]
342 fn clone(&self) -> Self {
343 Self {
344 f: self.f.clone(),
345 ph: PhantomData,
346 }
347 }
348}
349
350impl<F, St, Req, Res, Err> fmt::Debug for FnServiceStFactory<F, St, Req, Res, Err>
351where
352 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
353{
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 f.debug_struct("FnServiceStFactory")
356 .field("f", &std::any::type_name::<F>())
357 .finish()
358 }
359}
360
361impl<F, St, Req, Res, Err, Cfg> ServiceFactory<St, Req, Cfg>
362 for FnServiceStFactory<F, St, Req, Res, Err>
363where
364 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
365{
366 type Res = Res;
367 type Error = Err;
368
369 type Service = FnServiceSt<F, St, Req, Res, Err>;
370 type InitError = Infallible;
371
372 #[inline]
373 async fn create(&self, _: &Cfg) -> Result<Self::Service, Self::InitError> {
374 Ok(FnServiceSt {
375 f: self.f.clone(),
376 _t: PhantomData,
377 })
378 }
379}
380
381impl<F, St, Req, Res, Err, Cfg>
382 IntoServiceFactory<FnServiceStFactory<F, St, Req, Res, Err>, St, Req, Cfg> for F
383where
384 F: AsyncFn(&St, Req) -> Result<Res, Err> + Clone,
385{
386 #[inline]
387 fn into_factory(self) -> FnServiceStFactory<F, St, Req, Res, Err> {
388 FnServiceStFactory::new(self)
389 }
390}
391
392pub struct FnServiceConfig<St, F, Cfg, Srv, Req, Err>
396where
397 F: AsyncFn(&Cfg) -> Result<Srv, Err>,
398{
399 f: F,
400 _t: PhantomData<(St, Cfg, Srv, Req, Err)>,
401}
402
403impl<St, F, Cfg, Srv, Req, Err> Clone for FnServiceConfig<St, F, Cfg, Srv, Req, Err>
404where
405 F: AsyncFn(&Cfg) -> Result<Srv, Err> + Clone,
406{
407 #[inline]
408 fn clone(&self) -> Self {
409 FnServiceConfig {
410 f: self.f.clone(),
411 _t: PhantomData,
412 }
413 }
414}
415
416impl<St, F, Cfg, Srv, Req, Err> fmt::Debug for FnServiceConfig<St, F, Cfg, Srv, Req, Err>
417where
418 F: AsyncFn(&Cfg) -> Result<Srv, Err>,
419{
420 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421 f.debug_struct("FnServiceConfig")
422 .field("f", &std::any::type_name::<F>())
423 .finish()
424 }
425}
426
427impl<St, F, Cfg, S, Req, Err> ServiceFactory<St, Req, Cfg>
428 for FnServiceConfig<St, F, Cfg, S, Req, Err>
429where
430 F: AsyncFn(&Cfg) -> Result<S, Err>,
431 S: Service<St, Req>,
432{
433 type Res = S::Res;
434 type Error = S::Error;
435
436 type Service = S;
437 type InitError = Err;
438
439 #[inline]
440 async fn create(&self, cfg: &Cfg) -> Result<Self::Service, Self::InitError> {
441 (self.f)(cfg).await
442 }
443}
444
445impl<F, St, Cfg, S, Req, Err>
446 IntoServiceFactory<FnServiceConfig<St, F, Cfg, S, Req, Err>, St, Req, Cfg> for F
447where
448 F: AsyncFn(&Cfg) -> Result<S, Err> + Clone,
449 S: Service<St, Req>,
450{
451 #[inline]
452 fn into_factory(self) -> FnServiceConfig<St, F, Cfg, S, Req, Err> {
453 FnServiceConfig {
454 f: self,
455 _t: PhantomData,
456 }
457 }
458}
459
460pub struct FnServiceNoConfig<St, F, S, E, C = ()>
464where
465 F: AsyncFn() -> Result<S, E>,
466{
467 f: F,
468 _t: PhantomData<(St, C)>,
469}
470
471impl<St, F, S, E, C> FnServiceNoConfig<St, F, S, E, C>
472where
473 F: AsyncFn() -> Result<S, E>,
474{
475 fn new(f: F) -> Self {
476 Self { f, _t: PhantomData }
477 }
478}
479
480impl<St, F, S, Req, E, C> ServiceFactory<St, Req, C> for FnServiceNoConfig<St, F, S, E, C>
481where
482 F: AsyncFn() -> Result<S, E>,
483 S: Service<St, Req>,
484 C: 'static,
485{
486 type Res = S::Res;
487 type Error = S::Error;
488 type Service = S;
489 type InitError = E;
490
491 #[inline]
492 async fn create(&self, _: &C) -> Result<S, E> {
493 (self.f)().await
494 }
495}
496
497impl<St, F, S, E, C> Clone for FnServiceNoConfig<St, F, S, E, C>
498where
499 F: AsyncFn() -> Result<S, E> + Clone,
500{
501 #[inline]
502 fn clone(&self) -> Self {
503 Self::new(self.f.clone())
504 }
505}
506
507impl<St, F, S, E, C> fmt::Debug for FnServiceNoConfig<St, F, S, E, C>
508where
509 F: AsyncFn() -> Result<S, E>,
510{
511 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
512 f.debug_struct("FnServiceNoConfig")
513 .field("f", &std::any::type_name::<F>())
514 .finish()
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use ntex::util::lazy;
521 use std::task::Poll;
522
523 use super::*;
524 use crate::{Pipeline, factory_no_st};
525
526 #[ntex::test]
527 async fn test_fn_service() {
528 let new_srv = factory_no_st(fn_service(async |()| Ok::<_, ()>("srv")).clone());
529 let _ = format!("{new_srv:?}");
530
531 let srv = Pipeline::with((), new_srv.create(&()).await.unwrap());
532 let res = srv.call(()).await;
533 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
534 assert!(res.is_ok());
535 assert_eq!(res.unwrap(), "srv");
536 let _ = format!("{srv:?}");
537
538 let new_srv = fn_service(async |()| Ok::<_, ()>("srv"));
539 let srv = Pipeline::with((), new_srv.clone());
540 let res = srv.call(()).await;
541 assert!(res.is_ok());
542 assert_eq!(res.unwrap(), "srv");
543 let _ = format!("{srv:?}");
544
545 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
546 }
547
548 #[ntex::test]
549 async fn test_fn_service_comp() {
550 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
551 let _ = format!("{new_srv:?}");
552
553 let srv = Pipeline::with((), factory_no_st(new_srv).create(&()).await.unwrap());
554 let res = srv.call(()).await;
555 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
556 assert!(res.is_ok());
557 assert_eq!(res.unwrap(), "srv");
558 let _ = format!("{srv:?}");
559
560 let new_srv = fn_service(async |()| Ok::<_, ()>("srv")).clone();
561 let srv = Pipeline::with((), new_srv.clone());
562 let res = srv.call(()).await;
563 assert!(res.is_ok());
564 assert_eq!(res.unwrap(), "srv");
565 let _ = format!("{srv:?}");
566
567 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
568 }
569
570 #[ntex::test]
571 async fn test_fn_service_service() {
572 let srv = Pipeline::with(
573 (),
574 factory_no_st(fn_service(async |()| Ok::<_, ()>("srv")).clone())
575 .create(&())
576 .await
577 .unwrap()
578 .clone(),
579 );
580
581 let res = srv.call(()).await;
582 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
583 assert!(res.is_ok());
584 assert_eq!(res.unwrap(), "srv");
585 assert_eq!(lazy(|cx| srv.poll_shutdown(cx)).await, Poll::Ready(()));
586 }
587
588 #[ntex::test]
589 async fn test_fn_service_with_config() {
590 let new_srv = factory_no_st(fn_factory_with_config(async move |cfg: &usize| {
591 let cfg = *cfg;
592 Ok::<_, ()>(fn_service(async move |()| Ok::<_, ()>(("srv", cfg))))
593 }))
594 .clone();
595
596 let srv = Pipeline::with((), new_srv.create(&1).await.unwrap());
597 let res = srv.call(()).await;
598 assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
599 assert!(res.is_ok());
600 assert_eq!(res.unwrap(), ("srv", 1));
601 }
602}