ukraine 1.1.0

Glory to Ukraine. Library for transliterating Ukrainian Cyrillic text into Latin script representation
Documentation
/// Transliteration according to DSTU 9112:2021 system A.
/// https://en.wikipedia.org/wiki/DSTU_9112:2021
//

/// # Examples
/// ```rust
/// use ukraine::latin::transliterate_dstu9112a;
/// # fn main() {
/// let original = "Слава Україні. Героям слава!";
/// let transliterated = transliterate_dstu9112a(original);
/// assert_eq!(transliterated, "Slava Ukraïni. Ğerojam slava!");
/// }
/// ```
pub fn transliterate_dstu9112a(text: &str) -> String {
    let chars: Vec<char> = text.chars().collect();
    let mut output = String::with_capacity(text.len() * 2);
    let mut index = 0usize;

    while index < chars.len() {
        let ch = chars[index];
        let next = chars.get(index + 1).copied();

        match ch {
            'Щ' | 'щ' => {
                output.push_str(transliterate_shcha(ch, next));
                index += 1;
            }
            'Ь' | 'ь' => {
                output.push_str(transliterate_soft_sign(ch, next));
                index += 1;
            }
            'Х' | 'х' => {
                output.push_str(if ch.is_uppercase() { "X" } else { "x" });
                index += 1;
            }
            '' | '\'' => {
                output.push('');
                index += 1;
            }
            _ => {
                if let Some(mapped) = map_basic(ch) {
                    output.push_str(mapped);
                } else {
                    output.push(ch);
                }
                index += 1;
            }
        }
    }

    output
}

fn transliterate_shcha(current: char, next: Option<char>) -> &'static str {
    let is_upper = current.is_uppercase();
    match next {
        Some('а') | Some('А') | Some('я') | Some('Я') | Some('ю') | Some('Ю') | Some('є')
        | Some('Є') => {
            if is_upper {
                "Šč"
            } else {
                "šč"
            }
        }
        Some('і') | Some('І') | Some('ї') | Some('Ї') | Some('й') | Some('Й') | Some('ь')
        | Some('Ь') | Some('е') | Some('Е') | Some('о') | Some('О') | Some('и') | Some('И') => {
            if is_upper {
                "Ŝ"
            } else {
                "ŝ"
            }
        }
        _ => {
            if is_upper {
                "Šč"
            } else {
                "šč"
            }
        }
    }
}

fn transliterate_soft_sign(current: char, next: Option<char>) -> &'static str {
    match next {
        Some('в') | Some('В') => "",
        _ => {
            if current.is_uppercase() {
                "J"
            } else {
                "j"
            }
        }
    }
}

fn map_basic(ch: char) -> Option<&'static str> {
    match ch {
        'А' => Some("A"),
        'а' => Some("a"),
        'Б' => Some("B"),
        'б' => Some("b"),
        'В' => Some("V"),
        'в' => Some("v"),
        'Г' => Some("Ğ"),
        'г' => Some("ğ"),
        'Ґ' => Some("G"),
        'ґ' => Some("g"),
        'Д' => Some("D"),
        'д' => Some("d"),
        'Е' => Some("E"),
        'е' => Some("e"),
        'Є' => Some("Je"),
        'є' => Some("je"),
        'Ж' => Some("Ž"),
        'ж' => Some("ž"),
        'З' => Some("Z"),
        'з' => Some("z"),
        'И' => Some("Y"),
        'и' => Some("y"),
        'І' => Some("I"),
        'і' => Some("i"),
        'Ї' => Some("Ï"),
        'ї' => Some("ï"),
        'Й' => Some("J"),
        'й' => Some("j"),
        'К' => Some("K"),
        'к' => Some("k"),
        'Л' => Some("L"),
        'л' => Some("l"),
        'М' => Some("M"),
        'м' => Some("m"),
        'Н' => Some("N"),
        'н' => Some("n"),
        'О' => Some("O"),
        'о' => Some("o"),
        'П' => Some("P"),
        'п' => Some("p"),
        'Р' => Some("R"),
        'р' => Some("r"),
        'С' => Some("S"),
        'с' => Some("s"),
        'Т' => Some("T"),
        'т' => Some("t"),
        'У' => Some("U"),
        'у' => Some("u"),
        'Ф' => Some("F"),
        'ф' => Some("f"),
        'Х' => Some("X"),
        'х' => Some("x"),
        'Ц' => Some("C"),
        'ц' => Some("c"),
        'Ч' => Some("Č"),
        'ч' => Some("č"),
        'Ш' => Some("Š"),
        'ш' => Some("š"),
        'Ю' => Some("Ju"),
        'ю' => Some("ju"),
        'Я' => Some("Ja"),
        'я' => Some("ja"),
        'Ь' => Some(""),
        'ь' => Some(""),
        _ => None,
    }
}