mod names;
use rand::{rngs::ThreadRng, thread_rng, Rng};
use std::{
cell::RefCell,
fmt::{Display, Formatter},
sync::LazyLock,
};
const THREAD_RNG: LazyLock<RefCell<ThreadRng>> = LazyLock::new(|| RefCell::new(thread_rng()));
#[derive(Copy, Clone, Debug)]
pub enum Gender {
Male,
Female,
Intersex,
}
#[derive(Debug)]
pub struct GenError(String);
impl Display for GenError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
pub fn random<const LEN: usize>(gender: Gender) -> Result<&'static str, GenError> {
use names::NAMES;
let data = NAMES
.iter()
.filter_map(move |(name, gender2)| match (gender, gender2) {
(Gender::Male, 0) | (Gender::Female, 1) | (Gender::Intersex, _)
if LEN > 0 && LEN == name.chars().collect::<Vec<_>>().len() || LEN <= 0 =>
{
Some(name)
}
_ => None,
})
.collect::<Vec<_>>();
if data.is_empty() {
return Err(GenError(format!("No result for {:?}: len {}", gender, LEN)));
}
let index = THREAD_RNG.borrow_mut().gen_range(0..data.len());
Ok(data[index])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert!(random::<1>(Gender::Female).is_ok());
assert!(random::<2>(Gender::Female).is_ok());
assert!(random::<3>(Gender::Female).is_ok());
assert!(random::<4>(Gender::Female).is_ok());
assert!(random::<1>(Gender::Male).is_ok());
assert!(random::<2>(Gender::Male).is_ok());
assert!(random::<3>(Gender::Male).is_ok());
assert!(random::<4>(Gender::Male).is_ok());
}
}