wasm_dbms_api/dbms/validate/
chain.rs1use std::fmt;
2
3use crate::prelude::{DbmsResult, Validate, Value};
4
5pub struct ValidatorChain(Vec<Box<dyn Validate>>);
27
28impl ValidatorChain {
29 pub fn new(validators: Vec<Box<dyn Validate>>) -> Self {
31 Self(validators)
32 }
33}
34
35impl fmt::Debug for ValidatorChain {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.debug_struct("ValidatorChain")
38 .field("len", &self.0.len())
39 .finish()
40 }
41}
42
43impl Validate for ValidatorChain {
44 fn validate(&self, value: &Value) -> DbmsResult<()> {
45 self.0
46 .iter()
47 .try_for_each(|validator| validator.validate(value))
48 }
49}
50
51#[cfg(test)]
52mod tests {
53
54 use super::*;
55 use crate::prelude::{DbmsError, MaxStrlenValidator, MinStrlenValidator};
56
57 struct FailingValidator(&'static str);
58
59 impl Validate for FailingValidator {
60 fn validate(&self, _value: &Value) -> DbmsResult<()> {
61 Err(DbmsError::Validation(self.0.to_string()))
62 }
63 }
64
65 #[test]
66 fn test_should_accept_value_valid_for_every_validator() {
67 let validator = ValidatorChain::new(vec![
68 Box::new(MinStrlenValidator(2)),
69 Box::new(MaxStrlenValidator(5)),
70 ]);
71 assert!(validator.validate(&Value::Text("abc".into())).is_ok());
72 assert!(validator.validate(&Value::Text("a".into())).is_err());
73 assert!(validator.validate(&Value::Text("abcdef".into())).is_err());
74 }
75
76 #[test]
77 fn test_should_accept_any_value_when_empty() {
78 let validator = ValidatorChain::new(vec![]);
79 assert!(validator.validate(&Value::Text("anything".into())).is_ok());
80 }
81
82 #[test]
83 fn test_should_return_first_error() {
84 let validator = ValidatorChain::new(vec![
85 Box::new(FailingValidator("first")),
86 Box::new(FailingValidator("second")),
87 ]);
88 let err = validator.validate(&Value::Text("x".into())).unwrap_err();
89 assert!(matches!(err, DbmsError::Validation(message) if message == "first"));
90 }
91}