Validators
A validator assesses (and may transform) a field's value. Lax,
required and virtual fields can each have
up to two: a primary #[validate] and a secondary #[re_validate], which only runs once the
primary validator has already succeeded.
Both share the same signature: |value, ctx, opts| -> Result<Option<T>, (String, Option<Metadata>)>.
Ok(None)accepts the value as-is.Ok(Some(new_value))replaces it.Err((reason, metadata))rejects it --metadataisNoneunless you're using a customIvoErrorSanitizer.
use ivo::ivo_schema;
#[ivo_schema(input(DataInput, derive(Debug, Clone, PartialEq)))]
mod re_validate_schema {
struct Fields {
#[required]
#[validate(|v: String, _, _| Ok(Some(v)))]
#[re_validate(|v: String, _, _| Ok(Some(format!("revalidated-{v}"))))]
pub username: String,
}
}
fn main() {
let created = re_validate_schema::DataInputModel
.create(
re_validate_schema::PartialDataInput {
username: Some("jane".into()),
},
(),
)
.unwrap();
println!("{:?}", created.data); // DataInput { username: "revalidated-jane" }
}
#[re_validate] requires #[validate] to be present on the same field -- it's a compile error
otherwise. See it used for real (checking a username isn't already taken, via ctx_options) in
examples/main_demo.
- Validators & re-validators: see lax fields, required fields and virtual fields
- Custom required errors: see Required Fields
Built-in validation helpers
Enable the optional validators feature (ivo = { version = "*", features = ["validators"] },
crate ivo-validators) for a small set of built-in validators:
validate_email(value: &str) -> Result<String, String>validate_credit_card(value: &str) -> Result<String, String>
#[lax(None)]
#[validate(|v: Option<String>, _, _| {
let Some(email) = v else { return Ok(None) };
match validate_email(&email) {
Ok(validated) => Ok(Some(Some(validated))),
Err(e) => Err((e, None)),
}
})]
pub email: Option<String>,
See the
crate source
for implementation details, and
main_demo
for a schema that uses them.