ntex_service/
map_state.rs1use crate::{Ctx, IntoService, IntoServiceFactory, Service, ServiceFactory};
2
3pub fn map_state<S, St, Req>(st: St, s: impl IntoService<S, St, Req>) -> MapState<S, St>
7where
8 S: Service<St, Req>,
9{
10 MapState {
11 st,
12 s: s.into_service(),
13 }
14}
15
16pub fn map_state_factory<Sf, St, Req>(
20 st: St,
21 sf: impl IntoServiceFactory<Sf, St, Req>,
22) -> MapStateFactory<Sf, St>
23where
24 Sf: ServiceFactory<St, Req>,
25 St: Clone,
26{
27 MapStateFactory {
28 st,
29 sf: sf.into_factory(),
30 }
31}
32
33#[derive(Clone, Debug)]
34pub struct MapState<S, St> {
36 s: S,
37 st: St,
38}
39
40impl<OtSt, S, St, Req> Service<OtSt, Req> for MapState<S, St>
41where
42 S: Service<St, Req>,
43{
44 type Res = S::Res;
45 type Error = S::Error;
46
47 #[inline]
48 async fn call(&self, req: Req, ctx: Ctx<'_, Self, OtSt>) -> Result<S::Res, S::Error> {
49 ctx.map_state(&self.st).call_nowait(&self.s, req).await
50 }
51
52 #[inline]
53 async fn ready(&self, ctx: Ctx<'_, Self, OtSt>) -> Result<(), S::Error> {
54 ctx.map_state(&self.st).ready(&self.s).await
55 }
56
57 #[inline]
58 async fn shutdown(&self, ctx: Ctx<'_, Self, OtSt>) {
59 ctx.map_state(&self.st).shutdown(&self.s).await;
60 }
61}
62
63#[derive(Clone, Debug)]
64pub struct MapStateFactory<Sf, St> {
66 sf: Sf,
67 st: St,
68}
69
70impl<OtSt, Sf, St, Req> ServiceFactory<OtSt, Req> for MapStateFactory<Sf, St>
71where
72 Sf: ServiceFactory<St, Req>,
73 St: Clone,
74{
75 type Res = Sf::Res;
76 type Error = Sf::Error;
77
78 type Service = MapState<Sf::Service, St>;
79 type InitError = Sf::InitError;
80
81 #[inline]
82 async fn create(&self, _: &OtSt) -> Result<Self::Service, Self::InitError> {
83 Ok(MapState {
84 s: self.sf.create(&self.st).await?,
85 st: self.st.clone(),
86 })
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use crate::{Pipeline, ServiceFactory, fn_service_st, map_state, map_state_factory};
93
94 #[ntex::test]
95 async fn test_map_state() {
96 let svc = map_state(
97 100,
98 fn_service_st(|_: &usize, item: usize| async move { Ok::<_, ()>(item) }),
99 )
100 .clone();
101 let _ = format!("{svc:?}");
102
103 let svc = Pipeline::new((), svc);
104 assert_eq!(svc.call(1).await.unwrap(), 1);
105 assert!(!svc.is_shutdown());
106 svc.shutdown().await;
107 assert!(svc.is_shutdown());
108
109 let factory = map_state_factory(
110 100,
111 fn_service_st(|_: &usize, item: usize| async move { Ok::<_, ()>(item) }),
112 )
113 .clone();
114 let _ = format!("{factory:?}");
115
116 let svc = Pipeline::new((), factory.create(&1).await.unwrap());
117 assert_eq!(svc.call(1).await.unwrap(), 1);
118 }
119}