Skip to main content

mail_parser/decoders/charsets/
map.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7use super::{
8    DecoderFnc,
9    multi_byte::*,
10    single_byte::*,
11    utf::{decoder_utf7, decoder_utf16, decoder_utf16_be, decoder_utf16_le},
12};
13
14pub fn charset_decoder(charset: &[u8]) -> Option<DecoderFnc> {
15    let mut l_charset = [0u8; 45];
16
17    for (dest, src) in l_charset.iter_mut().zip(charset.iter()) {
18        *dest = match src {
19            b'A'..=b'Z' => *src + 32,
20            b'-' => b'_',
21            _ => *src,
22        };
23    }
24
25    hashify::tiny_map!(&l_charset[..charset.len().clamp(1, 45)],
26        "850" => decoder_ibm_850,
27        "866" => decoder_ibm866,
28        "ansi_x3.4_1968" => decoder_cp1252,
29        "arabic" => decoder_iso_8859_6,
30        "ascii" => decoder_cp1252,
31        "asmo_708" => decoder_iso_8859_6,
32        "big5" => decoder_big5,
33        "big5_hkscs" => decoder_big5,
34        "chinese" => decoder_gbk,
35        "cn_big5" => decoder_big5,
36        "cp1250" => decoder_cp1250,
37        "cp1251" => decoder_cp1251,
38        "cp1252" => decoder_cp1252,
39        "cp1253" => decoder_cp1253,
40        "cp1254" => decoder_cp1254,
41        "cp1255" => decoder_cp1255,
42        "cp1256" => decoder_cp1256,
43        "cp1257" => decoder_cp1257,
44        "cp1258" => decoder_cp1258,
45        "cp819" => decoder_cp1252,
46        "cp850" => decoder_ibm_850,
47        "cp866" => decoder_ibm866,
48        "cp936" => decoder_gbk,
49        "csbig5" => decoder_big5,
50        "cseuckr" => decoder_euc_kr,
51        "cseucpkdfmtjapanese" => decoder_euc_jp,
52        "csgb18030" => decoder_gb18030,
53        "csgb2312" => decoder_gbk,
54        "csgbk" => decoder_gbk,
55        "csibm866" => decoder_ibm866,
56        "csiso2022jp" => decoder_iso2022_jp,
57        "csiso2022kr" => decoder_replacement,
58        "csiso58gb231280" => decoder_gbk,
59        "csiso885913" => decoder_iso_8859_13,
60        "csiso885914" => decoder_iso_8859_14,
61        "csiso885915" => decoder_iso_8859_15,
62        "csiso885916" => decoder_iso_8859_16,
63        "csiso88596e" => decoder_iso_8859_6,
64        "csiso88596i" => decoder_iso_8859_6,
65        "csiso88598e" => decoder_iso_8859_8,
66        "csiso88598i" => decoder_iso_8859_8,
67        "csisolatin1" => decoder_cp1252,
68        "csisolatin2" => decoder_iso_8859_2,
69        "csisolatin3" => decoder_iso_8859_3,
70        "csisolatin4" => decoder_iso_8859_4,
71        "csisolatin5" => decoder_iso_8859_9,
72        "csisolatin6" => decoder_iso_8859_10,
73        "csisolatin9" => decoder_iso_8859_15,
74        "csisolatinarabic" => decoder_iso_8859_6,
75        "csisolatincyrillic" => decoder_iso_8859_5,
76        "csisolatingreek" => decoder_iso_8859_7,
77        "csisolatinhebrew" => decoder_iso_8859_8,
78        "cskoi8r" => decoder_koi8_r,
79        "cskoi8u" => decoder_koi8_u,
80        "csksc56011987" => decoder_euc_kr,
81        "csmacintosh" => decoder_macintosh,
82        "cspc850multilingual" => decoder_ibm_850,
83        "csshiftjis" => decoder_shift_jis,
84        "cstis620" => decoder_tis_620,
85        "csunicode" => decoder_utf16,
86        "csutf16" => decoder_utf16,
87        "csutf16be" => decoder_utf16_be,
88        "csutf16le" => decoder_utf16_le,
89        "csutf7" => decoder_utf7,
90        "cswindows1250" => decoder_cp1250,
91        "cswindows1251" => decoder_cp1251,
92        "cswindows1252" => decoder_cp1252,
93        "cswindows1253" => decoder_cp1253,
94        "cswindows1254" => decoder_cp1254,
95        "cswindows1255" => decoder_cp1255,
96        "cswindows1256" => decoder_cp1256,
97        "cswindows1257" => decoder_cp1257,
98        "cswindows1258" => decoder_cp1258,
99        "cswindows874" => decoder_windows874,
100        "cyrillic" => decoder_iso_8859_5,
101        "dos_874" => decoder_windows874,
102        "ecma_114" => decoder_iso_8859_6,
103        "ecma_118" => decoder_iso_8859_7,
104        "elot_928" => decoder_iso_8859_7,
105        "euc_jp" => decoder_euc_jp,
106        "euc_kr" => decoder_euc_kr,
107        "extended_unix_code_packed_format_for_japanese" => decoder_euc_jp,
108        "gb18030" => decoder_gb18030,
109        "gb2312" => decoder_gb18030,
110        "gb_2312" => decoder_gbk,
111        "gb_2312_80" => decoder_gbk,
112        "gbk" => decoder_gbk,
113        "greek" => decoder_iso_8859_7,
114        "greek8" => decoder_iso_8859_7,
115        "hebrew" => decoder_iso_8859_8,
116        "hz_gb_2312" => decoder_replacement,
117        "ibm819" => decoder_cp1252,
118        "ibm850" => decoder_ibm_850,
119        "ibm866" => decoder_ibm866,
120        "iso88591" => decoder_cp1252,
121        "iso885910" => decoder_iso_8859_10,
122        "iso885911" => decoder_tis_620,
123        "iso885913" => decoder_iso_8859_13,
124        "iso885914" => decoder_iso_8859_14,
125        "iso885915" => decoder_iso_8859_15,
126        "iso88592" => decoder_iso_8859_2,
127        "iso88593" => decoder_iso_8859_3,
128        "iso88594" => decoder_iso_8859_4,
129        "iso88595" => decoder_iso_8859_5,
130        "iso88596" => decoder_iso_8859_6,
131        "iso88597" => decoder_iso_8859_7,
132        "iso88598" => decoder_iso_8859_8,
133        "iso88599" => decoder_iso_8859_9,
134        "iso8859_1" => decoder_cp1252,
135        "iso8859_10" => decoder_iso_8859_10,
136        "iso8859_11" => decoder_tis_620,
137        "iso8859_13" => decoder_iso_8859_13,
138        "iso8859_14" => decoder_iso_8859_14,
139        "iso8859_15" => decoder_iso_8859_15,
140        "iso8859_2" => decoder_iso_8859_2,
141        "iso8859_3" => decoder_iso_8859_3,
142        "iso8859_4" => decoder_iso_8859_4,
143        "iso8859_5" => decoder_iso_8859_5,
144        "iso8859_6" => decoder_iso_8859_6,
145        "iso8859_7" => decoder_iso_8859_7,
146        "iso8859_8" => decoder_iso_8859_8,
147        "iso8859_9" => decoder_iso_8859_9,
148        "iso_10646_ucs_2" => decoder_utf16,
149        "iso_2022_cn" => decoder_replacement,
150        "iso_2022_cn_ext" => decoder_replacement,
151        "iso_2022_jp" => decoder_iso2022_jp,
152        "iso_2022_kr" => decoder_replacement,
153        "iso_8859_1" => decoder_cp1252,
154        "iso_8859_10" => decoder_iso_8859_10,
155        "iso_8859_10:1992" => decoder_iso_8859_10,
156        "iso_8859_11" => decoder_tis_620,
157        "iso_8859_13" => decoder_iso_8859_13,
158        "iso_8859_14" => decoder_iso_8859_14,
159        "iso_8859_14:1998" => decoder_iso_8859_14,
160        "iso_8859_15" => decoder_iso_8859_15,
161        "iso_8859_16" => decoder_iso_8859_16,
162        "iso_8859_16:2001" => decoder_iso_8859_16,
163        "iso_8859_1:1987" => decoder_cp1252,
164        "iso_8859_2" => decoder_iso_8859_2,
165        "iso_8859_2:1987" => decoder_iso_8859_2,
166        "iso_8859_3" => decoder_iso_8859_3,
167        "iso_8859_3:1988" => decoder_iso_8859_3,
168        "iso_8859_4" => decoder_iso_8859_4,
169        "iso_8859_4:1988" => decoder_iso_8859_4,
170        "iso_8859_5" => decoder_iso_8859_5,
171        "iso_8859_5:1988" => decoder_iso_8859_5,
172        "iso_8859_6" => decoder_iso_8859_6,
173        "iso_8859_6:1987" => decoder_iso_8859_6,
174        "iso_8859_6_e" => decoder_iso_8859_6,
175        "iso_8859_6_i" => decoder_iso_8859_6,
176        "iso_8859_7" => decoder_iso_8859_7,
177        "iso_8859_7:1987" => decoder_iso_8859_7,
178        "iso_8859_8" => decoder_iso_8859_8,
179        "iso_8859_8:1988" => decoder_iso_8859_8,
180        "iso_8859_8_e" => decoder_iso_8859_8,
181        "iso_8859_8_i" => decoder_iso_8859_8,
182        "iso_8859_9" => decoder_iso_8859_9,
183        "iso_8859_9:1989" => decoder_iso_8859_9,
184        "iso_celtic" => decoder_iso_8859_14,
185        "iso_ir_100" => decoder_cp1252,
186        "iso_ir_101" => decoder_iso_8859_2,
187        "iso_ir_109" => decoder_iso_8859_3,
188        "iso_ir_110" => decoder_iso_8859_4,
189        "iso_ir_126" => decoder_iso_8859_7,
190        "iso_ir_127" => decoder_iso_8859_6,
191        "iso_ir_138" => decoder_iso_8859_8,
192        "iso_ir_144" => decoder_iso_8859_5,
193        "iso_ir_148" => decoder_iso_8859_9,
194        "iso_ir_149" => decoder_euc_kr,
195        "iso_ir_157" => decoder_iso_8859_10,
196        "iso_ir_199" => decoder_iso_8859_14,
197        "iso_ir_226" => decoder_iso_8859_16,
198        "iso_ir_58" => decoder_gbk,
199        "koi" => decoder_koi8_r,
200        "koi8" => decoder_koi8_r,
201        "koi8_r" => decoder_koi8_r,
202        "koi8_ru" => decoder_koi8_u,
203        "koi8_u" => decoder_koi8_u,
204        "korean" => decoder_euc_kr,
205        "ks_c_5601_1987" => decoder_euc_kr,
206        "ks_c_5601_1989" => decoder_euc_kr,
207        "ksc5601" => decoder_euc_kr,
208        "ksc_5601" => decoder_euc_kr,
209        "l1" => decoder_cp1252,
210        "l10" => decoder_iso_8859_16,
211        "l2" => decoder_iso_8859_2,
212        "l3" => decoder_iso_8859_3,
213        "l4" => decoder_iso_8859_4,
214        "l5" => decoder_iso_8859_9,
215        "l6" => decoder_iso_8859_10,
216        "l8" => decoder_iso_8859_14,
217        "l9" => decoder_iso_8859_15,
218        "latin1" => decoder_cp1252,
219        "latin10" => decoder_iso_8859_16,
220        "latin2" => decoder_iso_8859_2,
221        "latin3" => decoder_iso_8859_3,
222        "latin4" => decoder_iso_8859_4,
223        "latin5" => decoder_iso_8859_9,
224        "latin6" => decoder_iso_8859_10,
225        "latin8" => decoder_iso_8859_14,
226        "latin_9" => decoder_iso_8859_15,
227        "logical" => decoder_iso_8859_8,
228        "mac" => decoder_macintosh,
229        "macintosh" => decoder_macintosh,
230        "ms932" => decoder_shift_jis,
231        "ms936" => decoder_gbk,
232        "ms_kanji" => decoder_shift_jis,
233        "replacement" => decoder_replacement,
234        "shift_jis" => decoder_shift_jis,
235        "sjis" => decoder_shift_jis,
236        "sun_eu_greek" => decoder_iso_8859_7,
237        "tis_620" => decoder_tis_620,
238        "ucs_2" => decoder_utf16,
239        "unicode" => decoder_utf16,
240        "unicodefeff" => decoder_utf16,
241        "unicodefffe" => decoder_utf16_be,
242        "us_ascii" => decoder_cp1252,
243        "utf_16" => decoder_utf16,
244        "utf_16be" => decoder_utf16_be,
245        "utf_16le" => decoder_utf16_le,
246        "utf_7" => decoder_utf7,
247        "visual" => decoder_iso_8859_8,
248        "windows_1250" => decoder_cp1250,
249        "windows_1251" => decoder_cp1251,
250        "windows_1252" => decoder_cp1252,
251        "windows_1253" => decoder_cp1253,
252        "windows_1254" => decoder_cp1254,
253        "windows_1255" => decoder_cp1255,
254        "windows_1256" => decoder_cp1256,
255        "windows_1257" => decoder_cp1257,
256        "windows_1258" => decoder_cp1258,
257        "windows_31j" => decoder_shift_jis,
258        "windows_874" => decoder_windows874,
259        "windows_936" => decoder_gbk,
260        "windows_949" => decoder_euc_kr,
261        "x_cp1250" => decoder_cp1250,
262        "x_cp1251" => decoder_cp1251,
263        "x_cp1252" => decoder_cp1252,
264        "x_cp1253" => decoder_cp1253,
265        "x_cp1254" => decoder_cp1254,
266        "x_cp1255" => decoder_cp1255,
267        "x_cp1256" => decoder_cp1256,
268        "x_cp1257" => decoder_cp1257,
269        "x_cp1258" => decoder_cp1258,
270        "x_euc_jp" => decoder_euc_jp,
271        "x_gbk" => decoder_gbk,
272        "x_mac_cyrillic" => decoder_x_mac_cyrillic,
273        "x_mac_roman" => decoder_macintosh,
274        "x_mac_ukrainian" => decoder_x_mac_cyrillic,
275        "x_sjis" => decoder_shift_jis,
276        "x_user_defined" => decoder_x_user_defined,
277        "x_x_big5" => decoder_big5,
278    )
279}
280
281#[cfg(test)]
282mod tests {
283    use super::charset_decoder;
284
285    #[test]
286    fn decoder_charset() {
287        for input in ["gbk", "extended_unix_code_packed_format_for_japanese"] {
288            if !input.is_empty() {
289                assert!(
290                    charset_decoder(input.as_bytes()).is_some(),
291                    "Failed for {input}",
292                );
293            }
294        }
295    }
296
297    #[test]
298    fn decoder_charset_encoding_rs_labels() {
299        let supported = [
300            "l9", "koi", "koi8", "sjis", "ucs-2", "ms932", "ascii", "x-gbk", "cp1250", "cp1251",
301            "cp1252", "cp1253", "cp1254", "cp1255", "cp1256", "cp1257", "cp1258", "visual",
302            "korean", "x-sjis", "ksc5601", "gb_2312", "dos-874", "cn-big5", "unicode", "chinese",
303            "logical", "koi8-ru", "x-cp1250", "ksc_5601", "x-cp1251", "iso88591", "csgb2312",
304            "x-cp1252", "iso88592", "x-cp1253", "iso88593", "x-cp1254", "iso88594", "x-cp1255",
305            "iso88595", "x-x-big5", "x-cp1256", "iso88596", "x-cp1257", "iso88597", "x-cp1258",
306            "iso88598", "iso88599", "us-ascii", "x-euc-jp", "iso885910", "iso8859-1", "iso885911",
307            "iso8859-2", "iso8859-3", "iso885913", "iso8859-4", "iso885914", "iso8859-5",
308            "iso885915", "iso8859-6", "iso8859-7", "iso8859-8", "iso-ir-58", "iso8859-9",
309            "csunicode", "iso8859-10", "gb_2312-80", "iso8859-11", "iso8859-13", "iso8859-14",
310            "iso8859-15", "iso-ir-149", "big5-hkscs", "windows-949", "csisolatin9", "csiso88596e",
311            "csiso88598e", "unicodefffe", "unicodefeff", "csiso88596i", "csiso88598i", "windows-31j",
312            "x-mac-roman", "sun_eu_greek", "csksc56011987", "ansi_x3.4-1968", "csiso58gb231280",
313            "iso-10646-ucs-2", "iso-8859-6-e", "iso-8859-8-e", "iso-8859-6-i", "replacement",
314            "iso-2022-kr", "csiso2022kr", "iso-2022-cn", "iso-2022-cn-ext", "hz-gb-2312",
315            "x-user-defined", "x-mac-cyrillic", "x-mac-ukrainian",
316        ];
317        for input in supported {
318            assert!(
319                charset_decoder(input.as_bytes()).is_some(),
320                "Expected a decoder for {input}",
321            );
322        }
323
324        let unsupported = [
325            "utf8", "utf-8", "unicode11utf8", "unicode20utf8", "x-unicode20utf8",
326            "unicode-1-1-utf-8",
327        ];
328        for input in unsupported {
329            assert!(
330                charset_decoder(input.as_bytes()).is_none(),
331                "Did not expect a decoder for {input}",
332            );
333        }
334    }
335}