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/greek/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded greek/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Greek 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(), "Greek base rules should not be empty");
assert!(
rules.len() >= 80,
"expected >=80 base rules, got {}",
rules.len()
);
}
#[test]
fn test_digraph_au() {
let rules = base();
let result = rules.apply("αυ");
assert!(
result.contains("av"),
"αυ should become av, got: {}",
result
);
}
#[test]
fn test_digraph_eu() {
let rules = base();
let result = rules.apply("ευ");
assert!(
result.contains("ev"),
"ευ should become ev, got: {}",
result
);
}
#[test]
fn test_digraph_ou() {
let rules = base();
let result = rules.apply("ου");
assert!(result.contains('u'), "ου should become u, got: {}", result);
}
#[test]
fn test_digraph_ai() {
let rules = base();
let result = rules.apply("αι");
assert!(result.contains('e'), "αι should become e, got: {}", result);
}
#[test]
fn test_digraph_ei() {
let rules = base();
let result = rules.apply("ει");
assert!(result.contains('i'), "ει should become i, got: {}", result);
}
#[test]
fn test_digraph_oi() {
let rules = base();
let result = rules.apply("οι");
assert!(result.contains('i'), "οι should become i, got: {}", result);
}
#[test]
fn test_combo_mp() {
let rules = base();
let result = rules.apply("μπ");
assert!(result.contains('b'), "μπ should become b, got: {}", result);
}
#[test]
fn test_combo_nt() {
let rules = base();
let result = rules.apply("ντ");
assert!(result.contains('d'), "ντ should become d, got: {}", result);
}
#[test]
fn test_combo_gk() {
let rules = base();
let result = rules.apply("γκ");
assert!(result.contains('ɡ'), "γκ should become g, got: {}", result);
}
#[test]
fn test_combo_gg() {
let rules = base();
let result = rules.apply("γγ");
assert!(result.contains("ŋ"), "γγ should become ng, got: {}", result);
}
#[test]
fn test_combo_ts() {
let rules = base();
let result = rules.apply("τσ");
assert!(
result.contains("t͡s"),
"τσ should become ts, got: {}",
result
);
}
#[test]
fn test_combo_tz() {
let rules = base();
let result = rules.apply("τζ");
assert!(
result.contains("d͡z") || result.contains("dz"),
"τζ should become d͡z, got: {}",
result
);
}
#[test]
fn test_vowel_alpha() {
let rules = base();
let result = rules.apply("α");
assert!(result.contains('a'), "α should become a, got: {}", result);
}
#[test]
fn test_vowel_epsilon() {
let rules = base();
let result = rules.apply("ε");
assert!(result.contains('e'), "ε should become e, got: {}", result);
}
#[test]
fn test_vowel_eta() {
let rules = base();
let result = rules.apply("η");
assert!(result.contains('i'), "η should become i, got: {}", result);
}
#[test]
fn test_vowel_iota() {
let rules = base();
let result = rules.apply("ι");
assert!(result.contains('i'), "ι should become i, got: {}", result);
}
#[test]
fn test_vowel_omicron() {
let rules = base();
let result = rules.apply("ο");
assert!(
result.contains('o') || result.contains('ɔ'),
"ο should become o, got: {}",
result
);
}
#[test]
fn test_vowel_upsilon() {
let rules = base();
let result = rules.apply("υ");
assert!(result.contains('i'), "υ should become i, got: {}", result);
}
#[test]
fn test_vowel_omega() {
let rules = base();
let result = rules.apply("ω");
assert!(
result.contains('o') || result.contains('ɔ'),
"ω should become o, got: {}",
result
);
}
#[test]
fn test_accented_alpha() {
let rules = base();
let result = rules.apply("ά");
assert!(result.contains('a'), "ά should become a, got: {}", result);
}
#[test]
fn test_accented_epsilon() {
let rules = base();
let result = rules.apply("έ");
assert!(result.contains('e'), "έ should become e, got: {}", result);
}
#[test]
fn test_diaeresis_iota() {
let rules = base();
let result = rules.apply("ϊ");
assert!(result.contains('i'), "ϊ should become i, got: {}", result);
}
#[test]
fn test_consonant_beta() {
let rules = base();
let result = rules.apply("β");
assert!(result.contains('v'), "β should become v, got: {}", result);
}
#[test]
fn test_consonant_gamma() {
let rules = base();
let result = rules.apply("γ");
assert!(result.contains('ɡ'), "γ should become g, got: {}", result);
}
#[test]
fn test_consonant_delta() {
let rules = base();
let result = rules.apply("δ");
assert!(
result.contains('ð') || result.contains("th"),
"δ should become ð, got: {}",
result
);
}
#[test]
fn test_consonant_theta() {
let rules = base();
let result = rules.apply("θ");
assert!(result.contains("θ"), "θ should become th, got: {}", result);
}
#[test]
fn test_consonant_xi() {
let rules = base();
let result = rules.apply("ξ");
assert!(result.contains('x'), "ξ should become x, got: {}", result);
}
#[test]
fn test_consonant_phi() {
let rules = base();
let result = rules.apply("φ");
assert!(result.contains('f'), "φ should become f, got: {}", result);
}
#[test]
fn test_consonant_chi() {
let rules = base();
let result = rules.apply("χ");
assert!(
result.contains('x') || result.contains("ch"),
"χ should become x, got: {}",
result
);
}
#[test]
fn test_consonant_psi() {
let rules = base();
let result = rules.apply("ψ");
assert!(result.contains("ps"), "ψ should become ps, got: {}", result);
}
#[test]
fn test_final_sigma() {
let rules = base();
let result = rules.apply("ς");
assert!(result.contains('s'), "ς should become s, got: {}", result);
}
#[test]
fn test_word_ellada() {
let rules = base();
let result = rules.apply_full("Ελλάδα");
let lower = result.to_lowercase();
assert!(
lower.contains('e')
&& lower.contains('l')
&& (lower.contains('ð') || lower.contains("th"))
&& lower.contains('a'),
"Ελλάδα should contain e, l, ð, a, got: {}",
result
);
}
#[test]
fn test_word_athina() {
let rules = base();
let result = rules.apply_full("Αθήνα");
let lower = result.to_lowercase();
assert!(
lower.contains('a')
&& lower.contains("θ")
&& lower.contains('i')
&& lower.contains('n'),
"Αθήνα should contain a, th, i, n, got: {}",
result
);
}
#[test]
fn test_word_olympos() {
let rules = base();
let result = rules.apply_full("Όλυμπος");
let lower = result.to_lowercase();
assert!(
(lower.contains('o') || lower.contains('ɔ'))
&& lower.contains('l')
&& lower.contains('i')
&& lower.contains('b'),
"Όλυμπος should normalize with μπ → b, got: {}",
result
);
}
}