[go: up one dir, main page]

Crate garde

source ·
Expand description

Validation library

use garde::{Validate, Valid};
use serde::Deserialize;

#[derive(Deserialize, Validate)]
struct User<'a> {
    #[garde(ascii, length(min=3, max=25))]
    username: &'a str,
    #[garde(length(min=15))]
    password: &'a str,
}

let user = serde_json::from_str::<User>(r#"
{
    "username": "lolcode",
    "password": "hunter2"
}
"#).unwrap();

println!("{}", user.validate(&()).unwrap_err());

Garde can also validate enums:

use garde::{Validate, Valid};
use serde::Deserialize;

#[derive(Deserialize, Validate)]
#[serde(rename_all="lowercase")]
enum Data {
    Struct {
        #[garde(range(min=-10, max=10))]
        field: i32,
    },
    Tuple(
        #[garde(rename="important", ascii)]
        String
    ),
}

let data = serde_json::from_str::<Vec<Data>>(r#"
[
    { "struct": { "field": 100 } },
    { "tuple": "test" }
]
"#).unwrap();

for item in &data {
    println!("{:?}", item.validate(&()));
}

Typestate

This crate supports the typestate pattern via the Unvalidated and Valid types:

use garde::{Valid, Validate, Unvalidated};

#[derive(Debug, Validate)]
struct Test {
  #[garde(range(min = 10, max = 100))]
  field: u64,
}

let value = Unvalidated::new(Test { field: 20 });
// This is the only method for obtaining a `Valid<T>`
let value: Valid<Test> = value.validate(&()).unwrap();

let value = Unvalidated::new(Test { field: 0 });
println!("{:?}", value.validate(&()));

Available validation rules

nameformatvalidationfeature flag
ascii#[garde(ascii)]only contains ASCII-
alphanumeric#[garde(alphanumeric)]only letters and digits-
email#[garde(email)]an email according to the HTML5 spec1email
url#[garde(url)]a URLurl
ip#[garde(ip)]an IP address (either IPv4 or IPv6)-
ipv4#[garde(ipv4)]an IPv4 address-
ipv6#[garde(ipv6)]an IPv6 address-
credit card#[garde(credit_card)]a credit card numbercredit-card
phone number#[garde(phone_number)]a phone numberphone-number
length#[garde(length(min=<usize>, max=<usize>)]a dynamically-sized value with size in the range min..=max-
range#[garde(range(min=<expr>, max=<expr>))]a number in the range min..=max-
contains#[garde(contains(<string>))]a string-like value containing a substring-
prefix#[garde(prefix(<string>))]a string-like value prefixed by some string-
suffix#[garde(suffix(<string>))]a string-like value suffixed by some string-
pattern#[garde(pattern(<regex>))]a string-like value matching some regular expressionpattern
dive#[garde(dive)]nested validation, calls validate on the value-
custom#[garde(custom(<function or closure>))]a custom validator-

Additional notes:

  • For length and range, either min or max may be omitted, but not both.
  • length and range use an inclusive upper bound (min..=max).
  • length uses .chars().count() for UTF-8 strings instead of .len().
  • For contains, prefix, and suffix, the pattern must be a string literal, because the Pattern API is currently unstable.
  • Nested validation using dive may not be combined with any other rule.

  1.  

Re-exports

Modules

Derive Macros