tosic_http/extractors/
path.rs1use 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)]
12pub struct Path<V>(pub V);
14
15impl<T> Path<T> {
16 #[inline]
17 pub(crate) fn new(value: T) -> Self {
19 Path(value)
20 }
21
22 #[inline]
23 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
100macro_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}