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/serbian/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded serbian/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Serbian base rules - this is a bug in liblevenshtein")
})
}
pub fn latin() -> &'static RuleSetChar {
static RULESET: OnceLock<RuleSetChar> = OnceLock::new();
RULESET.get_or_init(|| {
let content = include_str!("../../../data/rules/serbian/latin.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded serbian/latin.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Serbian Latin 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(), "Serbian base rules should not be empty");
assert!(
rules.len() >= 30,
"expected >=30 base rules, got {}",
rules.len()
);
}
#[test]
fn test_cyrillic_lj() {
let rules = base();
let result = rules.apply("љ");
assert!(
result.contains('ʎ') || result.contains("lj"),
"љ should become ʎ, got: {}",
result
);
}
#[test]
fn test_cyrillic_nj() {
let rules = base();
let result = rules.apply("њ");
assert!(
result.contains('ɲ') || result.contains("nj"),
"њ should become ɲ, got: {}",
result
);
}
#[test]
fn test_cyrillic_dzh() {
let rules = base();
let result = rules.apply("џ");
assert!(
result.contains("d͡ʒ") || result.contains("dz"),
"џ should become d͡ʒ, got: {}",
result
);
}
#[test]
fn test_cyrillic_soft_ch() {
let rules = base();
let result = rules.apply("ћ");
assert!(
result.contains("tɕ") || result.contains('c'),
"ћ should become tɕ, got: {}",
result
);
}
#[test]
fn test_cyrillic_dj() {
let rules = base();
let result = rules.apply("ђ");
assert!(
result.contains("dʑ") || result.contains("d͡ʒ"),
"ђ should become dʑ, got: {}",
result
);
}
#[test]
fn test_cyrillic_zh() {
let rules = base();
let result = rules.apply("ж");
assert!(result.contains("ʒ"), "ж should become zh, got: {}", result);
}
#[test]
fn test_cyrillic_sh() {
let rules = base();
let result = rules.apply("ш");
assert!(result.contains("ʃ"), "ш should become sh, got: {}", result);
}
#[test]
fn test_cyrillic_ch() {
let rules = base();
let result = rules.apply("ч");
assert!(result.contains("t͡ʃ"), "ч should become ch, got: {}", result);
}
#[test]
fn test_cyrillic_word_beograd() {
let rules = base();
let result = rules.apply_full("београд");
assert!(
result.contains('b') && result.contains('r') && result.contains('d'),
"београд should contain b, r, d, got: {}",
result
);
}
#[test]
fn test_cyrillic_word_srbija() {
let rules = base();
let result = rules.apply_full("србија");
let lower = result.to_lowercase();
assert!(
lower.contains('s') && lower.contains('r') && lower.contains('b'),
"србија should contain s, r, b, got: {}",
result
);
}
#[test]
fn test_latin_loads() {
let rules = latin();
assert!(!rules.is_empty(), "Serbian Latin rules should not be empty");
assert!(
rules.len() >= 8,
"expected >=8 latin rules, got {}",
rules.len()
);
}
#[test]
fn test_latin_c_caron() {
let rules = latin();
let result = rules.apply("č");
assert!(result.contains("t͡ʃ"), "č should become ch, got: {}", result);
}
#[test]
fn test_latin_c_acute() {
let rules = latin();
let result = rules.apply("ć");
assert!(
result.contains("tɕ") || result.contains('c'),
"ć should become tɕ, got: {}",
result
);
}
#[test]
fn test_latin_s_caron() {
let rules = latin();
let result = rules.apply("š");
assert!(result.contains("ʃ"), "š should become sh, got: {}", result);
}
#[test]
fn test_latin_z_caron() {
let rules = latin();
let result = rules.apply("ž");
assert!(result.contains("ʒ"), "ž should become zh, got: {}", result);
}
#[test]
fn test_latin_d_stroke() {
let rules = latin();
let result = rules.apply("đ");
assert!(
result.contains("dʑ") || result.contains("d͡ʒ"),
"đ should become dʑ, got: {}",
result
);
}
#[test]
fn test_latin_dz_digraph() {
let rules = latin();
let result = rules.apply("dž");
assert!(
result.contains("d͡ʒ") || result.contains("dz"),
"dž should become d͡ʒ, got: {}",
result
);
}
#[test]
fn test_latin_word_beograd() {
let rules = latin();
let result = rules.apply_full("Beograd");
assert!(
result.contains('b') && result.contains('r') && result.contains('d'),
"Beograd should contain b, r, d, got: {}",
result
);
}
#[test]
fn test_latin_word_srbija() {
let rules = latin();
let result = rules.apply_full("Srbija");
let lower = result.to_lowercase();
assert!(
lower.contains('s') && lower.contains('r') && lower.contains('b'),
"Srbija should contain s, r, b, got: {}",
result
);
}
}