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
108
109
110
111
112
113
114
115
use crate::Result;
use crate::{has_hardened_diacritic, has_softened_diacritic};
pub trait HalfWidth {
fn half_width(self) -> Result;
}
impl HalfWidth for &str {
fn half_width(self) -> Result {
let mut s = String::new();
for c in self.chars() {
let has_softened_diacritic = has_softened_diacritic(c);
let has_hardened_diacritic = has_hardened_diacritic(c);
let c = match c {
'ー' => 'ー',
'ア' => 'ア',
'イ' => 'イ',
'ウ' | 'ヴ' => 'ウ',
'エ' => 'エ',
'オ' => 'オ',
'カ' | 'ガ' => 'カ',
'キ' | 'ギ' => 'キ',
'ク' | 'グ' => 'ク',
'ケ' | 'ゲ' => 'ケ',
'コ' | 'ゴ' => 'コ',
'サ' | 'ザ' => 'サ',
'シ' | 'ジ' => 'シ',
'ス' | 'ズ' => 'ス',
'セ' | 'ゼ' => 'セ',
'ソ' | 'ゾ' => 'ソ',
'タ' | 'ダ' => 'タ',
'チ' | 'ヂ' => 'チ',
'ツ' | 'ヅ' => 'ツ',
'ッ' => 'ッ',
'テ' | 'デ' => 'テ',
'ト' | 'ド' => 'ト',
'ナ' => 'ナ',
'ニ' => 'ニ',
'ヌ' => 'ヌ',
'ネ' => 'ネ',
'ノ' => 'ノ',
'ハ' | 'バ' | 'パ' => 'ハ',
'ヒ' | 'ビ' | 'ピ' => 'ヒ',
'フ' | 'ブ' | 'プ' => 'フ',
'ヘ' | 'ベ' | 'ペ' => 'ヘ',
'ホ' | 'ボ' | 'ポ' => 'ホ',
'マ' => 'マ',
'ミ' => 'ミ',
'ム' => 'ム',
'メ' => 'メ',
'モ' => 'モ',
'ヤ' => 'ヤ',
'ユ' => 'ユ',
'ヨ' => 'ヨ',
'ャ' => 'ャ',
'ュ' => 'ュ',
'ョ' => 'ョ',
'ラ' => 'ラ',
'リ' => 'リ',
'ル' => 'ル',
'レ' => 'レ',
'ロ' => 'ロ',
'ワ' => 'ワ',
'ヲ' => 'ヲ',
'ン' => 'ン',
_ => c,
};
s.push(c);
if has_softened_diacritic {
s.push('゙');
} else if has_hardened_diacritic {
s.push('゚');
}
}
Ok(s)
}
}
impl HalfWidth for String {
fn half_width(self) -> Result {
let s: &str = &self;
s.half_width()
}
}
impl HalfWidth for Result {
fn half_width(self) -> Result {
self?.half_width()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn half_width_aiueo() {
assert_eq!("アイウエオ", "アイウエオ".half_width().unwrap());
}
#[test]
fn half_width_kakikukeko() {
assert_eq!(
"ガギグゲゴ",
"ガギグゲゴ".half_width().unwrap()
);
}
}