pub fn is_valid_email(s: &str) -> bool {
if s.chars().any(char::is_whitespace) {
return false;
}
let mut parts = s.split('@');
let (Some(local), Some(domain), None) = (parts.next(), parts.next(), parts.next()) else {
return false;
};
if local.is_empty() || domain.is_empty() {
return false;
}
domain.contains('.') && !domain.starts_with('.') && !domain.ends_with('.')
}
pub fn is_valid_phone(s: &str) -> bool {
if !s
.chars()
.all(|c| c.is_ascii_digit() || matches!(c, '+' | '-' | '(' | ')' | ' ' | '.'))
{
return false;
}
let digits = s.chars().filter(char::is_ascii_digit).count();
(7..=15).contains(&digits)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn email_accepts_typical_addresses() {
assert!(is_valid_email("alice@example.com"));
assert!(is_valid_email("a.b+tag@sub.example.co.uk"));
}
#[test]
fn email_rejects_obvious_typos() {
assert!(!is_valid_email("alice"));
assert!(!is_valid_email("alice@"));
assert!(!is_valid_email("@example.com"));
assert!(!is_valid_email("alice@example"));
assert!(!is_valid_email("a@b@c.com"));
assert!(!is_valid_email("alice @example.com"));
assert!(!is_valid_email("alice@.com"));
assert!(!is_valid_email("alice@example."));
assert!(!is_valid_email(""));
}
#[test]
fn phone_accepts_common_shapes() {
assert!(is_valid_phone("+1 (555) 123-4567"));
assert!(is_valid_phone("0701234567"));
assert!(is_valid_phone("555.123.4567"));
}
#[test]
fn phone_rejects_letters_and_bad_lengths() {
assert!(!is_valid_phone("call me"));
assert!(!is_valid_phone("123456")); assert!(!is_valid_phone("1234567890123456")); assert!(!is_valid_phone(""));
}
}