use super::insert_unique;
use std::collections::HashMap;
use std::sync::OnceLock;
pub type ConsonantRule = (&'static str, &'static str);
pub struct ConsonantSystem {
pub velars: &'static [ConsonantRule],
pub palatals: &'static [ConsonantRule],
pub retroflexes: &'static [ConsonantRule],
pub dentals: &'static [ConsonantRule],
pub labials: &'static [ConsonantRule],
pub semivowels: &'static [ConsonantRule],
pub fricatives: &'static [ConsonantRule],
pub special: &'static [ConsonantRule],
}
const VELARS: &[ConsonantRule] = &[
("k", "ক"), ("kh", "খ"), ("Kh", "খ"), ("KH", "খ"), ("g", "গ"), ("gh", "ঘ"), ("Gh", "ঘ"), ("GH", "ঘ"), ("Ng", "ঙ"), ];
const PALATALS: &[ConsonantRule] = &[
("c", "চ"), ("ch", "ছ"), ("chh", "ছ"), ("C", "ছ"), ("Ch", "ছ"), ("CH", "ছ"), ("Chh", "ছ"), ("CHH", "ছ"), ("J", "জ"), ("j", "জ"), ("jh", "ঝ"), ("Jh", "ঝ"), ("JH", "ঝ"), ("NG", "ঞ"), ];
const RETROFLEXES: &[ConsonantRule] = &[
("T", "ট"), ("Th", "ঠ"), ("TH", "ঠ"), ("D", "ড"), ("Dh", "ঢ"), ("DH", "ঢ"), ("N", "ণ"), ];
const DENTALS: &[ConsonantRule] = &[
("t", "ত"), ("th", "থ"), ("d", "দ"), ("dh", "ধ"), ("n", "ন"), ];
const LABIALS: &[ConsonantRule] = &[
("p", "প"), ("ph", "ফ"), ("Ph", "ফ"), ("PH", "ফ"), ("f", "ফ"), ("b", "ব"), ("bh", "ভ"), ("Bh", "ভ"), ("BH", "ভ"), ("v", "ভ"), ("m", "ম"), ];
const SEMIVOWELS: &[ConsonantRule] = &[
("z", "য"), ("r", "র"), ("l", "ল"), ];
const FRICATIVES: &[ConsonantRule] = &[
("sh", "শ"), ("S", "শ"), ("Sh", "ষ"), ("SH", "ষ"), ("s", "স"), ("h", "হ"), ];
const SPECIAL: &[ConsonantRule] = &[
("R", "ড়"), ("Rh", "ঢ়"), ("y", "য়"), ("Y", "য়"), ];
const CONSONANT_CATEGORIES: [&[ConsonantRule]; 8] = [
VELARS,
PALATALS,
RETROFLEXES,
DENTALS,
LABIALS,
SEMIVOWELS,
FRICATIVES,
SPECIAL,
];
const CONSONANT_RULE_COUNT: usize = VELARS.len()
+ PALATALS.len()
+ RETROFLEXES.len()
+ DENTALS.len()
+ LABIALS.len()
+ SEMIVOWELS.len()
+ FRICATIVES.len()
+ SPECIAL.len();
pub const fn consonant_system() -> ConsonantSystem {
ConsonantSystem {
velars: VELARS,
palatals: PALATALS,
retroflexes: RETROFLEXES,
dentals: DENTALS,
labials: LABIALS,
semivowels: SEMIVOWELS,
fricatives: FRICATIVES,
special: SPECIAL,
}
}
pub const fn consonant_categories() -> [&'static [ConsonantRule]; 8] {
CONSONANT_CATEGORIES
}
pub fn consonant_value(roman: &str) -> Option<&'static str> {
match roman {
"k" => Some("ক"),
"kh" | "Kh" | "KH" => Some("খ"),
"g" => Some("গ"),
"gh" | "Gh" | "GH" => Some("ঘ"),
"Ng" => Some("ঙ"),
"c" => Some("চ"),
"ch" | "chh" | "C" | "Ch" | "CH" | "Chh" | "CHH" => Some("ছ"),
"J" | "j" => Some("জ"),
"jh" | "Jh" | "JH" => Some("ঝ"),
"NG" => Some("ঞ"),
"T" => Some("ট"),
"Th" | "TH" => Some("ঠ"),
"D" => Some("ড"),
"Dh" | "DH" => Some("ঢ"),
"N" => Some("ণ"),
"t" => Some("ত"),
"th" => Some("থ"),
"d" => Some("দ"),
"dh" => Some("ধ"),
"n" => Some("ন"),
"p" => Some("প"),
"ph" | "Ph" | "PH" | "f" => Some("ফ"),
"b" => Some("ব"),
"bh" | "Bh" | "BH" | "v" => Some("ভ"),
"m" => Some("ম"),
"z" => Some("য"),
"r" => Some("র"),
"l" => Some("ল"),
"sh" | "S" => Some("শ"),
"Sh" | "SH" => Some("ষ"),
"s" => Some("স"),
"h" => Some("হ"),
"R" => Some("ড়"),
"Rh" => Some("ঢ়"),
"y" | "Y" => Some("য়"),
_ => None,
}
}
pub fn is_consonant(roman: &str) -> bool {
consonant_value(roman).is_some()
}
fn build_consonants() -> HashMap<&'static str, &'static str> {
let mut map = HashMap::with_capacity(CONSONANT_RULE_COUNT);
for category in CONSONANT_CATEGORIES {
for &(roman, bengali) in category {
insert_unique(&mut map, "consonant", roman, bengali);
}
}
map
}
pub fn consonants_static() -> &'static HashMap<&'static str, &'static str> {
static INSTANCE: OnceLock<HashMap<&'static str, &'static str>> = OnceLock::new();
INSTANCE.get_or_init(build_consonants)
}
pub fn consonants() -> HashMap<&'static str, &'static str> {
consonants_static().clone()
}