tis620/
chars.rs

1use std::fmt::{self, Display, Write};
2
3macro_rules! declare_thai_char {
4    ([$(($value:literal, $char:literal, $variant:ident)),+ $(,)?]) => {
5        // reference
6        // https://en.wikipedia.org/wiki/Thai_(Unicode_block)
7        // https://en.wikipedia.org/wiki/Thai_Industrial_Standard_620-2533
8        /// An enum represent thai character.
9        #[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/// TIS-620 replacement character.
185#[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}