use super::common::{Gender, HUNDREDS, SCALES, TEENS, TENS, UNITS, UNITS_FEMININE};
pub fn to_words(mut number: u64) -> String {
if number == 0 {
return UNITS[0].to_string();
}
let mut parts: Vec<String> = Vec::new();
let mut scale_index = 0usize;
while number > 0 {
let chunk = (number % 1000) as u16;
if chunk != 0 {
let scale = if scale_index == 0 {
None
} else {
Some(&SCALES[scale_index.saturating_sub(1)])
};
let gender = scale.map(|s| s.gender).unwrap_or(Gender::Masculine);
let mut chunk_words = chunk_to_words(chunk, gender);
if let Some(scale_data) = scale {
let form = select_scale_form(chunk, &scale_data.forms);
if !form.is_empty() {
if !chunk_words.is_empty() {
chunk_words.push(' ');
}
chunk_words.push_str(form);
}
}
parts.push(chunk_words);
}
number /= 1000;
scale_index += 1;
}
parts.reverse();
parts.join(" ")
}
fn chunk_to_words(chunk: u16, gender: Gender) -> String {
let mut pieces: Vec<&'static str> = Vec::new();
let hundreds = chunk / 100;
if hundreds > 0 {
pieces.push(HUNDREDS[hundreds as usize]);
}
let remainder = chunk % 100;
if remainder >= 10 && remainder <= 19 {
pieces.push(TEENS[(remainder - 10) as usize]);
} else {
let tens = remainder / 10;
if tens > 0 {
pieces.push(TENS[tens as usize]);
}
let units = remainder % 10;
if units > 0 {
let word = match gender {
Gender::Masculine => UNITS[units as usize],
Gender::Feminine => UNITS_FEMININE[units as usize],
};
pieces.push(word);
}
}
pieces.join(" ")
}
fn select_scale_form(chunk: u16, forms: &[&'static str; 3]) -> &'static str {
let last_two = chunk % 100;
if last_two >= 11 && last_two <= 14 {
return forms[2];
}
match chunk % 10 {
1 => forms[0],
2 | 3 | 4 => forms[1],
_ => forms[2],
}
}