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()
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
.
Object Safety§
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.