Skip to main content

yuru_core/
normalize.rs

1use unicode_normalization::UnicodeNormalization;
2
3pub fn normalize(text: &str) -> String {
4    text.nfkc().flat_map(char::to_lowercase).collect()
5}
6
7pub fn katakana_to_hiragana(text: &str) -> String {
8    text.chars()
9        .map(|ch| {
10            if ('ァ'..='ヶ').contains(&ch) {
11                char::from_u32(ch as u32 - 0x60).unwrap_or(ch)
12            } else {
13                ch
14            }
15        })
16        .collect()
17}
18
19pub fn hiragana_to_katakana(text: &str) -> String {
20    text.chars()
21        .map(|ch| {
22            if ('ぁ'..='ゖ').contains(&ch) {
23                char::from_u32(ch as u32 + 0x60).unwrap_or(ch)
24            } else {
25                ch
26            }
27        })
28        .collect()
29}
30
31pub fn contains_kana(text: &str) -> bool {
32    text.chars()
33        .any(|ch| ('ぁ'..='ゖ').contains(&ch) || ('ァ'..='ヶ').contains(&ch))
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn normalize_ascii_lowercase() {
42        assert_eq!(normalize("README.MD"), "readme.md");
43    }
44
45    #[test]
46    fn normalize_fullwidth_ascii_nfkc() {
47        assert_eq!(normalize("ABC123"), "abc123");
48    }
49
50    #[test]
51    fn normalize_halfwidth_katakana() {
52        assert_eq!(normalize("カメラ"), "カメラ");
53    }
54
55    #[test]
56    fn katakana_to_hiragana_basic() {
57        assert_eq!(katakana_to_hiragana("カメラ"), "かめら");
58    }
59
60    #[test]
61    fn hiragana_to_katakana_basic() {
62        assert_eq!(hiragana_to_katakana("しんじゅく"), "シンジュク");
63    }
64}