rocket::form

Trait 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.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so 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 char

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.