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<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<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