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/finnish/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded finnish/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Finnish 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(), "Finnish base rules should not be empty");
assert!(
rules.len() >= 15,
"expected >=15 base rules, got {}",
rules.len()
);
}
#[test]
fn test_a_umlaut() {
let rules = base();
let result = rules.apply("ä");
assert!(result.contains("æ"), "ä should become AE, 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_y_vowel() {
let rules = base();
let result = rules.apply("y");
assert!(
result.contains('y'),
"y should stay as y (or become y), got: {}",
result
);
}
#[test]
fn test_ng_digraph() {
let rules = base();
let result = rules.apply("ng");
assert!(
result.contains("ŋː") || result.contains("ŋ"),
"ng should become ŋː (or ŋ), got: {}",
result
);
}
#[test]
fn test_nk_digraph() {
let rules = base();
let result = rules.apply("nk");
assert!(
result.contains("ŋk"),
"nk should become ŋk, got: {}",
result
);
}
#[test]
fn test_b_to_p() {
let rules = base();
let result = rules.apply("b");
assert!(result.contains('p'), "b should become p, got: {}", result);
}
#[test]
fn test_z_to_ts() {
let rules = base();
let result = rules.apply("z");
assert!(result.contains("t͡s"), "z should become ts, got: {}", result);
}
#[test]
fn test_word_suomi() {
let rules = base();
let result = rules.apply("suomi");
assert!(
result.contains('s') && result.contains('u') && result.contains('o'),
"suomi should contain s, u, o, got: {}",
result
);
}
#[test]
fn test_word_helsinki() {
let rules = base();
let result = rules.apply("Helsinki");
let upper = result.to_uppercase();
assert!(
upper.contains('H') && upper.contains('E') && upper.contains('L'),
"Helsinki should contain h, e, l, got: {}",
result
);
}
#[test]
fn test_word_aiti() {
let rules = base();
let result = rules.apply("äiti");
assert!(
result.contains("æ"),
"äiti should contain AE, got: {}",
result
);
}
}