rocket/form/
from_form.rs

1use std::borrow::Cow;
2use std::collections::{HashMap, BTreeMap};
3use std::hash::Hash;
4use std::sync::Arc;
5
6use either::Either;
7use indexmap::IndexMap;
8
9use crate::form::prelude::*;
10use crate::http::uncased::AsUncased;
11
12/// Trait implemented by form guards: types parseable from HTTP forms.
13///
14/// Only form guards that are _collections_, that is, collect more than one form
15/// field while parsing, should implement `FromForm`. All other types should
16/// implement [`FromFormField`] instead, which offers a simplified interface to
17/// parsing a single form field.
18///
19/// For a gentle introduction to forms in Rocket, see the [forms guide].
20///
21/// # Form Guards
22///
23/// A form guard is a guard that operates on form fields, typically those with a
24/// particular name prefix. Form guards validate and parse form field data via
25/// implementations of `FromForm`. In other words, a type is a form guard _iff_
26/// it implements `FromForm`.
27///
28/// Form guards are used as the inner type of the [`Form`] data guard:
29///
30/// ```rust
31/// # use rocket::post;
32/// use rocket::form::Form;
33///
34/// # type FormGuard = String;
35/// #[post("/submit", data = "<var>")]
36/// fn submit(var: Form<FormGuard>) { /* ... */ }
37/// ```
38///
39/// # Deriving
40///
41/// This trait can, and largely _should_, be automatically derived. When
42/// deriving `FromForm`, every field in the structure must implement
43/// [`FromForm`]. Form fields with the struct field's name are [shifted] and
44/// then pushed to the struct field's `FromForm` parser.
45///
46/// [shifted]: NameView::shift()
47///
48/// ```rust
49/// use rocket::form::FromForm;
50///
51/// #[derive(FromForm)]
52/// struct TodoTask<'r> {
53///     #[field(validate = len(1..))]
54///     description: &'r str,
55///     #[field(name = "done")]
56///     completed: bool
57/// }
58/// ```
59///
60/// For full details on deriving `FromForm`, see the [`FromForm` derive].
61///
62/// [`Form`]: crate::form::Form
63/// [`FromForm`]: crate::form::FromForm
64/// [`FromForm` derive]: derive@crate::FromForm
65/// [FromFormField]: crate::form::FromFormField
66/// [`shift()`ed]: NameView::shift()
67/// [`key()`]: NameView::key()
68/// [forms guide]: https://rocket.rs/master/guide/requests/#forms
69///
70/// # Parsing Strategy
71///
72/// Form parsing is either _strict_ or _lenient_, controlled by
73/// [`Options::strict`]. A _strict_ parse errors when there are missing or extra
74/// fields, while a _lenient_ parse allows both, providing there is a
75/// [`default()`](FromForm::default()) in the case of a missing field.
76///
77/// Most type inherit their strategy on [`FromForm::init()`], but some types
78/// like `Option` override the requested strategy. The strategy can also be
79/// overwritten manually, per-field or per-value, by using the [`Strict`] or
80/// [`Lenient`] form guard:
81///
82/// ```rust
83/// use rocket::form::{self, FromForm, Strict, Lenient};
84///
85/// #[derive(FromForm)]
86/// struct TodoTask<'r> {
87///     strict_bool: Strict<bool>,
88///     lenient_inner_option: Option<Lenient<bool>>,
89///     strict_inner_result: form::Result<'r, Strict<bool>>,
90/// }
91/// ```
92///
93/// # Defaults
94///
95/// A form guard may have a _default_ which is used in case of a missing field
96/// when parsing is _lenient_. When parsing is strict, all errors, including
97/// missing fields, are propagated directly.
98///
99/// # Provided Implementations
100///
101/// Rocket implements `FromForm` for many common types. As a result, most
102/// applications will never need a custom implementation of `FromForm` or
103/// `FromFormField`. Their behavior is documented in the table below.
104///
105/// | Type                   | Strategy    | Default           | Data   | Value  | Notes                                              |
106/// |------------------------|-------------|-------------------|--------|--------|----------------------------------------------------|
107/// | [`Strict<T>`]          | **strict**  | if `strict` `T`   | if `T` | if `T` | `T: FromForm`                                      |
108/// | [`Lenient<T>`]         | **lenient** | if `lenient` `T`  | if `T` | if `T` | `T: FromForm`                                      |
109/// | `Option<T>`            | **strict**  | `None`            | if `T` | if `T` | Infallible, `T: FromForm`                          |
110/// | [`Result<T>`]          | _inherit_   | `T::finalize()`   | if `T` | if `T` | Infallible, `T: FromForm`                          |
111/// | `Vec<T>`               | _inherit_   | `vec![]`          | if `T` | if `T` | `T: FromForm`                                      |
112/// | [`HashMap<K, V>`]      | _inherit_   | `HashMap::new()`  | if `V` | if `V` | `K: FromForm + Eq + Hash`, `V: FromForm`           |
113/// | [`BTreeMap<K, V>`]     | _inherit_   | `BTreeMap::new()` | if `V` | if `V` | `K: FromForm + Ord`, `V: FromForm`                 |
114/// | [`Range<T>`]           | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `start`, `end` fields       |
115/// | [`RangeFrom<T>`]       | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `start` field               |
116/// | [`RangeTo<T>`]         | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `end` field                 |
117/// | [`RangeToInclusive<T>`]| _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `end` field                 |
118/// | `bool`                 | _inherit_   | `false`           | No     | Yes    | `"yes"/"on"/"true"`, `"no"/"off"/"false"`          |
119/// | (un)signed int         | _inherit_   | **no default**    | No     | Yes    | `{u,i}{size,8,16,32,64,128}`                       |
120/// | _nonzero_ int          | _inherit_   | **no default**    | No     | Yes    | `NonZero{I,U}{size,8,16,32,64,128}`                |
121/// | float                  | _inherit_   | **no default**    | No     | Yes    | `f{32,64}`                                         |
122/// | `&str`                 | _inherit_   | **no default**    | Yes    | Yes    | Percent-decoded. Data limit `string` applies.      |
123/// | `&[u8]`                | _inherit_   | **no default**    | Yes    | Yes    | Raw bytes. Data limit `bytes` applies.             |
124/// | `String`               | _inherit_   | **no default**    | Yes    | Yes    | Exactly `&str`, but owned. Prefer `&str`.          |
125/// | IP Address             | _inherit_   | **no default**    | No     | Yes    | [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`]             |
126/// | Socket Address         | _inherit_   | **no default**    | No     | Yes    | [`SocketAddr`], [`SocketAddrV4`], [`SocketAddrV6`] |
127/// | [`TempFile`]           | _inherit_   | **no default**    | Yes    | Yes    | Data limits apply. See [`TempFile`].               |
128/// | [`Capped<C>`]          | _inherit_   | **no default**    | Yes    | Yes    | `C` is `&str`, `String`, `&[u8]` or `TempFile`.    |
129/// | [`time::Date`]         | _inherit_   | **no default**    | No     | Yes    | `%F` (`YYYY-MM-DD`). HTML "date" input.            |
130/// | [`time::DateTime`]     | _inherit_   | **no default**    | No     | Yes    | `%FT%R` or `%FT%T` (`YYYY-MM-DDTHH:MM[:SS]`)       |
131/// | [`time::Time`]         | _inherit_   | **no default**    | No     | Yes    | `%R` or `%T` (`HH:MM[:SS]`)                        |
132///
133/// [`Result<T>`]: crate::form::Result
134/// [`Strict<T>`]: crate::form::Strict
135/// [`Lenient<T>`]: crate::form::Lenient
136/// [`HashMap<K, V>`]: std::collections::HashMap
137/// [`BTreeMap<K, V>`]: std::collections::BTreeMap
138/// [`TempFile`]: crate::fs::TempFile
139/// [`Capped<C>`]: crate::data::Capped
140/// [`time::DateTime`]: time::PrimitiveDateTime
141/// [`IpAddr`]: std::net::IpAddr
142/// [`Ipv4Addr`]: std::net::Ipv4Addr
143/// [`Ipv6Addr`]: std::net::Ipv6Addr
144/// [`SocketAddr`]: std::net::SocketAddr
145/// [`SocketAddrV4`]: std::net::SocketAddrV4
146/// [`SocketAddrV6`]: std::net::SocketAddrV6
147/// [`Range<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html
148/// [`RangeFrom<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeFrom.html
149/// [`RangeTo<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeTo.html
150/// [`RangeToInclusive<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeToInclusive.html
151///
152/// ## Additional Notes
153///
154///   * **`Vec<T>` where `T: FromForm`**
155///
156///     Parses a sequence of `T`'s. A new `T` is created whenever the field
157///     name's key changes or is empty; the previous `T` is finalized and errors
158///     are stored. While the key remains the same and non-empty, form values
159///     are pushed to the current `T` after being shifted. All collected errors
160///     are returned at finalization, if any, or the successfully created vector
161///     is returned.
162///
163///   * **`HashMap<K, V>` where `K: FromForm + Eq + Hash`, `V: FromForm`**
164///
165///     **`BTreeMap<K, V>` where `K: FromForm + Ord`, `V: FromForm`**
166///
167///     Parses a sequence of `(K, V)`'s. A new pair is created for every unique
168///     first index of the key.
169///
170///     If the key has only one index (`map[index]=value`), the index itself is
171///     pushed to `K`'s parser and the remaining shifted field is pushed to
172///     `V`'s parser.
173///
174///     If the key has two indices (`map[k:index]=value` or
175///     `map[v:index]=value`), the first index must start with `k` or `v`. If
176///     the first index starts with `k`, the shifted field is pushed to `K`'s
177///     parser. If the first index starts with `v`, the shifted field is pushed
178///     to `V`'s parser. If the first index is anything else, an error is
179///     created for the offending form field.
180///
181///     Errors are collected as they occur. Finalization finalizes all pairs and
182///     returns errors, if any, or the map.
183///
184///   * **`bool`**
185///
186///     Parses as `false` for missing values (when lenient) and case-insensitive
187///     values of `off`, `false`, and `no`. Parses as `true` for values of `on`,
188///     `true`, `yes`, and the empty value. Failed to parse otherwise.
189///
190///   * **[`time::DateTime`]**
191///
192///     Parses a date in `%FT%R` or `%FT%T` format, that is, `YYYY-MM-DDTHH:MM`
193///     or `YYYY-MM-DDTHH:MM:SS`. This is the `"datetime-local"` HTML input type
194///     without support for the millisecond variant.
195///
196///   * **[`time::Time`]**
197///
198///     Parses a time in `%R` or `%T` format, that is, `HH:MM` or `HH:MM:SS`.
199///     This is the `"time"` HTML input type without support for the millisecond
200///     variant.
201///
202/// # Push Parsing
203///
204/// `FromForm` describes a push-based parser for Rocket's [field wire format].
205/// Fields are preprocessed into either [`ValueField`]s or [`DataField`]s which
206/// are then pushed to the parser in [`FromForm::push_value()`] or
207/// [`FromForm::push_data()`], respectively. Both url-encoded forms and
208/// multipart forms are supported. All url-encoded form fields are preprocessed
209/// as [`ValueField`]s. Multipart form fields with Content-Types are processed
210/// as [`DataField`]s while those without a set Content-Type are processed as
211/// [`ValueField`]s. `ValueField` field names and values are percent-decoded.
212///
213/// [field wire format]: crate::form#field-wire-format
214///
215/// Parsing is split into 3 stages. After preprocessing, the three stages are:
216///
217///   1. **Initialization.** The type sets up a context for later `push`es.
218///
219///      ```rust
220///      # use rocket::form::prelude::*;
221///      # struct Foo;
222///      use rocket::form::Options;
223///
224///      # #[rocket::async_trait]
225///      # impl<'r> FromForm<'r> for Foo {
226///          # type Context = std::convert::Infallible;
227///      fn init(opts: Options) -> Self::Context {
228///          todo!("return a context for storing parse state")
229///      }
230///          # fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) { todo!() }
231///          # async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) { todo!() }
232///          # fn finalize(ctxt: Self::Context) -> Result<'r, Self> { todo!() }
233///      # }
234///      ```
235///
236///   2. **Push.** The structure is repeatedly pushed form fields; the latest
237///      context is provided with each `push`. If the structure contains
238///      children, it uses the first [`key()`] to identify a child to which it
239///      then `push`es the remaining `field` to, likely with a [`shift()`ed]
240///      name. Otherwise, the structure parses the `value` itself. The context
241///      is updated as needed.
242///
243///      ```rust
244///      # use rocket::form::prelude::*;
245///      # struct Foo;
246///      use rocket::form::{ValueField, DataField};
247///
248///      # #[rocket::async_trait]
249///      # impl<'r> FromForm<'r> for Foo {
250///          # type Context = std::convert::Infallible;
251///          # fn init(opts: Options) -> Self::Context { todo!() }
252///      fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) {
253///          todo!("modify context as necessary for `field`")
254///      }
255///
256///      async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) {
257///          todo!("modify context as necessary for `field`")
258///      }
259///          # fn finalize(ctxt: Self::Context) -> Result<'r, Self> { todo!() }
260///      # }
261///      ```
262///
263///   3. **Finalization.** The structure is informed that there are no further
264///      fields. It systemizes the effects of previous `push`es via its context
265///      to return a parsed structure or generate [`Errors`].
266///
267///      ```rust
268///      # use rocket::form::prelude::*;
269///      # struct Foo;
270///      use rocket::form::Result;
271///
272///      # #[rocket::async_trait]
273///      # impl<'r> FromForm<'r> for Foo {
274///          # type Context = std::convert::Infallible;
275///          # fn init(opts: Options) -> Self::Context { todo!() }
276///          # fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) { todo!() }
277///          # async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) { todo!() }
278///      fn finalize(ctxt: Self::Context) -> Result<'r, Self> {
279///          todo!("inspect context to generate `Self` or `Errors`")
280///      }
281///      # }
282///      ```
283///
284/// These three stages make up the entirety of the `FromForm` trait.
285///
286/// ## Nesting and [`NameView`]
287///
288/// Each field name key typically identifies a unique child of a structure. As
289/// such, when processed left-to-right, the keys of a field jointly identify a
290/// unique leaf of a structure. The value of the field typically represents the
291/// desired value of the leaf.
292///
293/// A [`NameView`] captures and simplifies this "left-to-right" processing of a
294/// field's name by exposing a sliding-prefix view into a name. A [`shift()`]
295/// shifts the view one key to the right. Thus, a `Name` of `a.b.c` when viewed
296/// through a new [`NameView`] is `a`. Shifted once, the view is `a.b`.
297/// [`key()`] returns the last (or "current") key in the view. A nested
298/// structure can thus handle a field with a `NameView`, operate on the
299/// [`key()`], [`shift()`] the `NameView`, and pass the field with the shifted
300/// `NameView` to the next processor which handles `b` and so on.
301///
302/// [`shift()`]: NameView::shift()
303/// [`key()`]: NameView::key()
304///
305/// ## A Simple Example
306///
307/// The following example uses `f1=v1&f2=v2` to illustrate field/value pairs
308/// `(f1, v2)` and `(f2, v2)`. This is the same encoding used to send HTML forms
309/// over HTTP, though Rocket's push-parsers are unaware of any specific
310/// encoding, dealing only with logical `field`s, `index`es, and `value`s.
311///
312/// ### A Single Field (`T: FormFormField`)
313///
314/// The simplest example parses a single value of type `T` from a string with an
315/// optional default value: this is `impl<T: FromFormField> FromForm for T`:
316///
317///   1. **Initialization.** The context stores form options and an `Option` of
318///      `Result<T, form::Error>` for storing the `result` of parsing `T`, which
319///      is initially set to `None`.
320///
321///      ```rust
322///      use rocket::form::{self, FromFormField};
323///
324///      struct Context<'r, T: FromFormField<'r>> {
325///          opts: form::Options,
326///          result: Option<form::Result<'r, T>>,
327///      }
328///
329///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {
330///      fn init(opts: form::Options) -> Context<'r, T> {
331///         Context { opts, result: None }
332///      }
333///      # }
334///      ```
335///
336///   2. **Push.** If `ctxt.result` is `None`, `T` is parsed from `field`, and
337///      the result is stored in `context.result`. Otherwise a field has already
338///      been parsed and nothing is done.
339///
340///      ```rust
341///      # use rocket::form::{self, ValueField, FromFormField};
342///      # struct Context<'r, T: FromFormField<'r>> {
343///      #     opts: form::Options,
344///      #     result: Option<form::Result<'r, T>>,
345///      # }
346///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {
347///      fn push_value(ctxt: &mut Context<'r, T>, field: ValueField<'r>) {
348///          if ctxt.result.is_none() {
349///              ctxt.result = Some(T::from_value(field));
350///          }
351///      }
352///      # }
353///      ```
354///
355///   3. **Finalization.** If `ctxt.result` is `None`, parsing is lenient, and
356///      `T` has a default, the default is returned. Otherwise a `Missing` error
357///      is returned. If `ctxt.result` is `Some(v)`, the result `v` is returned.
358///
359///      ```rust
360///      # use rocket::form::{self, FromFormField, error::{Errors, ErrorKind}};
361///      # struct Context<'r, T: FromFormField<'r>> {
362///      #     opts: form::Options,
363///      #     result: Option<form::Result<'r, T>>,
364///      # }
365///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {
366///      fn finalize(ctxt: Context<'r, T>) -> form::Result<'r, T> {
367///          match ctxt.result {
368///              Some(result) => result,
369///              None if ctxt.opts.strict => Err(Errors::from(ErrorKind::Missing)),
370///              None => match T::default() {
371///                  Some(default) => Ok(default),
372///                  None => Err(Errors::from(ErrorKind::Missing)),
373///              }
374///          }
375///      }
376///      # }
377///      ```
378///
379/// This implementation is complete except for the following details:
380///
381///   * handling both `push_data` and `push_value`
382///   * checking for duplicate pushes when parsing is `strict`
383///   * tracking the field's name and value to generate a complete [`Error`]
384///
385/// # Implementing
386///
387/// Implementing `FromForm` should be a rare occurrence. Prefer instead to use
388/// Rocket's built-in derivation or, for custom types, implementing
389/// [`FromFormField`].
390///
391/// An implementation of `FromForm` consists of implementing the three stages
392/// outlined above. `FromForm` is an async trait, so implementations must be
393/// decorated with an attribute of `#[rocket::async_trait]`:
394///
395/// ```rust
396/// # #[macro_use] extern crate rocket;
397/// # struct MyType;
398/// # struct MyContext;
399/// use rocket::form::{self, FromForm, DataField, ValueField};
400///
401/// #[rocket::async_trait]
402/// impl<'r> FromForm<'r> for MyType {
403///     type Context = MyContext;
404///
405///     fn init(opts: form::Options) -> Self::Context {
406///         todo!()
407///     }
408///
409///     fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) {
410///         todo!()
411///     }
412///
413///     async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) {
414///         todo!()
415///     }
416///
417///     fn finalize(this: Self::Context) -> form::Result<'r, Self> {
418///         todo!()
419///     }
420/// }
421/// ```
422///
423/// The lifetime `'r` corresponds to the lifetime of the request.
424///
425/// ## A More Involved Example
426///
427/// We illustrate implementation of `FromForm` through an example. The example
428/// implements `FromForm` for a `Pair(A, B)` type where `A: FromForm` and `B:
429/// FromForm`, parseable from forms with at least two fields, one with a key of
430/// `0` and the other with a key of `1`. The field with key `0` is parsed as an
431/// `A` while the field with key `1` is parsed as a `B`. Specifically, to parse
432/// a `Pair(A, B)` from a field with prefix `pair`, a form with the following
433/// fields must be submitted:
434///
435///   * `pair[0]` - type A
436///   * `pair[1]` - type B
437///
438/// Examples include:
439///
440///   * `pair[0]=id&pair[1]=100` as `Pair(&str, usize)`
441///   * `pair[0]=id&pair[1]=100` as `Pair(&str, &str)`
442///   * `pair[0]=2012-10-12&pair[1]=100` as `Pair(time::Date, &str)`
443///   * `pair.0=2012-10-12&pair.1=100` as `Pair(time::Date, usize)`
444///
445/// ```rust
446/// use either::Either;
447/// use rocket::form::{self, FromForm, ValueField, DataField, Error, Errors};
448///
449/// /// A form guard parseable from fields `.0` and `.1`.
450/// struct Pair<A, B>(A, B);
451///
452/// // The parsing context. We'll be pushing fields with key `.0` to `left`
453/// // and fields with `.1` to `right`. We'll collect errors along the way.
454/// struct PairContext<'v, A: FromForm<'v>, B: FromForm<'v>> {
455///     left: A::Context,
456///     right: B::Context,
457///     errors: Errors<'v>,
458/// }
459///
460/// #[rocket::async_trait]
461/// impl<'v, A: FromForm<'v>, B: FromForm<'v>> FromForm<'v> for Pair<A, B> {
462///     type Context = PairContext<'v, A, B>;
463///
464///     // We initialize the `PairContext` as expected.
465///     fn init(opts: form::Options) -> Self::Context {
466///         PairContext {
467///             left: A::init(opts),
468///             right: B::init(opts),
469///             errors: Errors::new()
470///         }
471///     }
472///
473///     // For each value, we determine if the key is `.0` (left) or `.1`
474///     // (right) and push to the appropriate parser. If it was neither, we
475///     // store the error for emission on finalization. The parsers for `A` and
476///     // `B` will handle duplicate values and so on.
477///     fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
478///         match ctxt.context(field.name) {
479///             Ok(Either::Left(ctxt)) => A::push_value(ctxt, field.shift()),
480///             Ok(Either::Right(ctxt)) => B::push_value(ctxt, field.shift()),
481///             Err(e) => ctxt.errors.push(e),
482///         }
483///     }
484///
485///     // This is identical to `push_value` but for data fields.
486///     async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
487///         match ctxt.context(field.name) {
488///             Ok(Either::Left(ctxt)) => A::push_data(ctxt, field.shift()).await,
489///             Ok(Either::Right(ctxt)) => B::push_data(ctxt, field.shift()).await,
490///             Err(e) => ctxt.errors.push(e),
491///         }
492///     }
493///
494///     // Finally, we finalize `A` and `B`. If both returned `Ok` and we
495///     // encountered no errors during the push phase, we return our pair. If
496///     // there were errors, we return them. If `A` and/or `B` failed, we
497///     // return the commutative errors.
498///     fn finalize(mut ctxt: Self::Context) -> form::Result<'v, Self> {
499///         match (A::finalize(ctxt.left), B::finalize(ctxt.right)) {
500///             (Ok(l), Ok(r)) if ctxt.errors.is_empty() => Ok(Pair(l, r)),
501///             (Ok(_), Ok(_)) => Err(ctxt.errors),
502///             (left, right) => {
503///                 if let Err(e) = left { ctxt.errors.extend(e); }
504///                 if let Err(e) = right { ctxt.errors.extend(e); }
505///                 Err(ctxt.errors)
506///             }
507///         }
508///     }
509/// }
510///
511/// impl<'v, A: FromForm<'v>, B: FromForm<'v>> PairContext<'v, A, B> {
512///     // Helper method used by `push_{value, data}`. Determines which context
513///     // we should push to based on the field name's key. If the key is
514///     // neither `0` nor `1`, we return an error.
515///     fn context(
516///         &mut self,
517///         name: form::name::NameView<'v>
518///     ) -> Result<Either<&mut A::Context, &mut B::Context>, Error<'v>> {
519///         use std::borrow::Cow;
520///
521///         match name.key().map(|k| k.as_str()) {
522///             Some("0") => Ok(Either::Left(&mut self.left)),
523///             Some("1") => Ok(Either::Right(&mut self.right)),
524///             _ => Err(Error::from(&[Cow::Borrowed("0"), Cow::Borrowed("1")])
525///                 .with_entity(form::error::Entity::Index(0))
526///                 .with_name(name)),
527///         }
528///     }
529/// }
530/// ```
531#[crate::async_trait]
532pub trait FromForm<'r>: Send + Sized {
533    /// The form guard's parsing context.
534    type Context: Send;
535
536    /// Initializes and returns the parsing context for `Self`.
537    fn init(opts: Options) -> Self::Context;
538
539    /// Processes the value field `field`.
540    fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>);
541
542    /// Processes the data field `field`.
543    async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>);
544
545    /// Processes the external form or field error `_error`.
546    ///
547    /// The default implementation does nothing, which is always correct.
548    fn push_error(_ctxt: &mut Self::Context, _error: Error<'r>) { }
549
550    /// Finalizes parsing. Returns the parsed value when successful or
551    /// collection of [`Errors`] otherwise.
552    fn finalize(ctxt: Self::Context) -> Result<'r, Self>;
553
554    /// Returns a default value, if any, to use when a value is desired and
555    /// parsing fails.
556    ///
557    /// The default implementation initializes `Self` with `opts` and finalizes
558    /// immediately, returning the value if finalization succeeds. This is
559    /// always correct and should likely not be changed. Returning a different
560    /// value may result in ambiguous parses.
561    fn default(opts: Options) -> Option<Self> {
562        Self::finalize(Self::init(opts)).ok()
563    }
564}
565
566#[doc(hidden)]
567pub struct VecContext<'v, T: FromForm<'v>> {
568    opts: Options,
569    last_key: Option<&'v Key>,
570    current: Option<T::Context>,
571    errors: Errors<'v>,
572    items: Vec<T>
573}
574
575impl<'v, T: FromForm<'v>> VecContext<'v, T> {
576    fn new(opts: Options) -> Self {
577        VecContext {
578            opts,
579            last_key: None,
580            current: None,
581            items: vec![],
582            errors: Errors::new(),
583        }
584    }
585
586    fn shift(&mut self) {
587        if let Some(current) = self.current.take() {
588            match T::finalize(current) {
589                Ok(v) => self.items.push(v),
590                Err(e) => self.errors.extend(e)
591            }
592        }
593    }
594
595    fn context(&mut self, name: &NameView<'v>) -> &mut T::Context {
596        let this_key = name.key();
597        let keys_match = match (self.last_key, this_key) {
598            (Some(k1), Some(k2)) => k1 == k2,
599            _ => false
600        };
601
602        if !keys_match {
603            self.shift();
604            self.current = Some(T::init(self.opts));
605        }
606
607        self.last_key = name.key();
608        self.current.as_mut().expect("must have current if last == index")
609    }
610}
611
612#[crate::async_trait]
613impl<'v, T: FromForm<'v> + 'v> FromForm<'v> for Vec<T> {
614    type Context = VecContext<'v, T>;
615
616    fn init(opts: Options) -> Self::Context {
617        VecContext::new(opts)
618    }
619
620    fn push_value(this: &mut Self::Context, field: ValueField<'v>) {
621        T::push_value(this.context(&field.name), field.shift());
622    }
623
624    async fn push_data(this: &mut Self::Context, field: DataField<'v, '_>) {
625        T::push_data(this.context(&field.name), field.shift()).await
626    }
627
628    fn finalize(mut this: Self::Context) -> Result<'v, Self> {
629        this.shift();
630        if !this.errors.is_empty() {
631            Err(this.errors)
632        } else if this.opts.strict && this.items.is_empty() {
633            Err(Errors::from(ErrorKind::Missing))
634        } else {
635            Ok(this.items)
636        }
637    }
638}
639
640// impl_strict_from_form_field_from_capped!(Vec<u8>);
641
642#[doc(hidden)]
643pub struct MapContext<'v, K, V> where K: FromForm<'v>, V: FromForm<'v> {
644    opts: Options,
645    /// Maps an index key (&str, map.key=foo, map.k:key) to its entry.
646    /// NOTE: `table`, `entries`, and `metadata` are always the same size.
647    table: IndexMap<&'v str, usize>,
648    /// The `FromForm` context for the (key, value) indexed by `table`.
649    entries: Vec<(K::Context, V::Context)>,
650    /// Recorded metadata for a given key/value pair.
651    metadata: Vec<NameView<'v>>,
652    /// Errors collected while finalizing keys and values.
653    errors: Errors<'v>,
654}
655
656impl<'v, K, V> MapContext<'v, K, V>
657    where K: FromForm<'v>, V: FromForm<'v>
658{
659    fn new(opts: Options) -> Self {
660        MapContext {
661            opts,
662            table: IndexMap::new(),
663            entries: vec![],
664            metadata: vec![],
665            errors: Errors::new(),
666        }
667    }
668
669    fn ctxt(&mut self, key: &'v str, name: NameView<'v>) -> &mut (K::Context, V::Context) {
670        match self.table.get(key) {
671            Some(i) => &mut self.entries[*i],
672            None => {
673                let i = self.entries.len();
674                self.table.insert(key, i);
675                self.entries.push((K::init(self.opts), V::init(self.opts)));
676                self.metadata.push(name);
677                &mut self.entries[i]
678            }
679        }
680    }
681
682    fn push(&mut self, name: NameView<'v>) -> Option<Either<&mut K::Context, &mut V::Context>> {
683        let index_pair = name.key()
684            .map(|k| k.indices())
685            .map(|mut i| (i.next(), i.next()))
686            .unwrap_or_default();
687
688        match index_pair {
689            (Some(key), None) => {
690                let is_new_key = !self.table.contains_key(key);
691                let (key_ctxt, val_ctxt) = self.ctxt(key, name);
692                if is_new_key {
693                    K::push_value(key_ctxt, ValueField::from_value(key));
694                }
695
696                return Some(Either::Right(val_ctxt));
697            },
698            (Some(kind), Some(key)) => {
699                if kind.as_uncased().starts_with("k") {
700                    return Some(Either::Left(&mut self.ctxt(key, name).0));
701                } else if kind.as_uncased().starts_with("v") {
702                    return Some(Either::Right(&mut self.ctxt(key, name).1));
703                } else {
704                    let error = Error::from(&[Cow::Borrowed("k"), Cow::Borrowed("v")])
705                        .with_entity(Entity::Index(0))
706                        .with_name(name);
707
708                    self.errors.push(error);
709                }
710            }
711            _ => {
712                let error = Error::from(ErrorKind::Missing)
713                    .with_entity(Entity::Key)
714                    .with_name(name);
715
716                self.errors.push(error);
717            }
718        };
719
720        None
721    }
722
723    fn push_value(&mut self, field: ValueField<'v>) {
724        match self.push(field.name) {
725            Some(Either::Left(ctxt)) => K::push_value(ctxt, field.shift()),
726            Some(Either::Right(ctxt)) => V::push_value(ctxt, field.shift()),
727            _ => {}
728        }
729    }
730
731    async fn push_data(&mut self, field: DataField<'v, '_>) {
732        match self.push(field.name) {
733            Some(Either::Left(ctxt)) => K::push_data(ctxt, field.shift()).await,
734            Some(Either::Right(ctxt)) => V::push_data(ctxt, field.shift()).await,
735            _ => {}
736        }
737    }
738
739    fn finalize<T: std::iter::FromIterator<(K, V)>>(mut self) -> Result<'v, T> {
740        let map: T = self.entries.into_iter()
741            .zip(self.metadata.iter())
742            .zip(self.table.keys())
743            .filter_map(|(((k_ctxt, v_ctxt), name), idx)| {
744                let key = K::finalize(k_ctxt)
745                    .map_err(|e| {
746                        // FIXME: Fix `NameBuf` to take in `k` and add it.
747                        // FIXME: Perhaps the `k` should come after: `map.0:k`.
748                        let form_key = format!("k:{}", idx);
749                        self.errors.extend(e.with_name((name.parent(), form_key)));
750                    })
751                    .ok();
752
753                let val = V::finalize(v_ctxt)
754                    .map_err(|e| self.errors.extend(e.with_name((name.parent(), *idx))))
755                    .ok();
756
757                Some((key?, val?))
758            })
759            .collect();
760
761        if !self.errors.is_empty() {
762            Err(self.errors)
763        } else if self.opts.strict && self.table.is_empty() {
764            Err(Errors::from(ErrorKind::Missing))
765        } else {
766            Ok(map)
767        }
768    }
769}
770
771#[crate::async_trait]
772impl<'v, K, V> FromForm<'v> for HashMap<K, V>
773    where K: FromForm<'v> + Eq + Hash, V: FromForm<'v>
774{
775    type Context = MapContext<'v, K, V>;
776
777    fn init(opts: Options) -> Self::Context {
778        MapContext::new(opts)
779    }
780
781    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
782        ctxt.push_value(field);
783    }
784
785    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
786        ctxt.push_data(field).await;
787    }
788
789    fn finalize(this: Self::Context) -> Result<'v, Self> {
790        this.finalize()
791    }
792}
793
794#[crate::async_trait]
795impl<'v, K, V> FromForm<'v> for BTreeMap<K, V>
796    where K: FromForm<'v> + Ord, V: FromForm<'v>
797{
798    type Context = MapContext<'v, K, V>;
799
800    fn init(opts: Options) -> Self::Context {
801        MapContext::new(opts)
802    }
803
804    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
805        ctxt.push_value(field);
806    }
807
808    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
809        ctxt.push_data(field).await;
810    }
811
812    fn finalize(this: Self::Context) -> Result<'v, Self> {
813        this.finalize()
814    }
815}
816
817#[crate::async_trait]
818impl<'v, T: FromForm<'v>> FromForm<'v> for Option<T> {
819    type Context = <T as FromForm<'v>>::Context;
820
821    fn init(_: Options) -> Self::Context {
822        T::init(Options { strict: true })
823    }
824
825    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
826        T::push_value(ctxt, field)
827    }
828
829    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
830        T::push_data(ctxt, field).await
831    }
832
833    fn finalize(this: Self::Context) -> Result<'v, Self> {
834        Ok(T::finalize(this).ok())
835    }
836}
837
838#[crate::async_trait]
839impl<'v, T: FromForm<'v>> FromForm<'v> for Result<'v, T> {
840    type Context = <T as FromForm<'v>>::Context;
841
842    fn init(opts: Options) -> Self::Context {
843        T::init(opts)
844    }
845
846    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
847        T::push_value(ctxt, field)
848    }
849
850    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
851        T::push_data(ctxt, field).await
852    }
853
854    fn finalize(this: Self::Context) -> Result<'v, Self> {
855        Ok(T::finalize(this))
856    }
857}
858
859#[doc(hidden)]
860pub struct PairContext<'v, A: FromForm<'v>, B: FromForm<'v>> {
861    left: A::Context,
862    right: B::Context,
863    errors: Errors<'v>,
864}
865
866impl<'v, A: FromForm<'v>, B: FromForm<'v>> PairContext<'v, A, B> {
867    fn context(
868        &mut self,
869        name: NameView<'v>
870    ) -> std::result::Result<Either<&mut A::Context, &mut B::Context>, Error<'v>> {
871        match name.key().map(|k| k.as_str()) {
872            Some("0") => Ok(Either::Left(&mut self.left)),
873            Some("1") => Ok(Either::Right(&mut self.right)),
874            _ => Err(Error::from(&[Cow::Borrowed("0"), Cow::Borrowed("1")])
875                .with_entity(Entity::Index(0))
876                .with_name(name)),
877        }
878    }
879}
880
881#[crate::async_trait]
882impl<'v, A: FromForm<'v>, B: FromForm<'v>> FromForm<'v> for (A, B) {
883    type Context = PairContext<'v, A, B>;
884
885    fn init(opts: Options) -> Self::Context {
886        PairContext {
887            left: A::init(opts),
888            right: B::init(opts),
889            errors: Errors::new()
890        }
891    }
892
893    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
894        match ctxt.context(field.name) {
895            Ok(Either::Left(ctxt)) => A::push_value(ctxt, field.shift()),
896            Ok(Either::Right(ctxt)) => B::push_value(ctxt, field.shift()),
897            Err(e) => ctxt.errors.push(e),
898        }
899    }
900
901    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
902        match ctxt.context(field.name) {
903            Ok(Either::Left(ctxt)) => A::push_data(ctxt, field.shift()).await,
904            Ok(Either::Right(ctxt)) => B::push_data(ctxt, field.shift()).await,
905            Err(e) => ctxt.errors.push(e),
906        }
907    }
908
909    fn finalize(mut ctxt: Self::Context) -> Result<'v, Self> {
910        match (A::finalize(ctxt.left), B::finalize(ctxt.right)) {
911            (Ok(key), Ok(val)) if ctxt.errors.is_empty() => Ok((key, val)),
912            (Ok(_), Ok(_)) => Err(ctxt.errors)?,
913            (left, right) => {
914                if let Err(e) = left { ctxt.errors.extend(e); }
915                if let Err(e) = right { ctxt.errors.extend(e); }
916                Err(ctxt.errors)?
917            }
918        }
919    }
920}
921
922#[crate::async_trait]
923impl<'v, T: FromForm<'v> + Sync> FromForm<'v> for Arc<T> {
924    type Context = <T as FromForm<'v>>::Context;
925
926    fn init(opts: Options) -> Self::Context {
927        T::init(opts)
928    }
929
930    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
931        T::push_value(ctxt, field)
932    }
933
934    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
935        T::push_data(ctxt, field).await
936    }
937
938    fn finalize(this: Self::Context) -> Result<'v, Self> {
939        T::finalize(this).map(Arc::new)
940    }
941}
942
943macro_rules! impl_via_proxy {
944    ($R:ident => struct $T:ident <$($G:ident),*> { $($f:ident : $F:ident),* }) => {
945        const _: () = {
946            use super::*;
947
948            mod proxy {
949                #[derive(rocket::FromForm)]
950                pub struct $T<$($G),*> {
951                    $(pub $f : $F),*
952                }
953            }
954
955            #[crate::async_trait]
956            impl<'v, $($G: Send),*> FromForm<'v> for $R<$($G),*>
957                where proxy::$T<$($G),*>: FromForm<'v>
958            {
959                type Context = <proxy::$T<$($G),*> as FromForm<'v>>::Context;
960
961                fn init(opts: Options) -> Self::Context {
962                    <proxy::$T<$($G),*>>::init(opts)
963                }
964
965                fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
966                    <proxy::$T<$($G),*>>::push_value(ctxt, field)
967                }
968
969                async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
970                    <proxy::$T<$($G),*>>::push_data(ctxt, field).await
971                }
972
973                fn finalize(this: Self::Context) -> Result<'v, Self> {
974                    let proxy = <proxy::$T<$($G),*>>::finalize(this)?;
975                    Ok($R {
976                        $($f : proxy.$f),*
977                    })
978                }
979            }
980        };
981    }
982}
983
984use std::ops::{Range, RangeFrom, RangeTo, RangeToInclusive};
985
986impl_via_proxy!(Range => struct Range<T> { start: T, end: T });
987impl_via_proxy!(RangeFrom => struct RangeFrom<T> { start: T });
988impl_via_proxy!(RangeTo => struct RangeTo<T> { end: T });
989impl_via_proxy!(RangeToInclusive => struct RangeToInclusive<T> { end: T });