1use std::char;
5
6#[allow(dead_code)]
8pub fn is_half(c: char) -> bool {
9 (c as u32) < 0xF0u32
10}
11
12macro_rules! in_range {
13 ( $v:expr => $( $a:expr ),* ) => {
14 $( ($a).contains( & $v ) || )* false
15 };
16}
17
18#[allow(dead_code)]
20pub fn is_alpha(c: char) -> bool {
21 in_range![c => 'a'..='z', 'A'..='Z']
22}
23
24#[allow(dead_code)]
26pub fn is_numeric(c: char) -> bool {
27 ('0'..='9').contains(&c)
28}
29
30pub fn is_hiragana(c: char) -> bool {
32 ('ぁ'..='ゟ').contains(&c)
34 }
37
38pub fn is_word_chars(c: char) -> bool {
40 let cu: u32 = c as u32;
41 if cu <= 0xFF {
43 if in_range![
44 c => '0'..='9', 'a'..='z', 'A'..='Z', '_'..='_'
45 ] { return true; }
46 return false;
47 }
48 if in_range![
66 cu =>
67 0x2190..=0x21FF, 0x25A0..=0x25FF, 0x3000..=0x303F ] { return false; }
71 return true;
72}
73
74pub fn char_from_u32(i: u32, def: char) -> char {
75 char::from_u32(i).unwrap_or(def)
76}
77
78pub fn to_half_ascii(c: char) -> char {
81 let ci = c as u32;
82 match ci {
83 0x0020..=0x007E => c,
85 0xFF01..=0xFF5E => char_from_u32(ci - 0xFF01 + 0x21, c),
87 0x2002..=0x200B => ' ',
89 0x3000 | 0xFEFF => ' ',
90 _ => c,
92 }
93}
94
95#[cfg(test)]
96mod test_charutils {
97 use super::*;
98 #[test]
99 fn test_to_half() {
100 assert_eq!(is_half('!'), true);
101 assert_eq!(is_half('!'), false);
102 assert_eq!('!' as u32, 0xFF01);
103 assert_eq!(to_half_ascii('!'), '!');
104 assert_eq!(to_half_ascii('A'), 'A');
105 assert_eq!(to_half_ascii('#'), '#');
106 assert_eq!(to_half_ascii(' '), ' ');
107 }
108 #[test]
109 fn test_range() {
110 assert_eq!(is_alpha('a'), true);
111 assert_eq!(is_alpha('B'), true);
112 assert_eq!(is_alpha('3'), false);
113 assert_eq!(is_alpha('$'), false);
114 }
115}