Skip to main content

Module rule

Module rule 

Source
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§

ClosureRule
Adapter wrapping a sync closure as a Rule (used by .refine(...)).
RefineRejection
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).