use crate::phonetic::llev::RuleSetChar;
use std::sync::OnceLock;
pub fn base() -> &'static RuleSetChar {
static RULESET: OnceLock<RuleSetChar> = OnceLock::new();
RULESET.get_or_init(|| {
let content = include_str!("../../../data/rules/tamil/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded tamil/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Tamil base rules - this is a bug in liblevenshtein")
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_loads() {
let rules = base();
assert!(!rules.is_empty(), "Tamil base rules should not be empty");
assert!(
rules.len() >= 55,
"expected >=55 base rules, got {}",
rules.len()
);
}
#[test]
fn test_retroflex_approximant() {
let rules = base();
let result = rules.apply("ழ");
assert!(
result.contains("ɻ") || result.contains("ʒ"),
"ழ should become ɻ (retroflex approximant), got: {}",
result
);
}
#[test]
fn test_alveolar_trill() {
let rules = base();
let result = rules.apply("ற");
assert!(result.contains("r"), "ற should become RR, got: {}", result);
}
#[test]
fn test_alveolar_nasal() {
let rules = base();
let result = rules.apply("ன");
assert!(
result.contains("n̺") || result.contains("nn") || result.contains('n'),
"ன should become n̺ (alveolar nasal), got: {}",
result
);
}
#[test]
fn test_retroflex_lateral() {
let rules = base();
let result = rules.apply("ள");
assert!(
result.contains("ɭ") || result.contains("ʎ"),
"ள should become ɭ (retroflex lateral), got: {}",
result
);
}
#[test]
fn test_independent_vowels() {
let rules = base();
let result = rules.apply("அ");
assert!(result.contains('a'), "அ should become a, got: {}", result);
let result = rules.apply("ஆ");
assert!(result.contains("aː"), "ஆ should become A, got: {}", result);
let result = rules.apply("இ");
assert!(result.contains('i'), "இ should become i, got: {}", result);
}
#[test]
fn test_short_long_vowels() {
let rules = base();
let result = rules.apply("எ");
assert!(result.contains('e'), "எ should become e, got: {}", result);
let result = rules.apply("ஏ");
assert!(
result.contains("eː") || result.contains('E'),
"ஏ should become eː (long e), got: {}",
result
);
let result = rules.apply("ஒ");
assert!(
result.contains('o') || result.contains('ɔ'),
"ஒ should become o, got: {}",
result
);
let result = rules.apply("ஓ");
assert!(
result.contains("oː") || result.contains('O'),
"ஓ should become oː (long o), got: {}",
result
);
}
#[test]
fn test_diphthongs() {
let rules = base();
let result = rules.apply("ஐ");
assert!(result.contains("aɪ"), "ஐ should become AI, got: {}", result);
let result = rules.apply("ஔ");
assert!(result.contains("aʊ"), "ஔ should become AU, got: {}", result);
}
#[test]
fn test_vallinam_consonants() {
let rules = base();
let result = rules.apply("க");
assert!(result.contains('k'), "க should become k, got: {}", result);
let result = rules.apply("ச");
assert!(result.contains('c'), "ச should become c, got: {}", result);
let result = rules.apply("ட");
assert!(result.contains("ʈ"), "ட should become TT, got: {}", result);
let result = rules.apply("த");
assert!(result.contains('t'), "த should become t, got: {}", result);
let result = rules.apply("ப");
assert!(result.contains('p'), "ப should become p, got: {}", result);
}
#[test]
fn test_mellinam_consonants() {
let rules = base();
let result = rules.apply("ங");
assert!(result.contains('ŋ'), "ங should become N, got: {}", result);
let result = rules.apply("ஞ");
assert!(result.contains("ɲ"), "ஞ should become NY, got: {}", result);
let result = rules.apply("ண");
assert!(result.contains("ɳ"), "ண should become NN, got: {}", result);
}
#[test]
fn test_grantha_consonants() {
let rules = base();
let result = rules.apply("ஜ");
assert!(
result.contains('j') || result.contains('ʝ'),
"ஜ should become j, got: {}",
result
);
let result = rules.apply("ஶ");
assert!(
result.contains("ʃ"),
"ஶ should become ʃ (SH), got: {}",
result
);
let result = rules.apply("ஸ");
assert!(result.contains('s'), "ஸ should become s, got: {}", result);
let result = rules.apply("ஹ");
assert!(result.contains('h'), "ஹ should become h, got: {}", result);
}
#[test]
fn test_vowel_matras() {
let rules = base();
let result = rules.apply("ா");
assert!(result.contains("aː"), "ா should become A, got: {}", result);
let result = rules.apply("ி");
assert!(result.contains('i'), "ி should become i, got: {}", result);
let result = rules.apply("ை");
assert!(result.contains("aɪ"), "ை should become AI, got: {}", result);
}
#[test]
fn test_word_tamil() {
let rules = base();
let result = rules.apply_full("தமிழ்");
assert!(
result.contains('t') && result.contains('m'),
"தமிழ் should contain t, m, got: {}",
result
);
assert!(
result.contains("ɻ") || result.contains("ʒ"),
"தமிழ் should contain ɻ (retroflex approximant), got: {}",
result
);
}
#[test]
fn test_word_chennai() {
let rules = base();
let result = rules.apply_full("சென்னை");
assert!(
result.contains('c') && result.contains('e'),
"சென்னை should contain c, e, got: {}",
result
);
}
#[test]
fn test_word_madurai() {
let rules = base();
let result = rules.apply_full("மதுரை");
assert!(
result.contains('m') && result.contains('t') && result.contains('r'),
"மதுரை should contain m, t, r, got: {}",
result
);
}
#[test]
fn test_numerals() {
let rules = base();
let result = rules.apply("௦");
assert!(result.contains('0'), "௦ should become 0, got: {}", result);
let result = rules.apply("௫");
assert!(result.contains('5'), "௫ should become 5, got: {}", result);
let result = rules.apply("௯");
assert!(result.contains('9'), "௯ should become 9, got: {}", result);
}
}