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/tagalog/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded tagalog/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Tagalog 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(), "Tagalog base rules should not be empty");
assert!(
rules.len() >= 20,
"expected >=20 base rules, got {}",
rules.len()
);
}
#[test]
fn test_ng_digraph() {
let rules = base();
let result = rules.apply("ng");
assert!(result.contains("ŋ"), "ng should become NG, got: {}", result);
let result = rules.apply("ang");
assert!(
result.contains("ŋ"),
"ang should contain NG, got: {}",
result
);
}
#[test]
fn test_spanish_ll_adaptation() {
let rules = base();
let result = rules.apply("ll");
assert!(
result.contains("ʎ") || result.contains("ly"),
"ll should become ʎ or ly, got: {}",
result
);
}
#[test]
fn test_spanish_ene_adaptation() {
let rules = base();
let result = rules.apply("ñ");
assert!(result.contains("ɲ"), "ñ should become ny, got: {}", result);
}
#[test]
fn test_spanish_qu_adaptation() {
let rules = base();
let result = rules.apply("qu");
assert!(result.contains('k'), "qu should become k, got: {}", result);
}
#[test]
fn test_borrowed_f_to_p() {
let rules = base();
let result = rules.apply("familia");
assert!(
result.contains('p') && !result.contains('f'),
"familia should have p not f, got: {}",
result
);
}
#[test]
fn test_borrowed_v_to_b() {
let rules = base();
let result = rules.apply("vino");
assert!(
result.contains('b') && !result.contains('v'),
"vino should have b not v, got: {}",
result
);
}
#[test]
fn test_borrowed_z_to_s() {
let rules = base();
let result = rules.apply("zona");
assert!(
result.contains('s') && !result.contains('z'),
"zona should have s not z, got: {}",
result
);
}
#[test]
fn test_native_consonants() {
let rules = base();
let result = rules.apply("bahay");
assert!(
result.contains('b') && result.contains('h') && result.contains('y'),
"bahay should contain b, h, y, got: {}",
result
);
}
#[test]
fn test_vowels() {
let rules = base();
let result = rules.apply("aeiou");
assert!(
result.contains('a')
&& result.contains('e')
&& result.contains('i')
&& (result.contains('o') || result.contains('ɔ'))
&& result.contains('u'),
"aeiou should remain, got: {}",
result
);
}
#[test]
fn test_word_maganda() {
let rules = base();
let result = rules.apply("maganda");
assert!(
result.contains('m')
&& (result.contains('g') || result.contains('ɡ'))
&& result.contains('d'),
"maganda should contain m, g, d, got: {}",
result
);
}
#[test]
fn test_word_pangalan() {
let rules = base();
let result = rules.apply("pangalan");
assert!(
result.contains("ŋ"),
"pangalan should contain NG, got: {}",
result
);
}
}