use crate::RedactionStrategy;
use std::fmt;
#[derive(Default, Clone)]
pub struct EmailRedactor;
impl<T: AsRef<str>> RedactionStrategy<T> for EmailRedactor {
fn display(&self, value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
redact_email(value.as_ref(), f)
}
}
fn redact_email(email: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some((local, domain)) = email.split_once('@') {
let mut chars = local.chars();
let first = chars.next();
let last = chars.next_back();
let more = chars.next();
if let (Some(first), Some(last), Some(_)) = (first, last, more) {
write!(f, "{first}***{last}@{domain}")
} else {
write!(f, "***@{domain}")
}
} else {
write!(f, "[REDACTED: invalid email]")
}
}
#[cfg(test)]
mod tests {
use crate::Redacted;
use crate::strategy::EmailRedactor;
fn email(input: &str) -> String {
Redacted::<_, EmailRedactor>::new(input).to_string()
}
#[test]
fn special_inputs() {
assert_eq!(email("not an email"), "[REDACTED: invalid email]");
assert_eq!(email("@nolocal.com"), "***@nolocal.com");
assert_eq!(email("nodomain@"), "n***n@");
assert_eq!(email("a@onechar.com"), "***@onechar.com");
assert_eq!(email("ab@twochar.com"), "***@twochar.com");
assert_eq!(email("abc@threechar.com"), "a***c@threechar.com");
assert_eq!(email("안녕하세요@unicode.com"), "안***요@unicode.com");
assert_eq!(email("안녕@unicode.com"), "***@unicode.com");
}
}