use once_cell::sync::Lazy;
use std::collections::HashMap;
include!(concat!(env!("OUT_DIR"), "/confusables_gen.rs"));
static CONFUSABLES_MAP: Lazy<HashMap<char, char>> = Lazy::new(|| {
let mut m = HashMap::with_capacity(CONFUSABLE_COUNT);
for &(src, tgt) in CONFUSABLE_TABLE {
if let (Some(s), Some(t)) = (char::from_u32(src), char::from_u32(tgt)) {
m.insert(s, t);
}
}
m
});
pub fn is_confusable(ch: char) -> Option<char> {
CONFUSABLES_MAP.get(&ch).copied()
}
pub fn skeleton(s: &str) -> String {
s.chars()
.map(|c| CONFUSABLES_MAP.get(&c).copied().unwrap_or(c))
.collect()
}
pub fn are_confusable(a: &str, b: &str) -> bool {
skeleton(&a.to_lowercase()) == skeleton(&b.to_lowercase())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cyrillic_a() {
assert_eq!(is_confusable('\u{0430}'), Some('a'));
}
#[test]
fn test_ascii_not_confusable() {
assert_eq!(is_confusable('a'), None);
}
#[test]
fn test_skeleton() {
assert_eq!(skeleton("\u{0430}"), "a");
}
#[test]
fn test_confusable_domain() {
assert!(are_confusable("g\u{0456}thub.com", "github.com"));
}
}