verba 0.5.1

A library for working with Latin words.
Documentation
use smallvec::{smallvec, SmallVec};

use crate::decline::{Gender, Case};
use crate::inflection::{Number};

pub(super) type Suffixes<'a> = SmallVec::<[&'a str; 2]>;

/// Declines first declension regular nouns.
pub(super) fn first_endings<'a>(number: Number, case: Case, _gender: Gender) -> Option<Suffixes<'a>> {
    match (number, case) {
        (Number::Singular, Case::Nominative) => Some(smallvec!["a"]),
        (Number::Singular, Case::Genitive) => Some(smallvec!["ae"]),
        (Number::Singular, Case::Dative) => Some(smallvec!["ae"]),
        (Number::Singular, Case::Accusative) => Some(smallvec!["am"]),
        (Number::Singular, Case::Ablative) => Some(smallvec!["ā"]),
        (Number::Singular, Case::Vocative) => Some(smallvec!["a"]),
        (Number::Plural, Case::Nominative) => Some(smallvec!["ae"]),
        (Number::Plural, Case::Genitive) => Some(smallvec!["ārum"]),
        (Number::Plural, Case::Dative) => Some(smallvec!["īs"]),
        (Number::Plural, Case::Accusative) => Some(smallvec!["ās"]),
        (Number::Plural, Case::Ablative) => Some(smallvec!["īs"]),
        (Number::Plural, Case::Vocative) => Some(smallvec!["ae"]),
    }
}

pub(super) fn second_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
    match (gender, number, case) {
        (Gender::Neuter, Number::Singular, Case::Nominative) => Some(smallvec!["um"]),
        (Gender::Neuter, Number::Singular, Case::Genitive) => Some(smallvec!["ī"]),
        (Gender::Neuter, Number::Singular, Case::Dative) => Some(smallvec!["ō"]),
        (Gender::Neuter, Number::Singular, Case::Accusative) => Some(smallvec!["um"]),
        (Gender::Neuter, Number::Singular, Case::Ablative) => Some(smallvec!["ō"]),
        (Gender::Neuter, Number::Singular, Case::Vocative) => Some(smallvec!["um"]),
        (Gender::Neuter, Number::Plural, Case::Nominative) => Some(smallvec!["a"]),
        (Gender::Neuter, Number::Plural, Case::Genitive) => Some(smallvec!["ōrum"]),
        (Gender::Neuter, Number::Plural, Case::Dative) => Some(smallvec!["īs"]),
        (Gender::Neuter, Number::Plural, Case::Accusative) => Some(smallvec!["a"]),
        (Gender::Neuter, Number::Plural, Case::Ablative) => Some(smallvec!["īs"]),
        (Gender::Neuter, Number::Plural, Case::Vocative) => Some(smallvec!["a"]),
        // There are a few feminine second declension nouns, but since they 
        // decline in the same way as masculine second declension nouns, gender
        // can be ignored from here on out. 
        (_, Number::Singular, Case::Nominative) => Some(smallvec!["us"]),
        (_, Number::Singular, Case::Genitive) => Some(smallvec!["ī"]),
        (_, Number::Singular, Case::Dative) => Some(smallvec!["ō"]),
        (_, Number::Singular, Case::Accusative) => Some(smallvec!["um"]),
        (_, Number::Singular, Case::Ablative) => Some(smallvec!["ō"]),
        (_, Number::Singular, Case::Vocative) => Some(smallvec!["e"]),
        (_, Number::Plural, Case::Nominative) => Some(smallvec!["ī"]),
        (_, Number::Plural, Case::Genitive) => Some(smallvec!["ōrum"]),
        (_, Number::Plural, Case::Dative) => Some(smallvec!["īs"]),
        (_, Number::Plural, Case::Accusative) => Some(smallvec!["ōs"]),
        (_, Number::Plural, Case::Ablative) => Some(smallvec!["īs"]),
        (_, Number::Plural, Case::Vocative) => Some(smallvec!["ī"]),
    }
}

