1use std::{convert::Infallible, fmt, marker::PhantomData};
2
3use crate::{Ctx, Service, ServiceFactory};
4
5pub struct FnReadiness<F, Err> {
7 f: F,
8 err: PhantomData<Err>,
9}
10
11impl<F, Err> FnReadiness<F, Err> {
12 pub fn new<St>(f: F) -> Self
14 where
15 F: AsyncFn(&St) -> Result<(), Err>,
16 {
17 Self {
18 f,
19 err: PhantomData,
20 }
21 }
22}
23
24impl<F, Err> Clone for FnReadiness<F, Err>
25where
26 F: Clone,
27{
28 #[inline]
29 fn clone(&self) -> Self {
30 Self {
31 f: self.f.clone(),
32 err: PhantomData,
33 }
34 }
35}
36
37impl<F, Err> fmt::Debug for FnReadiness<F, Err> {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.debug_struct("FnReadiness")
40 .field("fn", &std::any::type_name::<F>())
41 .finish()
42 }
43}
44
45impl<F, Err, St, Req> ServiceFactory<St, Req> for FnReadiness<F, Err>
46where
47 F: AsyncFn(&St) -> Result<(), Err> + Clone,
48{
49 type Res = Req;
50 type Error = Err;
51
52 type Service = FnReadiness<F, Err>;
53 type InitError = Infallible;
54
55 #[inline]
56 async fn create(&self, _: &St) -> Result<Self::Service, Self::InitError> {
57 Ok(self.clone())
58 }
59}
60
61impl<F, St, Req, Err> Service<St, Req> for FnReadiness<F, Err>
62where
63 F: AsyncFn(&St) -> Result<(), Err> + Clone,
64{
65 type Res = Req;
66 type Error = Err;
67
68 #[inline]
69 async fn ready(&self, ctx: Ctx<'_, Self, St>) -> Result<(), Err> {
70 (self.f)(ctx.st()).await
71 }
72
73 #[inline]
74 async fn call(&self, req: Req, _: Ctx<'_, Self, St>) -> Result<Req, Err> {
75 Ok(req)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use std::{cell::Cell, rc::Rc};
82
83 use crate::{Pipeline, factory, service};
84
85 use super::*;
86
87 #[ntex::test]
88 async fn test_fn_readiness() {
89 let is_called = Rc::new(Cell::new(false));
91 let is_called2 = is_called.clone();
92
93 let svc = service(async |()| Ok::<_, ()>("pipe")).readiness(async move |()| {
94 is_called2.set(true);
95 Ok(())
96 });
97 let _ = format!("{svc:?}");
98 let pipe = Pipeline::new((), svc);
99
100 let res = pipe.call(()).await;
101 assert_eq!(pipe.ready().await, Ok(()));
102 assert!(res.is_ok());
103 assert_eq!(res.unwrap(), "pipe");
104 assert!(is_called.get());
105
106 let is_called = Rc::new(Cell::new(false));
108 let is_called2 = is_called.clone();
109
110 let factory = factory(|()| async { Ok::<_, ()>("pipe") }).readiness(async move |()| {
111 is_called2.set(true);
112 Ok(())
113 });
114 let pipe = Pipeline::new((), factory.create(&()).await.unwrap());
115
116 let res = pipe.call(()).await;
117 assert_eq!(pipe.ready().await, Ok(()));
118 assert!(res.is_ok());
119 assert_eq!(res.unwrap(), "pipe");
120 assert!(is_called.get());
121 }
122}