1use encoding_rs::Encoding;
10use std::fmt;
11
12use crate::error::Error;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct Collation {
18 info: u32,
20 sort_id: u8,
22}
23
24impl Collation {
25 pub fn new(info: u32, sort_id: u8) -> Self {
27 Self { info, sort_id }
28 }
29
30 pub fn lcid(&self) -> u16 {
32 (self.info & 0xffff) as u16
33 }
34
35 pub fn sort_id(&self) -> u8 {
37 self.sort_id
38 }
39
40 pub fn info(&self) -> u32 {
42 self.info
43 }
44
45 pub fn encoding(&self) -> crate::Result<&'static Encoding> {
50 if self.info & UTF8_FLAG != 0 {
53 return Ok(encoding_rs::UTF_8);
54 }
55
56 let res = if self.sort_id == 0 {
57 lcid_to_encoding(self.lcid())
58 } else {
59 sortid_to_encoding(self.sort_id)
60 };
61
62 res.ok_or_else(|| {
63 Error::Encoding(
64 format!(
65 "encoding: unspported encoding (LCID: {:#04x}, sort ID: {})",
66 self.lcid(),
67 self.sort_id(),
68 )
69 .into(),
70 )
71 })
72 }
73
74 pub(crate) fn charset(&self) -> crate::Result<Charset> {
76 match self.sort_id {
77 30..=35 => Ok(Charset::Oem(&CP437)),
78 40..=45 | 49 | 55..=61 => Ok(Charset::Oem(&CP850)),
79 _ => self.encoding().map(Charset::Encoding),
80 }
81 }
82}
83
84impl fmt::Display for Collation {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self.charset() {
87 Ok(Charset::Encoding(encoding)) => write!(f, "{}", encoding.name()),
88 Ok(Charset::Oem(table)) if std::ptr::eq(table, &CP437) => write!(f, "IBM437"),
89 Ok(Charset::Oem(_)) => write!(f, "IBM850"),
90 _ => write!(f, "None"),
91 }
92 }
93}
94
95const UTF8_FLAG: u32 = 0x0400_0000;
97
98#[derive(Clone, Copy, Debug)]
99pub(crate) enum Charset {
100 Encoding(&'static Encoding),
101 Oem(&'static [char; 128]),
104}
105
106pub(crate) fn decode_oem(table: &[char; 128], buf: &[u8]) -> String {
107 buf.iter()
108 .map(|&b| match b {
109 0..=0x7f => b as char,
110 _ => table[b as usize - 0x80],
111 })
112 .collect()
113}
114
115pub(crate) fn encode_oem(table: &[char; 128], s: &str) -> crate::Result<Vec<u8>> {
116 s.chars()
117 .map(|c| match c {
118 '\0'..='\x7f' => Ok(c as u8),
119 _ => table
120 .iter()
121 .position(|&t| t == c)
122 .map(|i| 0x80 + i as u8)
123 .ok_or_else(|| {
124 Error::Encoding(
125 format!("{c:?} has no representation in the OEM code page").into(),
126 )
127 }),
128 })
129 .collect()
130}
131
132#[rustfmt::skip]
134static CP437: [char; 128] = [
135 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
136 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', '¢', '£', '¥', '₧', 'ƒ',
137 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
138 '░', '▒', '▓', '│', '┤', '╡', '╢', '╖', '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
139 '└', '┴', '┬', '├', '─', '┼', '╞', '╟', '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
140 '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫', '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
141 'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
142 '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∙', '·', '√', 'ⁿ', '²', '■', '\u{a0}',
143];
144
145#[rustfmt::skip]
146static CP850: [char; 128] = [
147 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
148 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', 'ø', '£', 'Ø', '×', 'ƒ',
149 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '®', '¬', '½', '¼', '¡', '«', '»',
150 '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'À', '©', '╣', '║', '╗', '╝', '¢', '¥', '┐',
151 '└', '┴', '┬', '├', '─', '┼', 'ã', 'Ã', '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
152 'ð', 'Ð', 'Ê', 'Ë', 'È', 'ı', 'Í', 'Î', 'Ï', '┘', '┌', '█', '▄', '¦', 'Ì', '▀',
153 'Ó', 'ß', 'Ô', 'Ò', 'õ', 'Õ', 'µ', 'þ', 'Þ', 'Ú', 'Û', 'Ù', 'ý', 'Ý', '¯', '´',
154 '\u{ad}', '±', '‗', '¾', '¶', '§', '÷', '¸', '°', '¨', '·', '¹', '³', '²', '■', '\u{a0}',
155];
156
157pub fn lcid_to_encoding(locale: u16) -> Option<&'static Encoding> {
167 match locale {
168 0x0401 => Some(encoding_rs::WINDOWS_1256),
169 0x0402 => Some(encoding_rs::WINDOWS_1251),
170 0x0403 => Some(encoding_rs::WINDOWS_1252),
171 0x0404 | 0x0c04 | 0x1404 => Some(encoding_rs::BIG5),
173 0x0405 => Some(encoding_rs::WINDOWS_1250),
174 0x0406 => Some(encoding_rs::WINDOWS_1252),
175 0x0407 => Some(encoding_rs::WINDOWS_1252),
176 0x0408 => Some(encoding_rs::WINDOWS_1253),
177 0x0409 => Some(encoding_rs::WINDOWS_1252),
178 0x040a => Some(encoding_rs::WINDOWS_1252),
179 0x040b => Some(encoding_rs::WINDOWS_1252),
180 0x040c => Some(encoding_rs::WINDOWS_1252),
181 0x040d => Some(encoding_rs::WINDOWS_1255),
182 0x040e => Some(encoding_rs::WINDOWS_1250),
183 0x040f => Some(encoding_rs::WINDOWS_1252),
184 0x0410 => Some(encoding_rs::WINDOWS_1252),
185 0x0411 => Some(encoding_rs::SHIFT_JIS),
187 0x0412 => Some(encoding_rs::EUC_KR),
188 0x0413 => Some(encoding_rs::WINDOWS_1252),
189 0x0414 => Some(encoding_rs::WINDOWS_1252),
190 0x0415 => Some(encoding_rs::WINDOWS_1250),
191 0x0416 => Some(encoding_rs::WINDOWS_1252),
192 0x0417 => Some(encoding_rs::WINDOWS_1252),
193 0x0418 => Some(encoding_rs::WINDOWS_1250),
194 0x0419 => Some(encoding_rs::WINDOWS_1251),
195 0x041a => Some(encoding_rs::WINDOWS_1250),
196 0x041b => Some(encoding_rs::WINDOWS_1250),
197 0x041c => Some(encoding_rs::WINDOWS_1250),
198 0x041d => Some(encoding_rs::WINDOWS_1252),
199 0x041e => Some(encoding_rs::WINDOWS_874),
200 0x041f => Some(encoding_rs::WINDOWS_1254),
201 0x0420 => Some(encoding_rs::WINDOWS_1256),
202 0x0421 => Some(encoding_rs::WINDOWS_1252),
203 0x0422 => Some(encoding_rs::WINDOWS_1251),
204 0x0423 => Some(encoding_rs::WINDOWS_1251),
205 0x0424 => Some(encoding_rs::WINDOWS_1250),
206 0x0425 => Some(encoding_rs::WINDOWS_1257),
207 0x0426 => Some(encoding_rs::WINDOWS_1257),
208 0x0427 => Some(encoding_rs::WINDOWS_1257),
209 0x0428 => Some(encoding_rs::WINDOWS_1251),
210 0x0429 => Some(encoding_rs::WINDOWS_1256),
211 0x042a => Some(encoding_rs::WINDOWS_1258),
212 0x042b => Some(encoding_rs::WINDOWS_1252),
213 0x042c => Some(encoding_rs::WINDOWS_1254),
214 0x042d => Some(encoding_rs::WINDOWS_1252),
215 0x042e => Some(encoding_rs::WINDOWS_1252),
216 0x042f => Some(encoding_rs::WINDOWS_1251),
217 0x0432 => Some(encoding_rs::WINDOWS_1252),
218 0x0434 => Some(encoding_rs::WINDOWS_1252),
219 0x0435 => Some(encoding_rs::WINDOWS_1252),
220 0x0436 => Some(encoding_rs::WINDOWS_1252),
221 0x0437 => Some(encoding_rs::WINDOWS_1252),
222 0x0438 => Some(encoding_rs::WINDOWS_1252),
223 0x0439 => Some(encoding_rs::UTF_16LE),
224 0x043a => Some(encoding_rs::UTF_16LE),
225 0x043b => Some(encoding_rs::WINDOWS_1252),
226 0x043e => Some(encoding_rs::WINDOWS_1252),
227 0x043f => Some(encoding_rs::WINDOWS_1251),
228 0x0440 => Some(encoding_rs::WINDOWS_1251),
229 0x0441 => Some(encoding_rs::WINDOWS_1252),
230 0x0442 => Some(encoding_rs::WINDOWS_1250),
231 0x0443 => Some(encoding_rs::WINDOWS_1254),
232 0x0444 => Some(encoding_rs::WINDOWS_1251),
233 0x0445 => Some(encoding_rs::UTF_16LE),
234 0x0446 => Some(encoding_rs::UTF_16LE),
235 0x0447 => Some(encoding_rs::UTF_16LE),
236 0x0448 => Some(encoding_rs::UTF_16LE),
237 0x0449 => Some(encoding_rs::UTF_16LE),
238 0x044a => Some(encoding_rs::UTF_16LE),
239 0x044b => Some(encoding_rs::UTF_16LE),
240 0x044c => Some(encoding_rs::UTF_16LE),
241 0x044d => Some(encoding_rs::UTF_16LE),
242 0x044e => Some(encoding_rs::UTF_16LE),
243 0x044f => Some(encoding_rs::UTF_16LE),
244 0x0450 => Some(encoding_rs::WINDOWS_1251),
245 0x0451 => Some(encoding_rs::UTF_16LE),
246 0x0452 => Some(encoding_rs::WINDOWS_1252),
247 0x0453 => Some(encoding_rs::UTF_16LE),
248 0x0454 => Some(encoding_rs::UTF_16LE),
249 0x0456 => Some(encoding_rs::WINDOWS_1252),
250 0x0457 => Some(encoding_rs::UTF_16LE),
251 0x045a => Some(encoding_rs::UTF_16LE),
252 0x045b => Some(encoding_rs::UTF_16LE),
253 0x045d => Some(encoding_rs::WINDOWS_1252),
254 0x045e => Some(encoding_rs::WINDOWS_1252),
255 0x0461 => Some(encoding_rs::UTF_16LE),
256 0x0462 => Some(encoding_rs::WINDOWS_1252),
257 0x0463 => Some(encoding_rs::UTF_16LE),
258 0x0464 => Some(encoding_rs::WINDOWS_1252),
259 0x0465 => Some(encoding_rs::UTF_16LE),
260 0x0468 => Some(encoding_rs::WINDOWS_1252),
261 0x046a => Some(encoding_rs::WINDOWS_1252),
262 0x046b => Some(encoding_rs::WINDOWS_1252),
263 0x046c => Some(encoding_rs::WINDOWS_1252),
264 0x046d => Some(encoding_rs::WINDOWS_1251),
265 0x046e => Some(encoding_rs::WINDOWS_1252),
266 0x046f => Some(encoding_rs::WINDOWS_1252),
267 0x0470 => Some(encoding_rs::WINDOWS_1252),
268 0x0478 => Some(encoding_rs::WINDOWS_1252),
269 0x047a => Some(encoding_rs::WINDOWS_1252),
270 0x047c => Some(encoding_rs::WINDOWS_1252),
271 0x047e => Some(encoding_rs::WINDOWS_1252),
272 0x0480 => Some(encoding_rs::WINDOWS_1256),
273 0x0481 => Some(encoding_rs::UTF_16LE),
274 0x0482 => Some(encoding_rs::WINDOWS_1252),
275 0x0483 => Some(encoding_rs::WINDOWS_1252),
276 0x0484 => Some(encoding_rs::WINDOWS_1252),
277 0x0485 => Some(encoding_rs::WINDOWS_1251),
278 0x0486 => Some(encoding_rs::WINDOWS_1252),
279 0x0487 => Some(encoding_rs::WINDOWS_1252),
280 0x0488 => Some(encoding_rs::WINDOWS_1252),
281 0x048c => Some(encoding_rs::WINDOWS_1256),
282 0x0801 => Some(encoding_rs::WINDOWS_1256),
283 0x0804 | 0x1004 => Some(encoding_rs::GB18030),
285 0x0807 => Some(encoding_rs::WINDOWS_1252),
286 0x0809 => Some(encoding_rs::WINDOWS_1252),
287 0x080a => Some(encoding_rs::WINDOWS_1252),
288 0x080c => Some(encoding_rs::WINDOWS_1252),
289 0x0810 => Some(encoding_rs::WINDOWS_1252),
290 0x0813 => Some(encoding_rs::WINDOWS_1252),
291 0x0814 => Some(encoding_rs::WINDOWS_1252),
292 0x0816 => Some(encoding_rs::WINDOWS_1252),
293 0x081a => Some(encoding_rs::WINDOWS_1250),
294 0x081d => Some(encoding_rs::WINDOWS_1252),
295 0x0827 => Some(encoding_rs::WINDOWS_1257),
296 0x082c => Some(encoding_rs::WINDOWS_1251),
297 0x082e => Some(encoding_rs::WINDOWS_1252),
298 0x083b => Some(encoding_rs::WINDOWS_1252),
299 0x083c => Some(encoding_rs::WINDOWS_1252),
300 0x083e => Some(encoding_rs::WINDOWS_1252),
301 0x0843 => Some(encoding_rs::WINDOWS_1251),
302 0x0845 => Some(encoding_rs::UTF_16LE),
303 0x0850 => Some(encoding_rs::WINDOWS_1251),
304 0x085d => Some(encoding_rs::WINDOWS_1252),
305 0x085f => Some(encoding_rs::WINDOWS_1252),
306 0x086b => Some(encoding_rs::WINDOWS_1252),
307 0x0c01 => Some(encoding_rs::WINDOWS_1256),
308 0x0c07 => Some(encoding_rs::WINDOWS_1252),
309 0x0c09 => Some(encoding_rs::WINDOWS_1252),
310 0x0c0a => Some(encoding_rs::WINDOWS_1252),
311 0x0c0c => Some(encoding_rs::WINDOWS_1252),
312 0x0c1a => Some(encoding_rs::WINDOWS_1251),
313 0x0c3b => Some(encoding_rs::WINDOWS_1252),
314 0x0c6b => Some(encoding_rs::WINDOWS_1252),
315 0x1001 => Some(encoding_rs::WINDOWS_1256),
316 0x1007 => Some(encoding_rs::WINDOWS_1252),
317 0x1009 => Some(encoding_rs::WINDOWS_1252),
318 0x100a => Some(encoding_rs::WINDOWS_1252),
319 0x100c => Some(encoding_rs::WINDOWS_1252),
320 0x101a => Some(encoding_rs::WINDOWS_1250),
321 0x103b => Some(encoding_rs::WINDOWS_1252),
322 0x1401 => Some(encoding_rs::WINDOWS_1256),
323 0x1407 => Some(encoding_rs::WINDOWS_1252),
324 0x1409 => Some(encoding_rs::WINDOWS_1252),
325 0x140a => Some(encoding_rs::WINDOWS_1252),
326 0x140c => Some(encoding_rs::WINDOWS_1252),
327 0x141a => Some(encoding_rs::WINDOWS_1250),
328 0x143b => Some(encoding_rs::WINDOWS_1252),
329 0x1801 => Some(encoding_rs::WINDOWS_1256),
330 0x1809 => Some(encoding_rs::WINDOWS_1252),
331 0x180a => Some(encoding_rs::WINDOWS_1252),
332 0x180c => Some(encoding_rs::WINDOWS_1252),
333 0x181a => Some(encoding_rs::WINDOWS_1250),
334 0x183b => Some(encoding_rs::WINDOWS_1252),
335 0x1c01 => Some(encoding_rs::WINDOWS_1256),
336 0x1c09 => Some(encoding_rs::WINDOWS_1252),
337 0x1c0a => Some(encoding_rs::WINDOWS_1252),
338 0x1c1a => Some(encoding_rs::WINDOWS_1251),
339 0x1c3b => Some(encoding_rs::WINDOWS_1252),
340 0x2001 => Some(encoding_rs::WINDOWS_1256),
341 0x2009 => Some(encoding_rs::WINDOWS_1252),
342 0x200a => Some(encoding_rs::WINDOWS_1252),
343 0x201a => Some(encoding_rs::WINDOWS_1251),
344 0x203b => Some(encoding_rs::WINDOWS_1252),
345 0x2401 => Some(encoding_rs::WINDOWS_1256),
346 0x2409 => Some(encoding_rs::WINDOWS_1252),
347 0x240a => Some(encoding_rs::WINDOWS_1252),
348 0x243b => Some(encoding_rs::WINDOWS_1252),
349 0x2801 => Some(encoding_rs::WINDOWS_1256),
350 0x2809 => Some(encoding_rs::WINDOWS_1252),
351 0x280a => Some(encoding_rs::WINDOWS_1252),
352 0x2c01 => Some(encoding_rs::WINDOWS_1256),
353 0x2c09 => Some(encoding_rs::WINDOWS_1252),
354 0x2c0a => Some(encoding_rs::WINDOWS_1252),
355 0x3001 => Some(encoding_rs::WINDOWS_1256),
356 0x3009 => Some(encoding_rs::WINDOWS_1252),
357 0x300a => Some(encoding_rs::WINDOWS_1252),
358 0x3401 => Some(encoding_rs::WINDOWS_1256),
359 0x3409 => Some(encoding_rs::WINDOWS_1252),
360 0x340a => Some(encoding_rs::WINDOWS_1252),
361 0x3801 => Some(encoding_rs::WINDOWS_1256),
362 0x380a => Some(encoding_rs::WINDOWS_1252),
363 0x3c01 => Some(encoding_rs::WINDOWS_1256),
364 0x3c0a => Some(encoding_rs::WINDOWS_1252),
365 0x4001 => Some(encoding_rs::WINDOWS_1256),
366 0x4009 => Some(encoding_rs::WINDOWS_1252),
367 0x400a => Some(encoding_rs::WINDOWS_1252),
368 0x4409 => Some(encoding_rs::WINDOWS_1252),
369 0x440a => Some(encoding_rs::WINDOWS_1252),
370 0x4809 => Some(encoding_rs::WINDOWS_1252),
371 0x480a => Some(encoding_rs::WINDOWS_1252),
372 0x4c0a => Some(encoding_rs::WINDOWS_1252),
373 0x500a => Some(encoding_rs::WINDOWS_1252),
374 0x540a => Some(encoding_rs::WINDOWS_1252),
375 _ => None,
376 }
377}
378
379pub fn sortid_to_encoding(sort_id: u8) -> Option<&'static Encoding> {
388 match sort_id {
389 50 => Some(encoding_rs::WINDOWS_1252),
392 51 => Some(encoding_rs::WINDOWS_1252),
393 52 => Some(encoding_rs::WINDOWS_1252),
394 53 => Some(encoding_rs::WINDOWS_1252),
395 54 => Some(encoding_rs::WINDOWS_1252),
396 71 => Some(encoding_rs::WINDOWS_1252),
398 72 => Some(encoding_rs::WINDOWS_1252),
399 73 => Some(encoding_rs::WINDOWS_1252),
400 74 => Some(encoding_rs::WINDOWS_1252),
401 75 => Some(encoding_rs::WINDOWS_1252),
402 80 => Some(encoding_rs::WINDOWS_1250),
403 81 => Some(encoding_rs::WINDOWS_1250),
404 82 => Some(encoding_rs::WINDOWS_1250),
405 83 => Some(encoding_rs::WINDOWS_1250),
406 84 => Some(encoding_rs::WINDOWS_1250),
407 85 => Some(encoding_rs::WINDOWS_1250),
408 86 => Some(encoding_rs::WINDOWS_1250),
409 87 => Some(encoding_rs::WINDOWS_1250),
410 88 => Some(encoding_rs::WINDOWS_1250),
411 89 => Some(encoding_rs::WINDOWS_1250),
412 90 => Some(encoding_rs::WINDOWS_1250),
413 91 => Some(encoding_rs::WINDOWS_1250),
414 92 => Some(encoding_rs::WINDOWS_1250),
415 93 => Some(encoding_rs::WINDOWS_1250),
416 94 => Some(encoding_rs::WINDOWS_1250),
417 95 => Some(encoding_rs::WINDOWS_1250),
418 96 => Some(encoding_rs::WINDOWS_1250),
419 97 => Some(encoding_rs::WINDOWS_1250),
420 98 => Some(encoding_rs::WINDOWS_1250),
421 104 => Some(encoding_rs::WINDOWS_1251),
422 105 => Some(encoding_rs::WINDOWS_1251),
423 106 => Some(encoding_rs::WINDOWS_1251),
424 107 => Some(encoding_rs::WINDOWS_1251),
425 108 => Some(encoding_rs::WINDOWS_1251),
426 112 => Some(encoding_rs::WINDOWS_1253),
427 113 => Some(encoding_rs::WINDOWS_1253),
428 114 => Some(encoding_rs::WINDOWS_1253),
429 120 => Some(encoding_rs::WINDOWS_1253),
430 121 => Some(encoding_rs::WINDOWS_1253),
431 122 => Some(encoding_rs::WINDOWS_1253),
432 124 => Some(encoding_rs::WINDOWS_1253),
433 128 => Some(encoding_rs::WINDOWS_1254),
434 129 => Some(encoding_rs::WINDOWS_1254),
435 130 => Some(encoding_rs::WINDOWS_1254),
436 136 => Some(encoding_rs::WINDOWS_1255),
437 137 => Some(encoding_rs::WINDOWS_1255),
438 138 => Some(encoding_rs::WINDOWS_1255),
439 144 => Some(encoding_rs::WINDOWS_1256),
440 145 => Some(encoding_rs::WINDOWS_1256),
441 146 => Some(encoding_rs::WINDOWS_1256),
442 152 => Some(encoding_rs::WINDOWS_1257),
443 153 => Some(encoding_rs::WINDOWS_1257),
444 154 => Some(encoding_rs::WINDOWS_1257),
445 155 => Some(encoding_rs::WINDOWS_1257),
446 156 => Some(encoding_rs::WINDOWS_1257),
447 157 => Some(encoding_rs::WINDOWS_1257),
448 158 => Some(encoding_rs::WINDOWS_1257),
449 159 => Some(encoding_rs::WINDOWS_1257),
450 160 => Some(encoding_rs::WINDOWS_1257),
451 183 => Some(encoding_rs::WINDOWS_1252),
452 184 => Some(encoding_rs::WINDOWS_1252),
453 185 => Some(encoding_rs::WINDOWS_1252),
454 186 => Some(encoding_rs::WINDOWS_1252),
455 192 | 193 | 200 => Some(encoding_rs::SHIFT_JIS),
457 194 => Some(encoding_rs::EUC_KR),
458 195 => Some(encoding_rs::EUC_KR),
459 196 | 197 | 202 => Some(encoding_rs::BIG5),
461 198 | 199 | 203 => Some(encoding_rs::GB18030),
463 201 => Some(encoding_rs::BIG5),
464 204 => Some(encoding_rs::WINDOWS_874),
465 205 => Some(encoding_rs::WINDOWS_874),
466 206 => Some(encoding_rs::WINDOWS_874),
467 210 => Some(encoding_rs::WINDOWS_1252),
468 211 => Some(encoding_rs::WINDOWS_1252),
469 212 => Some(encoding_rs::WINDOWS_1252),
470 213 => Some(encoding_rs::WINDOWS_1252),
471 214 => Some(encoding_rs::WINDOWS_1252),
472 215 => Some(encoding_rs::WINDOWS_1252),
473 216 => Some(encoding_rs::WINDOWS_1252),
474 217 => Some(encoding_rs::WINDOWS_1252),
475 _ => None,
476 }
477}
478
479#[cfg(test)]
480mod tests {
481 use super::*;
482
483 #[test]
484 fn accessors_split_info_and_sort_id() {
485 let collation = Collation::new(0x0020_0409, 52);
487 assert_eq!(collation.info(), 0x0020_0409);
488 assert_eq!(collation.lcid(), 0x0409);
489 assert_eq!(collation.sort_id(), 52);
490 }
491
492 #[test]
493 fn encoding_from_lcid_when_sort_id_zero() {
494 let collation = Collation::new(0x0409, 0);
496 let encoding = collation.encoding().expect("known LCID must resolve");
497 assert_eq!(encoding, encoding_rs::WINDOWS_1252);
498 }
499
500 #[test]
501 fn encoding_from_sort_id_when_present() {
502 let collation = Collation::new(0x0405, 80);
504 let encoding = collation.encoding().expect("known sort id must resolve");
505 assert_eq!(encoding, encoding_rs::WINDOWS_1250);
506 }
507
508 #[test]
509 fn encoding_unknown_lcid_errors() {
510 let collation = Collation::new(0xFFFF, 0);
511 let err = collation.encoding().unwrap_err();
512 assert!(matches!(err, Error::Encoding(_)));
513 }
514
515 #[test]
516 fn encoding_unknown_sort_id_errors() {
517 let collation = Collation::new(0x0409, 250);
518 assert!(collation.encoding().is_err());
519 }
520
521 #[test]
522 fn display_uses_encoding_name() {
523 let collation = Collation::new(0x0409, 0);
524 assert_eq!(format!("{}", collation), encoding_rs::WINDOWS_1252.name());
525 }
526
527 #[test]
528 fn display_falls_back_to_none_on_unknown() {
529 let collation = Collation::new(0xFFFF, 0);
530 assert_eq!(format!("{}", collation), "None");
531 }
532
533 #[test]
534 fn lcid_to_encoding_known_and_unknown() {
535 assert_eq!(lcid_to_encoding(0x0401), Some(encoding_rs::WINDOWS_1256));
536 assert_eq!(lcid_to_encoding(0x0404), Some(encoding_rs::BIG5));
537 assert_eq!(lcid_to_encoding(0x0411), Some(encoding_rs::SHIFT_JIS));
538 assert_eq!(lcid_to_encoding(0x0412), Some(encoding_rs::EUC_KR));
539 assert_eq!(lcid_to_encoding(0x0804), Some(encoding_rs::GB18030));
540 assert_eq!(lcid_to_encoding(0x0439), Some(encoding_rs::UTF_16LE));
541 assert_eq!(lcid_to_encoding(0x041e), Some(encoding_rs::WINDOWS_874));
542 assert_eq!(lcid_to_encoding(0x0000), None);
543 }
544
545 #[test]
546 fn sortid_to_encoding_known_and_unknown() {
547 assert_eq!(sortid_to_encoding(50), Some(encoding_rs::WINDOWS_1252));
548 assert_eq!(sortid_to_encoding(80), Some(encoding_rs::WINDOWS_1250));
549 assert_eq!(sortid_to_encoding(104), Some(encoding_rs::WINDOWS_1251));
550 assert_eq!(sortid_to_encoding(112), Some(encoding_rs::WINDOWS_1253));
551 assert_eq!(sortid_to_encoding(192), Some(encoding_rs::SHIFT_JIS));
552 assert_eq!(sortid_to_encoding(194), Some(encoding_rs::EUC_KR));
553 assert_eq!(sortid_to_encoding(196), Some(encoding_rs::BIG5));
554 assert_eq!(sortid_to_encoding(198), Some(encoding_rs::GB18030));
555 assert_eq!(sortid_to_encoding(204), Some(encoding_rs::WINDOWS_874));
556 assert_eq!(sortid_to_encoding(0), None);
557 assert_eq!(sortid_to_encoding(255), None);
558 }
559
560 #[test]
561 fn lcid_to_encoding_covers_all_documented_locales() {
562 let cases: &[(u16, &encoding_rs::Encoding)] = &[
563 (0x0401, encoding_rs::WINDOWS_1256),
564 (0x0402, encoding_rs::WINDOWS_1251),
565 (0x0403, encoding_rs::WINDOWS_1252),
566 (0x0404, encoding_rs::BIG5),
567 (0x0c04, encoding_rs::BIG5),
568 (0x1404, encoding_rs::BIG5),
569 (0x0405, encoding_rs::WINDOWS_1250),
570 (0x0406, encoding_rs::WINDOWS_1252),
571 (0x0407, encoding_rs::WINDOWS_1252),
572 (0x0408, encoding_rs::WINDOWS_1253),
573 (0x0409, encoding_rs::WINDOWS_1252),
574 (0x040a, encoding_rs::WINDOWS_1252),
575 (0x040b, encoding_rs::WINDOWS_1252),
576 (0x040c, encoding_rs::WINDOWS_1252),
577 (0x040d, encoding_rs::WINDOWS_1255),
578 (0x040e, encoding_rs::WINDOWS_1250),
579 (0x040f, encoding_rs::WINDOWS_1252),
580 (0x0410, encoding_rs::WINDOWS_1252),
581 (0x0411, encoding_rs::SHIFT_JIS),
582 (0x0412, encoding_rs::EUC_KR),
583 (0x0413, encoding_rs::WINDOWS_1252),
584 (0x0414, encoding_rs::WINDOWS_1252),
585 (0x0415, encoding_rs::WINDOWS_1250),
586 (0x0416, encoding_rs::WINDOWS_1252),
587 (0x0417, encoding_rs::WINDOWS_1252),
588 (0x0418, encoding_rs::WINDOWS_1250),
589 (0x0419, encoding_rs::WINDOWS_1251),
590 (0x041a, encoding_rs::WINDOWS_1250),
591 (0x041b, encoding_rs::WINDOWS_1250),
592 (0x041c, encoding_rs::WINDOWS_1250),
593 (0x041d, encoding_rs::WINDOWS_1252),
594 (0x041e, encoding_rs::WINDOWS_874),
595 (0x041f, encoding_rs::WINDOWS_1254),
596 (0x0420, encoding_rs::WINDOWS_1256),
597 (0x0421, encoding_rs::WINDOWS_1252),
598 (0x0422, encoding_rs::WINDOWS_1251),
599 (0x0423, encoding_rs::WINDOWS_1251),
600 (0x0424, encoding_rs::WINDOWS_1250),
601 (0x0425, encoding_rs::WINDOWS_1257),
602 (0x0426, encoding_rs::WINDOWS_1257),
603 (0x0427, encoding_rs::WINDOWS_1257),
604 (0x0428, encoding_rs::WINDOWS_1251),
605 (0x0429, encoding_rs::WINDOWS_1256),
606 (0x042a, encoding_rs::WINDOWS_1258),
607 (0x042b, encoding_rs::WINDOWS_1252),
608 (0x042c, encoding_rs::WINDOWS_1254),
609 (0x042d, encoding_rs::WINDOWS_1252),
610 (0x042e, encoding_rs::WINDOWS_1252),
611 (0x042f, encoding_rs::WINDOWS_1251),
612 (0x0432, encoding_rs::WINDOWS_1252),
613 (0x0434, encoding_rs::WINDOWS_1252),
614 (0x0435, encoding_rs::WINDOWS_1252),
615 (0x0436, encoding_rs::WINDOWS_1252),
616 (0x0437, encoding_rs::WINDOWS_1252),
617 (0x0438, encoding_rs::WINDOWS_1252),
618 (0x0439, encoding_rs::UTF_16LE),
619 (0x043a, encoding_rs::UTF_16LE),
620 (0x043b, encoding_rs::WINDOWS_1252),
621 (0x043e, encoding_rs::WINDOWS_1252),
622 (0x043f, encoding_rs::WINDOWS_1251),
623 (0x0440, encoding_rs::WINDOWS_1251),
624 (0x0441, encoding_rs::WINDOWS_1252),
625 (0x0442, encoding_rs::WINDOWS_1250),
626 (0x0443, encoding_rs::WINDOWS_1254),
627 (0x0444, encoding_rs::WINDOWS_1251),
628 (0x0445, encoding_rs::UTF_16LE),
629 (0x0446, encoding_rs::UTF_16LE),
630 (0x0447, encoding_rs::UTF_16LE),
631 (0x0448, encoding_rs::UTF_16LE),
632 (0x0449, encoding_rs::UTF_16LE),
633 (0x044a, encoding_rs::UTF_16LE),
634 (0x044b, encoding_rs::UTF_16LE),
635 (0x044c, encoding_rs::UTF_16LE),
636 (0x044d, encoding_rs::UTF_16LE),
637 (0x044e, encoding_rs::UTF_16LE),
638 (0x044f, encoding_rs::UTF_16LE),
639 (0x0450, encoding_rs::WINDOWS_1251),
640 (0x0451, encoding_rs::UTF_16LE),
641 (0x0452, encoding_rs::WINDOWS_1252),
642 (0x0453, encoding_rs::UTF_16LE),
643 (0x0454, encoding_rs::UTF_16LE),
644 (0x0456, encoding_rs::WINDOWS_1252),
645 (0x0457, encoding_rs::UTF_16LE),
646 (0x045a, encoding_rs::UTF_16LE),
647 (0x045b, encoding_rs::UTF_16LE),
648 (0x045d, encoding_rs::WINDOWS_1252),
649 (0x045e, encoding_rs::WINDOWS_1252),
650 (0x0461, encoding_rs::UTF_16LE),
651 (0x0462, encoding_rs::WINDOWS_1252),
652 (0x0463, encoding_rs::UTF_16LE),
653 (0x0464, encoding_rs::WINDOWS_1252),
654 (0x0465, encoding_rs::UTF_16LE),
655 (0x0468, encoding_rs::WINDOWS_1252),
656 (0x046a, encoding_rs::WINDOWS_1252),
657 (0x046b, encoding_rs::WINDOWS_1252),
658 (0x046c, encoding_rs::WINDOWS_1252),
659 (0x046d, encoding_rs::WINDOWS_1251),
660 (0x046e, encoding_rs::WINDOWS_1252),
661 (0x046f, encoding_rs::WINDOWS_1252),
662 (0x0470, encoding_rs::WINDOWS_1252),
663 (0x0478, encoding_rs::WINDOWS_1252),
664 (0x047a, encoding_rs::WINDOWS_1252),
665 (0x047c, encoding_rs::WINDOWS_1252),
666 (0x047e, encoding_rs::WINDOWS_1252),
667 (0x0480, encoding_rs::WINDOWS_1256),
668 (0x0481, encoding_rs::UTF_16LE),
669 (0x0482, encoding_rs::WINDOWS_1252),
670 (0x0483, encoding_rs::WINDOWS_1252),
671 (0x0484, encoding_rs::WINDOWS_1252),
672 (0x0485, encoding_rs::WINDOWS_1251),
673 (0x0486, encoding_rs::WINDOWS_1252),
674 (0x0487, encoding_rs::WINDOWS_1252),
675 (0x0488, encoding_rs::WINDOWS_1252),
676 (0x048c, encoding_rs::WINDOWS_1256),
677 (0x0801, encoding_rs::WINDOWS_1256),
678 (0x0804, encoding_rs::GB18030),
679 (0x1004, encoding_rs::GB18030),
680 (0x0807, encoding_rs::WINDOWS_1252),
681 (0x0809, encoding_rs::WINDOWS_1252),
682 (0x080a, encoding_rs::WINDOWS_1252),
683 (0x080c, encoding_rs::WINDOWS_1252),
684 (0x0810, encoding_rs::WINDOWS_1252),
685 (0x0813, encoding_rs::WINDOWS_1252),
686 (0x0814, encoding_rs::WINDOWS_1252),
687 (0x0816, encoding_rs::WINDOWS_1252),
688 (0x081a, encoding_rs::WINDOWS_1250),
689 (0x081d, encoding_rs::WINDOWS_1252),
690 (0x0827, encoding_rs::WINDOWS_1257),
691 (0x082c, encoding_rs::WINDOWS_1251),
692 (0x082e, encoding_rs::WINDOWS_1252),
693 (0x083b, encoding_rs::WINDOWS_1252),
694 (0x083c, encoding_rs::WINDOWS_1252),
695 (0x083e, encoding_rs::WINDOWS_1252),
696 (0x0843, encoding_rs::WINDOWS_1251),
697 (0x0845, encoding_rs::UTF_16LE),
698 (0x0850, encoding_rs::WINDOWS_1251),
699 (0x085d, encoding_rs::WINDOWS_1252),
700 (0x085f, encoding_rs::WINDOWS_1252),
701 (0x086b, encoding_rs::WINDOWS_1252),
702 (0x0c01, encoding_rs::WINDOWS_1256),
703 (0x0c07, encoding_rs::WINDOWS_1252),
704 (0x0c09, encoding_rs::WINDOWS_1252),
705 (0x0c0a, encoding_rs::WINDOWS_1252),
706 (0x0c0c, encoding_rs::WINDOWS_1252),
707 (0x0c1a, encoding_rs::WINDOWS_1251),
708 (0x0c3b, encoding_rs::WINDOWS_1252),
709 (0x0c6b, encoding_rs::WINDOWS_1252),
710 (0x1001, encoding_rs::WINDOWS_1256),
711 (0x1007, encoding_rs::WINDOWS_1252),
712 (0x1009, encoding_rs::WINDOWS_1252),
713 (0x100a, encoding_rs::WINDOWS_1252),
714 (0x100c, encoding_rs::WINDOWS_1252),
715 (0x101a, encoding_rs::WINDOWS_1250),
716 (0x103b, encoding_rs::WINDOWS_1252),
717 (0x1401, encoding_rs::WINDOWS_1256),
718 (0x1407, encoding_rs::WINDOWS_1252),
719 (0x1409, encoding_rs::WINDOWS_1252),
720 (0x140a, encoding_rs::WINDOWS_1252),
721 (0x140c, encoding_rs::WINDOWS_1252),
722 (0x141a, encoding_rs::WINDOWS_1250),
723 (0x143b, encoding_rs::WINDOWS_1252),
724 (0x1801, encoding_rs::WINDOWS_1256),
725 (0x1809, encoding_rs::WINDOWS_1252),
726 (0x180a, encoding_rs::WINDOWS_1252),
727 (0x180c, encoding_rs::WINDOWS_1252),
728 (0x181a, encoding_rs::WINDOWS_1250),
729 (0x183b, encoding_rs::WINDOWS_1252),
730 (0x1c01, encoding_rs::WINDOWS_1256),
731 (0x1c09, encoding_rs::WINDOWS_1252),
732 (0x1c0a, encoding_rs::WINDOWS_1252),
733 (0x1c1a, encoding_rs::WINDOWS_1251),
734 (0x1c3b, encoding_rs::WINDOWS_1252),
735 (0x2001, encoding_rs::WINDOWS_1256),
736 (0x2009, encoding_rs::WINDOWS_1252),
737 (0x200a, encoding_rs::WINDOWS_1252),
738 (0x201a, encoding_rs::WINDOWS_1251),
739 (0x203b, encoding_rs::WINDOWS_1252),
740 (0x2401, encoding_rs::WINDOWS_1256),
741 (0x2409, encoding_rs::WINDOWS_1252),
742 (0x240a, encoding_rs::WINDOWS_1252),
743 (0x243b, encoding_rs::WINDOWS_1252),
744 (0x2801, encoding_rs::WINDOWS_1256),
745 (0x2809, encoding_rs::WINDOWS_1252),
746 (0x280a, encoding_rs::WINDOWS_1252),
747 (0x2c01, encoding_rs::WINDOWS_1256),
748 (0x2c09, encoding_rs::WINDOWS_1252),
749 (0x2c0a, encoding_rs::WINDOWS_1252),
750 (0x3001, encoding_rs::WINDOWS_1256),
751 (0x3009, encoding_rs::WINDOWS_1252),
752 (0x300a, encoding_rs::WINDOWS_1252),
753 (0x3401, encoding_rs::WINDOWS_1256),
754 (0x3409, encoding_rs::WINDOWS_1252),
755 (0x340a, encoding_rs::WINDOWS_1252),
756 (0x3801, encoding_rs::WINDOWS_1256),
757 (0x380a, encoding_rs::WINDOWS_1252),
758 (0x3c01, encoding_rs::WINDOWS_1256),
759 (0x3c0a, encoding_rs::WINDOWS_1252),
760 (0x4001, encoding_rs::WINDOWS_1256),
761 (0x4009, encoding_rs::WINDOWS_1252),
762 (0x400a, encoding_rs::WINDOWS_1252),
763 (0x4409, encoding_rs::WINDOWS_1252),
764 (0x440a, encoding_rs::WINDOWS_1252),
765 (0x4809, encoding_rs::WINDOWS_1252),
766 (0x480a, encoding_rs::WINDOWS_1252),
767 (0x4c0a, encoding_rs::WINDOWS_1252),
768 (0x500a, encoding_rs::WINDOWS_1252),
769 (0x540a, encoding_rs::WINDOWS_1252),
770 ];
771
772 for (locale, expected) in cases {
773 assert_eq!(
774 lcid_to_encoding(*locale),
775 Some(*expected),
776 "locale {:#06x}",
777 locale
778 );
779 }
780 }
781
782 #[test]
783 fn sortid_to_encoding_covers_all_documented_sort_ids() {
784 let cases: &[(u8, &encoding_rs::Encoding)] = &[
785 (50, encoding_rs::WINDOWS_1252),
786 (51, encoding_rs::WINDOWS_1252),
787 (52, encoding_rs::WINDOWS_1252),
788 (53, encoding_rs::WINDOWS_1252),
789 (54, encoding_rs::WINDOWS_1252),
790 (71, encoding_rs::WINDOWS_1252),
791 (72, encoding_rs::WINDOWS_1252),
792 (73, encoding_rs::WINDOWS_1252),
793 (74, encoding_rs::WINDOWS_1252),
794 (75, encoding_rs::WINDOWS_1252),
795 (80, encoding_rs::WINDOWS_1250),
796 (81, encoding_rs::WINDOWS_1250),
797 (82, encoding_rs::WINDOWS_1250),
798 (83, encoding_rs::WINDOWS_1250),
799 (84, encoding_rs::WINDOWS_1250),
800 (85, encoding_rs::WINDOWS_1250),
801 (86, encoding_rs::WINDOWS_1250),
802 (87, encoding_rs::WINDOWS_1250),
803 (88, encoding_rs::WINDOWS_1250),
804 (89, encoding_rs::WINDOWS_1250),
805 (90, encoding_rs::WINDOWS_1250),
806 (91, encoding_rs::WINDOWS_1250),
807 (92, encoding_rs::WINDOWS_1250),
808 (93, encoding_rs::WINDOWS_1250),
809 (94, encoding_rs::WINDOWS_1250),
810 (95, encoding_rs::WINDOWS_1250),
811 (96, encoding_rs::WINDOWS_1250),
812 (97, encoding_rs::WINDOWS_1250),
813 (98, encoding_rs::WINDOWS_1250),
814 (104, encoding_rs::WINDOWS_1251),
815 (105, encoding_rs::WINDOWS_1251),
816 (106, encoding_rs::WINDOWS_1251),
817 (107, encoding_rs::WINDOWS_1251),
818 (108, encoding_rs::WINDOWS_1251),
819 (112, encoding_rs::WINDOWS_1253),
820 (113, encoding_rs::WINDOWS_1253),
821 (114, encoding_rs::WINDOWS_1253),
822 (120, encoding_rs::WINDOWS_1253),
823 (121, encoding_rs::WINDOWS_1253),
824 (122, encoding_rs::WINDOWS_1253),
825 (124, encoding_rs::WINDOWS_1253),
826 (128, encoding_rs::WINDOWS_1254),
827 (129, encoding_rs::WINDOWS_1254),
828 (130, encoding_rs::WINDOWS_1254),
829 (136, encoding_rs::WINDOWS_1255),
830 (137, encoding_rs::WINDOWS_1255),
831 (138, encoding_rs::WINDOWS_1255),
832 (144, encoding_rs::WINDOWS_1256),
833 (145, encoding_rs::WINDOWS_1256),
834 (146, encoding_rs::WINDOWS_1256),
835 (152, encoding_rs::WINDOWS_1257),
836 (153, encoding_rs::WINDOWS_1257),
837 (154, encoding_rs::WINDOWS_1257),
838 (155, encoding_rs::WINDOWS_1257),
839 (156, encoding_rs::WINDOWS_1257),
840 (157, encoding_rs::WINDOWS_1257),
841 (158, encoding_rs::WINDOWS_1257),
842 (159, encoding_rs::WINDOWS_1257),
843 (160, encoding_rs::WINDOWS_1257),
844 (183, encoding_rs::WINDOWS_1252),
845 (184, encoding_rs::WINDOWS_1252),
846 (185, encoding_rs::WINDOWS_1252),
847 (186, encoding_rs::WINDOWS_1252),
848 (192, encoding_rs::SHIFT_JIS),
849 (193, encoding_rs::SHIFT_JIS),
850 (200, encoding_rs::SHIFT_JIS),
851 (194, encoding_rs::EUC_KR),
852 (195, encoding_rs::EUC_KR),
853 (196, encoding_rs::BIG5),
854 (197, encoding_rs::BIG5),
855 (202, encoding_rs::BIG5),
856 (198, encoding_rs::GB18030),
857 (199, encoding_rs::GB18030),
858 (203, encoding_rs::GB18030),
859 (201, encoding_rs::BIG5),
860 (204, encoding_rs::WINDOWS_874),
861 (205, encoding_rs::WINDOWS_874),
862 (206, encoding_rs::WINDOWS_874),
863 (210, encoding_rs::WINDOWS_1252),
864 (211, encoding_rs::WINDOWS_1252),
865 (212, encoding_rs::WINDOWS_1252),
866 (213, encoding_rs::WINDOWS_1252),
867 (214, encoding_rs::WINDOWS_1252),
868 (215, encoding_rs::WINDOWS_1252),
869 (216, encoding_rs::WINDOWS_1252),
870 (217, encoding_rs::WINDOWS_1252),
871 ];
872
873 for (sort_id, expected) in cases {
874 assert_eq!(
875 sortid_to_encoding(*sort_id),
876 Some(*expected),
877 "sort_id {}",
878 sort_id
879 );
880 }
881 }
882
883 #[test]
884 fn derives_eq_and_copy() {
885 let a = Collation::new(0x0409, 0);
886 let b = a;
887 assert_eq!(a, b);
888 assert_ne!(a, Collation::new(0x0409, 1));
889 }
890}