axum_core/extract/
tuple.rs1use super::{FromRequest, FromRequestParts, Request};
2use crate::response::{IntoResponse, Response};
3use http::request::Parts;
4use std::{convert::Infallible, future::Future};
5
6#[diagnostic::do_not_recommend]
7impl<S> FromRequestParts<S> for ()
8where
9 S: Send + Sync,
10{
11 type Rejection = Infallible;
12
13 async fn from_request_parts(_: &mut Parts, _: &S) -> Result<(), Self::Rejection> {
14 Ok(())
15 }
16}
17
18macro_rules! impl_from_request {
19 (
20 [$($ty:ident),*], $last:ident
21 ) => {
22 #[diagnostic::do_not_recommend]
23 #[allow(non_snake_case, unused_mut, unused_variables)]
24 impl<S, $($ty,)* $last> FromRequestParts<S> for ($($ty,)* $last,)
25 where
26 $( $ty: FromRequestParts<S> + Send, )*
27 $last: FromRequestParts<S> + Send,
28 S: Send + Sync,
29 {
30 type Rejection = Response;
31
32 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
33 $(
34 let $ty = $ty::from_request_parts(parts, state)
35 .await
36 .map_err(|err| err.into_response())?;
37 )*
38 let $last = $last::from_request_parts(parts, state)
39 .await
40 .map_err(|err| err.into_response())?;
41
42 Ok(($($ty,)* $last,))
43 }
44 }
45
46 #[diagnostic::do_not_recommend]
49 #[allow(non_snake_case, unused_mut, unused_variables)]
50 impl<S, $($ty,)* $last> FromRequest<S> for ($($ty,)* $last,)
51 where
52 $( $ty: FromRequestParts<S> + Send, )*
53 $last: FromRequest<S> + Send,
54 S: Send + Sync,
55 {
56 type Rejection = Response;
57
58 fn from_request(req: Request, state: &S) -> impl Future<Output = Result<Self, Self::Rejection>> {
59 let (mut parts, body) = req.into_parts();
60
61 async move {
62 $(
63 let $ty = $ty::from_request_parts(&mut parts, state).await.map_err(|err| err.into_response())?;
64 )*
65
66 let req = Request::from_parts(parts, body);
67
68 let $last = $last::from_request(req, state).await.map_err(|err| err.into_response())?;
69
70 Ok(($($ty,)* $last,))
71 }
72 }
73 }
74 };
75}
76
77all_the_tuples!(impl_from_request);
78
79#[cfg(test)]
80mod tests {
81 use bytes::Bytes;
82 use http::Method;
83
84 use crate::extract::{FromRequest, FromRequestParts};
85
86 fn assert_from_request<M, T>()
87 where
88 T: FromRequest<(), M>,
89 {
90 }
91
92 fn assert_from_request_parts<T: FromRequestParts<()>>() {}
93
94 #[test]
95 fn unit() {
96 assert_from_request_parts::<()>();
97 assert_from_request::<_, ()>();
98 }
99
100 #[test]
101 fn tuple_of_one() {
102 assert_from_request_parts::<(Method,)>();
103 assert_from_request::<_, (Method,)>();
104 assert_from_request::<_, (Bytes,)>();
105 }
106
107 #[test]
108 fn tuple_of_two() {
109 assert_from_request_parts::<((), ())>();
110 assert_from_request::<_, ((), ())>();
111 assert_from_request::<_, (Method, Bytes)>();
112 }
113
114 #[test]
115 fn nested_tuple() {
116 assert_from_request_parts::<(((Method,),),)>();
117 assert_from_request::<_, ((((Bytes,),),),)>();
118 }
119}