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()
orT::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, anErrorKind::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()
orT::from_data()
with the field’s value, respectively. Unexpected values, identified by returning anErrorKind::Unexpected
fromfrom_value()
orfrom_data()
are ignored. Any additional fields with a matching field name are ignored. If no matching field is seen andT
has a default, it is used, otherwise anErrorKind::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§
Sourcefn from_value(field: ValueField<'v>) -> Result<'v, Self>
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()
.
Sourcefn 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 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()
.
Sourcefn default() -> Option<Self>
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
impl<'v> FromFormField<'v> for &'v str
fn default() -> Option<Self>
fn from_value(f: 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,
Source§impl<'v> FromFormField<'v> for &'v [u8]
impl<'v> FromFormField<'v> for &'v [u8]
fn default() -> Option<Self>
fn from_value(f: 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,
Source§impl<'v> FromFormField<'v> for Cow<'v, str>
impl<'v> FromFormField<'v> for Cow<'v, str>
fn default() -> Option<Self>
fn from_value(f: 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,
Source§impl<'v> FromFormField<'v> for IpAddr
impl<'v> FromFormField<'v> for IpAddr
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for SocketAddr
impl<'v> FromFormField<'v> for SocketAddr
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for bool
impl<'v> FromFormField<'v> for bool
fn default() -> Option<Self>
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for char
impl<'v> FromFormField<'v> for char
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for f32
impl<'v> FromFormField<'v> for f32
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for f64
impl<'v> FromFormField<'v> for f64
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for i8
impl<'v> FromFormField<'v> for i8
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for i16
impl<'v> FromFormField<'v> for i16
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for i32
impl<'v> FromFormField<'v> for i32
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for i64
impl<'v> FromFormField<'v> for i64
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for i128
impl<'v> FromFormField<'v> for i128
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for isize
impl<'v> FromFormField<'v> for isize
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for u8
impl<'v> FromFormField<'v> for u8
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for u16
impl<'v> FromFormField<'v> for u16
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for u32
impl<'v> FromFormField<'v> for u32
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for u64
impl<'v> FromFormField<'v> for u64
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for u128
impl<'v> FromFormField<'v> for u128
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for usize
impl<'v> FromFormField<'v> for usize
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for Ipv4Addr
impl<'v> FromFormField<'v> for Ipv4Addr
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for Ipv6Addr
impl<'v> FromFormField<'v> for Ipv6Addr
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for SocketAddrV4
impl<'v> FromFormField<'v> for SocketAddrV4
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for SocketAddrV6
impl<'v> FromFormField<'v> for SocketAddrV6
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for Date
impl<'v> FromFormField<'v> for Date
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for PrimitiveDateTime
impl<'v> FromFormField<'v> for PrimitiveDateTime
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for Time
impl<'v> FromFormField<'v> for Time
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroI8
impl<'v> FromFormField<'v> for NonZeroI8
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroI16
impl<'v> FromFormField<'v> for NonZeroI16
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroI32
impl<'v> FromFormField<'v> for NonZeroI32
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroI64
impl<'v> FromFormField<'v> for NonZeroI64
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroI128
impl<'v> FromFormField<'v> for NonZeroI128
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroIsize
impl<'v> FromFormField<'v> for NonZeroIsize
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroU8
impl<'v> FromFormField<'v> for NonZeroU8
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroU16
impl<'v> FromFormField<'v> for NonZeroU16
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroU32
impl<'v> FromFormField<'v> for NonZeroU32
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroU64
impl<'v> FromFormField<'v> for NonZeroU64
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroU128
impl<'v> FromFormField<'v> for NonZeroU128
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Source§impl<'v> FromFormField<'v> for NonZeroUsize
impl<'v> FromFormField<'v> for NonZeroUsize
fn from_value(field: ValueField<'v>) -> Result<'v, Self>
Implementors§
impl<'v> FromFormField<'v> for TempFile<'v>
impl<'v> FromFormField<'v> for Capped<&'v str>
impl<'v> FromFormField<'v> for Capped<&'v [u8]>
impl<'v> FromFormField<'v> for Capped<TempFile<'v>>
impl<'v> FromFormField<'v> for Capped<Cow<'v, str>>
impl<'v> FromFormField<'v> for Capped<String>
impl<'v> FromFormField<'v> for String
impl<'v> FromFormField<'v> for Uuid
uuid
only.impl<'v, T: Deserialize<'v> + Send> FromFormField<'v> for Json<T>
json
only.impl<'v, T: Deserialize<'v> + Send> FromFormField<'v> for MsgPack<T>
msgpack
only.