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/hebrew/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded hebrew/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Hebrew 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(), "Hebrew base rules should not be empty");
assert!(
rules.len() > 35,
"expected >35 base rules, got {}",
rules.len()
);
}
#[test]
fn test_dagesh_consonants() {
let rules = base();
let result = rules.apply("בּ");
assert!(
result.contains('b') || result.contains('v'),
"בּ should become b or v, got: {}",
result
);
let result = rules.apply("כּ");
assert!(result.contains('k'), "כּ should become k, got: {}", result);
let result = rules.apply("פּ");
assert!(result.contains('p'), "פּ should become p, got: {}", result);
}
#[test]
fn test_shin_sin() {
let rules = base();
let result = rules.apply("שׁ");
assert!(result.contains("ʃ"), "שׁ should become sh, got: {}", result);
let result = rules.apply("שׂ");
assert!(
result.contains('s') && !result.contains("ʃ"),
"שׂ should become s (not sh), got: {}",
result
);
}
#[test]
fn test_basic_consonants() {
let rules = base();
let result = rules.apply("ב");
assert!(
result.contains('v') || result.contains('b'),
"ב should become v or b, got: {}",
result
);
let result = rules.apply("ג");
assert!(result.contains('ɡ'), "ג should become ɡ, got: {}", result);
let result = rules.apply("ד");
assert!(result.contains('d'), "ד should become d, got: {}", result);
let result = rules.apply("ה");
assert!(
result.contains('h') || result.contains('x'),
"ה should become h or x, got: {}",
result
);
let result = rules.apply("ל");
assert!(result.contains('l'), "ל should become l, got: {}", result);
let result = rules.apply("מ");
assert!(result.contains('m'), "מ should become m, got: {}", result);
let result = rules.apply("ר");
assert!(result.contains('r'), "ר should become r, got: {}", result);
}
#[test]
fn test_final_forms() {
let rules = base();
let result = rules.apply("ך");
assert!(result.contains("x"), "ך should become kh, got: {}", result);
let result = rules.apply("ם");
assert!(result.contains('m'), "ם should become m, got: {}", result);
let result = rules.apply("ן");
assert!(result.contains('n'), "ן should become n, got: {}", result);
let result = rules.apply("ף");
assert!(result.contains('f'), "ף should become f, got: {}", result);
let result = rules.apply("ץ");
assert!(result.contains("t͡s"), "ץ should become ts, got: {}", result);
}
#[test]
fn test_niqqud_vowels() {
let rules = base();
let result = rules.apply("ִ");
assert!(result.contains('i'), "ִ should become i, got: {}", result);
let result = rules.apply("ַ");
assert!(result.contains('a'), "ַ should become a, got: {}", result);
let result = rules.apply("ֹ");
assert!(result.contains('o'), "ֹ should become o, got: {}", result);
let result = rules.apply("ֻ");
assert!(result.contains('u'), "ֻ should become u, got: {}", result);
}
#[test]
fn test_gutturals() {
let rules = base();
let result = rules.apply("ח");
assert!(
result.contains('x'),
"ח should become x (velar fricative), got: {}",
result
);
let result = rules.apply("צ");
assert!(result.contains("t͡s"), "צ should become ts, got: {}", result);
}
#[test]
fn test_word_shalom() {
let rules = base();
let result = rules.apply("שלום");
assert!(
result.contains("ʃ") && result.contains('l') && result.contains('m'),
"שלום should become shalom-like, got: {}",
result
);
}
}