Trait rocket::form::FromFormField

source ·
pub trait FromFormField<'v>: Send + Sized {
    // Provided methods
    fn from_value(field: ValueField<'v>) -> Result<'v, Self> { ... }
    fn from_data<'life0, 'async_trait>(
        field: DataField<'v, 'life0>
    ) -> Pin<Box<dyn Future<Output = Result<'v, Self>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'v: 'async_trait,
             'life0: 'async_trait { ... }
    fn default() -> Option<Self> { ... }
}
Expand description

Implied form guard (FromForm) for parsing a single form field.

Types that implement FromFormField automatically implement FromForm via a blanket implementation. As such, all FromFormField types are form guards and can appear as the type of values in derived FromForm struct fields:

#[derive(FromForm)]
struct Person<'r> {
    name: &'r str,
    age: u16
}

§Semantics

The implementation of FromForm for a T: FromFormField type operates as follows:

  • When parsing is strict, the parser accepts the first value or data field with the corresponding field name and calls T::from_value() or T::from_data() with the field’s value, respectively. If more than one field value is seen, an [ErrorKind::Duplicate) is emitted. If no matching field is seen, an ErrorKind::Missing is emitted. Otherwise, the result from the call is emitted.

  • When parsing is lenient, the parser accepts the first expected value or data field with the corresponding field name and calls T::from_value() or T::from_data() with the field’s value, respectively. Unexpected values, identified by returning an ErrorKind::Unexpected from from_value() or from_data() are ignored. Any additional fields with a matching field name are ignored. If no matching field is seen and T has a default, it is used, otherwise an ErrorKind::Missing is emitted.

§Deriving

FromFormField can be derived for C-like enums, where the generated implementation case-insensitively parses fields with values equal to the name of the variant or the value in field().

/// Fields with value `"simple"` parse as `Kind::Simple`. Fields with value
/// `"fancy"` parse as `Kind::SoFancy`.
#[derive(FromFormField)]
enum Kind {
    Simple,
    #[field(value = "fancy")]
    SoFancy,
}

§Provided Implementations

See FromForm for a list of all form guards, including those implemented via FromFormField.

§Implementing

Implementing FromFormField requires implementing one or both of from_value or from_data, depending on whether the type can be parsed from a value field (text) and/or streaming binary data. Typically, a value can be parsed from either, either directly or by using request-local cache as an intermediary, and parsing from both should be preferred when sensible.

FromFormField is an async trait, so implementations must be decorated with an attribute of #[rocket::async_trait]:

use rocket::form::{self, FromFormField, DataField, ValueField};

#[rocket::async_trait]
impl<'r> FromFormField<'r> for MyType {
    fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {
        todo!("parse from a value or use default impl")
    }

    async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {
        todo!("parse from a value or use default impl")
    }
}

§Example

The following example parses a custom Person type with the format $name:$data, where $name is expected to be string and data is expected to be any slice of bytes.

use rocket::data::ToByteUnit;
use rocket::form::{self, FromFormField, DataField, ValueField};

use memchr::memchr;

struct Person<'r> {
    name: &'r str,
    data: &'r [u8]
}

#[rocket::async_trait]
impl<'r> FromFormField<'r> for Person<'r> {
    fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {
        match field.value.find(':') {
            Some(i) => Ok(Person {
                name: &field.value[..i],
                data: field.value[(i + 1)..].as_bytes()
            }),
            None => Err(form::Error::validation("does not contain ':'"))?
        }
    }

    async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {
        // Retrieve the configured data limit or use `256KiB` as default.
        let limit = field.request.limits()
            .get("person")
            .unwrap_or(256.kibibytes());

        // Read the capped data stream, returning a limit error as needed.
        let bytes = field.data.open(limit).into_bytes().await?;
        if !bytes.is_complete() {
            Err((None, Some(limit)))?;
        }

        // Store the bytes in request-local cache and split at ':'.
        let bytes = bytes.into_inner();
        let bytes = rocket::request::local_cache!(field.request, bytes);
        let (raw_name, data) = match memchr(b':', bytes) {
            Some(i) => (&bytes[..i], &bytes[(i + 1)..]),
            None => Err(form::Error::validation("does not contain ':'"))?
        };

        // Try to parse the name as UTF-8 or return an error if it fails.
        let name = std::str::from_utf8(raw_name)?;
        Ok(Person { name, data })
    }
}

