rocket_community/form/
from_form.rs

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