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/icelandic/base.llev");
let file = crate::phonetic::llev::parse_str(content)
.expect("Invalid embedded icelandic/base.llev - this is a bug in liblevenshtein");
RuleSetChar::from_llev(&file)
.expect("Failed to compile Icelandic 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(),
"Icelandic base rules should not be empty"
);
assert!(
rules.len() >= 15,
"expected >=15 base rules, got {}",
rules.len()
);
}
#[test]
fn test_thorn() {
let rules = base();
let result = rules.apply("þ");
assert!(result.contains("θ"), "þ should become th, got: {}", result);
}
#[test]
fn test_eth() {
let rules = base();
let result = rules.apply("ð");
assert!(result.contains("ð"), "ð should become dh, got: {}", result);
}
#[test]
fn test_ash() {
let rules = base();
let result = rules.apply("æ");
assert!(result.contains("aɪ"), "æ should become aɪ, got: {}", result);
}
#[test]
fn test_o_umlaut() {
let rules = base();
let result = rules.apply("ö");
assert!(result.contains('ø'), "ö should become ø, got: {}", result);
}
#[test]
fn test_a_acute() {
let rules = base();
let result = rules.apply("á");
assert!(result.contains("au"), "á should become au, got: {}", result);
}
#[test]
fn test_e_acute() {
let rules = base();
let result = rules.apply("é");
assert!(
result.contains('j') || result.contains('ɛ'),
"é should contain j or ɛ, got: {}",
result
);
}
#[test]
fn test_i_acute() {
let rules = base();
let result = rules.apply("í");
assert!(
result.contains("iː") || result.contains('i'),
"í should become iː, got: {}",
result
);
}
#[test]
fn test_o_acute() {
let rules = base();
let result = rules.apply("ó");
assert!(result.contains("ou"), "ó should become ou, got: {}", result);
}
#[test]
fn test_u_acute() {
let rules = base();
let result = rules.apply("ú");
assert!(
result.contains("uː") || result.contains('u'),
"ú should become uː, got: {}",
result
);
}
#[test]
fn test_y_acute() {
let rules = base();
let result = rules.apply("ý");
assert!(
result.contains("iː") || result.contains('i'),
"ý should become iː, got: {}",
result
);
}
#[test]
fn test_cluster_hv() {
let rules = base();
let result = rules.apply("hv");
assert!(
result.contains("kv"),
"hv should become kv, got: {}",
result
);
}
#[test]
fn test_cluster_ll() {
let rules = base();
let result = rules.apply("ll");
assert!(
result.contains("tl"),
"ll should become tl, got: {}",
result
);
}
#[test]
fn test_cluster_rl() {
let rules = base();
let result = rules.apply("rl");
assert!(
result.contains("rtl"),
"rl should become rtl, got: {}",
result
);
}
#[test]
fn test_cluster_rn() {
let rules = base();
let result = rules.apply("rn");
assert!(
result.contains("rtn"),
"rn should become rtn, got: {}",
result
);
}
#[test]
fn test_cluster_nn() {
let rules = base();
let result = rules.apply("nn");
assert!(
result.contains("tn"),
"nn should become tn, got: {}",
result
);
}
#[test]
fn test_cluster_hj() {
let rules = base();
let result = rules.apply("hj");
assert!(result.contains('j'), "hj should become j, got: {}", result);
}
#[test]
fn test_cluster_fn() {
let rules = base();
let result = rules.apply("fn");
assert!(
result.contains("pn"),
"fn should become pn, got: {}",
result
);
}
#[test]
fn test_word_island() {
let rules = base();
let result = rules.apply_full("Ísland");
let lower = result.to_lowercase();
assert!(
lower.contains("iː")
&& lower.contains('s')
&& lower.contains('l')
&& lower.contains('a')
&& lower.contains('n')
&& lower.contains('d'),
"Ísland should normalize í to iː, got: {}",
result
);
}
#[test]
fn test_word_reykjavik() {
let rules = base();
let result = rules.apply_full("Reykjavík");
let lower = result.to_lowercase();
assert!(
lower.contains('r')
&& lower.contains('k')
&& lower.contains('j')
&& lower.contains("iː"),
"Reykjavík should normalize í to iː, got: {}",
result
);
}
#[test]
fn test_word_fjall() {
let rules = base();
let result = rules.apply_full("fjall");
let lower = result.to_lowercase();
assert!(
lower.contains("tl"),
"fjall should have ll → tl, got: {}",
result
);
}
#[test]
fn test_word_thingvellir() {
let rules = base();
let result = rules.apply_full("Þingvellir");
let lower = result.to_lowercase();
assert!(
lower.contains("θ") && lower.contains("tl"),
"Þingvellir should have Þ → th and ll → tl, got: {}",
result
);
}
}