macro_rules! validator {
(
@impl [$(#[$meta:meta])*]
$vis:vis $name:ident($arg:ident: &$ty:ty) $body:block ($code:expr)
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) => $cond:expr, $message:expr,
code = $code:literal $(,)?
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) => $cond:expr, $message:expr $(,)?
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) = $func:path, code = $code:literal $(,)?
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) = $func:path $(,)?
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) $body:block, code = $code:literal $(,)?
) => { ... };
(
$(#[$meta:meta])*
$vis:vis $name:ident($arg:ident: &$ty:ty) $body:block $(,)?
) => { ... };
}Expand description
Creates a validator type.
The validator is a unit struct which implements Validator
for the type of its argument and for all types that borrow as it (see
Borrow): a validator of str validates String,
Box<str> and Cow<str> too, a validator of [T] validates Vec<T>.
There are three forms:
use deser_validate::{Validator, validator};
// a condition and the message if it's false
validator!(pub NonZero(port: &u16) => *port != 0, "must not be zero");
// a function
fn check_slug(value: &str) -> Result<(), &'static str> {
if value.bytes().all(|b| b.is_ascii_lowercase() || b == b'-') {
Ok(())
} else {
Err("must be a lowercase identifier")
}
}
validator!(pub Slug(value: &str) = check_slug);
// a block
validator!(
/// Requires an even number of items.
pub EvenLength(items: &[u32]) {
if items.len() % 2 != 0 {
return Err(format!(
"must have an even number of items, not {}",
items.len()
));
}
Ok(())
}
);
assert!(NonZero::validate(&80u16).is_ok());
assert!(Slug::validate(&String::from("my-service")).is_ok());
let violation = EvenLength::validate(&vec![1, 2, 3]).unwrap_err();
assert_eq!(violation.code(), "even_length");
assert_eq!(
violation.message(),
"must have an even number of items, not 3"
);Functions and blocks return a Result<(), E>, where the error is a
message (&'static str, String or Cow<'static, str>) or a
Violation, or a bool. Messages become violations with the name of
the validator in snake case as code (NonZero has the code non_zero).
Functions that return false fail with the message is not valid.
The code is part of what clients see, renaming the validator changes it. All forms accept a code that is used instead of the name as last argument, violations that functions return keep their code:
use deser_validate::{Validator, validator};
validator!(
pub Port(port: &u16) => *port != 0,
"must not be zero",
code = "port"
);
assert_eq!(Port::validate(&0u16).unwrap_err().code(), "port");The macro does not support types with generics or lifetimes (like
Either<T> or Name<'a>). For those, implement
Validator yourself (see there).