1use std::{fmt, marker::PhantomData, rc::Rc};
2
3use super::{FromRequest, Responder, State, WebRequest, WebResponse, WebResponseError};
4use crate::util::BoxFuture;
5
6pub trait HandlerSt<St, U, T>: 'static
13where
14 St: State,
15{
16 type Output: Responder<St>;
18
19 async fn call(&self, st: &St, req: U, param: T) -> Self::Output;
21}
22
23impl<St, U, F, R> HandlerSt<St, U, ()> for F
24where
25 F: AsyncFn(&St, U) -> R + 'static,
26 R: Responder<St>,
27 St: State,
28{
29 type Output = R;
30
31 #[allow(clippy::ignored_unit_patterns)]
32 async fn call(&self, st: &St, req: U, _: ()) -> R {
33 (self)(st, req).await
34 }
35}
36
37pub trait Handler<St, T>: 'static
44where
45 St: State,
46{
47 type Output: Responder<St>;
49
50 async fn call(&self, param: T) -> Self::Output;
52}
53
54impl<St, F, R> Handler<St, ()> for F
55where
56 F: AsyncFn() -> R + 'static,
57 R: Responder<St>,
58 St: State,
59{
60 type Output = R;
61
62 #[allow(clippy::ignored_unit_patterns)]
63 async fn call(&self, _: ()) -> R {
64 (self)().await
65 }
66}
67
68pub(super) trait HandlerFn<St: State, U>: fmt::Debug {
69 fn call<'a>(&'a self, _: &'a St, _: WebRequest<U>) -> BoxFuture<'a, WebResponse>;
70}
71
72pub(super) struct HandlerStWrapper<St, U, F, T> {
73 hnd: F,
74 _t: PhantomData<(St, U, T)>,
75}
76
77impl<St, U, F, T> HandlerStWrapper<St, U, F, T>
78where
79 F: HandlerSt<St, U, T> + 'static,
80 T: FromRequest<St> + 'static,
81 T::Error: WebResponseError<St, St::Error>,
82 St: State,
83 U: 'static,
84{
85 pub(super) fn create(hnd: F) -> Rc<dyn HandlerFn<St, U>> {
86 Rc::new(HandlerStWrapper {
87 hnd,
88 _t: PhantomData,
89 })
90 }
91}
92
93impl<St, U, F, T> fmt::Debug for HandlerStWrapper<St, U, F, T> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "HandlerSt({:?})", std::any::type_name::<F>())
96 }
97}
98
99impl<St, U, F, T> HandlerFn<St, U> for HandlerStWrapper<St, U, F, T>
100where
101 F: HandlerSt<St, U, T> + 'static,
102 T: FromRequest<St> + 'static,
103 T::Error: WebResponseError<St, St::Error>,
104 St: State,
105{
106 fn call<'a>(&'a self, st: &'a St, req: WebRequest<U>) -> BoxFuture<'a, WebResponse> {
107 Box::pin(async move {
108 let (req, mut payload, reqst) = req.into_parts();
109 let param = match T::from_request(st, &req, &mut payload).await {
110 Ok(param) => param,
111 Err(e) => return WebResponse::from_err(st, &e, req),
112 };
113
114 let result = self.hnd.call(st, reqst, param).await;
115 let response = result.respond_to(st, &req).await;
116 WebResponse::new(response, req)
117 })
118 }
119}
120
121pub(super) struct HandlerWrapper<St, U, F, T> {
122 hnd: F,
123 _t: PhantomData<(St, U, T)>,
124}
125
126impl<St, U, F, T> HandlerWrapper<St, U, F, T>
127where
128 F: Handler<St, T> + 'static,
129 T: FromRequest<St> + 'static,
130 T::Error: WebResponseError<St, St::Error>,
131 St: State,
132 U: 'static,
133{
134 pub(super) fn create(hnd: F) -> Rc<dyn HandlerFn<St, U>> {
135 Rc::new(HandlerWrapper {
136 hnd,
137 _t: PhantomData,
138 })
139 }
140}
141
142impl<St, U, F, T> fmt::Debug for HandlerWrapper<St, U, F, T> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "HandlerNoState({:?})", std::any::type_name::<F>())
145 }
146}
147
148impl<St, U, F, T> HandlerFn<St, U> for HandlerWrapper<St, U, F, T>
149where
150 F: Handler<St, T> + 'static,
151 T: FromRequest<St> + 'static,
152 T::Error: WebResponseError<St, St::Error>,
153 St: State,
154{
155 fn call<'a>(&'a self, st: &'a St, req: WebRequest<U>) -> BoxFuture<'a, WebResponse> {
156 Box::pin(async move {
157 let (req, mut payload, _) = req.into_parts();
158 let param = match T::from_request(st, &req, &mut payload).await {
159 Ok(param) => param,
160 Err(e) => return WebResponse::from_err(st, &e, req),
161 };
162
163 let result = self.hnd.call(param).await;
164 let response = result.respond_to(st, &req).await;
165 WebResponse::new(response, req)
166 })
167 }
168}
169
170macro_rules! factory_tuple (
172 {$(#[$meta:meta])* $(($T:ident, $t:ident)),+} => {
173 $(#[$meta])*
174 impl<St, Func, U, $($T,)+ Res> HandlerSt<St, U, ($($T,)+)> for Func
175 where
176 St: State,
177 Func: 'static,
178 Func: AsyncFn(&St, U, $($T,)+) -> Res,
179 Res: Responder<St>,
180 {
181 type Output = Res;
182
183 async fn call(&self, st: &St, req: U, ($($t,)+): ($($T,)+)) -> Self::Output {
184 (self)(st, req, $($t,)+).await
185 }
186 }
187 }
188);
189
190macro_rules! factory_tuple_no_state (
191 {$(#[$meta:meta])* $(($T:ident, $t:ident)),+} => {
192 $(#[$meta])*
193 impl<St, Func, $($T,)+ Res> Handler<St, ($($T,)+)> for Func
194 where
195 St: State,
196 Func: 'static,
197 Func: AsyncFn($($T,)+) -> Res,
198 Res: Responder<St>,
199 {
200 type Output = Res;
201
202 async fn call(&self, ($($t,)+): ($($T,)+)) -> Self::Output {
203 (self)($($t,)+).await
204 }
205 }
206 }
207);
208
209#[allow(clippy::wildcard_imports)]
210#[rustfmt::skip]
211mod m {
212 use super::*;
213 use variadics_please::all_tuples;
214
215 all_tuples!(factory_tuple, 1, 16, T, t);
217
218 all_tuples!(factory_tuple_no_state, 1, 16, T, t);
219}