Skip to main content

Crate deser_validate

Crate deser_validate 

Source
Expand description

Validation for deser.

Values are validated while they are deserialized, so errors point at the value in the input (with its line, column and path) like the errors of the format. Validators are types (see Validator), so they are named in adapters and in the types of fields:

  • The Check<V> adapter (#[deser(as = Check<V>)]) fails the deserialization if the value is invalid. The type of the field does not change. On a type (#[deser(deserialize_as = Check<V, _>)]) it checks the whole value, for rules that span fields.
  • Validated<T, V> keeps all errors of the value in it instead of failing, so the value around it can still be deserialized. This also covers errors like a string that is given where a number is expected.
  • A Validation reports all problems of an input.
use deser::Deserialize;
use deser_validate::{
    Check, Email, MaxLen, NonEmpty, Validated, Validation,
};

#[derive(Deserialize)]
struct Signup {
    // must be valid, or the signup is invalid
    #[deser(as = Check<(NonEmpty, MaxLen<32>)>)]
    name: String,
    // kept even if it is invalid
    email: Validated<String, Email>,
    newsletter: bool,
}

let input = r#"{"name": "", "email": "jane@", "newsletter": "yes"}"#;
let validation = Validation::new();
let rv = deser_json::Deserializer::from_str(input)
    .deserialize_with::<Signup, _>(|driver| validation.setup(driver));
let report = validation.finish(rv).into_result().err().unwrap();
let issues: Vec<_> = report
    .iter()
    .map(|issue| {
        format!("{}: {}", issue.path().unwrap(), issue.message())
    })
    .collect();
assert_eq!(
    issues,
    [
        "name: invalid value: must not be empty",
        "email: invalid value: must be an email address",
        "newsletter: unexpected string, expected bool",
    ]
);

Types that are always valid are newtypes which check themselves:

use deser::Deserialize;
use deser_validate::Check;

#[derive(Deserialize)]
#[deser(transparent)]
pub struct Email(#[deser(as = Check<deser_validate::Email>)] String);

§Validators

The validators of this crate are NonEmpty, Len (and MinLen and MaxLen), Range (and Min and Max), Email and Each, which validates the items of collections. Tuples of validators require all of them. The validator! macro creates validators from conditions and functions:

use deser::Deserialize;
use deser_validate::{Check, validator};

// a condition and a message
validator!(NonZero(port: &u16) => *port != 0, "must not be zero");

// a function
fn check_host(host: &str) -> Result<(), String> {
    match host.contains(' ') {
        true => Err(format!("`{}` is not a host name", host)),
        false => Ok(()),
    }
}
validator!(HostName(host: &str) = check_host);

#[derive(Deserialize)]
struct Server {
    #[deser(as = Check<HostName>)]
    host: String,
    #[deser(as = Check<NonZero>)]
    port: u16,
}

Validators of types with generics or lifetimes implement Validator themselves, the macro does not support them.

Validators report a Violation with a code and parameters for programs and a message for humans. Errors have the violation attached.

§Naming Validators

Validators are named for the property that valid values have, as a noun or an adjective: Email, Slug, NonEmpty, NonZero, MaxLen<64>. They read as Check<NonZero> and do not need affixes like Valid, Is or Rules. Negations start with Non (like NonZero). Validators of a whole type name the rule they check (OrderedBounds, not BoundsRules), combinators name their structure (Each). The code of a violation is the name of the validator in snake case (max_len, non_zero), for the validators of this crate and the ones validator! creates.

Macros§

validator
Creates a validator type.

Structs§

Check
An adapter that validates values with V.
Each
Validates every item of a collection with V.
Email
Requires a string that looks like an email address.
Issue
A problem of the input.
Len
Requires the length of a string or collection to be in a range.
NonEmpty
Requires a string or collection that is not empty.
Outcome
The result of a Validation.
Range
Requires an integer to be in a range.
Report
All problems of an input.
Validated
A value that might be invalid, together with its errors.
Validation
Finds all problems of an input.
Violation
Why a value is invalid.

Enums§

Param
A parameter of a Violation.

Traits§

Integer
Integers (see Range).
IntoViolation
What the functions of validators fail with.
Length
Values that have a length (see Len and NonEmpty).
ValidationResult
What the functions of validators return.
Validator
Validates values of type T.

Type Aliases§

Max
Requires a maximum value (see Range).
MaxLen
Requires a maximum length (see Len).
Min
Requires a minimum value (see Range).
MinLen
Requires a minimum length (see Len).