macro_rules! form {
(
$(#[$meta:meta])*
$vis:vis struct $name:ident {
$(
$(#[$fmeta:meta])*
$fvis:vis $field:ident : $ty:ty $(= $wire:literal)?
),* $(,)?
}
$( ignore = [ $($ignored:literal),* $(,)? ]; )?
) => { ... };
}Available on crate feature
alloc only.Expand description
Declares a struct and its FromForm implementation.
- The struct is emitted exactly as written (attributes, doc comments, visibility); it may not be generic and must have named fields.
- A field’s wire name is its Rust name;
= "wire-name"after the type overrides it. Bracket names such astags[]are plain names, matched byte for byte, never expanded into a structure. - The optional
ignore = [ ... ];after the struct lists names that are accepted and dropped (the anti-forgery field and_charset_are the usual ones). Every other undeclared name is refused. - Field types implement
FromField; see the value rules indocs/API.md.
Matching a name is a chain of byte comparisons the compiler turns into a length switch: no hash map, no allocation beyond what the field types own.
§Examples
use form_net::FromForm;
form_net::form! {
/// The sign-up form.
#[derive(Debug)]
pub struct Signup {
pub email: String,
pub password: form_net::Secret,
pub display_name: Option<String> = "display-name",
pub age: u8,
pub newsletter: bool,
pub tags: Vec<String> = "tags[]",
}
ignore = ["csrf_token", "_charset_"];
}
let s = Signup::from_urlencoded(b"email=a%40b.example&password=pw&age=30&tags[]=x&tags[]=y&csrf_token=t")?;
assert_eq!((s.age, s.newsletter, s.tags.len()), (30, false, 2));
assert!(s.display_name.is_none());
let err = Signup::from_urlencoded(b"email=a&password=p&age=300").unwrap_err();
assert_eq!(err.code(), "extract.invalid");
assert!(Signup::from_urlencoded(b"email=a&password=p&age=1&admin=1").is_err());