axum_core/extract/
tuple.rs

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