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