use crate::definitions::consonant_value;
pub(super) fn canonical_conjunct_part(part: &str) -> &str {
match part {
"chh" | "C" | "Ch" | "CH" | "Chh" | "CHH" => "ch",
"Kh" | "KH" => "kh",
"Gh" | "GH" => "gh",
"J" => "j",
"Jh" | "JH" => "jh",
"TH" => "Th",
"DH" => "Dh",
"Ph" | "PH" | "f" => "ph",
"Bh" | "BH" | "v" => "bh",
"Y" => "y",
"S" => "sh",
"SH" => "Sh",
_ => part,
}
}
pub(super) fn is_ya_phola_marker(part: &str) -> bool {
matches!(part, "y" | "Y")
}
pub(super) fn ya_phola_attaches_to(base_last: &str) -> bool {
let canonical = canonical_conjunct_part(base_last);
consonant_value(canonical).is_some()
&& !is_ya_phola_refusing(canonical)
&& !is_phola_marker_component(base_last)
}
fn is_ya_phola_refusing(canonical: &str) -> bool {
matches!(canonical, "r" | "R" | "Rh" | "Ng")
}
fn is_phola_marker_component(part: &str) -> bool {
matches!(canonical_conjunct_part(part), "y" | "w")
}
pub(super) fn is_special_form_key(form: &str) -> bool {
matches!(form, "rr" | "y" | "Y" | "w")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn canonical_conjunct_parts_are_declared_aliases_only() {
let cases = [
("chh", "ch"),
("CHH", "ch"),
("KH", "kh"),
("J", "j"),
("PH", "ph"),
("v", "bh"),
("Y", "y"),
("S", "sh"),
("SH", "Sh"),
("q", "q"),
];
for (input, expected) in cases {
assert_eq!(canonical_conjunct_part(input), expected);
}
}
#[test]
fn special_conjunct_forms_are_narrow() {
for form in ["rr", "y", "Y", "w"] {
assert!(is_special_form_key(form));
}
for form in ["z", "b", "Z", "ph"] {
assert!(!is_special_form_key(form));
}
}
#[test]
fn ya_phola_attaches_to_real_consonants_except_the_refusing_set() {
for base_last in ["kh", "Ch", "JH", "TH", "f", "v", "p", "l", "sh", "z", "s"] {
assert!(ya_phola_attaches_to(base_last), "{base_last:?} should take ya-phola");
}
for base_last in ["r", "R", "Rh", "Ng", "y", "Y", "w", "q"] {
assert!(!ya_phola_attaches_to(base_last), "{base_last:?} must refuse ya-phola");
}
}
}