Simplify macros for implementing Handler and FromRequest (#340)

Makes the generated docs nicer and avoids having a recursive macro.
This commit is contained in:
David Pedersen
2021-09-19 15:51:25 +00:00
committed by GitHub
parent 0b9e0c7508
commit 48401f2c8d
2 changed files with 45 additions and 31 deletions
+21 -11
View File
@@ -20,29 +20,39 @@ where
} }
macro_rules! impl_from_request { macro_rules! impl_from_request {
() => { () => {};
};
( $head:ident, $($tail:ident),* $(,)? ) => { ( $($ty:ident),* $(,)? ) => {
#[async_trait] #[async_trait]
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl<B, $head, $($tail,)*> FromRequest<B> for ($head, $($tail,)*) impl<B, $($ty,)*> FromRequest<B> for ($($ty,)*)
where where
$head: FromRequest<B> + Send, $( $ty: FromRequest<B> + Send, )*
$( $tail: FromRequest<B> + Send, )*
B: Send, B: Send,
{ {
type Rejection = Response<BoxBody>; type Rejection = Response<BoxBody>;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> { async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
let $head = $head::from_request(req).await.map_err(|err| err.into_response().map(box_body))?; $( let $ty = $ty::from_request(req).await.map_err(|err| err.into_response().map(box_body))?; )*
$( let $tail = $tail::from_request(req).await.map_err(|err| err.into_response().map(box_body))?; )* Ok(($($ty,)*))
Ok(($head, $($tail,)*))
} }
} }
impl_from_request!($($tail,)*);
}; };
} }
impl_from_request!(T1);
impl_from_request!(T1, T2);
impl_from_request!(T1, T2, T3);
impl_from_request!(T1, T2, T3, T4);
impl_from_request!(T1, T2, T3, T4, T5);
impl_from_request!(T1, T2, T3, T4, T5, T6);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); impl_from_request!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
+24 -20
View File
@@ -2,7 +2,7 @@
use crate::{ use crate::{
body::{box_body, BoxBody}, body::{box_body, BoxBody},
extract::FromRequest, extract::{FromRequest, RequestParts},
response::IntoResponse, response::IntoResponse,
routing::{EmptyRouter, MethodFilter}, routing::{EmptyRouter, MethodFilter},
service::HandleError, service::HandleError,
@@ -319,48 +319,52 @@ where
} }
macro_rules! impl_handler { macro_rules! impl_handler {
() => { ( $($ty:ident),* $(,)? ) => {
};
( $head:ident, $($tail:ident),* $(,)? ) => {
#[async_trait] #[async_trait]
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl<F, Fut, B, Res, $head, $($tail,)*> Handler<B, ($head, $($tail,)*)> for F impl<F, Fut, B, Res, $($ty,)*> Handler<B, ($($ty,)*)> for F
where where
F: FnOnce($head, $($tail,)*) -> Fut + Clone + Send + Sync + 'static, F: FnOnce($($ty,)*) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = Res> + Send, Fut: Future<Output = Res> + Send,
B: Send + 'static, B: Send + 'static,
Res: IntoResponse, Res: IntoResponse,
$head: FromRequest<B> + Send, $( $ty: FromRequest<B> + Send,)*
$( $tail: FromRequest<B> + Send,)*
{ {
type Sealed = sealed::Hidden; type Sealed = sealed::Hidden;
async fn call(self, req: Request<B>) -> Response<BoxBody> { async fn call(self, req: Request<B>) -> Response<BoxBody> {
let mut req = crate::extract::RequestParts::new(req); let mut req = RequestParts::new(req);
let $head = match $head::from_request(&mut req).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response().map(box_body),
};
$( $(
let $tail = match $tail::from_request(&mut req).await { let $ty = match $ty::from_request(&mut req).await {
Ok(value) => value, Ok(value) => value,
Err(rejection) => return rejection.into_response().map(box_body), Err(rejection) => return rejection.into_response().map(box_body),
}; };
)* )*
let res = self($head, $($tail,)*).await; let res = self($($ty,)*).await;
res.into_response().map(crate::body::box_body) res.into_response().map(box_body)
} }
} }
impl_handler!($($tail,)*);
}; };
} }
impl_handler!(T1);
impl_handler!(T1, T2);
impl_handler!(T1, T2, T3);
impl_handler!(T1, T2, T3, T4);
impl_handler!(T1, T2, T3, T4, T5);
impl_handler!(T1, T2, T3, T4, T5, T6);
impl_handler!(T1, T2, T3, T4, T5, T6, T7);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
/// A [`Service`] created from a [`Handler`] by applying a Tower middleware. /// A [`Service`] created from a [`Handler`] by applying a Tower middleware.