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/italian/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded italian/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Italian rules - this is a bug in liblevenshtein")
})
}
pub fn combined() -> &'static RuleSetChar {
base()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base_loads() {
let rules = base();
assert!(!rules.is_empty(), "Italian rules should not be empty");
assert!(rules.len() > 40, "expected >40 rules, got {}", rules.len());
}
#[test]
fn test_c_softening_before_i() {
let rules = base();
let result = rules.apply("ciao");
assert!(
result.contains("t͡ʃ") || result.contains("tsh"),
"c before i should become t͡ʃ, got: {}",
result
);
}
#[test]
fn test_c_softening_before_e() {
let rules = base();
let result = rules.apply("cena");
assert!(
result.contains("t͡ʃ") || result.contains("tsh"),
"c before e should become t͡ʃ, got: {}",
result
);
}
#[test]
fn test_c_hard_before_a() {
let rules = base();
let result = rules.apply("casa");
assert!(
result.starts_with('k'),
"c before a should be k, got: {}",
result
);
}
#[test]
fn test_ch_preserves_hard_c() {
let rules = base();
let result = rules.apply("che");
assert!(
result.starts_with('k'),
"ch before e should be k, got: {}",
result
);
}
#[test]
fn test_g_softening_before_e() {
let rules = base();
let result = rules.apply("gelato");
assert!(
result.contains("d͡ʒ"),
"g before e should become DZH, got: {}",
result
);
}
#[test]
fn test_g_softening_before_i() {
let rules = base();
let result = rules.apply("giorno");
assert!(
result.contains("d͡ʒ"),
"g before i should become DZH, got: {}",
result
);
}
#[test]
fn test_gh_preserves_hard_g() {
let rules = base();
let result = rules.apply("ghetto");
assert!(
result.starts_with('G'),
"gh before e should be G (hard), got: {}",
result
);
}
#[test]
fn test_sc_before_e() {
let rules = base();
let result = rules.apply("pesce");
assert!(
result.contains("ʃ"),
"sc before e should become sh, got: {}",
result
);
}
#[test]
fn test_sc_before_i() {
let rules = base();
let result = rules.apply("scimmia");
assert!(
result.contains("ʃ"),
"sc before i should become sh, got: {}",
result
);
}
#[test]
fn test_sch_preserves_sk() {
let rules = base();
let result = rules.apply("schema");
assert!(result.contains("sk"), "sch should be sk, got: {}", result);
}
#[test]
fn test_gn_pattern() {
let rules = base();
let result = rules.apply("gnocchi");
assert!(result.contains("ɲ"), "gn should become ny, got: {}", result);
}
#[test]
fn test_gli_pattern() {
let rules = base();
let result = rules.apply("figlio");
assert!(
result.contains("ʎ"),
"gli should become LY, got: {}",
result
);
}
#[test]
fn test_qu_pattern() {
let rules = base();
let result = rules.apply("questo");
assert!(
result.contains("kv") || result.contains("kw"),
"qu should become kv or kw, got: {}",
result
);
}
#[test]
fn test_silent_h() {
let rules = base();
let result = rules.apply("ho");
assert!(!result.contains('h'), "h should be silent, got: {}", result);
}
#[test]
fn test_z_pronunciation() {
let rules = base();
let result = rules.apply("pizza");
assert!(result.contains("t͡s"), "z should become ts, got: {}", result);
}
#[test]
fn test_geminate_preserved() {
let rules = base();
let result = rules.apply("fatto");
assert!(
result.contains('f') && result.contains('t'),
"double consonants should process correctly, got: {}",
result
);
}
#[test]
fn test_cia_pattern() {
let rules = base();
let result = rules.apply("ciabatta");
assert!(
result.contains("t͡ʃa") || result.contains("tsha"),
"cia should become t͡ʃa, got: {}",
result
);
}
#[test]
fn test_accent_normalization() {
let rules = base();
let result = rules.apply("città");
assert!(
!result.contains('à'),
"accents should be normalized, got: {}",
result
);
}
#[test]
fn test_foreign_j() {
let rules = base();
let result = rules.apply("jazz");
assert!(
result.contains("d͡ʒ"),
"j should become DZH, got: {}",
result
);
}
#[test]
fn test_combined_alias() {
let base_rules = base();
let combined_rules = combined();
assert_eq!(
base_rules.len(),
combined_rules.len(),
"combined() should be alias for base()"
);
}
}