1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
extern crate phf;
use std::cmp::Ordering;
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
#[derive(Eq, Debug)]
pub enum PinYin {
Other(char),
Chinese(char, &'static str),
}
impl PinYin {
fn is_other(&self) -> bool {
match *self {
PinYin::Other(_) => true,
PinYin::Chinese(_, _) => false,
}
}
fn is_chinese(&self) -> bool {
match *self {
PinYin::Other(_) => false,
PinYin::Chinese(_, _) => true,
}
}
fn get_other(&self) -> char {
match *self {
PinYin::Other(r) => r,
PinYin::Chinese(_, _) => panic!(),
}
}
fn get_chinese(&self) -> (char, &str) {
match *self {
PinYin::Other(_) => panic!(),
PinYin::Chinese(c, p) => (c, p),
}
}
}
impl PartialEq for PinYin {
fn eq(&self, other: &PinYin) -> bool {
if self.is_other() && other.is_other() {
self.get_other().eq(&other.get_other())
} else if self.is_chinese() && other.is_chinese() {
self.get_chinese().0.eq(&other.get_chinese().0)
} else {
false
}
}
}
impl PartialOrd for PinYin {
fn partial_cmp(&self, other: &PinYin) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for PinYin {
fn cmp(&self, other: &PinYin) -> Ordering {
if self.is_other() && other.is_other() {
self.get_other().cmp(&other.get_other())
} else if self.is_chinese() && other.is_chinese() {
let (sc, sp) = self.get_chinese();
let (oc, op) = other.get_chinese();
let pinyin_order = sp.cmp(&op);
if pinyin_order == Ordering::Equal {
sc.cmp(&oc)
} else {
pinyin_order
}
} else {
if self.is_other() {
Ordering::Less
} else {
Ordering::Greater
}
}
}
}
pub fn as_pinyin(s: &str) -> Vec<PinYin> {
s.chars()
.map(|c| match PINYIN_MAP.get(&c) {
Some(pinyin) => PinYin::Chinese(c, pinyin),
None => PinYin::Other(c),
})
.collect()
}