1 use std::str::FromStr;
2 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr};
3 use std::num::{
4     NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
5     NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
6 };
7 
8 use crate::http::RawStr;
9 
10 /// Trait to parse a typed value from a form value.
11 ///
12 /// This trait is used by Rocket's code generation in two places:
13 ///
14 ///   1. Fields in structs deriving [`FromForm`](crate::request::FromForm) are
15 ///      required to implement this trait.
16 ///   2. Types of dynamic query parameters (`?<param>`) are required to
17 ///      implement this trait.
18 ///
19 /// # `FromForm` Fields
20 ///
21 /// When deriving the `FromForm` trait, Rocket uses the `FromFormValue`
22 /// implementation of each field's type to validate the form input. To
23 /// illustrate, consider the following structure:
24 ///
25 /// ```rust
26 /// # #[macro_use] extern crate rocket;
27 /// #[derive(FromForm)]
28 /// struct Person {
29 ///     name: String,
30 ///     age: u16
31 /// }
32 /// ```
33 ///
34 /// The `FromForm` implementation generated by Rocket will call
35 /// `String::from_form_value` for the `name` field, and `u16::from_form_value`
36 /// for the `age` field. The `Person` structure can only be created from a form
37 /// if both calls return successfully.
38 ///
39 /// # Dynamic Query Parameters
40 ///
41 /// Types of dynamic query parameters are required to implement this trait. The
42 /// `FromFormValue` implementation is used to parse and validate each parameter
43 /// according to its target type:
44 ///
45 /// ```rust
46 /// # #![feature(proc_macro_hygiene)]
47 /// # #[macro_use] extern crate rocket;
48 /// # type Size = String;
49 /// #[get("/item?<id>&<size>")]
50 /// fn item(id: usize, size: Size) { /* ... */ }
51 /// # fn main() { }
52 /// ```
53 ///
54 /// To generate values for `id` and `size`, Rocket calls
55 /// `usize::from_form_value()` and `Size::from_form_value()`, respectively.
56 ///
57 /// # Validation Errors
58 ///
59 /// It is sometimes desired to prevent a validation error from forwarding a
60 /// request to another route. The `FromFormValue` implementation for `Option<T>`
61 /// and `Result<T, T::Error>` make this possible. Their implementations always
62 /// return successfully, effectively "catching" the error.
63 ///
64 /// For instance, if we wanted to know if a user entered an invalid `age` in the
65 /// form corresponding to the `Person` structure in the first example, we could
66 /// use the following structure:
67 ///
68 /// ```rust
69 /// # use rocket::http::RawStr;
70 /// struct Person<'r> {
71 ///     name: String,
72 ///     age: Result<u16, &'r RawStr>
73 /// }
74 /// ```
75 ///
76 /// The `Err` value in this case is `&RawStr` since `u16::from_form_value`
77 /// returns a `Result<u16, &RawStr>`.
78 ///
79 /// # Provided Implementations
80 ///
81 /// Rocket implements `FromFormValue` for many standard library types. Their
82 /// behavior is documented here.
83 ///
84 ///   *
85 ///       * Primitive types: **f32, f64, isize, i8, i16, i32, i64, i128,
86 ///         usize, u8, u16, u32, u64, u128**
87 ///       * `IpAddr` and `SocketAddr` types: **IpAddr, Ipv4Addr, Ipv6Addr,
88 ///         SocketAddrV4, SocketAddrV6, SocketAddr**
89 ///       * `NonZero*` types: **NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64,
90 ///         NonZeroI128, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32,
91 ///         NonZeroU64, NonZeroU128, NonZeroUsize**
92 ///
93 ///     A value is validated successfully if the `from_str` method for the given
94 ///     type returns successfully. Otherwise, the raw form value is returned as
95 ///     the `Err` value.
96 ///
97 ///   * **bool**
98 ///
99 ///     A value is validated successfully as `true` if the the form value is
100 ///     `"true"` or `"on"`, and as a `false` value if the form value is
101 ///     `"false"`, `"off"`, or not present. In any other case, the raw form
102 ///     value is returned in the `Err` value.
103 ///
104 ///   * **[`&RawStr`](RawStr)**
105 ///
106 ///     _This implementation always returns successfully._
107 ///
108 ///     The raw, undecoded string is returned directly without modification.
109 ///
110 ///   * **String**
111 ///
112 ///     URL decodes the form value. If the decode is successful, the decoded
113 ///     string is returned. Otherwise, an `Err` with the original form value is
114 ///     returned.
115 ///
116 ///   * **Option&lt;T>** _where_ **T: FromFormValue**
117 ///
118 ///     _This implementation always returns successfully._
119 ///
120 ///     The form value is validated by `T`'s `FromFormValue` implementation. If
121 ///     the validation succeeds, a `Some(validated_value)` is returned.
122 ///     Otherwise, a `None` is returned.
123 ///
124 ///   * **Result&lt;T, T::Error>** _where_ **T: FromFormValue**
125 ///
126 ///     _This implementation always returns successfully._
127 ///
128 ///     The from value is validated by `T`'s `FromFormvalue` implementation. The
129 ///     returned `Result` value is returned.
130 ///
131 /// # Example
132 ///
133 /// This trait is generally implemented to parse and validate form values. While
134 /// Rocket provides parsing and validation for many of the standard library
135 /// types such as `u16` and `String`, you can implement `FromFormValue` for a
136 /// custom type to get custom validation.
137 ///
138 /// Imagine you'd like to verify that some user is over some age in a form. You
139 /// might define a new type and implement `FromFormValue` as follows:
140 ///
141 /// ```rust
142 /// use rocket::request::FromFormValue;
143 /// use rocket::http::RawStr;
144 ///
145 /// struct AdultAge(usize);
146 ///
147 /// impl<'v> FromFormValue<'v> for AdultAge {
148 ///     type Error = &'v RawStr;
149 ///
150 ///     fn from_form_value(form_value: &'v RawStr) -> Result<AdultAge, &'v RawStr> {
151 ///         match form_value.parse::<usize>() {
152 ///             Ok(age) if age >= 21 => Ok(AdultAge(age)),
153 ///             _ => Err(form_value),
154 ///         }
155 ///     }
156 /// }
157 /// ```
158 ///
159 /// The type can then be used in a `FromForm` struct as follows:
160 ///
161 /// ```rust
162 /// # #[macro_use] extern crate rocket;
163 /// # type AdultAge = usize;
164 /// #[derive(FromForm)]
165 /// struct Person {
166 ///     name: String,
167 ///     age: AdultAge
168 /// }
169 /// ```
170 ///
171 /// A form using the `Person` structure as its target will only parse and
172 /// validate if the `age` field contains a `usize` greater than `21`.
173 pub trait FromFormValue<'v>: Sized {
174     /// The associated error which can be returned from parsing. It is a good
175     /// idea to have the return type be or contain an `&'v str` so that the
176     /// unparseable string can be examined after a bad parse.
177     type Error;
178 
179     /// Parses an instance of `Self` from an HTTP form field value or returns an
180     /// `Error` if one cannot be parsed.
from_form_value(form_value: &'v RawStr) -> Result<Self, Self::Error>181     fn from_form_value(form_value: &'v RawStr) -> Result<Self, Self::Error>;
182 
183     /// Returns a default value to be used when the form field does not exist.
184     /// If this returns `None`, then the field is required. Otherwise, this
185     /// should return `Some(default_value)`. The default implementation simply
186     /// returns `None`.
187     #[inline(always)]
default() -> Option<Self>188     fn default() -> Option<Self> {
189         None
190     }
191 }
192 
193 impl<'v> FromFormValue<'v> for &'v RawStr {
194     type Error = std::convert::Infallible;
195 
196     // This just gives the raw string.
197     #[inline(always)]
from_form_value(v: &'v RawStr) -> Result<Self, Self::Error>198     fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
199         Ok(v)
200     }
201 }
202 
203 impl<'v> FromFormValue<'v> for String {
204     type Error = &'v RawStr;
205 
206     // This actually parses the value according to the standard.
207     #[inline(always)]
from_form_value(v: &'v RawStr) -> Result<Self, Self::Error>208     fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
209         v.url_decode().map_err(|_| v)
210     }
211 }
212 
213 impl<'v> FromFormValue<'v> for bool {
214     type Error = &'v RawStr;
215 
from_form_value(v: &'v RawStr) -> Result<Self, Self::Error>216     fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
217         match v.as_str() {
218             "on" | "true" => Ok(true),
219             "off" | "false" => Ok(false),
220             _ => Err(v),
221         }
222     }
223 
224     #[inline(always)]
default() -> Option<bool>225     fn default() -> Option<bool> {
226         Some(false)
227     }
228 }
229 
230 macro_rules! impl_with_fromstr {
231     ($($T:ident),+) => ($(
232         impl<'v> FromFormValue<'v> for $T {
233             type Error = &'v RawStr;
234 
235             #[inline(always)]
236             fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
237                 $T::from_str(v.as_str()).map_err(|_| v)
238             }
239         }
240     )+)
241 }
242 
243 impl_with_fromstr!(
244     f32, f64, isize, i8, i16, i32, i64, i128, usize, u8, u16, u32, u64, u128,
245     NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
246     NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
247     IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr
248 );
249 
250 impl<'v, T: FromFormValue<'v>> FromFormValue<'v> for Option<T> {
251     type Error = std::convert::Infallible;
252 
253     #[inline(always)]
from_form_value(v: &'v RawStr) -> Result<Self, Self::Error>254     fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
255         match T::from_form_value(v) {
256             Ok(v) => Ok(Some(v)),
257             Err(_) => Ok(None),
258         }
259     }
260 
261     #[inline(always)]
default() -> Option<Option<T>>262     fn default() -> Option<Option<T>> {
263         Some(None)
264     }
265 }
266 
267 // // TODO: Add more useful implementations (range, regex, etc.).
268 impl<'v, T: FromFormValue<'v>> FromFormValue<'v> for Result<T, T::Error> {
269     type Error = std::convert::Infallible;
270 
271     #[inline(always)]
from_form_value(v: &'v RawStr) -> Result<Self, Self::Error>272     fn from_form_value(v: &'v RawStr) -> Result<Self, Self::Error> {
273         match T::from_form_value(v) {
274             ok@Ok(_) => Ok(ok),
275             e@Err(_) => Ok(e),
276         }
277     }
278 }
279