pub(super) fn second_ius_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
    match (gender, number, case) {
        (Gender::Neuter, Number::Singular, Case::Nominative) => Some(smallvec!["ium"]),
        (Gender::Neuter, Number::Singular, Case::Genitive) => Some(smallvec![""]),
        (Gender::Neuter, Number::Singular, Case::Dative) => Some(smallvec![""]),
        (Gender::Neuter, Number::Singular, Case::Accusative) => Some(smallvec!["ium"]),
        (Gender::Neuter, Number::Singular, Case::Ablative) => Some(smallvec![""]),
        (Gender::Neuter, Number::Singular, Case::Vocative) => Some(smallvec!["ium"]),
        (Gender::Neuter, Number::Plural, Case::Nominative) => Some(smallvec!["ia"]),
        (Gender::Neuter, Number::Plural, Case::Genitive) => Some(smallvec!["iōrum"]),
        (Gender::Neuter, Number::Plural, Case::Dative) => Some(smallvec!["iīs"]),
        (Gender::Neuter, Number::Plural, Case::Accusative) => Some(smallvec!["ia"]),
        (Gender::Neuter, Number::Plural, Case::Ablative) => Some(smallvec!["iīs"]),
        (Gender::Neuter, Number::Plural, Case::Vocative) => Some(smallvec!["ia"]),

        (_, Number::Singular, Case::Nominative) => Some(smallvec!["ius"]),
        (_, Number::Singular, Case::Genitive) => Some(smallvec![""]),
        (_, Number::Singular, Case::Dative) => Some(smallvec![""]),
        (_, Number::Singular, Case::Accusative) => Some(smallvec!["ium"]),
        (_, Number::Singular, Case::Ablative) => Some(smallvec![""]),
        (_, Number::Singular, Case::Vocative) => Some(smallvec!["ī"]),
        (_, Number::Plural, Case::Nominative) => Some(smallvec![""]),
        (_, Number::Plural, Case::Genitive) => Some(smallvec!["iōrum"]),
        (_, Number::Plural, Case::Dative) => Some(smallvec!["iīs"]),
        (_, Number::Plural, Case::Accusative) => Some(smallvec!["iōs"]),
        (_, Number::Plural, Case::Ablative) => Some(smallvec!["iīs"]),
        (_, Number::Plural, Case::Vocative) => Some(smallvec![""]),
    }
}

pub(super) fn second_r_endings<'a>(number: Number, case: Case, gender: Gender) ->Option<Suffixes<'a>> {
    match (gender, number, case) {
        // The nominative and vocative forms of second declension nouns ending
        // in -r cannot be constructed from the stem alone. For example, the 
        // stem of puer, puerī is puer- whereas the stem of ager, agrī is agr-.
        // Ager cannot be constructed with agr-. However, for every other case,
        // the declension is the same as any regular second declension noun. 
        // This function returns None of the two cases that cannot be
        // constructed. Otherwise it returns the proper second declension
        // ending. 
        (_, Number::Singular, Case::Nominative) => None,
        (_, Number::Singular, Case::Vocative) => None,
        // (_, Number::Plural, Case::Nominative) => None,
        _ => second_endings(number, case, gender),
    }
}

pub(super) fn third_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
        match (gender, number, case) {
        // The singular nominative form of third declension nouns cannot be 
        // created from the stem, therefore this function returns None and 
        // requires the calling function to override and provide a form. 
        (Gender::Neuter, Number::Singular, Case::Nominative) => None,
        (Gender::Neuter, Number::Singular, Case::Genitive) => Some(smallvec!["is"]),
        (Gender::Neuter, Number::Singular, Case::Dative) => Some(smallvec!["ī"]),
        (Gender::Neuter, Number::Singular, Case::Accusative) => None,
        (Gender::Neuter, Number::Singular, Case::Ablative) => Some(smallvec!["e"]),
        (Gender::Neuter, Number::Singular, Case::Vocative) => None,
        (Gender::Neuter, Number::Plural, Case::Nominative) => Some(smallvec!["a"]),
        (Gender::Neuter, Number::Plural, Case::Genitive) => Some(smallvec!["um"]),
        (Gender::Neuter, Number::Plural, Case::Dative) => Some(smallvec!["ibus"]),
        (Gender::Neuter, Number::Plural, Case::Accusative) => Some(smallvec!["a"]),
        (Gender::Neuter, Number::Plural, Case::Ablative) => Some(smallvec!["ibus"]),
        (Gender::Neuter, Number::Plural, Case::Vocative) => Some(smallvec!["a"]),
        // Masculine and feminine third declension nouns decline in the same 
        // way, so gender can be ignored from here on out. 
        (_, Number::Singular, Case::Nominative) => None,
        (_, Number::Singular, Case::Genitive) => Some(smallvec!["is"]),
        (_, Number::Singular, Case::Dative) => Some(smallvec!["ī"]),
        (_, Number::Singular, Case::Accusative) => Some(smallvec!["em"]),
        (_, Number::Singular, Case::Ablative) => Some(smallvec!["e"]),
        (_, Number::Singular, Case::Vocative) => None,
        (_, Number::Plural, Case::Nominative) => Some(smallvec!["ēs"]),
        (_, Number::Plural, Case::Genitive) => Some(smallvec!["um"]),
        (_, Number::Plural, Case::Dative) => Some(smallvec!["ibus"]),
        (_, Number::Plural, Case::Accusative) => Some(smallvec!["ēs"]),
        (_, Number::Plural, Case::Ablative) => Some(smallvec!["ibus"]),
        (_, Number::Plural, Case::Vocative) => Some(smallvec!["ēs"]),
    }
}

