liblevenshtein 0.9.1

Levenshtein/Universal Automata for approximate string matching using various dictionary backends
Documentation
//! Gujarati script vowel classifier.
//!
//! Supports Gujarati (ગુજરાતી) and related languages.
//! Gujarati is an abugida derived from Devanagari but without the
//! characteristic headline (shirorekha).

use super::VowelClassifier;

/// Vowel classifier for Gujarati script.
///
/// Gujarati has two types of vowels:
/// - **Independent vowels (svara)**: Stand-alone vowel letters (અ, આ, ઇ, ઈ, etc.)
/// - **Dependent vowels (matra)**: Vowel signs attached to consonants (ા, િ, ી, etc.)
///
/// Like Devanagari, the inherent vowel is /a/. The virama (્) removes it.
#[derive(Debug, Clone, Copy, Default)]
pub struct GujaratiClassifier;

impl GujaratiClassifier {
    /// Create a new Gujarati classifier.
    pub fn new() -> Self {
        Self
    }
}

/// Gujarati vowels (independent and dependent).
static GUJARATI_VOWELS: &[char] = &[
    // Independent vowels (svara)
    '', // a (short)
    '', // aa (long)
    '', // i (short)
    '', // ii (long)
    '', // u (short)
    '', // uu (long)
    '', // ri (vocalic r)
    '', // e
    '', // ai
    '', // o
    '', // au
    // Dependent vowels (matra)
    '', // aa matra
    'િ', // i matra
    '', // ii matra
    '',  // u matra
    '',  // uu matra
    '',  // ri matra
    '',  // e matra
    '',  // ai matra
    '', // o matra
    '', // au matra
];

impl VowelClassifier for GujaratiClassifier {
    fn is_vowel(&self, c: char) -> bool {
        let code = c as u32;
        match code {
            // Independent vowels (Gujarati block)
            0x0A85..=0x0A94 => true, // અ through ઔ

            // Dependent vowel signs (matras)
            0x0ABE..=0x0ACC => true, // ા through ૌ

            // Vowel sign for vocalic r (long form)
            0x0AE0..=0x0AE3 => true, // ૠ, ૡ, ૢ, ૣ

            _ => false,
        }
    }

    fn script_name(&self) -> &'static str {
        "Gujarati"
    }

    fn vowels(&self) -> &[char] {
        GUJARATI_VOWELS
    }

    fn is_consonant(&self, c: char) -> bool {
        let code = c as u32;
        match code {
            // Consonants (ka through ha)
            0x0A95..=0x0AB9 => true,

            // Virama is neither vowel nor consonant
            0x0ACD => false,

            // Chandrabindu, anusvara, visarga are special marks
            0x0A81..=0x0A83 => false,

            _ => false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_independent_vowels() {
        let c = GujaratiClassifier::new();
        assert!(c.is_vowel('')); // a
        assert!(c.is_vowel('')); // aa
        assert!(c.is_vowel('')); // i
        assert!(c.is_vowel('')); // ii
        assert!(c.is_vowel('')); // u
        assert!(c.is_vowel('')); // uu
        assert!(c.is_vowel('')); // ri
        assert!(c.is_vowel('')); // e
        assert!(c.is_vowel('')); // ai
        assert!(c.is_vowel('')); // o
        assert!(c.is_vowel('')); // au
    }

    #[test]
    fn test_dependent_vowels() {
        let c = GujaratiClassifier::new();
        assert!(c.is_vowel('')); // aa matra
        assert!(c.is_vowel('િ')); // i matra
        assert!(c.is_vowel('')); // ii matra
        assert!(c.is_vowel('')); // u matra
        assert!(c.is_vowel('')); // uu matra
        assert!(c.is_vowel('')); // ri matra
        assert!(c.is_vowel('')); // e matra
        assert!(c.is_vowel('')); // ai matra
    }

    #[test]
    fn test_consonants() {
        let c = GujaratiClassifier::new();
        assert!(!c.is_vowel('')); // ka
        assert!(!c.is_vowel('')); // kha
        assert!(!c.is_vowel('')); // ga
        assert!(!c.is_vowel('')); // gha
        assert!(!c.is_vowel('')); // cha
        assert!(!c.is_vowel('')); // ja
        assert!(!c.is_vowel('')); // ta
        assert!(!c.is_vowel('')); // da
        assert!(!c.is_vowel('')); // na
        assert!(!c.is_vowel('')); // pa
        assert!(!c.is_vowel('')); // ma
        assert!(!c.is_vowel('')); // ha
    }

    #[test]
    fn test_is_consonant() {
        let c = GujaratiClassifier::new();
        assert!(c.is_consonant('')); // ka
        assert!(c.is_consonant('')); // ga
        assert!(c.is_consonant('')); // ta
        assert!(c.is_consonant('')); // na
        assert!(c.is_consonant('')); // ma
        assert!(c.is_consonant('')); // ha
    }

    #[test]
    fn test_virama_not_vowel() {
        let c = GujaratiClassifier::new();
        assert!(!c.is_vowel('')); // virama
        assert!(!c.is_consonant('')); // virama is neither
    }

    #[test]
    fn test_diacritics() {
        let c = GujaratiClassifier::new();
        // Chandrabindu, anusvara, visarga are not vowels or consonants
        assert!(!c.is_vowel('')); // chandrabindu
        assert!(!c.is_vowel('')); // anusvara
        assert!(!c.is_vowel('')); // visarga
        assert!(!c.is_consonant(''));
        assert!(!c.is_consonant(''));
        assert!(!c.is_consonant(''));
    }
}