1use std::fmt::{self, Display, Write};
2
3macro_rules! declare_thai_char {
4 ([$(($value:literal, $char:literal, $variant:ident)),+ $(,)?]) => {
5 #[repr(u8)]
10 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
11 #[allow(clippy::upper_case_acronyms)]
12 #[allow(non_camel_case_types)]
13 pub enum ThaiChar {
14 $(
15 $variant = $value
16 ),+
17 }
18
19 impl ThaiChar {
20 pub fn from_char(ch: char) -> Option<Self> {
21 use ThaiChar::*;
22 let variant = match ch {
23 $(
24 $char => $variant
25 ),+,
26 _ => return None,
27 };
28 Some(variant)
29 }
30
31 pub fn from_tis620_byte(byte: u8) -> Option<Self> {
32 use ThaiChar::*;
33 let variant = match byte {
34 $(
35 $value => $variant
36 ),+,
37 _ => return None,
38 };
39 Some(variant)
40 }
41
42 pub fn to_tis620_byte(self) -> u8 {
43 self as u8
44 }
45
46 pub fn to_char(self) -> char {
47 use ThaiChar::*;
48 match self {
49 $(
50 $variant => $char
51 ),+,
52 }
53 }
54
55 pub fn byte_to_char(byte: u8) -> Option<char> {
56 let ch = match byte {
57 $(
58 $value => $char
59 ),+,
60 _ => return None,
61 };
62 Some(ch)
63 }
64 }
65 };
66}
67
68declare_thai_char!([
69 (0xA1, 'ก', KO_KAI),
70 (0xA2, 'ข', KHO_KHAI),
71 (0xA3, 'ฃ', KHO_KHUAT),
72 (0xA4, 'ค', KHO_KHWAI),
73 (0xA5, 'ฅ', KHO_KHON),
74 (0xA6, 'ฆ', KHO_RAKHANG),
75 (0xA7, 'ง', NGO_NGU),
76 (0xA8, 'จ', CHO_CHAN),
77 (0xA9, 'ฉ', CHO_CHING),
78 (0xAA, 'ช', CHO_CHANG),
79 (0xAB, 'ซ', SO_SO),
80 (0xAC, 'ฌ', CHO_CHOE),
81 (0xAD, 'ญ', YO_YING),
82 (0xAE, 'ฎ', DO_CHADA),
83 (0xAF, 'ฏ', TO_PATAK),
84 (0xB0, 'ฐ', THO_THAN),
85 (0xB1, 'ฑ', THO_NANGMONTHO),
86 (0xB2, 'ฒ', THO_PHUTHAO),
87 (0xB3, 'ณ', NO_NEN),
88 (0xB4, 'ด', DO_DEK),
89 (0xB5, 'ต', TO_TAO),
90 (0xB6, 'ถ', THO_THUNG),
91 (0xB7, 'ท', THO_THAHAN),
92 (0xB8, 'ธ', THO_THONG),
93 (0xB9, 'น', NO_NU),
94 (0xBA, 'บ', BO_BAIMAI),
95 (0xBB, 'ป', PO_PLA),
96 (0xBC, 'ผ', PHO_PHUNG),
97 (0xBD, 'ฝ', FO_FA),
98 (0xBE, 'พ', PHO_PHAN),
99 (0xBF, 'ฟ', FO_FAN),
100 (0xC0, 'ภ', PHO_SAMPHAO),
101 (0xC1, 'ม', MO_MA),
102 (0xC2, 'ย', YO_YAK),
103 (0xC3, 'ร', RO_RUA),
104 (0xC4, 'ฤ', RU),
105 (0xC5, 'ล', LO_LING),
106 (0xC6, 'ฦ', LU),
107 (0xC7, 'ว', WO_WAEN),
108 (0xC8, 'ศ', SO_SALA),
109 (0xC9, 'ษ', SO_RUSI),
110 (0xCA, 'ส', SO_SUA),
111 (0xCB, 'ห', HO_HIP),
112 (0xCC, 'ฬ', LO_CHULA),
113 (0xCD, 'อ', O_ANG),
114 (0xCE, 'ฮ', HO_NOKHUK),
115 (0xCF, 'ฯ', PAIYANNOI),
116 (0xD0, 'ะ', SARA_A),
117 (0xD1, 'ั', MAI_HAN_AKAT),
118 (0xD2, 'า', SARA_AA),
119 (0xD3, 'ำ', SARA_AM),
120 (0xD4, 'ิ', SARA_I),
121 (0xD5, 'ี', SARA_II),
122 (0xD6, 'ึ', SARA_UE),
123 (0xD7, 'ื', SARA_UEE),
124 (0xD8, 'ุ', SARA_U),
125 (0xD9, 'ู', SARA_UU),
126 (0xDA, 'ฺ', PHINTHU),
127 (0xDF, '฿', BAHT),
128 (0xE0, 'เ', SARA_E),
129 (0xE1, 'แ', SARA_AE),
130 (0xE2, 'โ', SARA_O),
131 (0xE3, 'ใ', SARA_AI_MAIMUAN),
132 (0xE4, 'ไ', SARA_AI_MAIMALAI),
133 (0xE5, 'ๅ', LAKKHANGYAO),
134 (0xE6, 'ๆ', MAIYAMOK),
135 (0xE7, '็', MAITAIKHU),
136 (0xE8, '่', MAI_EK),
137 (0xE9, '้', MAI_THO),
138 (0xEA, '๊', MAI_TRI),
139 (0xEB, '๋', MAI_CHATTAWA),
140 (0xEC, '์', THANTHAKHAT),
141 (0xED, 'ํ', NIKHAHIT),
142 (0xEE, '๎', YAMAKKAN),
143 (0xEF, '๏', FONGMAN),
144 (0xF0, '๐', ZERO),
145 (0xF1, '๑', ONE),
146 (0xF2, '๒', TWO),
147 (0xF3, '๓', THREE),
148 (0xF4, '๔', FOUR),
149 (0xF5, '๕', FIVE),
150 (0xF6, '๖', SIX),
151 (0xF7, '๗', SEVEN),
152 (0xF8, '๘', EIGHT),
153 (0xF9, '๙', NINE),
154 (0xFA, '๚', ANGKHANKHU),
155 (0xFB, '๛', KHOMUT),
156]);
157
158impl Display for ThaiChar {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 f.write_char(self.to_char())
161 }
162}
163
164impl TryFrom<char> for ThaiChar {
165 type Error = ();
166
167 fn try_from(ch: char) -> Result<Self, Self::Error> {
168 ThaiChar::from_char(ch).ok_or(())
169 }
170}
171
172impl From<ThaiChar> for char {
173 fn from(tc: ThaiChar) -> Self {
174 tc.to_char()
175 }
176}
177
178impl From<ThaiChar> for u8 {
179 fn from(tc: ThaiChar) -> Self {
180 tc.to_tis620_byte()
181 }
182}
183
184#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
186pub struct ReplacementChar(u8);
187
188impl ReplacementChar {
189 pub fn from_char(ch: char) -> Option<Self> {
190 let byte = if ch.is_ascii() {
191 ch as u32 as u8
192 } else {
193 ThaiChar::from_char(ch)?.to_tis620_byte()
194 };
195 Some(Self(byte))
196 }
197
198 pub fn to_tis620_byte(self) -> u8 {
199 self.0
200 }
201}