pub(super) fn third_i_stem_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
    match (gender, number, case) {
        (Gender::Neuter, Number::Singular, Case::Ablative) => Some(smallvec!["ī"]),
        (Gender::Neuter, Number::Plural, Case::Nominative) => Some(smallvec!["ia"]),
        (Gender::Neuter, Number::Plural, Case::Genitive) => Some(smallvec!["ium"]),
        (Gender::Neuter, Number::Plural, Case::Accusative) => Some(smallvec!["ia"]),
        (Gender::Neuter, Number::Plural, Case::Vocative) => Some(smallvec!["ia"]),
        (_, Number::Singular, Case::Accusative) => Some(smallvec!["em", "im"]),
        (_, Number::Plural, Case::Genitive) => Some(smallvec!["ium"]),
        (_, Number::Plural, Case::Accusative) => Some(smallvec!["ēs", "īs"]),
        _ => third_endings(number, case, gender),
    }
}

/// Most fourth declension nouns decline using this function. There is only a
/// handful of neuter nouns that will use [`fourth_u_endings`]. However, not 
/// every fourth declension neauter noun uses that function. Spectus, spectūs
/// is a fourth declension neuter noun that uses this function.
/// 
/// Ultimately, determining which of the two functions is used is as easy as 
/// checking the singular nominative form. If it ends in -us, use this
/// function. If it ends in -ū, use [`fourth_u_endings`].
pub(super) fn fourth_endings<'a>(number: Number, case: Case, _gender: Gender) -> Option<Suffixes<'a>> {
    match (number, case) {
        (Number::Singular, Case::Nominative) => Some(smallvec!["us"]),
        (Number::Singular, Case::Genitive) => Some(smallvec!["ūs"]),
        (Number::Singular, Case::Dative) => Some(smallvec![""]),
        (Number::Singular, Case::Accusative) => Some(smallvec!["um"]),
        (Number::Singular, Case::Ablative) => Some(smallvec!["ū"]),
        (Number::Singular, Case::Vocative) => Some(smallvec!["us"]),
        (Number::Plural, Case::Nominative) => Some(smallvec!["ūs"]),
        (Number::Plural, Case::Genitive) => Some(smallvec!["uum"]),
        (Number::Plural, Case::Dative) => Some(smallvec!["ibus"]),
        (Number::Plural, Case::Accusative) => Some(smallvec!["ūs"]),
        (Number::Plural, Case::Ablative) => Some(smallvec!["ibus"]),
        (Number::Plural, Case::Vocative) => Some(smallvec!["ūs"]),
    }
}

pub(super) fn fourth_u_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
    match (number, case) {
        (Number::Singular, Case::Nominative) => Some(smallvec!["ū"]),
        (Number::Singular, Case::Dative) => Some(smallvec!["ū"]),
        (Number::Singular, Case::Accusative) => Some(smallvec!["ū"]),
        (Number::Singular, Case::Vocative) => Some(smallvec!["ū"]),
        (Number::Plural, Case::Nominative) => Some(smallvec!["ua"]),
        (Number::Plural, Case::Accusative) => Some(smallvec!["ua"]),
        (Number::Plural, Case::Vocative) => Some(smallvec!["ua"]),
        _ => fourth_endings(number, case, gender),
    }
}

pub(super) fn fifth_endings<'a>(number: Number, case: Case, _gender: Gender) -> Option<Suffixes<'a>> {
    match (number, case) {
        (Number::Singular, Case::Nominative) => Some(smallvec!["ēs"]),
        (Number::Singular, Case::Genitive) => Some(smallvec![""]),
        (Number::Singular, Case::Dative) => Some(smallvec![""]),
        (Number::Singular, Case::Accusative) => Some(smallvec!["em"]),
        (Number::Singular, Case::Ablative) => Some(smallvec!["ē"]),
        (Number::Singular, Case::Vocative) => Some(smallvec!["ēs"]),
        (Number::Plural, Case::Nominative) => Some(smallvec!["ēs"]),
        (Number::Plural, Case::Genitive) => Some(smallvec!["ērum"]),
        (Number::Plural, Case::Dative) => Some(smallvec!["ēbus"]),
        (Number::Plural, Case::Accusative) => Some(smallvec!["ēs"]),
        (Number::Plural, Case::Ablative) => Some(smallvec!["ēbus"]),
        (Number::Plural, Case::Vocative) => Some(smallvec!["ēs"]),
    }
}

pub(super) fn fifth_vowel_stem_endings<'a>(number: Number, case: Case, gender: Gender) -> Option<Suffixes<'a>> {
    match (number, case) {
        (Number::Singular, Case::Genitive) => Some(smallvec!["ēī"]),
        (Number::Singular, Case::Dative) => Some(smallvec!["ēī"]),
        _ => fifth_endings(number, case, gender),
    }
}