use super::common::{HUNDREDS, TENS};
#[derive(Copy, Clone)]
pub enum OrdinalGender {
Masculine,
Feminine,
Neuter,
}
struct OrdinalForms {
masculine: &'static str,
feminine: &'static str,
neuter: &'static str,
}
impl OrdinalForms {
fn get(&self, gender: OrdinalGender) -> &'static str {
match gender {
OrdinalGender::Masculine => self.masculine,
OrdinalGender::Feminine => self.feminine,
OrdinalGender::Neuter => self.neuter,
}
}
}
const ORDINAL_UNDER_TWENTY: [OrdinalForms; 20] = [
OrdinalForms {
masculine: "нульовий",
feminine: "нульова",
neuter: "нульове",
},
OrdinalForms {
masculine: "перший",
feminine: "перша",
neuter: "перше",
},
OrdinalForms {
masculine: "другий",
feminine: "друга",
neuter: "друге",
},
OrdinalForms {
masculine: "третій",
feminine: "третя",
neuter: "третє",
},
OrdinalForms {
masculine: "четвертий",
feminine: "четверта",
neuter: "четверте",
},
OrdinalForms {
masculine: "п'ятий",
feminine: "п'ята",
neuter: "п'яте",
},
OrdinalForms {
masculine: "шостий",
feminine: "шоста",
neuter: "шосте",
},
OrdinalForms {
masculine: "сьомий",
feminine: "сьома",
neuter: "сьоме",
},
OrdinalForms {
masculine: "восьмий",
feminine: "восьма",
neuter: "восьме",
},
OrdinalForms {
masculine: "дев'ятий",
feminine: "дев'ята",
neuter: "дев'яте",
},
OrdinalForms {
masculine: "десятий",
feminine: "десята",
neuter: "десяте",
},
OrdinalForms {
masculine: "одинадцятий",
feminine: "одинадцята",
neuter: "одинадцяте",
},
OrdinalForms {
masculine: "дванадцятий",
feminine: "дванадцята",
neuter: "дванадцяте",
},
OrdinalForms {
masculine: "тринадцятий",
feminine: "тринадцята",
neuter: "тринадцяте",
},
OrdinalForms {
masculine: "чотирнадцятий",
feminine: "чотирнадцята",
neuter: "чотирнадцяте",
},
OrdinalForms {
masculine: "п'ятнадцятий",
feminine: "п'ятнадцята",
neuter: "п'ятнадцяте",
},
OrdinalForms {
masculine: "шістнадцятий",
feminine: "шістнадцята",
neuter: "шістнадцяте",
},
OrdinalForms {
masculine: "сімнадцятий",
feminine: "сімнадцята",
neuter: "сімнадцяте",
},
OrdinalForms {
masculine: "вісімнадцятий",
feminine: "вісімнадцята",
neuter: "вісімнадцяте",
},
OrdinalForms {
masculine: "дев'ятнадцятий",
feminine: "дев'ятнадцята",
neuter: "дев'ятнадцяте",
},
];
const ORDINAL_TENS: [Option<OrdinalForms>; 10] = [
None,
None,
Some(OrdinalForms {
masculine: "двадцятий",
feminine: "двадцята",
neuter: "двадцяте",
}),
Some(OrdinalForms {
masculine: "тридцятий",
feminine: "тридцята",
neuter: "тридцяте",
}),
Some(OrdinalForms {
masculine: "сороковий",
feminine: "сорокова",
neuter: "сорокове",
}),
Some(OrdinalForms {
masculine: "п'ятдесятий",
feminine: "п'ятдесята",
neuter: "п'ятдесяте",
}),
Some(OrdinalForms {
masculine: "шістдесятий",
feminine: "шістдесята",
neuter: "шістдесяте",
}),
Some(OrdinalForms {
masculine: "сімдесятий",
feminine: "сімдесята",
neuter: "сімдесяте",
}),
Some(OrdinalForms {
masculine: "вісімдесятий",
feminine: "вісімдесята",
neuter: "вісімдесяте",
}),
Some(OrdinalForms {
masculine: "дев'яностий",
feminine: "дев'яноста",
neuter: "дев'яносте",
}),
];
const ORDINAL_HUNDREDS: [Option<OrdinalForms>; 10] = [
None,
Some(OrdinalForms {
masculine: "сотий",
feminine: "сота",
neuter: "соте",
}),
Some(OrdinalForms {
masculine: "двохсотий",
feminine: "двохсота",
neuter: "двохсоте",
}),
Some(OrdinalForms {
masculine: "трьохсотий",
feminine: "трьохсота",
neuter: "трьохсоте",
}),
Some(OrdinalForms {
masculine: "чотирьохсотий",
feminine: "чотирьохсота",
neuter: "чотирьохсоте",
}),
Some(OrdinalForms {
masculine: "п'ятисотий",
feminine: "п'ятисота",
neuter: "п'ятисоте",
}),
Some(OrdinalForms {
masculine: "шістсотий",
feminine: "шістсота",
neuter: "шістсоте",
}),
Some(OrdinalForms {
masculine: "сімсотий",
feminine: "сімсота",
neuter: "сімсоте",
}),
Some(OrdinalForms {
masculine: "вісімсотий",
feminine: "вісімсота",
neuter: "вісімсоте",
}),
Some(OrdinalForms {
masculine: "дев'ятсотий",
feminine: "дев'ятсота",
neuter: "дев'ятсоте",
}),
];
pub fn to_ordinal_words(number: u64, gender: OrdinalGender) -> String {
assert!(
number <= 999,
"Ordinal conversion currently supports numbers up to 999"
);
ordinal_under_thousand(number as u16, gender)
}
fn ordinal_under_thousand(number: u16, gender: OrdinalGender) -> String {
if number < 20 {
return ORDINAL_UNDER_TWENTY[number as usize]
.get(gender)
.to_string();
}
if number < 100 {
let tens = number / 10;
let units = number % 10;
if units == 0 {
if let Some(forms) = &ORDINAL_TENS[tens as usize] {
return forms.get(gender).to_string();
}
}
let mut parts: Vec<&str> = Vec::new();
if tens > 0 {
let tens_word = TENS[tens as usize];
if !tens_word.is_empty() {
parts.push(tens_word);
}
}
if units > 0 {
parts.push(ORDINAL_UNDER_TWENTY[units as usize].get(gender));
}
return parts.join(" ");
}
let hundreds = number / 100;
let remainder = number % 100;
if remainder == 0 {
if let Some(forms) = &ORDINAL_HUNDREDS[hundreds as usize] {
return forms.get(gender).to_string();
}
}
let mut parts: Vec<&str> = Vec::new();
if hundreds > 0 {
let hundreds_word = HUNDREDS[hundreds as usize];
if !hundreds_word.is_empty() {
parts.push(hundreds_word);
}
}
if remainder < 20 {
parts.push(ORDINAL_UNDER_TWENTY[remainder as usize].get(gender));
} else {
let tens = remainder / 10;
let units = remainder % 10;
if units == 0 {
if let Some(forms) = &ORDINAL_TENS[tens as usize] {
parts.push(forms.get(gender));
}
} else {
if tens > 0 {
let tens_word = TENS[tens as usize];
if !tens_word.is_empty() {
parts.push(tens_word);
}
}
parts.push(ORDINAL_UNDER_TWENTY[units as usize].get(gender));
}
}
parts.join(" ")
}