1use axum::body::Body;
4use axum::extract::Request;
5use axum::{
6 extract::FromRequest,
7 handler::Handler,
8 response::{IntoResponse, Response},
9};
10use futures_util::future::{BoxFuture, FutureExt, Map};
11use std::{future::Future, marker::PhantomData};
12
13mod or;
14
15pub use self::or::Or;
16
17pub trait HandlerCallWithExtractors<T, S>: Sized {
25 type Future: Future<Output = Response> + Send + 'static;
27
28 fn call(self, extractors: T, state: S) -> <Self as HandlerCallWithExtractors<T, S>>::Future;
30
31 fn into_handler(self) -> IntoHandler<Self, T, S> {
33 IntoHandler {
34 handler: self,
35 _marker: PhantomData,
36 }
37 }
38
39 fn or<R, Rt>(self, rhs: R) -> Or<Self, R, T, Rt, S>
105 where
106 R: HandlerCallWithExtractors<Rt, S>,
107 {
108 Or {
109 lhs: self,
110 rhs,
111 _marker: PhantomData,
112 }
113 }
114}
115
116macro_rules! impl_handler_call_with {
117 ( $($ty:ident),* $(,)? ) => {
118 #[allow(non_snake_case)]
119 impl<F, Fut, S, $($ty,)*> HandlerCallWithExtractors<($($ty,)*), S> for F
120 where
121 F: FnOnce($($ty,)*) -> Fut,
122 Fut: Future + Send + 'static,
123 Fut::Output: IntoResponse,
124 {
125 type Future = Map<Fut, fn(Fut::Output) -> Response>;
127
128 fn call(
129 self,
130 ($($ty,)*): ($($ty,)*),
131 _state: S,
132 ) -> <Self as HandlerCallWithExtractors<($($ty,)*), S>>::Future {
133 self($($ty,)*).map(IntoResponse::into_response)
134 }
135 }
136 };
137 }
138
139impl_handler_call_with!();
140impl_handler_call_with!(T1);
141impl_handler_call_with!(T1, T2);
142impl_handler_call_with!(T1, T2, T3);
143impl_handler_call_with!(T1, T2, T3, T4);
144impl_handler_call_with!(T1, T2, T3, T4, T5);
145impl_handler_call_with!(T1, T2, T3, T4, T5, T6);
146impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7);
147impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8);
148impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
149impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
150impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
151impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
152impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
153impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
154impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
155impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
156
157#[allow(missing_debug_implementations)]
161pub struct IntoHandler<H, T, S> {
162 handler: H,
163 _marker: PhantomData<fn() -> (T, S)>,
164}
165
166impl<H, T, S> Handler<T, S> for IntoHandler<H, T, S>
167where
168 H: HandlerCallWithExtractors<T, S> + Clone + Send + Sync + 'static,
169 T: FromRequest<S> + Send + 'static,
170 T::Rejection: Send,
171 S: Send + Sync + 'static,
172{
173 type Future = BoxFuture<'static, Response>;
174
175 fn call(self, req: Request, state: S) -> Self::Future {
176 let req = req.map(Body::new);
177 Box::pin(async move {
178 match T::from_request(req, &state).await {
179 Ok(t) => self.handler.call(t, state).await,
180 Err(rejection) => rejection.into_response(),
181 }
182 })
183 }
184}
185
186impl<H, T, S> Copy for IntoHandler<H, T, S> where H: Copy {}
187
188impl<H, T, S> Clone for IntoHandler<H, T, S>
189where
190 H: Clone,
191{
192 fn clone(&self) -> Self {
193 Self {
194 handler: self.handler.clone(),
195 _marker: self._marker,
196 }
197 }
198}