pub mod list;
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};
use crate::list::{ADJECTIVES, NAMES, WORDS};
pub trait ToName {
fn to_name(&self) -> String;
}
pub trait ToWordSequence {
fn to_word_sequence(&self) -> String;
}
fn number_to_name<U: Into<u64>>(number: U) -> String {
let num = hash_number(number.into());
let adjective_index = (num % (ADJECTIVES.len() as u64)) as usize;
let name_index = (num / (ADJECTIVES.len() as u64) % (NAMES.len() as u64)) as usize;
format!("{}_{}", ADJECTIVES[adjective_index], NAMES[name_index])
}
fn number_to_words<U: Into<u64>>(number: U) -> String {
let mut num = hash_number(number.into());
let mut words = Vec::new();
while num > 0 {
let index = (num % 2048) as usize;
words.push(WORDS[index]);
num /= 2048;
}
words.reverse();
words.join(" ")
}
fn hash_number(number: u64) -> u64 {
let mut hasher = DefaultHasher::new();
number.hash(&mut hasher);
hasher.finish()
}
macro_rules! impl_to_name {
($($t:ty),*) => {
$(impl ToName for $t {
fn to_name(&self) -> String {
number_to_name(*self)
}
})*
};
}
macro_rules! impl_to_word_sequence {
($($t:ty),*) => {
$(impl ToWordSequence for $t {
fn to_word_sequence(&self) -> String {
number_to_words(*self)
}
})*
};
}
impl_to_name!(u8, u16, u32, u64);
impl_to_word_sequence!(u8, u16, u32, u64);