use rocket::form::{Form, FromForm};

// The type can be used directly, if only one field is expected...
#[post("/person", data = "<person>")]
fn person(person: Form<Person<'_>>) { /* ... */ }

// ...or as a named field in another form guard...
#[derive(FromForm)]
struct NewPerson<'r> {
    person: Person<'r>
}

#[post("/person", data = "<person>")]
fn new_person(person: Form<NewPerson<'_>>) { /* ... */ }

Provided Methods§

source

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

Parse a value of T from a form value field.

The default implementation returns an error of ValueField::unexpected().

source

fn from_data<'life0, 'async_trait>( field: DataField<'v, 'life0> ) -> Pin<Box<dyn Future<Output = Result<'v, Self>> + Send + 'async_trait>>
where Self: 'async_trait, 'v: 'async_trait, 'life0: 'async_trait,

Parse a value of T from a form data field.

The default implementation returns an error of DataField::unexpected().

source

fn default() -> Option<Self>

Returns a default value, if any exists, to be used during lenient parsing when the form field is missing.

A return value of None means that field is required to exist and parse successfully, always. A return value of Some(default) means that default should be used when a field is missing.

The default implementation returns None.

Object Safety§

This trait is not object safe.

Implementations on Foreign Types§

source§

impl<'v> FromFormField<'v> for &'v str

source§

fn default() -> Option<Self>

source§

fn from_value(f: ValueField<'v>) -> Result<'v, Self>

source§

fn from_data<'life0, 'async_trait>( field: DataField<'v, 'life0> ) -> Pin<Box<dyn Future<Output = Result<'v, Self>> + Send + 'async_trait>>
where Self: 'async_trait, 'v: 'async_trait, 'life0: 'async_trait,

source§

impl<'v> FromFormField<'v> for &'v [u8]

source§

fn default() -> Option<Self>

source§

fn from_value(f: ValueField<'v>) -> Result<'v, Self>

source§

fn from_data<'life0, 'async_trait>( field: DataField<'v, 'life0> ) -> Pin<Box<dyn Future<Output = Result<'v, Self>> + Send + 'async_trait>>
where Self: 'async_trait, 'v: 'async_trait, 'life0: 'async_trait,

source§

impl<'v> FromFormField<'v> for Cow<'v, str>

source§

fn default() -> Option<Self>

source§

fn from_value(f: ValueField<'v>) -> Result<'v, Self>

source§

fn from_data<'life0, 'async_trait>( field: DataField<'v, 'life0> ) -> Pin<Box<dyn Future<Output = Result<'v, Self>> + Send + 'async_trait>>
where Self: 'async_trait, 'v: 'async_trait, 'life0: 'async_trait,

source§

impl<'v> FromFormField<'v> for IpAddr

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for SocketAddr

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for bool

source§

fn default() -> Option<Self>

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for f32

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for f64

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for i8

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for i16

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for i32

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for i64

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for i128

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for isize

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for u8

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for u16

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for u32

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for u64

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for u128

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for usize

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for Ipv4Addr

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for Ipv6Addr

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for SocketAddrV4

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for SocketAddrV6

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for Date

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for PrimitiveDateTime

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for Time

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroI8

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroI16

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroI32

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroI64

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroI128

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroIsize

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroU8

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroU16

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroU32

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroU64

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroU128

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

source§

impl<'v> FromFormField<'v> for NonZeroUsize

source§

fn from_value(field: ValueField<'v>) -> Result<'v, Self>

Implementors§

source§

impl<'v> FromFormField<'v> for TempFile<'v>

source§

impl<'v> FromFormField<'v> for Capped<&'v str>

source§

impl<'v> FromFormField<'v> for Capped<&'v [u8]>

source§

impl<'v> FromFormField<'v> for Capped<TempFile<'v>>

source§

impl<'v> FromFormField<'v> for Capped<Cow<'v, str>>

source§

impl<'v> FromFormField<'v> for Capped<String>

source§

impl<'v> FromFormField<'v> for String

source§

impl<'v> FromFormField<'v> for Uuid

Available on crate feature uuid only.
source§

impl<'v, T: Deserialize<'v> + Send> FromFormField<'v> for Json<T>

Available on crate feature json only.
source§

impl<'v, T: Deserialize<'v> + Send> FromFormField<'v> for MsgPack<T>

Available on crate feature msgpack only.