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/georgian/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded georgian/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Georgian 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(), "Georgian base rules should not be empty");
assert!(
rules.len() >= 40,
"expected >=40 base rules, got {}",
rules.len()
);
}
#[test]
fn test_vowels() {
let rules = base();
let result = rules.apply("ა");
assert!(result.contains('a'), "ა should become a, got: {}", result);
let result = rules.apply("ე");
assert!(result.contains('e'), "ე should become e, got: {}", result);
let result = rules.apply("ი");
assert!(result.contains('i'), "ი should become i, 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_voiced_stops() {
let rules = base();
let result = rules.apply("ბ");
assert!(result.contains('b'), "ბ should become b, got: {}", result);
let result = rules.apply("გ");
assert!(result.contains('ɡ'), "გ should become g, got: {}", result);
let result = rules.apply("დ");
assert!(result.contains('d'), "დ should become d, got: {}", result);
}
#[test]
fn test_aspirated_stops() {
let rules = base();
let result = rules.apply("თ");
assert!(
result.contains('t'),
"თ should become t (aspirated T simplified), got: {}",
result
);
let result = rules.apply("ფ");
assert!(
result.contains('p'),
"ფ should become p (aspirated P simplified), got: {}",
result
);
let result = rules.apply("ქ");
assert!(
result.contains('k'),
"ქ should become k (aspirated K simplified), got: {}",
result
);
}
#[test]
fn test_ejective_stops() {
let rules = base();
let result = rules.apply("კ");
assert!(
result.contains('k'),
"კ should become k (ejective k' simplified), got: {}",
result
);
let result = rules.apply("პ");
assert!(
result.contains('p'),
"პ should become p (ejective p' simplified), got: {}",
result
);
let result = rules.apply("ტ");
assert!(
result.contains('t'),
"ტ should become t (ejective t' simplified), got: {}",
result
);
}
#[test]
fn test_voiced_affricates() {
let rules = base();
let result = rules.apply("ძ");
assert!(
result.contains("d͡z") || result.contains("dz"),
"ძ should become d͡z, got: {}",
result
);
let result = rules.apply("ჯ");
assert!(
result.contains("d͡ʒ") || result.contains("dʒ"),
"ჯ should become d͡ʒ, got: {}",
result
);
}
#[test]
fn test_aspirated_affricates() {
let rules = base();
let result = rules.apply("ც");
assert!(
result.contains("t͡s"),
"ც should become ts (aspirated TS simplified), got: {}",
result
);
let result = rules.apply("ჩ");
assert!(
result.contains("t͡ʃ"),
"ჩ should become ch (aspirated CH simplified), got: {}",
result
);
}
#[test]
fn test_ejective_affricates() {
let rules = base();
let result = rules.apply("წ");
assert!(
result.contains("t͡s"),
"წ should become ts (ejective ts' simplified), got: {}",
result
);
let result = rules.apply("ჭ");
assert!(
result.contains("t͡ʃ"),
"ჭ should become ch (ejective ch' simplified), got: {}",
result
);
}
#[test]
fn test_sibilants() {
let rules = base();
let result = rules.apply("ზ");
assert!(result.contains('z'), "ზ should become z, got: {}", result);
let result = rules.apply("ს");
assert!(result.contains('s'), "ს should become s, got: {}", result);
let result = rules.apply("შ");
assert!(
result.contains("ʃ"),
"შ should become sh (SH simplified), got: {}",
result
);
let result = rules.apply("ჟ");
assert!(
result.contains("ʒ"),
"ჟ should become zh (ZH simplified), got: {}",
result
);
}
#[test]
fn test_velar_fricatives() {
let rules = base();
let result = rules.apply("ღ");
assert!(
result.contains("ɣ"),
"ღ should become gh (GH simplified), got: {}",
result
);
let result = rules.apply("ხ");
assert!(result.contains('x'), "ხ should become x, got: {}", result);
}
#[test]
fn test_uvular_ejective() {
let rules = base();
let result = rules.apply("ყ");
assert!(
result.contains('q'),
"ყ should become q (ejective q' simplified), got: {}",
result
);
}
#[test]
fn test_nasals() {
let rules = base();
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);
}
#[test]
fn test_liquids() {
let rules = base();
let result = rules.apply("ლ");
assert!(result.contains('l'), "ლ should become l, got: {}", result);
let result = rules.apply("რ");
assert!(result.contains('r'), "რ should become r, got: {}", result);
}
#[test]
fn test_approximants() {
let rules = base();
let result = rules.apply("ვ");
assert!(result.contains('v'), "ვ should become v, got: {}", result);
let result = rules.apply("ჰ");
assert!(result.contains('h'), "ჰ should become h, got: {}", result);
}
#[test]
fn test_word_georgia() {
let rules = base();
let result = rules.apply_full("საქართველო");
assert!(
result.contains('s') && result.contains('r') && result.contains('v'),
"საქართველო should contain s, r, v, got: {}",
result
);
}
#[test]
fn test_word_tbilisi() {
let rules = base();
let result = rules.apply_full("თბილისი");
assert!(
result.contains('b') && result.contains('l') && result.contains('s'),
"თბილისი should contain b, l, s, got: {}",
result
);
}
#[test]
fn test_word_kartuli() {
let rules = base();
let result = rules.apply_full("ქართული");
assert!(
result.contains('k') && result.contains('r') && result.contains('l'),
"ქართული should contain k, r, l (simplified), got: {}",
result
);
}
}