use lazy_regex::{Lazy, Regex, lazy_regex};
use crate::prelude::{Validate, Value};
static EMAIL_REGEX: Lazy<Regex> =
lazy_regex!(r"^[A-Za-z0-9]{1}[A-Za-z0-9._%+-]*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$");
pub struct EmailValidator;
impl Validate for EmailValidator {
fn validate(&self, value: &Value) -> crate::prelude::DbmsResult<()> {
let Value::Text(text) = value else {
return Err(crate::prelude::DbmsError::Validation(
"EmailValidator can only be applied to Text values".to_string(),
));
};
if EMAIL_REGEX.is_match(text.as_str()) {
Ok(())
} else {
Err(crate::prelude::DbmsError::Validation(format!(
"Value '{text}' is not a valid email address",
)))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_email_validator() {
let validator = EmailValidator;
let valid_emails = vec![
"christian.visintin1997@yahoo.com",
"nome.cognome@gmail.com",
"user123@outlook.com",
"user.name+tag@gmail.com",
"info@azienda.it",
"support@sub.domain.com",
"hello-world@my-site.org",
"a@b.co",
"test_email@domain.travel",
"user99@domain.co.uk",
];
let invalid_emails = vec![
"",
"plainaddress",
"@gmail.com",
"user@",
"user@gmail",
"user@gmail.",
"user@.com",
"user@@gmail.com",
".user@gmail.com",
"user@111.222.333.444",
"user@[127.0.0.1]",
"\"user\"@gmail.com",
"user name@gmail.com",
];
for email in valid_emails {
let value = Value::Text(email.into());
assert!(
validator.validate(&value).is_ok(),
"Expected '{}' to be valid",
email
);
}
for email in invalid_emails {
let value = Value::Text(email.into());
assert!(
validator.validate(&value).is_err(),
"Expected '{}' to be invalid",
email
);
}
}
}