tosic_http/extractors/
path.rs

1//! Extracts data from the path
2
3use crate::error::response_error::ResponseError;
4use crate::extractors::ExtractionError;
5use crate::futures::{err, ok, Ready};
6use crate::request::{HttpPayload, HttpRequest};
7use crate::traits::from_request::FromRequest;
8use std::fmt::{Debug, Display};
9use std::str::FromStr;
10
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
12/// Path extractor
13pub struct Path<V>(pub V);
14
15impl<T> Path<T> {
16    #[inline]
17    /// Creates a new path extractor
18    pub(crate) fn new(value: T) -> Self {
19        Path(value)
20    }
21
22    #[inline]
23    /// Returns the inner value
24    pub fn into_inner(self) -> T {
25        self.0
26    }
27}
28
29impl<T> std::ops::Deref for Path<T> {
30    type Target = T;
31    #[inline]
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl<T> std::ops::DerefMut for Path<T> {
38    #[inline]
39    fn deref_mut(&mut self) -> &mut Self::Target {
40        &mut self.0
41    }
42}
43
44impl<V: FromStr> FromRequest for Path<Vec<V>>
45where
46    V::Err: ResponseError + Display + Debug,
47{
48    type Error = ExtractionError;
49    type Future = Ready<Result<Self, Self::Error>>;
50
51    #[inline]
52    fn from_request(req: &HttpRequest, _: &mut HttpPayload) -> Self::Future {
53        let params = req.params();
54
55        let mut parsed_params = Vec::new();
56
57        for value in params.values() {
58            let parsed: V = match value.clone().parse() {
59                Ok(val) => val,
60                Err(error) => return err(ExtractionError::Path(error.to_string())),
61            };
62
63            parsed_params.push(parsed);
64        }
65
66        ok(Path::new(parsed_params))
67    }
68}
69
70impl<V: FromStr, const N: usize> FromRequest for Path<[V; N]>
71where
72    V::Err: ResponseError + Display + Debug,
73{
74    type Error = ExtractionError;
75    type Future = Ready<Result<Self, Self::Error>>;
76
77    #[inline]
78    fn from_request(req: &HttpRequest, _: &mut HttpPayload) -> Self::Future {
79        let params = req.params();
80        if params.len() != N {
81            return err(ExtractionError::InvalidLength);
82        }
83
84        let mut parsed_params = Vec::new();
85        for value in params.values() {
86            let parsed: V = match value.clone().parse() {
87                Ok(val) => val,
88                Err(error) => return err(ExtractionError::Path(error.to_string())),
89            };
90            parsed_params.push(parsed);
91        }
92
93        match parsed_params.try_into() {
94            Ok(array) => ok(Path::new(array)),
95            Err(_) => err(ExtractionError::InvalidLength),
96        }
97    }
98}
99
100/*impl<V: FromStr> FromRequest for Path<V>
101where
102    V::Err: ResponseError + Display + Debug
103{
104    type Error = ExtractionError;
105    type Future = Ready<Result<Self, Self::Error>>;
106
107    #[inline]
108    fn from_request(req: &HttpRequest, _: &mut HttpPayload) -> Self::Future {
109        let params = req.params();
110        let value = params.first();
111        match value {
112            Some(value) => {
113                let parsed: V = match value.clone().parse() {
114                    Ok(val) => val,
115                    Err(error) => return err(ExtractionError::Path(error.to_string())),
116                };
117                ok(Path::new(parsed))
118            }
119            None => err(ExtractionError::MissingPathField),
120        }
121    }
122}*/
123
124macro_rules! impl_tuple (
125    {$($T:ident)+} => {
126        #[allow(non_snake_case)]
127        impl<$($T: FromStr),+> FromRequest for Path<($($T,)+)>
128        where
129            $($T::Err: ResponseError + Display + Debug,)+
130        {
131            type Error = ExtractionError;
132            type Future = Ready<Result<Self, Self::Error>>;
133
134            #[inline]
135            fn from_request(req: &HttpRequest, _: &mut HttpPayload) -> Self::Future {
136                let params = req.params();
137                let mut iter = params.values();
138
139                $(let $T: $T = match iter.next() {
140                    Some(val) => match val.clone().parse() {
141                        Ok(v) => v,
142                        Err(error) => return err(ExtractionError::Path(error.to_string())),
143                    },
144                    None => return err(ExtractionError::MissingPathField),
145                };)+
146
147                let result = ($($T,)+);
148
149                ok(Path::new(result))
150            }
151        }
152    };
153);
154
155impl_tuple! {A}
156impl_tuple! {A A1}
157impl_tuple! {A A1 A2}
158impl_tuple! {A A1 A2 A3}
159impl_tuple! {A A1 A2 A3 A4}
160impl_tuple! {A A1 A2 A3 A4 A5}
161impl_tuple! {A A1 A2 A3 A4 A5 A6}
162impl_tuple! {A A1 A2 A3 A4 A5 A6 A7}
163impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8}
164impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9}
165impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10}
166impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11}
167impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12}
168impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13}
169impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14}
170impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15}
171impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16}
172impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17}
173impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18}
174impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19}
175impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20}
176impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21}
177impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21 A22}
178impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21 A22 A23}
179impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21 A22 A23 A24}
180impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21 A22 A23 A24 A25}
181impl_tuple! {A A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18 A19 A20 A21 A22 A23 A24 A25 A26}