use crate::validation::Validator;
pub struct Required;
impl Validator for Required {
fn validate(&self, value: &str) -> Result<(), String> {
if value.trim().is_empty() {
Err("This field is required".to_string())
} else {
Ok(())
}
}
}
pub struct Email;
impl Validator for Email {
fn validate(&self, value: &str) -> Result<(), String> {
if value.is_empty() {
return Ok(()); }
let parts: Vec<&str> = value.split('@').collect();
if parts.len() != 2 {
return Err("Invalid email address".to_string());
}
let (local, domain) = (parts[0], parts[1]);
if local.is_empty() || domain.is_empty() {
return Err("Invalid email address".to_string());
}
if !domain.contains('.') {
return Err("Invalid email address".to_string());
}
let domain_parts: Vec<&str> = domain.split('.').collect();
if domain_parts.iter().any(|p| p.is_empty()) {
return Err("Invalid email address".to_string());
}
Ok(())
}
}
pub struct MinLength(pub usize);
impl Validator for MinLength {
fn validate(&self, value: &str) -> Result<(), String> {
if value.is_empty() {
return Ok(()); }
if value.len() < self.0 {
Err(format!("Must be at least {} characters", self.0))
} else {
Ok(())
}
}
}
pub struct MaxLength(pub usize);
impl Validator for MaxLength {
fn validate(&self, value: &str) -> Result<(), String> {
if value.len() > self.0 {
Err(format!("Must be at most {} characters", self.0))
} else {
Ok(())
}
}
}
pub struct Pattern {
regex: regex::Regex,
message: String,
}
impl Pattern {
pub fn new(pattern: &str, message: impl Into<String>) -> Self {
Self {
regex: regex::Regex::new(pattern).expect("Invalid regex pattern"),
message: message.into(),
}
}
pub fn zip_code() -> Self {
Self::new(r"^\d{5}(-\d{4})?$", "Invalid ZIP code format")
}
pub fn phone() -> Self {
Self::new(
r"^(\+1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}$",
"Invalid phone number format",
)
}
pub fn date() -> Self {
Self::new(r"^\d{4}-\d{2}-\d{2}$", "Invalid date format (use YYYY-MM-DD)")
}
}
impl Validator for Pattern {
fn validate(&self, value: &str) -> Result<(), String> {
if value.is_empty() {
return Ok(()); }
if self.regex.is_match(value) {
Ok(())
} else {
Err(self.message.clone())
}
}
}