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/persian/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded persian/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Persian 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(), "Persian base rules should not be empty");
assert!(
rules.len() >= 35,
"expected >=35 base rules, got {}",
rules.len()
);
}
#[test]
fn test_pe() {
let rules = base();
let result = rules.apply("پ");
assert!(result.contains('p'), "پ should become p, got: {}", result);
}
#[test]
fn test_che() {
let rules = base();
let result = rules.apply("چ");
assert!(result.contains("t͡ʃ"), "چ should become ch, got: {}", result);
}
#[test]
fn test_zhe() {
let rules = base();
let result = rules.apply("ژ");
assert!(result.contains("ʒ"), "ژ should become zh, got: {}", result);
}
#[test]
fn test_gaf() {
let rules = base();
let result = rules.apply("گ");
assert!(result.contains('ɡ'), "گ should become g, got: {}", result);
}
#[test]
fn test_se() {
let rules = base();
let result = rules.apply("ث");
assert!(
result.contains('s'),
"ث should become s in Persian, got: {}",
result
);
}
#[test]
fn test_zal() {
let rules = base();
let result = rules.apply("ذ");
assert!(
result.contains('z'),
"ذ should become z in Persian, got: {}",
result
);
}
#[test]
fn test_ayn() {
let rules = base();
let result = rules.apply("ع");
assert!(
result.contains('a'),
"ع should become a in Persian, got: {}",
result
);
}
#[test]
fn test_ghayn() {
let rules = base();
let result = rules.apply("غ");
assert!(result.contains("ɣ"), "غ should become gh, got: {}", result);
}
#[test]
fn test_qaf() {
let rules = base();
let result = rules.apply("ق");
assert!(
result.contains("ɣ"),
"ق should become gh in Persian, got: {}",
result
);
}
#[test]
fn test_khe() {
let rules = base();
let result = rules.apply("خ");
assert!(result.contains("x"), "خ should become kh, got: {}", result);
}
#[test]
fn test_shin() {
let rules = base();
let result = rules.apply("ش");
assert!(result.contains("ʃ"), "ش should become sh, got: {}", result);
}
#[test]
fn test_be() {
let rules = base();
let result = rules.apply("ب");
assert!(result.contains('b'), "ب should become b, got: {}", result);
}
#[test]
fn test_te() {
let rules = base();
let result = rules.apply("ت");
assert!(result.contains('t'), "ت should become t, got: {}", result);
}
#[test]
fn test_jim() {
let rules = base();
let result = rules.apply("ج");
assert!(
result.contains('j') || result.contains('ʝ') || result.contains("d͡ʒ"),
"ج should become j, got: {}",
result
);
}
#[test]
fn test_dal() {
let rules = base();
let result = rules.apply("د");
assert!(result.contains('d'), "د should become d, got: {}", result);
}
#[test]
fn test_sin() {
let rules = base();
let result = rules.apply("س");
assert!(result.contains('s'), "س should become s, got: {}", result);
}
#[test]
fn test_fe() {
let rules = base();
let result = rules.apply("ف");
assert!(result.contains('f'), "ف should become f, got: {}", result);
}
#[test]
fn test_kaf() {
let rules = base();
let result = rules.apply("ک");
assert!(result.contains('k'), "ک should become k, got: {}", result);
}
#[test]
fn test_alef() {
let rules = base();
let result = rules.apply("ا");
assert!(result.contains('a'), "ا should become a, got: {}", result);
}
#[test]
fn test_alef_madda() {
let rules = base();
let result = rules.apply("آ");
assert!(result.contains('a'), "آ should become a, got: {}", result);
}
#[test]
fn test_vav() {
let rules = base();
let result = rules.apply("و");
assert!(result.contains('v'), "و should become v, got: {}", result);
}
#[test]
fn test_ye() {
let rules = base();
let result = rules.apply("ی");
assert!(result.contains('y'), "ی should become y, got: {}", result);
}
#[test]
fn test_word_farsi() {
let rules = base();
let result = rules.apply_full("فارسی");
let lower = result.to_lowercase();
assert!(
lower.contains('f')
&& lower.contains('a')
&& lower.contains('r')
&& lower.contains('s')
&& lower.contains('y'),
"فارسی should contain f, a, r, s, y, got: {}",
result
);
}
#[test]
fn test_word_iran() {
let rules = base();
let result = rules.apply_full("ایران");
let lower = result.to_lowercase();
assert!(
lower.contains('a')
&& lower.contains('y')
&& lower.contains('r')
&& lower.contains('n'),
"ایران should contain a, y, r, n, got: {}",
result
);
}
#[test]
fn test_word_tehran() {
let rules = base();
let result = rules.apply_full("تهران");
let lower = result.to_lowercase();
assert!(
lower.contains('t')
&& lower.contains('h')
&& lower.contains('r')
&& lower.contains('a')
&& lower.contains('n'),
"تهران should contain t, h, r, a, n, got: {}",
result
);
}
}