use std::fmt::Debug;
use std::sync::Arc;
pub mod arabic;
pub mod armenian;
pub mod bengali;
pub mod cyrillic;
pub mod devanagari;
pub mod georgian;
pub mod greek;
pub mod gujarati;
pub mod gurmukhi;
pub mod hangul;
pub mod hanzi;
pub mod hebrew;
pub mod latin;
pub mod tamil;
pub mod telugu;
pub mod thai;
pub use arabic::ArabicClassifier;
pub use armenian::ArmenianClassifier;
pub use bengali::BengaliClassifier;
pub use cyrillic::CyrillicClassifier;
pub use devanagari::DevanagariClassifier;
pub use georgian::GeorgianClassifier;
pub use greek::GreekClassifier;
pub use gujarati::GujaratiClassifier;
pub use gurmukhi::GurmukhiClassifier;
pub use hangul::HangulClassifier;
pub use hanzi::HanziClassifier;
pub use hebrew::HebrewClassifier;
pub use latin::LatinClassifier;
pub use tamil::TamilClassifier;
pub use telugu::TeluguClassifier;
pub use thai::ThaiClassifier;
pub trait VowelClassifier: Debug + Send + Sync {
fn is_vowel(&self, c: char) -> bool;
fn script_name(&self) -> &'static str;
fn normalize(&self, input: &str) -> String {
input.to_string()
}
fn is_consonant(&self, c: char) -> bool {
!self.is_vowel(c) && c.is_alphabetic()
}
fn vowels(&self) -> &[char] {
&[]
}
}
#[derive(Clone)]
pub struct DynClassifier(Arc<dyn VowelClassifier>);
impl DynClassifier {
pub fn new<C: VowelClassifier + 'static>(classifier: C) -> Self {
Self(Arc::new(classifier))
}
pub fn latin() -> Self {
Self::new(LatinClassifier::default())
}
pub fn cyrillic() -> Self {
Self::new(CyrillicClassifier::default())
}
pub fn hangul() -> Self {
Self::new(HangulClassifier::default())
}
pub fn hebrew() -> Self {
Self::new(HebrewClassifier::default())
}
pub fn arabic() -> Self {
Self::new(ArabicClassifier::default())
}
pub fn devanagari() -> Self {
Self::new(DevanagariClassifier::default())
}
pub fn hanzi() -> Self {
Self::new(HanziClassifier::default())
}
pub fn greek() -> Self {
Self::new(GreekClassifier::default())
}
pub fn bengali() -> Self {
Self::new(BengaliClassifier::default())
}
pub fn gujarati() -> Self {
Self::new(GujaratiClassifier::default())
}
pub fn telugu() -> Self {
Self::new(TeluguClassifier::default())
}
pub fn tamil() -> Self {
Self::new(TamilClassifier::default())
}
pub fn gurmukhi() -> Self {
Self::new(GurmukhiClassifier::default())
}
pub fn thai() -> Self {
Self::new(ThaiClassifier::default())
}
pub fn georgian() -> Self {
Self::new(GeorgianClassifier::default())
}
pub fn armenian() -> Self {
Self::new(ArmenianClassifier::default())
}
}
impl VowelClassifier for DynClassifier {
fn is_vowel(&self, c: char) -> bool {
self.0.is_vowel(c)
}
fn script_name(&self) -> &'static str {
self.0.script_name()
}
fn normalize(&self, input: &str) -> String {
self.0.normalize(input)
}
fn is_consonant(&self, c: char) -> bool {
self.0.is_consonant(c)
}
fn vowels(&self) -> &[char] {
self.0.vowels()
}
}
impl Debug for DynClassifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "DynClassifier({})", self.script_name())
}
}
impl Default for DynClassifier {
fn default() -> Self {
Self::latin()
}
}
pub fn classifier_for_language(lang: &str) -> DynClassifier {
let lang_lower = lang.to_lowercase();
match lang_lower.as_str() {
"en" | "english" | "de" | "german" | "fr" | "french" | "es" | "spanish" | "pt"
| "portuguese" | "it" | "italian" | "nl" | "dutch" | "pl" | "polish" | "tr" | "turkish"
| "tl" | "tagalog" | "filipino" | "ja-latn" | "romaji" | "zh-latn" | "pinyin" => {
DynClassifier::latin()
}
"ru" | "russian" | "uk" | "ukrainian" | "bg" | "bulgarian" | "be" | "belarusian" | "sr"
| "serbian" => DynClassifier::cyrillic(),
"el" | "greek" => DynClassifier::greek(),
"ko" | "korean" => DynClassifier::hangul(),
"he" | "hebrew" | "iw" => DynClassifier::hebrew(),
"ar" | "arabic" | "ur" | "urdu" | "fa" | "persian" | "farsi" => DynClassifier::arabic(),
"hi" | "hindi" | "sa" | "sanskrit" | "mr" | "marathi" | "ne" | "nepali" => {
DynClassifier::devanagari()
}
"bn" | "bengali" | "as" | "assamese" => DynClassifier::bengali(),
"gu" | "gujarati" => DynClassifier::gujarati(),
"te" | "telugu" => DynClassifier::telugu(),
"ta" | "tamil" => DynClassifier::tamil(),
"pa" | "punjabi" => DynClassifier::gurmukhi(),
"pa-arab" | "punjabi-shahmukhi" => DynClassifier::arabic(),
"th" | "thai" => DynClassifier::thai(),
"ka" | "georgian" => DynClassifier::georgian(),
"hy" | "armenian" => DynClassifier::armenian(),
"zh" | "chinese" | "hanzi" => DynClassifier::hanzi(),
_ => DynClassifier::latin(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_latin_classifier_basic() {
let classifier = LatinClassifier::default();
assert!(classifier.is_vowel('a'));
assert!(classifier.is_vowel('e'));
assert!(classifier.is_vowel('i'));
assert!(classifier.is_vowel('o'));
assert!(classifier.is_vowel('u'));
assert!(classifier.is_vowel('A'));
assert!(!classifier.is_vowel('b'));
assert!(!classifier.is_vowel('z'));
}
#[test]
fn test_dyn_classifier_dispatch() {
let latin = DynClassifier::latin();
assert!(latin.is_vowel('a'));
assert_eq!(latin.script_name(), "Latin");
let cyrillic = DynClassifier::cyrillic();
assert!(cyrillic.is_vowel('а')); assert_eq!(cyrillic.script_name(), "Cyrillic");
}
#[test]
fn test_classifier_for_language() {
assert_eq!(classifier_for_language("en").script_name(), "Latin");
assert_eq!(classifier_for_language("ru").script_name(), "Cyrillic");
assert_eq!(classifier_for_language("ko").script_name(), "Hangul");
assert_eq!(classifier_for_language("he").script_name(), "Hebrew");
assert_eq!(classifier_for_language("ar").script_name(), "Arabic");
assert_eq!(classifier_for_language("hi").script_name(), "Devanagari");
assert_eq!(classifier_for_language("zh").script_name(), "Hanzi");
assert_eq!(classifier_for_language("el").script_name(), "Greek");
assert_eq!(classifier_for_language("bn").script_name(), "Bengali");
assert_eq!(classifier_for_language("gu").script_name(), "Gujarati");
assert_eq!(classifier_for_language("te").script_name(), "Telugu");
assert_eq!(classifier_for_language("ta").script_name(), "Tamil");
assert_eq!(classifier_for_language("pa").script_name(), "Gurmukhi");
assert_eq!(classifier_for_language("pa-arab").script_name(), "Arabic");
assert_eq!(classifier_for_language("th").script_name(), "Thai");
assert_eq!(classifier_for_language("ka").script_name(), "Georgian");
assert_eq!(classifier_for_language("hy").script_name(), "Armenian");
}
#[test]
fn test_default_classifier_is_latin() {
let default = DynClassifier::default();
assert_eq!(default.script_name(), "Latin");
}
}