use validator::validate_email; #[derive(Debug)] pub struct UserEmail(pub String); impl UserEmail { pub fn parse(s: String) -> Result { if s.trim().is_empty() { return Err(format!("Email can not be empty or whitespace")); } if validate_email(&s) { Ok(Self(s)) } else { Err(format!("{} is not a valid email.", s)) } } } impl AsRef for UserEmail { fn as_ref(&self) -> &str { &self.0 } } #[cfg(test)] mod tests { use super::*; use claim::assert_err; use fake::{faker::internet::en::SafeEmail, Fake}; #[test] fn empty_string_is_rejected() { let email = "".to_string(); assert_err!(UserEmail::parse(email)); } #[test] fn email_missing_at_symbol_is_rejected() { let email = "helloworld.com".to_string(); assert_err!(UserEmail::parse(email)); } #[test] fn email_missing_subject_is_rejected() { let email = "@domain.com".to_string(); assert_err!(UserEmail::parse(email)); } #[derive(Debug, Clone)] struct ValidEmailFixture(pub String); impl quickcheck::Arbitrary for ValidEmailFixture { fn arbitrary(g: &mut G) -> Self { let email = SafeEmail().fake_with_rng(g); Self(email) } } #[quickcheck_macros::quickcheck] fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool { UserEmail::parse(valid_email.0).is_ok() } }