competitive/tools/
char_convert.rs

1pub trait CharConvertTryInto<T>: Sized {
2    /// map `'0'..='9'` to `0..=9`
3    fn into_number(self) -> Option<T>;
4
5    /// map (`'A'..='Z'` or `'a'..='z'`) to `0..=25`
6    fn into_alphabetic_number(self) -> Option<T>;
7
8    /// map `'a'..='z'` to `0..=25`
9    fn into_lower_alphabetic_number(self) -> Option<T>;
10
11    /// map `'A'..='Z'` to `0..=25`
12    fn into_upper_alphabetic_number(self) -> Option<T>;
13}
14
15pub trait CharConvertTryFrom<T>: Sized {
16    /// map `0..=9` to `'0'..='9'`
17    fn from_number(num: T) -> Option<Self>;
18
19    /// map `0..=25` to `'A'..='Z'`
20    fn from_alphabetic_number(num: T) -> Option<Self>;
21
22    /// map `0..=25` to `'a'..='z'`
23    fn from_lower_alphabetic_number(num: T) -> Option<Self>;
24
25    /// map `0..=25` to `'A'..='Z'`
26    fn from_upper_alphabetic_number(num: T) -> Option<Self>;
27}
28
29macro_rules! impl_char_convert_unsigned {
30    ($($ty:ident)*) => {$(
31        impl CharConvertTryInto<$ty> for char {
32            fn into_number(self) -> Option<$ty> {
33                let num = (self as u8).wrapping_sub(b'0');
34                if num < 10 {
35                    Some(num as $ty)
36                } else {
37                    None
38                }
39            }
40
41            fn into_alphabetic_number(self) -> Option<$ty> {
42                match self {
43                    'A'..='Z' => Some((self as u8 - b'A') as $ty),
44                    'a'..='z' => Some((self as u8 - b'a') as $ty),
45                    _ => None,
46                }
47            }
48
49            fn into_lower_alphabetic_number(self) -> Option<$ty> {
50                if self.is_ascii_lowercase() {
51                    Some((self as u8 - b'a') as $ty)
52                } else {
53                    None
54                }
55            }
56
57            fn into_upper_alphabetic_number(self) -> Option<$ty> {
58                if self.is_ascii_uppercase() {
59                    Some((self as u8 - b'A') as $ty)
60                } else {
61                    None
62                }
63            }
64        }
65
66        impl CharConvertTryFrom<$ty> for char {
67            fn from_number(num: $ty) -> Option<Self> {
68                if num < 10 {
69                    Some((b'0' + num as u8) as char)
70                } else {
71                    None
72                }
73            }
74
75            fn from_alphabetic_number(num: $ty) -> Option<Self> {
76                if num < 26 {
77                    Some((b'A' + num as u8) as char)
78                } else {
79                    None
80                }
81            }
82
83            fn from_lower_alphabetic_number(num: $ty) -> Option<Self> {
84                if num < 26 {
85                    Some((b'a' + num as u8) as char)
86                } else {
87                    None
88                }
89            }
90
91            fn from_upper_alphabetic_number(num: $ty) -> Option<Self> {
92                if num < 26 {
93                    Some((b'A' + num as u8) as char)
94                } else {
95                    None
96                }
97            }
98        }
99
100        impl CharConvertTryInto<$ty> for u8 {
101            fn into_number(self) -> Option<$ty> {
102                let num = self.wrapping_sub(b'0');
103                if num < 10 {
104                    Some(num as $ty)
105                } else {
106                    None
107                }
108            }
109
110            fn into_alphabetic_number(self) -> Option<$ty> {
111                match self {
112                    b'A'..=b'Z' => Some((self - b'A') as $ty),
113                    b'a'..=b'z' => Some((self - b'a') as $ty),
114                    _ => None,
115                }
116            }
117
118            fn into_lower_alphabetic_number(self) -> Option<$ty> {
119                if self.is_ascii_lowercase() {
120                    Some((self - b'a') as $ty)
121                } else {
122                    None
123                }
124            }
125
126            fn into_upper_alphabetic_number(self) -> Option<$ty> {
127                if self.is_ascii_uppercase() {
128                    Some((self - b'A') as $ty)
129                } else {
130                    None
131                }
132            }
133        }
134
135        impl CharConvertTryFrom<$ty> for u8 {
136            fn from_number(num: $ty) -> Option<Self> {
137                if num < 10 {
138                    Some(b'0' + num as u8)
139                } else {
140                    None
141                }
142            }
143
144            fn from_alphabetic_number(num: $ty) -> Option<Self> {
145                if num < 26 {
146                    Some(b'A' + num as u8)
147                } else {
148                    None
149                }
150            }
151
152            fn from_lower_alphabetic_number(num: $ty) -> Option<Self> {
153                if num < 26 {
154                    Some(b'a' + num as u8)
155                } else {
156                    None
157                }
158            }
159
160            fn from_upper_alphabetic_number(num: $ty) -> Option<Self> {
161                if num < 26 {
162                    Some(b'A' + num as u8)
163                } else {
164                    None
165                }
166            }
167        }
168    )*};
169}
170impl_char_convert_unsigned!(u8 u16 u32 u64 u128 usize);