ukraine 1.1.0

Glory to Ukraine. Library for transliterating Ukrainian Cyrillic text into Latin script representation
Documentation
use super::common::{Gender, HUNDREDS, SCALES, TEENS, TENS, UNITS, UNITS_FEMININE};

/// Convert a non-negative integer into its Ukrainian words representation.
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],
    }
}