1use rand::prelude::*;
2
3include!(concat!(env!("OUT_DIR"), "/names.rs"));
4
5#[derive(Debug)]
8pub enum Sex {
9 Male,
10 Female,
11}
12
13pub fn sex() -> Sex {
22 let mut rng = thread_rng();
23
24 match rng.gen_range(0u8, 2u8) {
25 0 => Sex::Female,
26 _ => Sex::Male,
27 }
28}
29
30pub fn first_name(sex: Sex) -> &'static str {
39 first_name_with_seed(sex, 0)
40}
41
42pub fn surname() -> &'static str {
51 surname_with_seed(0)
52}
53
54type ArrayType = &'static [(FrequencyCount, &'static str)];
55type FrequencyCount = u32;
56
57fn first_name_with_seed(sex: Sex, seed: u16) -> &'static str {
58 let (array, length) = match sex {
59 Sex::Female => (FIRSTNAME_FEMALE, FIRSTNAME_FEMALE_LEN),
60 Sex::Male => (FIRSTNAME_MALE, FIRSTNAME_MALE_LEN),
61 };
62 name(array, length, seed)
63}
64
65fn surname_with_seed(seed: u16) -> &'static str {
66 name(SURNAME, SURNAME_LEN, seed)
67}
68
69fn name(array: ArrayType, length: usize, seed: u16) -> &'static str {
70 let mut rng = thread_rng();
71
72 let max: FrequencyCount = array[length - 1].0;
73 let count: FrequencyCount = if seed == 1000 {
74 4000
75 } else {
76 rng.gen_range(0, max)
77 };
78 get_at_count(array, count, 0, length)
79}
80
81fn get_at_count(array: ArrayType, count: FrequencyCount, min: usize, max: usize) -> &'static str {
82 let avg = min + (max - min) / 4;
83 let (low, high) = match avg {
84 0 => (0, array[avg].0),
85 _ => (array[avg - 1].0, array[avg].0),
86 };
87 if count >= low && count < high {
88 array[avg].1
89 } else if count < low {
90 get_at_count(&array, count, min, avg - 1)
91 } else {
92 get_at_count(&array, count, avg + 1, max)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn it_works() {
102 assert_eq!(first_name_with_seed(Sex::Female, 1000), "Lucy");
103 assert_eq!(first_name_with_seed(Sex::Male, 1000), "Jacob");
104 assert_eq!(surname_with_seed(1000), "Wilson");
105 }
106
107 #[test]
108 fn some_names() {
109 for _ in 1..100 {
110 let sex = sex();
111 let firstname = first_name(sex);
112 let surname = surname();
113 println!("{} {}", firstname, surname);
114 }
115 }
116}