ic_dbms_api/validate/
email.rs

1use ic_dbms_api::prelude::Value;
2use lazy_regex::{Lazy, Regex, lazy_regex};
3
4use crate::prelude::Validate;
5
6static EMAIL_REGEX: Lazy<Regex> =
7    lazy_regex!(r"^[A-Za-z0-9]{1}[A-Za-z0-9._%+-]*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$");
8
9/// A validator for email addresses.
10///
11/// This validator checks if a given text value conforms to a standard email format.
12///
13/// # Examples
14///
15/// ```rust
16/// use ic_dbms_api::prelude::{EmailValidator, Validate, Value};
17///
18/// let validator = EmailValidator;
19/// let valid_email = Value::Text("christian.visintin@gmail.com".into());
20/// let invalid_email = Value::Text("invalid-email".into());
21///
22/// assert!(validator.validate(&valid_email).is_ok());
23/// assert!(validator.validate(&invalid_email).is_err());
24/// ```
25pub struct EmailValidator;
26
27impl Validate for EmailValidator {
28    fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
29        let Value::Text(text) = value else {
30            return Err(ic_dbms_api::prelude::IcDbmsError::Validation(
31                "EmailValidator can only be applied to Text values".to_string(),
32            ));
33        };
34
35        if EMAIL_REGEX.is_match(text.as_str()) {
36            Ok(())
37        } else {
38            Err(ic_dbms_api::prelude::IcDbmsError::Validation(format!(
39                "Value '{text}' is not a valid email address",
40            )))
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47
48    use super::*;
49
50    #[test]
51    fn test_email_validator() {
52        let validator = EmailValidator;
53        let valid_emails = vec![
54            "christian.visintin1997@yahoo.com",
55            "nome.cognome@gmail.com",
56            "user123@outlook.com",
57            "user.name+tag@gmail.com",
58            "info@azienda.it",
59            "support@sub.domain.com",
60            "hello-world@my-site.org",
61            "a@b.co",
62            "test_email@domain.travel",
63            "user99@domain.co.uk",
64        ];
65        let invalid_emails = vec![
66            "",
67            "plainaddress",
68            "@gmail.com",
69            "user@",
70            "user@gmail",
71            "user@gmail.",
72            "user@.com",
73            "user@@gmail.com",
74            //"user@gmail..com",
75            //"user..name@gmail.com",
76            ".user@gmail.com",
77            //"user.@gmail.com",
78            //"user@-gmail.com",
79            //"user@gmail-.com",
80            "user@111.222.333.444",
81            "user@[127.0.0.1]",
82            "\"user\"@gmail.com",
83            "user name@gmail.com",
84        ];
85
86        for email in valid_emails {
87            let value = Value::Text(email.into());
88            assert!(
89                validator.validate(&value).is_ok(),
90                "Expected '{}' to be valid",
91                email
92            );
93        }
94        for email in invalid_emails {
95            let value = Value::Text(email.into());
96            assert!(
97                validator.validate(&value).is_err(),
98                "Expected '{}' to be invalid",
99                email
100            );
101        }
102    }
103}