mod generated {
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
}
fn normalize(s: &str) -> String {
s.trim().to_lowercase()
}
pub fn nicknames(name: &str) -> Vec<String> {
let key = normalize(name);
if key.is_empty() { return Vec::new(); }
let map = generated::nickname_map();
match map.get(key.as_str()) {
Some(list) => list.iter().map(|s| s.to_string()).collect(),
None => Vec::new(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn abigail_has_expected_nicknames() {
let nicks = nicknames("Abigail");
assert!(nicks.contains(&"abby".to_string()));
assert!(nicks.contains(&"gail".to_string()));
assert!(nicks.contains(&"abbey".to_string()));
assert!(!nicks.contains(&"abigail".to_string()));
}
#[test]
fn unknown_name_returns_empty() {
let nicks = nicknames("thisnameisnotlikelypresent");
assert!(nicks.is_empty());
}
#[test]
fn case_insensitivity() {
let lower = nicknames("abigail");
let upper = nicknames("ABIGAIL");
let mixed = nicknames("AbIgAiL");
assert_eq!(lower, upper);
assert_eq!(upper, mixed);
}
#[test]
fn no_self_inclusion() {
let nicks = nicknames("Abigail");
assert!(!nicks.contains(&"abigail".to_string()));
}
#[test]
fn name_with_no_alternates() {
let nicks = nicknames("abbey");
assert!(!nicks.contains(&"abbey".to_string()));
}
#[test]
fn symmetry() {
let abigail_nicks = nicknames("abigail");
let abby_nicks = nicknames("abby");
assert!(abigail_nicks.contains(&"abby".to_string()));
assert!(abby_nicks.contains(&"abigail".to_string()));
}
#[test]
fn trims_whitespace() {
let nicks = nicknames(" abigail ");
let expected = nicknames("abigail");
assert_eq!(nicks, expected);
}
}