1use std::{fmt, marker::PhantomData};
2
3use super::{IntoServiceFactory, ServiceFactory};
4
5pub fn map_config<T, R, U, F, C, C2>(factory: U, f: F) -> MapConfig<T, F, C, C2>
10where
11 T: ServiceFactory<R, C2>,
12 U: IntoServiceFactory<T, R, C2>,
13 F: Fn(C) -> C2,
14{
15 MapConfig::new(factory.into_factory(), f)
16}
17
18pub fn unit_config<T, R, U>(factory: U) -> UnitConfig<T>
20where
21 T: ServiceFactory<R>,
22 U: IntoServiceFactory<T, R>,
23{
24 UnitConfig::new(factory.into_factory())
25}
26
27pub struct MapConfig<A, F, C, C2> {
29 a: A,
30 f: F,
31 e: PhantomData<(C, C2)>,
32}
33
34impl<A, F, C, C2> MapConfig<A, F, C, C2> {
35 pub(crate) fn new(a: A, f: F) -> Self {
37 Self {
38 a,
39 f,
40 e: PhantomData,
41 }
42 }
43}
44
45impl<A, F, C, C2> Clone for MapConfig<A, F, C, C2>
46where
47 A: Clone,
48 F: Clone,
49{
50 fn clone(&self) -> Self {
51 Self {
52 a: self.a.clone(),
53 f: self.f.clone(),
54 e: PhantomData,
55 }
56 }
57}
58
59impl<A, F, C, C2> fmt::Debug for MapConfig<A, F, C, C2>
60where
61 A: fmt::Debug,
62{
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f.debug_struct("MapConfig")
65 .field("factory", &self.a)
66 .field("map", &std::any::type_name::<F>())
67 .finish()
68 }
69}
70
71impl<A, F, R, C, C2> ServiceFactory<R, C> for MapConfig<A, F, C, C2>
72where
73 A: ServiceFactory<R, C2>,
74 F: Fn(C) -> C2,
75{
76 type Response = A::Response;
77 type Error = A::Error;
78
79 type Service = A::Service;
80 type InitError = A::InitError;
81
82 async fn create(&self, cfg: C) -> Result<Self::Service, Self::InitError> {
83 self.a.create((self.f)(cfg)).await
84 }
85}
86
87#[derive(Clone, Debug)]
88pub struct UnitConfig<A> {
90 factory: A,
91}
92
93impl<A> UnitConfig<A> {
94 pub(crate) fn new(factory: A) -> Self {
96 Self { factory }
97 }
98}
99
100impl<A, R, C> ServiceFactory<R, C> for UnitConfig<A>
101where
102 A: ServiceFactory<R>,
103{
104 type Response = A::Response;
105 type Error = A::Error;
106
107 type Service = A::Service;
108 type InitError = A::InitError;
109
110 async fn create(&self, _: C) -> Result<Self::Service, Self::InitError> {
111 self.factory.create(()).await
112 }
113}
114
115#[cfg(test)]
116#[allow(clippy::redundant_closure)]
117mod tests {
118 use std::{cell::Cell, rc::Rc};
119
120 use super::*;
121 use crate::fn_service;
122
123 #[ntex::test]
124 async fn test_map_config() {
125 let item = Rc::new(Cell::new(1usize));
126
127 let factory = map_config(
128 fn_service(|item: usize| async move { Ok::<_, ()>(item) }),
129 |t: &usize| {
130 item.set(item.get() + *t);
131 },
132 )
133 .clone();
134
135 let _ = factory.create(&10).await;
136 assert_eq!(item.get(), 11);
137 let _ = format!("{:?}", factory);
138 }
139
140 #[ntex::test]
141 async fn test_unit_config() {
142 let _ = unit_config(fn_service(|item: usize| async move { Ok::<_, ()>(item) }))
143 .clone()
144 .create(&10)
145 .await;
146 }
147}