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/swedish/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded swedish/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Swedish 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(), "Swedish base rules should not be empty");
assert!(
rules.len() >= 30,
"expected >=30 base rules, got {}",
rules.len()
);
}
#[test]
fn test_sj_digraph() {
let rules = base();
let result = rules.apply("sj");
assert!(
result.contains("ɧ") || result.contains("ʃ"),
"sj should become ɧ (sj-sound), got: {}",
result
);
}
#[test]
fn test_stj_trigraph() {
let rules = base();
let result = rules.apply("stj");
assert!(
result.contains("ɧ") || result.contains("ʃ"),
"stj should become ɧ (sj-sound), got: {}",
result
);
}
#[test]
fn test_tj_digraph() {
let rules = base();
let result = rules.apply("tj");
assert!(
result.contains("ç") || result.contains("tɕ") || result.contains("ɕ"),
"tj should become ç (voiceless palatal fricative), got: {}",
result
);
}
#[test]
fn test_kj_digraph() {
let rules = base();
let result = rules.apply("kj");
assert!(
result.contains("ç") || result.contains("tɕ") || result.contains("ɕ"),
"kj should become ç (voiceless palatal fricative), got: {}",
result
);
}
#[test]
fn test_a_ring() {
let rules = base();
let result = rules.apply("å");
assert!(result.contains('ɔ'), "å should become o, got: {}", result);
}
#[test]
fn test_a_umlaut() {
let rules = base();
let result = rules.apply("ä");
assert!(
result.contains("ɛ") || result.contains("æ"),
"ä should become ɛ (front vowel), got: {}",
result
);
}
#[test]
fn test_o_umlaut() {
let rules = base();
let result = rules.apply("ö");
assert!(result.contains("ø"), "ö should become OE, got: {}", result);
}
#[test]
fn test_silent_dj() {
let rules = base();
let result = rules.apply("dj");
assert!(result.contains('j'), "dj should become J, got: {}", result);
}
#[test]
fn test_silent_hj() {
let rules = base();
let result = rules.apply("hj");
assert!(result.contains('j'), "hj should become J, got: {}", result);
}
#[test]
fn test_word_stockholm() {
let rules = base();
let result = rules.apply_full("stockholm");
let lower = result.to_lowercase();
assert!(
lower.contains('s') && lower.contains('t') && lower.contains('k'),
"stockholm should contain s, t, k, got: {}",
result
);
}
#[test]
fn test_word_sjo() {
let rules = base();
let result = rules.apply("sjö");
assert!(
result.contains("ɧ") || result.contains("ʃ"),
"sjö should contain ɧ (sj-sound), got: {}",
result
);
}
}