rocket/form/from_form_field.rs
1use std::borrow::Cow;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr};
3use std::num::{
4 NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
5 NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
6};
7
8use time::{Date, Time, PrimitiveDateTime};
9use time::{macros::format_description, format_description::FormatItem};
10
11use crate::data::Capped;
12use crate::http::uncased::AsUncased;
13use crate::form::prelude::*;
14
15/// Implied form guard ([`FromForm`]) for parsing a single form field.
16///
17/// Types that implement `FromFormField` automatically implement [`FromForm`]
18/// via a blanket implementation. As such, all `FromFormField` types are form
19/// guards and can appear as the type of values in derived `FromForm` struct
20/// fields:
21///
22/// ```rust
23/// # use rocket::form::FromForm;
24/// #[derive(FromForm)]
25/// struct Person<'r> {
26/// name: &'r str,
27/// age: u16
28/// }
29/// ```
30///
31/// # Semantics
32///
33/// The implementation of `FromForm` for a `T: FromFormField` type operates as
34/// follows:
35///
36/// * When parsing is **strict**, the parser accepts the _first_ value or data
37/// field with the corresponding field name and calls `T::from_value()` or
38/// `T::from_data()` with the field's value, respectively. If more than one
39/// field value is seen, an [`ErrorKind::Duplicate`) is emitted. If no
40/// matching field is seen, an [`ErrorKind::Missing`] is emitted. Otherwise,
41/// the result from the call is emitted.
42///
43/// * When parsing is **lenient**, the parser accepts the first _expected_
44/// value or data field with the corresponding field name and calls
45/// `T::from_value()` or `T::from_data()` with the field's value,
46/// respectively. Unexpected values, identified by returning an
47/// [`ErrorKind::Unexpected`] from `from_value()` or `from_data()` are
48/// ignored. Any additional fields with a matching field name are ignored.
49/// If no matching field is seen and `T` has a default, it is used,
50/// otherwise an [`ErrorKind::Missing`] is emitted.
51///
52/// # Deriving
53///
54/// `FromFormField` can be derived for C-like enums, where the generated
55/// implementation case-insensitively parses fields with values equal to the
56/// name of the variant or the value in `field()`.
57///
58/// ```rust
59/// # use rocket::form::FromFormField;
60/// /// Fields with value `"simple"` parse as `Kind::Simple`. Fields with value
61/// /// `"fancy"` parse as `Kind::SoFancy`.
62/// #[derive(FromFormField)]
63/// enum Kind {
64/// Simple,
65/// #[field(value = "fancy")]
66/// SoFancy,
67/// }
68/// ```
69///
70/// # Provided Implementations
71///
72/// See [`FromForm`](crate::form::FromForm#provided-implementations) for a list
73/// of all form guards, including those implemented via `FromFormField`.
74///
75/// # Implementing
76///
77/// Implementing `FromFormField` requires implementing one or both of
78/// `from_value` or `from_data`, depending on whether the type can be parsed
79/// from a value field (text) and/or streaming binary data. Typically, a value
80/// can be parsed from either, either directly or by using request-local cache
81/// as an intermediary, and parsing from both should be preferred when sensible.
82///
83/// `FromFormField` is an async trait, so implementations must be decorated with
84/// an attribute of `#[rocket::async_trait]`:
85///
86/// ```rust
87/// # #[macro_use] extern crate rocket;
88/// # struct MyType;
89/// use rocket::form::{self, FromFormField, DataField, ValueField};
90///
91/// #[rocket::async_trait]
92/// impl<'r> FromFormField<'r> for MyType {
93/// fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {
94/// todo!("parse from a value or use default impl")
95/// }
96///
97/// async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {
98/// todo!("parse from a value or use default impl")
99/// }
100/// }
101/// ```
102///
103/// ## Example
104///
105/// The following example parses a custom `Person` type with the format
106/// `$name:$data`, where `$name` is expected to be string and `data` is expected
107/// to be any slice of bytes.
108///
109/// ```rust
110/// # use rocket::post;
111/// use rocket::data::ToByteUnit;
112/// use rocket::form::{self, FromFormField, DataField, ValueField};
113///
114/// use memchr::memchr;
115///
116/// struct Person<'r> {
117/// name: &'r str,
118/// data: &'r [u8]
119/// }
120///
121/// #[rocket::async_trait]
122/// impl<'r> FromFormField<'r> for Person<'r> {
123/// fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {
124/// match field.value.find(':') {
125/// Some(i) => Ok(Person {
126/// name: &field.value[..i],
127/// data: field.value[(i + 1)..].as_bytes()
128/// }),
129/// None => Err(form::Error::validation("does not contain ':'"))?
130/// }
131/// }
132///
133/// async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {
134/// // Retrieve the configured data limit or use `256KiB` as default.
135/// let limit = field.request.limits()
136/// .get("person")
137/// .unwrap_or(256.kibibytes());
138///
139/// // Read the capped data stream, returning a limit error as needed.
140/// let bytes = field.data.open(limit).into_bytes().await?;
141/// if !bytes.is_complete() {
142/// Err((None, Some(limit)))?;
143/// }
144///
145/// // Store the bytes in request-local cache and split at ':'.
146/// let bytes = bytes.into_inner();
147/// let bytes = rocket::request::local_cache!(field.request, bytes);
148/// let (raw_name, data) = match memchr(b':', bytes) {
149/// Some(i) => (&bytes[..i], &bytes[(i + 1)..]),
150/// None => Err(form::Error::validation("does not contain ':'"))?
151/// };
152///
153/// // Try to parse the name as UTF-8 or return an error if it fails.
154/// let name = std::str::from_utf8(raw_name)?;
155/// Ok(Person { name, data })
156/// }
157/// }
158///
159/// use rocket::form::{Form, FromForm};
160///
161/// // The type can be used directly, if only one field is expected...
162/// #[post("/person", data = "<person>")]
163/// fn person(person: Form<Person<'_>>) { /* ... */ }
164///
165/// // ...or as a named field in another form guard...
166/// #[derive(FromForm)]
167/// struct NewPerson<'r> {
168/// person: Person<'r>
169/// }
170///
171/// #[post("/person", data = "<person>")]
172/// fn new_person(person: Form<NewPerson<'_>>) { /* ... */ }
173/// ```
174// NOTE: Ideally, we would have two traits instead one with two fallible
175// methods: `FromFormValue` and `FromFormData`. This would be especially nice
176// for use with query values, where `FromFormData` would make no sense.
177//
178// However, blanket implementations of `FromForm` for these traits would result
179// in duplicate implementations of `FromForm`; we need specialization to resolve
180// this concern. Thus, for now, we keep this as one trait.
181#[crate::async_trait]
182pub trait FromFormField<'v>: Send + Sized {
183 /// Parse a value of `T` from a form value field.
184 ///
185 /// The default implementation returns an error of
186 /// [`ValueField::unexpected()`].
187 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
188 Err(field.unexpected())?
189 }
190
191 /// Parse a value of `T` from a form data field.
192 ///
193 /// The default implementation returns an error of
194 /// [`DataField::unexpected()`].
195 async fn from_data(field: DataField<'v, '_>) -> Result<'v, Self> {
196 Err(field.unexpected())?
197 }
198
199 /// Returns a default value, if any exists, to be used during lenient
200 /// parsing when the form field is missing.
201 ///
202 /// A return value of `None` means that field is required to exist and parse
203 /// successfully, always. A return value of `Some(default)` means that
204 /// `default` should be used when a field is missing.
205 ///
206 /// The default implementation returns `None`.
207 fn default() -> Option<Self> { None }
208}
209
210#[doc(hidden)]
211pub struct FromFieldContext<'v, T: FromFormField<'v>> {
212 field_name: Option<NameView<'v>>,
213 field_value: Option<&'v str>,
214 opts: Options,
215 value: Option<Result<'v, T>>,
216 pushes: usize
217}
218
219impl<'v, T: FromFormField<'v>> FromFieldContext<'v, T> {
220 fn should_push(&mut self) -> bool {
221 self.pushes += 1;
222 self.value.is_none()
223 }
224
225 fn push(&mut self, name: NameView<'v>, result: Result<'v, T>) {
226 fn is_unexpected(e: &Errors<'_>) -> bool {
227 matches!(e.last().map(|e| &e.kind), Some(ErrorKind::Unexpected))
228 }
229
230 self.field_name = Some(name);
231 match result {
232 Err(e) if !self.opts.strict && is_unexpected(&e) => { /* ok */ },
233 result => self.value = Some(result),
234 }
235 }
236}
237
238#[crate::async_trait]
239impl<'v, T: FromFormField<'v>> FromForm<'v> for T {
240 type Context = FromFieldContext<'v, T>;
241
242 fn init(opts: Options) -> Self::Context {
243 FromFieldContext {
244 opts,
245 field_name: None,
246 field_value: None,
247 value: None,
248 pushes: 0,
249 }
250 }
251
252 fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
253 if ctxt.should_push() {
254 ctxt.field_value = Some(field.value);
255 ctxt.push(field.name, Self::from_value(field))
256 }
257 }
258
259 async fn push_data(ctxt: &mut FromFieldContext<'v, T>, field: DataField<'v, '_>) {
260 if ctxt.should_push() {
261 ctxt.push(field.name, Self::from_data(field).await);
262 }
263 }
264
265 fn finalize(ctxt: Self::Context) -> Result<'v, Self> {
266 let mut errors = match ctxt.value {
267 Some(Ok(val)) if !ctxt.opts.strict || ctxt.pushes <= 1 => return Ok(val),
268 Some(Ok(_)) => Errors::from(ErrorKind::Duplicate),
269 Some(Err(errors)) => errors,
270 None if !ctxt.opts.strict => match <T as FromFormField>::default() {
271 Some(default) => return Ok(default),
272 None => Errors::from(ErrorKind::Missing)
273 },
274 None => Errors::from(ErrorKind::Missing),
275 };
276
277 if let Some(name) = ctxt.field_name {
278 errors.set_name(name);
279 }
280
281 if let Some(value) = ctxt.field_value {
282 errors.set_value(value);
283 }
284
285 Err(errors)
286 }
287}
288
289#[crate::async_trait]
290impl<'v> FromFormField<'v> for Capped<&'v str> {
291 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
292 Ok(Capped::from(field.value))
293 }
294
295 async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {
296 use crate::data::{Capped, Outcome, FromData};
297
298 match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await {
299 Outcome::Success(p) => Ok(p),
300 Outcome::Error((_, e)) => Err(e)?,
301 Outcome::Forward(..) => {
302 Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
303 }
304 }
305 }
306}
307
308impl_strict_from_form_field_from_capped!(&'v str);
309
310#[crate::async_trait]
311impl<'v> FromFormField<'v> for Capped<String> {
312 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
313 Ok(Capped::from(field.value.to_string()))
314 }
315
316 async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {
317 use crate::data::{Capped, Outcome, FromData};
318
319 match <Capped<String> as FromData>::from_data(f.request, f.data).await {
320 Outcome::Success(p) => Ok(p),
321 Outcome::Error((_, e)) => Err(e)?,
322 Outcome::Forward(..) => {
323 Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
324 }
325 }
326 }
327}
328
329impl_strict_from_form_field_from_capped!(String);
330
331impl<'v> FromFormField<'v> for bool {
332 fn default() -> Option<Self> {
333 Some(false)
334 }
335
336 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
337 match field.value.as_uncased() {
338 v if v == "off" || v == "no" || v == "false" => Ok(false),
339 v if v.is_empty() || v == "on" || v == "yes" || v == "true" => Ok(true),
340 // force a `ParseBoolError`
341 _ => Ok("".parse()?),
342 }
343 }
344}
345
346#[crate::async_trait]
347impl<'v> FromFormField<'v> for Capped<&'v [u8]> {
348 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
349 Ok(Capped::from(field.value.as_bytes()))
350 }
351
352 async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {
353 use crate::data::{Capped, Outcome, FromData};
354
355 match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await {
356 Outcome::Success(p) => Ok(p),
357 Outcome::Error((_, e)) => Err(e)?,
358 Outcome::Forward(..) => {
359 Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
360 }
361 }
362 }
363}
364
365impl_strict_from_form_field_from_capped!(&'v [u8]);
366
367#[crate::async_trait]
368impl<'v> FromFormField<'v> for Capped<Cow<'v, str>> {
369 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
370 let capped = <Capped<&'v str>>::from_value(field)?;
371 Ok(capped.map(|s| s.into()))
372 }
373
374 async fn from_data(field: DataField<'v, '_>) -> Result<'v, Self> {
375 let capped = <Capped<&'v str>>::from_data(field).await?;
376 Ok(capped.map(|s| s.into()))
377 }
378}
379
380impl_strict_from_form_field_from_capped!(Cow<'v, str>);
381
382macro_rules! impl_with_parse {
383 ($($T:ident),+ $(,)?) => ($(
384 impl<'v> FromFormField<'v> for $T {
385 #[inline(always)]
386 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
387 Ok(field.value.parse()?)
388 }
389 }
390 )+)
391}
392
393impl_with_parse!(
394 char,
395 f32, f64,
396 isize, i8, i16, i32, i64, i128,
397 usize, u8, u16, u32, u64, u128,
398 NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,
399 NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
400 Ipv4Addr, IpAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr
401);
402
403// Keep formats in sync with 'FromFormField' impls.
404static DATE_FMT: &[FormatItem<'_>] = format_description!("[year padding:none]-[month]-[day]");
405static TIME_FMT1: &[FormatItem<'_>] = format_description!("[hour padding:none]:[minute]:[second]");
406static TIME_FMT2: &[FormatItem<'_>] = format_description!("[hour padding:none]:[minute]");
407static DATE_TIME_FMT1: &[FormatItem<'_>] =
408 format_description!("[year padding:none]-[month]-[day]T[hour padding:none]:[minute]:[second]");
409static DATE_TIME_FMT2: &[FormatItem<'_>] =
410 format_description!("[year padding:none]-[month]-[day]T[hour padding:none]:[minute]");
411
412impl<'v> FromFormField<'v> for Date {
413 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
414 let date = Self::parse(field.value, &DATE_FMT)
415 .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;
416
417 Ok(date)
418 }
419}
420
421impl<'v> FromFormField<'v> for Time {
422 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
423 let time = Self::parse(field.value, &TIME_FMT1)
424 .or_else(|_| Self::parse(field.value, &TIME_FMT2))
425 .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;
426
427 Ok(time)
428 }
429}
430
431impl<'v> FromFormField<'v> for PrimitiveDateTime {
432 fn from_value(field: ValueField<'v>) -> Result<'v, Self> {
433 let dt = Self::parse(field.value, &DATE_TIME_FMT1)
434 .or_else(|_| Self::parse(field.value, &DATE_TIME_FMT2))
435 .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;
436
437 Ok(dt)
438 }
439}