pub mod constraints;
use crate::error::ValidationResult;
use crate::rules::RuleRegistry;
use constraints::ConstraintSet;
pub struct SchemaValidator {
constraints: ConstraintSet,
registry: RuleRegistry,
}
impl SchemaValidator {
pub fn new(constraints: ConstraintSet, registry: RuleRegistry) -> Self {
Self {
constraints,
registry,
}
}
pub fn with_defaults() -> Self {
Self::new(ConstraintSet::new(), RuleRegistry::with_defaults())
}
pub fn validate_field(&self, path: &str, value: &str) -> ValidationResult {
self.constraints.validate_field(path, value, &self.registry)
}
pub fn validate_fields<'a>(
&self,
fields: impl IntoIterator<Item = (&'a str, &'a str)>,
) -> ValidationResult {
let mut result = ValidationResult::default();
for (path, value) in fields {
result.merge(self.validate_field(path, value));
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use constraints::FieldConstraint;
#[test]
fn with_defaults_produces_valid_for_unconstrained_path() {
let validator = SchemaValidator::with_defaults();
let result = validator.validate_field("/any/path", "any value");
assert!(result.is_valid());
}
#[test]
fn validate_field_iban() {
let mut cs = ConstraintSet::new();
cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
assert!(validator
.validate_field("/iban", "GB82WEST12345698765432")
.is_valid());
assert!(!validator.validate_field("/iban", "NOTANIBAN").is_valid());
}
#[test]
fn validate_fields_merges_results() {
let mut cs = ConstraintSet::new();
cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
cs.add(FieldConstraint::new("/bic", ["BIC_CHECK"]));
let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
let result = validator.validate_fields([("/iban", "NOTANIBAN"), ("/bic", "NOTABIC")]);
assert!(!result.is_valid());
assert!(result.error_count() >= 2);
}
#[test]
fn validate_fields_all_valid() {
let mut cs = ConstraintSet::new();
cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
cs.add(FieldConstraint::new("/bic", ["BIC_CHECK"]));
let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
let result =
validator.validate_fields([("/iban", "GB82WEST12345698765432"), ("/bic", "AAAAGB2L")]);
assert!(result.is_valid());
}
}