use std::collections::HashMap;
pub type FormatValidator = fn(&str) -> bool;
#[derive(Clone)]
pub struct FormatRegistry {
formats: HashMap<String, FormatValidator>,
}
impl FormatRegistry {
pub fn new() -> Self {
Self {
formats: HashMap::new(),
}
}
pub fn register(&mut self, name: impl Into<String>, validator: FormatValidator) {
self.formats.insert(name.into(), validator);
}
pub fn get(&self, name: &str) -> Option<&FormatValidator> {
self.formats.get(name)
}
pub fn has(&self, name: &str) -> bool {
self.formats.contains_key(name)
}
pub fn clear(&mut self) {
self.formats.clear();
}
pub fn validate(&self, format: &str, value: &str) -> Option<bool> {
self.formats.get(format).map(|validator| validator(value))
}
}
impl Default for FormatRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_and_validate() {
let mut registry = FormatRegistry::new();
registry.register("email", |s| s.contains('@') && s.contains('.'));
assert!(registry.has("email"));
assert!(!registry.has("unknown"));
assert!(registry.validate("email", "test@example.com").unwrap());
assert!(!registry.validate("email", "invalid").unwrap());
}
#[test]
fn test_unregistered_format() {
let registry = FormatRegistry::new();
assert!(registry.validate("email", "test@example.com").is_none());
}
#[test]
fn test_clear() {
let mut registry = FormatRegistry::new();
registry.register("email", |_| true);
assert!(registry.has("email"));
registry.clear();
assert!(!registry.has("email"));
}
}