piny/
lib.rs

1mod db;
2mod pinyin;
3pub use crate::pinyin::Pinyin;
4use std::fmt::Write;
5
6lazy_static::lazy_static! {
7    static ref DB: db::DB = {
8        db::DB::load(include_str!("pinyin.txt")).unwrap()
9    };
10}
11
12/// How to represent the tone of a pinyin syllable.
13#[derive(Copy, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
15#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
16pub enum ToneRepresentation {
17    None,
18    Numbered,
19    Unicode,
20}
21
22impl Default for ToneRepresentation {
23    fn default() -> Self {
24        Self::Unicode
25    }
26}
27
28/// Return pinyin of a Chinese characters separated by space.
29pub fn pinyin(s: &str, tone_repr: ToneRepresentation) -> String {
30    let mut result = String::new();
31    for c in s.chars() {
32        if let Some(pinyin) = DB.get(c) {
33            let repr = match tone_repr {
34                ToneRepresentation::None => pinyin::PinyinDisplay::NoTones(pinyin.into()),
35                ToneRepresentation::Numbered => pinyin::PinyinDisplay::NumberedTone(pinyin.into()),
36                ToneRepresentation::Unicode => pinyin::PinyinDisplay::UnicodeTone(pinyin.into()),
37            };
38            write!(&mut result, "{}", repr).unwrap();
39        } else {
40            result.push(c);
41        }
42        result.push(' ');
43    }
44    result
45}
46
47/// Replace Chinese characters with their first letter. Ignore non-printable characters.
48/// Non Chinese characters are kept as is.
49pub fn first_letters(s: &str) -> String {
50    let mut result = String::new();
51    for c in s.chars() {
52        if let Some(pinyin) = DB.get(c) {
53            write!(
54                &mut result,
55                "{}",
56                pinyin::PinyinDisplay::FirstLetter(pinyin.into())
57            )
58            .unwrap();
59        } else {
60            result.push(c);
61        }
62    }
63    result
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_pinyin() {
72        assert_eq!(pinyin("你好", ToneRepresentation::None), "ni hao ");
73        assert_eq!(pinyin("你好", ToneRepresentation::Numbered), "ni3 hao3 ");
74        assert_eq!(pinyin("你好", ToneRepresentation::Unicode), "nǐ hǎo ");
75    }
76
77    #[test]
78    fn test_first_letters() {
79        assert_eq!(first_letters("你l好"), "nlh");
80    }
81}