Skip to main content

form

Macro form 

Source
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 as tags[] 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 in docs/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());