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 });