use crate::error::ValidationErrors;
use crate::traits::Validator;
type SchemaRule<T> = Box<dyn Fn(&T, &mut ValidationErrors) + Send + Sync>;
pub struct Schema<T> {
rules: Vec<SchemaRule<T>>,
}
impl<T> Default for Schema<T> {
fn default() -> Self {
Self { rules: Vec::new() }
}
}
impl<T> Schema<T> {
pub fn new() -> Self {
Self::default()
}
pub fn field<F, V, Val>(mut self, name: impl Into<String>, extractor: F, validator: Val) -> Self
where
F: Fn(&T) -> &V + Send + Sync + 'static,
V: ?Sized + 'static,
Val: Validator<V> + Send + Sync + 'static,
{
let field_name = name.into();
self.rules.push(Box::new(move |obj, errors| {
let val = extractor(obj);
let field_errors = validator.validate_all(val);
errors.add_many(&field_name, field_errors);
}));
self
}
pub fn validate(&self, target: &T) -> Result<(), ValidationErrors> {
let mut errors = ValidationErrors::new();
for rule in &self.rules {
rule(target, &mut errors);
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
}