Garde

A Rust validation library
- Basic usage example
- Validation rules
- Inner type validation
- Handling Option
- Custom validation
- Implementing rules
- Implementing
Validate - Integration with web frameworks
- Feature flags
- Why
garde?
Basic usage example
To get started, use the Validate derive macro and add some validation rules to your type.
This generates an implementation of the Validate trait for you.
To use it, call the validate method on an instance of the type.
Here's what that looks like in full:
use ;
let user = User ;
if let Err = user.validate
Garde can also validate enums:
use ;
let data = Struct ;
if let Err = data.validate
Available validation rules
| name | format | validation | feature flag |
|---|---|---|---|
| required | #[garde(required)] |
is value set | - |
| ascii | #[garde(ascii)] |
only contains ASCII | - |
| alphanumeric | #[garde(alphanumeric)] |
only letters and digits | - |
#[garde(email)] |
an email according to the HTML5 spec[^1] | email |
|
| url | #[garde(url)] |
a URL | url |
| 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 number | credit-card |
| phone number | #[garde(phone_number)] |
a phone number | phone-number |
| length | #[garde(length(min=<usize>, max=<usize>)] |
a container with length in min..=max |
- |
| byte_length | #[garde(byte_length(min=<usize>, max=<usize>)] |
a byte sequence with length in 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 expression | pattern |
| dive | #[garde(dive)] |
nested validation, calls validate on the value |
- |
| skip | #[garde(skip)] |
skip validation | - |
| custom | #[garde(custom(<function or closure>))] |
a custom validator | - |
Additional notes:
requiredis only available forOptionfields.- For
lengthandrange, eitherminormaxmay be omitted, but not both. lengthandrangeuse an inclusive upper bound (min..=max).lengthuses.chars().count()for UTF-8 strings instead of.len().- For
contains,prefix, andsuffix, the pattern must be a string literal, because thePatternAPI is currently unstable. - Garde does not enable the default features of the
regexcrate - if you need extra regex features (e.g. Unicode) or better performance, add a dependency onregex = "1"to yourCargo.toml.
If most of the fields on your struct are annotated with #[garde(skip)], you may use #[garde(allow_unvalidated)] instead:
Inner type validation
If you need to validate the "inner" type of a container, such as the String in Vec<String>, then use the inner modifier:
The above type would fail validation if:
- the
Vecis empty - any of the inner
Stringelements is empty - any of the inner
Stringelements contains non-ASCII characters
Handling Option
Every rule works on Option<T> fields. The field will only be validated if it is Some. If you additionally want to validate that the Option<T> field is Some, use the required rule:
The above type would fail validation if:
valueisNone- the inner
valueis empty - the inner
valuecontains non-ASCII characters
Custom validation
Validation may be customized via the custom rule, and the context attribute.
The context may be any type without generic parameters. By default, the context is ().
let ctx = PasswordContext ;
let user = User ;
user.validate?;
The validator function may accept the value as a reference to any type which it derefs to.
In the above example, it is possible to use &str, because password is a String, and String derefs to &str.
Implementing rules
Say you want to implement length checking for a custom string-like type.
To do this, you would implement the garde::rules::length::HasLength trait for it.
;
Each rule comes with its own trait that may be implemented by custom types in your code.
They are all available under garde::rules.
Implementing Validate
In case you have a container type for which you'd like to support nested validation (using the #[garde(dive)] rule),
you may implement Validate for it:
;
To make implementing the trait easier, the Errors type supports a nesting builders.
- For list-like or tuple-like data structures, use
Errors::list, and its.pushmethod to attach nestedErrors. - For map-like data structures, use
Errors::fields, and its.insertmethod to attach nestedErrors. - For a "flat" error list, use
Errors::simple, and its.pushmethod to attach individual errors.
The ListErrorBuilder::push and ListErrorBuilder::insert methods will ignore any errors which are empty (via Errors::is_empty).
Integration with web frameworks
Feature flags
| name | description | extra dependencies |
|---|---|---|
derive |
Enables the usage of the derive(Validate) macro |
garde_derive |
url |
Validation of URLs via the url crate. |
url |
email |
Validation of emails according to HTML5 | regex, once_cell |
email-idna |
Support for Internationalizing Domain Names for Applications in email addresses | idna |
pattern |
Validation using regular expressions via the regex crate |
regex, once_cell |
credit-card |
Validation of credit card numbers via the card-validate crate |
card-validate |
phone-number |
Validation of phone numbers via the phonenumber crate |
phonenumber |
Why garde?
Garde means guard in French. I am not French, nor do I speak the language, but guard was taken, and this is close enough :).
Development
Contributing to garde only requires a somewhat recent version of Rust.
This repository also makes use of the following tools, but they are optional:
instafor snapshot testing (tests/rules).justfor running recipes defined in thejustfile. Runjust -lto see what recipes are available.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Acknowledgements
This crate is heavily inspired by the validator crate. It is essentially a full rewrite of validator.
The creation of this crate was prompted by this comment
and a few others talking about a potential rewrite.