Expand description
Custom validation rules that compose identically to built-in checks. Custom validation rules that compose identically to built-in checks.
Rules observe post-normalization values, return rejection data, and are
stored boxed inside schemas. Sync-only by signature (no async types), and
every Rule is Send + Sync: rules may be validated from any thread and
shared across threads via Arc without additional bounds.
use formars_core::error::IssueCode;
use formars_core::rule::{RefineRejection, Rule};
use std::borrow::Cow;
#[derive(Debug)]
struct StartsWith(char);
impl Rule<str> for StartsWith {
fn name(&self) -> &str { "starts_with" }
fn validate(&self, value: &str) -> Option<RefineRejection> {
if value.starts_with(self.0) { None } else {
Some(RefineRejection {
code: Some(IssueCode::Custom("starts_with".into())),
message: Cow::Borrowed("must start with the expected char"),
params: Vec::new(),
})
}
}
}
use formars_core::schema::Schema;
use formars_core::types::string;
let schema = string().min(2).rule(StartsWith('a'));
assert!(schema.parse(&"apple".to_string()).is_ok());
// The rule's own code survives to the issue, so a translation table can
// key off it without ever reading `message`.
let err = schema.parse(&"pear".to_string()).unwrap_err();
assert_eq!(err.issues[0].code, IssueCode::Custom("starts_with".into()));Structs§
- Closure
Rule - Adapter wrapping a sync closure as a
Rule(used by.refine(...)). - Refine
Rejection - Rejection data returned by a rule; the owning kernel handles paths, accumulation and fail-fast policy.
Traits§
- Rule
- Object-safe extension point stored boxed (
Box<dyn Rule<T>>) inside schemas (SC-7).