mx20022_validate/schema/
mod.rs1pub mod constraints;
21
22use crate::error::ValidationResult;
23use crate::rules::RuleRegistry;
24use constraints::ConstraintSet;
25
26pub struct SchemaValidator {
43 constraints: ConstraintSet,
44 registry: RuleRegistry,
45}
46
47impl SchemaValidator {
48 pub fn new(constraints: ConstraintSet, registry: RuleRegistry) -> Self {
50 Self {
51 constraints,
52 registry,
53 }
54 }
55
56 pub fn with_defaults() -> Self {
58 Self::new(ConstraintSet::new(), RuleRegistry::with_defaults())
59 }
60
61 pub fn validate_field(&self, path: &str, value: &str) -> ValidationResult {
67 self.constraints.validate_field(path, value, &self.registry)
68 }
69
70 pub fn validate_fields<'a>(
72 &self,
73 fields: impl IntoIterator<Item = (&'a str, &'a str)>,
74 ) -> ValidationResult {
75 let mut result = ValidationResult::default();
76 for (path, value) in fields {
77 result.merge(self.validate_field(path, value));
78 }
79 result
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use constraints::FieldConstraint;
87
88 #[test]
89 fn with_defaults_produces_valid_for_unconstrained_path() {
90 let validator = SchemaValidator::with_defaults();
91 let result = validator.validate_field("/any/path", "any value");
92 assert!(result.is_valid());
93 }
94
95 #[test]
96 fn validate_field_iban() {
97 let mut cs = ConstraintSet::new();
98 cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
99 let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
100
101 assert!(validator
102 .validate_field("/iban", "GB82WEST12345698765432")
103 .is_valid());
104 assert!(!validator.validate_field("/iban", "NOTANIBAN").is_valid());
105 }
106
107 #[test]
108 fn validate_fields_merges_results() {
109 let mut cs = ConstraintSet::new();
110 cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
111 cs.add(FieldConstraint::new("/bic", ["BIC_CHECK"]));
112 let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
113
114 let result = validator.validate_fields([("/iban", "NOTANIBAN"), ("/bic", "NOTABIC")]);
115 assert!(!result.is_valid());
117 assert!(result.error_count() >= 2);
118 }
119
120 #[test]
121 fn validate_fields_all_valid() {
122 let mut cs = ConstraintSet::new();
123 cs.add(FieldConstraint::new("/iban", ["IBAN_CHECK"]));
124 cs.add(FieldConstraint::new("/bic", ["BIC_CHECK"]));
125 let validator = SchemaValidator::new(cs, RuleRegistry::with_defaults());
126
127 let result =
128 validator.validate_fields([("/iban", "GB82WEST12345698765432"), ("/bic", "AAAAGB2L")]);
129 assert!(result.is_valid());
130 }
131}