1#![allow(clippy::type_complexity)]
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::Arc;
5
6use crate::context::Context;
7use crate::extractor::FromContext;
8use crate::responder::IntoResponse;
9use crate::response::Response;
10
11#[cfg(not(target_arch = "wasm32"))]
12pub type HandlerCallFuture<'a> = Pin<Box<dyn Future<Output = Response> + Send + 'a>>;
13#[cfg(target_arch = "wasm32")]
14pub type HandlerCallFuture<'a> = Pin<Box<dyn Future<Output = Response> + 'a>>;
15
16#[cfg(not(target_arch = "wasm32"))]
17pub trait HandlerBounds: Send + Sync {}
18#[cfg(not(target_arch = "wasm32"))]
19impl<T: Send + Sync + ?Sized> HandlerBounds for T {}
20
21#[cfg(target_arch = "wasm32")]
22pub trait HandlerBounds {}
23#[cfg(target_arch = "wasm32")]
24impl<T: ?Sized> HandlerBounds for T {}
25
26#[cfg(not(target_arch = "wasm32"))]
27pub trait HandlerFnBounds: Send + Sync {}
28#[cfg(not(target_arch = "wasm32"))]
29impl<T: Send + Sync + ?Sized> HandlerFnBounds for T {}
30
31#[cfg(target_arch = "wasm32")]
32pub trait HandlerFnBounds {}
33#[cfg(target_arch = "wasm32")]
34impl<T: ?Sized> HandlerFnBounds for T {}
35
36#[cfg(not(target_arch = "wasm32"))]
37pub trait HandlerFutureBounds: Future + Send {}
38#[cfg(not(target_arch = "wasm32"))]
39impl<T: Future + Send + ?Sized> HandlerFutureBounds for T {}
40
41#[cfg(target_arch = "wasm32")]
42pub trait HandlerFutureBounds: Future {}
43#[cfg(target_arch = "wasm32")]
44impl<T: Future + ?Sized> HandlerFutureBounds for T {}
45
46pub trait Handler: HandlerBounds + 'static {
75 fn call(&self, ctx: Context) -> HandlerCallFuture<'_>;
77}
78
79pub type BoxedHandler = Arc<dyn Handler>;
81
82pub trait IntoHandler<Args> {
84 fn into_handler(self) -> BoxedHandler;
86}
87
88impl<F, Fut, R> IntoHandler<()> for F
90where
91 F: Fn() -> Fut + HandlerFnBounds + 'static,
92 Fut: HandlerFutureBounds<Output = R> + 'static,
93 R: IntoResponse + 'static,
94{
95 fn into_handler(self) -> BoxedHandler {
96 struct H<F>(F);
97
98 impl<F, Fut, R> Handler for H<F>
99 where
100 F: Fn() -> Fut + HandlerFnBounds + 'static,
101 Fut: HandlerFutureBounds<Output = R> + 'static,
102 R: IntoResponse + 'static,
103 {
104 fn call(&self, _ctx: Context) -> HandlerCallFuture<'_> {
105 let fut = (self.0)();
106 Box::pin(async move { fut.await.into_response() })
107 }
108 }
109
110 Arc::new(H(self))
111 }
112}
113
114impl<F, Fut, T1, R> IntoHandler<(T1,)> for F
116where
117 F: Fn(T1) -> Fut + HandlerFnBounds + 'static,
118 Fut: HandlerFutureBounds<Output = R> + 'static,
119 T1: FromContext + 'static,
120 R: IntoResponse + 'static,
121{
122 fn into_handler(self) -> BoxedHandler {
123 struct H<F, T1>(F, std::marker::PhantomData<fn() -> T1>);
124
125 unsafe impl<F: Send, T1> Send for H<F, T1> {}
127 unsafe impl<F: Sync, T1> Sync for H<F, T1> {}
128
129 impl<F, Fut, T1, R> Handler for H<F, T1>
130 where
131 F: Fn(T1) -> Fut + HandlerFnBounds + 'static,
132 Fut: HandlerFutureBounds<Output = R> + 'static,
133 T1: FromContext + 'static,
134 R: IntoResponse + 'static,
135 {
136 fn call(&self, ctx: Context) -> HandlerCallFuture<'_> {
137 Box::pin(async move {
138 let t1 = T1::from_context(&ctx).await;
139 (self.0)(t1).await.into_response()
140 })
141 }
142 }
143
144 Arc::new(H(self, std::marker::PhantomData))
145 }
146}
147
148impl<F, Fut, T1, T2, R> IntoHandler<(T1, T2)> for F
150where
151 F: Fn(T1, T2) -> Fut + HandlerFnBounds + 'static,
152 Fut: HandlerFutureBounds<Output = R> + 'static,
153 T1: FromContext + 'static,
154 T2: FromContext + 'static,
155 R: IntoResponse + 'static,
156{
157 fn into_handler(self) -> BoxedHandler {
158 struct H<F, T1, T2>(F, std::marker::PhantomData<fn() -> (T1, T2)>);
159
160 unsafe impl<F: Send, T1, T2> Send for H<F, T1, T2> {}
161 unsafe impl<F: Sync, T1, T2> Sync for H<F, T1, T2> {}
162
163 impl<F, Fut, T1, T2, R> Handler for H<F, T1, T2>
164 where
165 F: Fn(T1, T2) -> Fut + HandlerFnBounds + 'static,
166 Fut: HandlerFutureBounds<Output = R> + 'static,
167 T1: FromContext + 'static,
168 T2: FromContext + 'static,
169 R: IntoResponse + 'static,
170 {
171 fn call(&self, ctx: Context) -> HandlerCallFuture<'_> {
172 Box::pin(async move {
173 let t1 = T1::from_context(&ctx).await;
174 let t2 = T2::from_context(&ctx).await;
175 (self.0)(t1, t2).await.into_response()
176 })
177 }
178 }
179
180 Arc::new(H(self, std::marker::PhantomData))
181 }
182}
183
184impl<F, Fut, T1, T2, T3, R> IntoHandler<(T1, T2, T3)> for F
186where
187 F: Fn(T1, T2, T3) -> Fut + HandlerFnBounds + 'static,
188 Fut: HandlerFutureBounds<Output = R> + 'static,
189 T1: FromContext + 'static,
190 T2: FromContext + 'static,
191 T3: FromContext + 'static,
192 R: IntoResponse + 'static,
193{
194 fn into_handler(self) -> BoxedHandler {
195 struct H<F, T1, T2, T3>(F, std::marker::PhantomData<fn() -> (T1, T2, T3)>);
196
197 unsafe impl<F: Send, T1, T2, T3> Send for H<F, T1, T2, T3> {}
198 unsafe impl<F: Sync, T1, T2, T3> Sync for H<F, T1, T2, T3> {}
199
200 impl<F, Fut, T1, T2, T3, R> Handler for H<F, T1, T2, T3>
201 where
202 F: Fn(T1, T2, T3) -> Fut + HandlerFnBounds + 'static,
203 Fut: HandlerFutureBounds<Output = R> + 'static,
204 T1: FromContext + 'static,
205 T2: FromContext + 'static,
206 T3: FromContext + 'static,
207 R: IntoResponse + 'static,
208 {
209 fn call(&self, ctx: Context) -> HandlerCallFuture<'_> {
210 Box::pin(async move {
211 let t1 = T1::from_context(&ctx).await;
212 let t2 = T2::from_context(&ctx).await;
213 let t3 = T3::from_context(&ctx).await;
214 (self.0)(t1, t2, t3).await.into_response()
215 })
216 }
217 }
218
219 Arc::new(H(self, std::marker::PhantomData))
220 }
221}
222
223impl<F, Fut, T1, T2, T3, T4, R> IntoHandler<(T1, T2, T3, T4)> for F
225where
226 F: Fn(T1, T2, T3, T4) -> Fut + HandlerFnBounds + 'static,
227 Fut: HandlerFutureBounds<Output = R> + 'static,
228 T1: FromContext + 'static,
229 T2: FromContext + 'static,
230 T3: FromContext + 'static,
231 T4: FromContext + 'static,
232 R: IntoResponse + 'static,
233{
234 fn into_handler(self) -> BoxedHandler {
235 struct H<F, T1, T2, T3, T4>(F, std::marker::PhantomData<fn() -> (T1, T2, T3, T4)>);
236
237 unsafe impl<F: Send, T1, T2, T3, T4> Send for H<F, T1, T2, T3, T4> {}
238 unsafe impl<F: Sync, T1, T2, T3, T4> Sync for H<F, T1, T2, T3, T4> {}
239
240 impl<F, Fut, T1, T2, T3, T4, R> Handler for H<F, T1, T2, T3, T4>
241 where
242 F: Fn(T1, T2, T3, T4) -> Fut + HandlerFnBounds + 'static,
243 Fut: HandlerFutureBounds<Output = R> + 'static,
244 T1: FromContext + 'static,
245 T2: FromContext + 'static,
246 T3: FromContext + 'static,
247 T4: FromContext + 'static,
248 R: IntoResponse + 'static,
249 {
250 fn call(&self, ctx: Context) -> HandlerCallFuture<'_> {
251 Box::pin(async move {
252 let t1 = T1::from_context(&ctx).await;
253 let t2 = T2::from_context(&ctx).await;
254 let t3 = T3::from_context(&ctx).await;
255 let t4 = T4::from_context(&ctx).await;
256 (self.0)(t1, t2, t3, t4).await.into_response()
257 })
258 }
259 }
260
261 Arc::new(H(self, std::marker::PhantomData))
262 }
263}