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/maltese/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded maltese/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Maltese 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(), "Maltese base rules should not be empty");
assert!(
rules.len() >= 5,
"expected >=5 base rules, got {}",
rules.len()
);
}
#[test]
fn test_gh_digraph() {
let rules = base();
let result = rules.apply("għ");
assert!(
result.is_empty() || !result.contains("ɣ"),
"għ should become silent (empty), got: '{}'",
result
);
}
#[test]
fn test_ie_digraph() {
let rules = base();
let result = rules.apply("ie");
assert!(result.contains('i'), "ie should become i, got: {}", result);
}
#[test]
fn test_c_dot() {
let rules = base();
let result = rules.apply("ċ");
assert!(result.contains("t͡ʃ"), "ċ should become ch, got: {}", result);
}
#[test]
fn test_g_dot() {
let rules = base();
let result = rules.apply("ġ");
assert!(result.contains("d͡ʒ"), "ġ should become d͡ʒ, got: {}", result);
}
#[test]
fn test_h_stroke() {
let rules = base();
let result = rules.apply("ħ");
assert!(
result.contains('h') || result.contains('ħ'),
"ħ should become h or pass through as ħ, got: {}",
result
);
}
#[test]
fn test_z_dot() {
let rules = base();
let result = rules.apply("ż");
assert!(result.contains('z'), "ż should become z, got: {}", result);
}
#[test]
fn test_x_sh() {
let rules = base();
let result = rules.apply("x");
assert!(result.contains("ʃ"), "x should become sh, got: {}", result);
}
#[test]
fn test_q_silent() {
let rules = base();
let result = rules.apply("q");
assert!(
result.is_empty() || !result.contains('q'),
"q should become silent (empty), got: '{}'",
result
);
}
#[test]
fn test_word_malta() {
let rules = base();
let result = rules.apply_full("Malta");
let lower = result.to_lowercase();
assert!(
lower.contains('m')
&& lower.contains('a')
&& lower.contains('l')
&& lower.contains('t'),
"Malta should contain m, a, l, t, got: {}",
result
);
}
#[test]
fn test_word_malti() {
let rules = base();
let result = rules.apply_full("Malti");
let lower = result.to_lowercase();
assert!(
lower.contains('m')
&& lower.contains('l')
&& lower.contains('t')
&& lower.contains('i'),
"Malti should contain m, l, t, i, got: {}",
result
);
}
#[test]
fn test_word_ghawdex() {
let rules = base();
let result = rules.apply_full("Għawdex");
let lower = result.to_lowercase();
assert!(
lower.contains('a')
&& lower.contains('w')
&& lower.contains('d')
&& lower.contains("ʃ"),
"Għawdex should have silent għ and x → sh, got: {}",
result
);
}
#[test]
fn test_word_valletta() {
let rules = base();
let result = rules.apply_full("Valletta");
let lower = result.to_lowercase();
assert!(
lower.contains('v')
&& lower.contains('a')
&& lower.contains('l')
&& lower.contains('e')
&& lower.contains('t'),
"Valletta should contain v, a, l, e, t, got: {}",
result
);
}
#[test]
fn test_word_with_c_dot() {
let rules = base();
let result = rules.apply_full("ċkejken");
let lower = result.to_lowercase();
assert!(
lower.contains("t͡ʃ"),
"Word with ċ should have ch, got: {}",
result
);
}
}