1mod names;
2
3use rand::{rngs::ThreadRng, rng, Rng};
4use std::{
5 cell::RefCell,
6 fmt::{Display, Formatter},
7 sync::LazyLock,
8};
9
10const THREAD_RNG: LazyLock<RefCell<ThreadRng>> = LazyLock::new(|| RefCell::new(rng()));
11
12#[derive(Copy, Clone, Debug)]
14pub enum Gender {
15 Male,
17 Female,
19 Intersex,
21}
22
23#[derive(Debug)]
25pub struct GenError(String);
26
27impl Display for GenError {
28 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29 write!(f, "{}", self.0)
30 }
31}
32
33pub fn random<const LEN: usize>(gender: Gender) -> Result<&'static str, GenError> {
62 use names::NAMES;
63 let data = NAMES
64 .iter()
65 .filter_map(move |(name, gender2)| match (gender, gender2) {
66 (Gender::Male, 0) | (Gender::Female, 1) | (Gender::Intersex, _)
67 if LEN > 0 && LEN == name.chars().collect::<Vec<_>>().len() || LEN <= 0 =>
68 {
69 Some(name)
70 }
71 _ => None,
72 })
73 .collect::<Vec<_>>();
74 if data.is_empty() {
75 return Err(GenError(format!("No result for {:?}: len {}", gender, LEN)));
76 }
77 let index = THREAD_RNG.borrow_mut().random_range(0..data.len());
78 Ok(data[index])
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn it_works() {
87 assert!(random::<1>(Gender::Female).is_ok());
88 assert!(random::<2>(Gender::Female).is_ok());
89 assert!(random::<3>(Gender::Female).is_ok());
90 assert!(random::<4>(Gender::Female).is_ok());
91 assert!(random::<1>(Gender::Male).is_ok());
92 assert!(random::<2>(Gender::Male).is_ok());
93 assert!(random::<3>(Gender::Male).is_ok());
94 assert!(random::<4>(Gender::Male).is_ok());
95 }
96}