1use sha2::{Digest, Sha256};
8
9const ADJECTIVES: &[&str] = &[
10 "ancient", "bold", "breezy", "bright", "calm", "clever", "cosmic", "crisp", "daring", "dusty",
11 "eager", "faded", "fierce", "gentle", "golden", "gusty", "hasty", "hidden", "hollow", "icy",
12 "jolly", "keen", "lazy", "lively", "lucky", "mighty", "misty", "narrow", "nimble", "noble",
13 "noisy", "odd", "pale", "plain", "proud", "quick", "quiet", "rapid", "rocky", "rosy", "rough",
14 "rusty", "sandy", "sharp", "shy", "silent", "sleek", "snowy", "solar", "spicy", "steep",
15 "stormy", "stout", "sunny", "swift", "tame", "thorny", "tidy", "tough", "twisted", "vast",
16 "vivid", "warm", "wild", "windy", "wispy", "witty", "young", "zesty",
17];
18
19const COLORS: &[&str] = &[
20 "amber", "aqua", "azure", "beige", "black", "blue", "brass", "bronze", "brown", "cedar",
21 "charcoal", "cherry", "cobalt", "copper", "coral", "cream", "crimson", "cyan", "ebony",
22 "ember", "garnet", "gold", "granite", "green", "grey", "hazel", "indigo", "ivory", "jade",
23 "khaki", "lemon", "lilac", "lime", "maple", "maroon", "mauve", "mint", "mocha", "navy",
24 "ochre", "olive", "onyx", "orange", "orchid", "peach", "pearl", "pine", "plum", "quartz",
25 "rose", "ruby", "rust", "sage", "sand", "scarlet", "silver", "slate", "smoke", "steel",
26 "stone", "tan", "teal", "topaz", "umber", "violet", "walnut", "wheat", "white", "wine",
27];
28
29const ANIMALS: &[&str] = &[
30 "badger", "bat", "bear", "beetle", "bison", "bobcat", "cobra", "condor", "crane", "crow",
31 "deer", "dingo", "eagle", "elk", "falcon", "ferret", "finch", "fox", "gecko", "goat", "goblin",
32 "grouse", "hare", "hawk", "heron", "horse", "ibex", "iguana", "jackal", "jay", "koala",
33 "lemur", "lion", "lizard", "llama", "lynx", "marten", "moose", "moth", "newt", "otter", "owl",
34 "panda", "parrot", "pelican", "pike", "puma", "quail", "rabbit", "raccoon", "raven", "robin",
35 "salmon", "shark", "snail", "snake", "sparrow", "squid", "stork", "swan", "tiger", "toad",
36 "toucan", "turtle", "viper", "walrus", "wasp", "whale", "wolf", "wren",
37];
38
39pub fn from_bytes(data: &[u8]) -> String {
44 let hash = Sha256::digest(data);
45
46 let adj_idx = u16::from_le_bytes([hash[0], hash[1]]) as usize % ADJECTIVES.len();
48 let color_idx = u16::from_le_bytes([hash[2], hash[3]]) as usize % COLORS.len();
49 let animal_idx = u16::from_le_bytes([hash[4], hash[5]]) as usize % ANIMALS.len();
50
51 format!(
52 "{}-{}-{}",
53 ADJECTIVES[adj_idx], COLORS[color_idx], ANIMALS[animal_idx]
54 )
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn deterministic() {
63 assert_eq!(from_bytes(b"hello"), from_bytes(b"hello"));
64 }
65
66 #[test]
67 fn different_input_different_name() {
68 assert_ne!(from_bytes(b"hello"), from_bytes(b"world"));
69 }
70
71 #[test]
72 fn three_words() {
73 let name = from_bytes(b"test");
74 assert_eq!(name.split('-').count(), 3);
75 }
76
77 #[test]
78 fn not_empty() {
79 let name = from_bytes(b"");
80 assert!(!name.is_empty());
81 assert!(name.len() > 5);
82 }
83}