Skip to main content

browsertap_shared/
codename.rs

1use rand::Rng;
2
3const ADJECTIVES: &[&str] = &[
4    "amber", "bold", "calm", "dark", "eager", "fast", "glad", "hazy", "iron", "jade", "keen",
5    "lush", "mild", "neat", "opal", "pale", "quiet", "rare", "sage", "teal", "ultra", "vast",
6    "warm", "zinc", "aqua", "blue", "crisp", "deep", "fair", "gold", "hush", "icy", "just", "kind",
7    "lean", "moss", "navy", "oak", "pure", "quick", "rosy", "slim", "true", "used", "vine", "wide",
8    "young", "zeal", "ashen", "brave", "clear", "dusty", "elite", "fresh", "green", "happy",
9    "ivory", "jolly", "lunar", "maple", "noble", "olive", "prime", "royal", "solar", "terra",
10    "urban", "vivid", "windy", "xenon", "misty", "coral",
11];
12
13const NOUNS: &[&str] = &[
14    "ant", "bat", "cat", "dove", "elk", "fox", "goat", "hare", "ibis", "jay", "koi", "lark",
15    "moth", "newt", "owl", "puma", "quail", "ram", "seal", "toad", "urchin", "vole", "wasp", "yak",
16    "ape", "bass", "crab", "deer", "eel", "frog", "gull", "hawk", "iguana", "jackal", "koala",
17    "lion", "mule", "narwhal", "otter", "parrot", "raven", "shark", "tiger", "tern", "viper",
18    "whale", "wren", "zebra", "bear", "crane", "duck", "eagle", "finch", "gecko", "horse", "imp",
19    "jaguar", "kite", "lynx", "mink", "osprey", "panda", "robin", "swan", "trout", "unicorn",
20    "walrus", "wolf", "falcon", "heron", "lemur", "moose",
21];
22
23/// Generate a friendly codename like "iron-falcon" or "calm-otter".
24pub fn generate_codename() -> String {
25    let mut rng = rand::thread_rng();
26    let adj = ADJECTIVES[rng.gen_range(0..ADJECTIVES.len())];
27    let noun = NOUNS[rng.gen_range(0..NOUNS.len())];
28    format!("{adj}-{noun}")
29}
30
31/// Generate a codename that doesn't collide with existing ones.
32pub fn generate_unique_codename(existing: &[String]) -> String {
33    for _ in 0..100 {
34        let name = generate_codename();
35        if !existing.contains(&name) {
36            return name;
37        }
38    }
39    // Fallback: append a number
40    let base = generate_codename();
41    let mut rng = rand::thread_rng();
42    format!("{base}-{}", rng.gen_range(100..999))
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn codename_format() {
51        let name = generate_codename();
52        assert!(name.contains('-'), "codename should contain a dash: {name}");
53        let parts: Vec<&str> = name.split('-').collect();
54        assert_eq!(
55            parts.len(),
56            2,
57            "codename should have exactly two parts: {name}"
58        );
59    }
60
61    #[test]
62    fn unique_codename_avoids_collisions() {
63        let existing = vec!["iron-falcon".into()];
64        let name = generate_unique_codename(&existing);
65        assert_ne!(name, "iron-falcon");
66    }
67}