dos_cp_generator/
lib.rs

1#![deny(warnings)]
2
3use dos_cp::{CodePage, hash};
4use std::env::var_os;
5use std::fs::{File, create_dir_all};
6use std::io::Write;
7use std::mem::{MaybeUninit, transmute};
8use std::path::Path;
9
10pub fn build() {
11    let out_dir = var_os("OUT_DIR").unwrap();
12    let out_dir = Path::new(&out_dir).join("CODEPAGE");
13    create_dir_all(&out_dir).unwrap();
14    for &code_page in KNOWN_CODE_PAGES {
15        let file = out_dir.join(format!("{}", code_page));
16        let mut file = File::create(file).unwrap();
17        file.write_all(&CodePage::generate(code_page).0).unwrap();
18    }
19}
20
21pub const KNOWN_CODE_PAGES: &[u16] = &[
22    437, 720, 737, 808, 850, 852, 855, 857, 858, 860,
23    861, 862, 863, 864, 865, 866, 869, 874,
24    912, 915,
25];
26
27#[derive(Copy, Clone)]
28enum Filled { None, Half, Full }
29
30pub trait CodePageGenExt {
31    fn generate(code_page: u16) -> Self;
32}
33
34impl CodePageGenExt for CodePage {
35    fn generate(code_page: u16) -> CodePage {
36        let (base_table, hash_param) = base_table_and_hash_param(code_page);
37        let mut res: [MaybeUninit<u8>; 512] = unsafe { MaybeUninit::uninit().assume_init() };
38        res[510].write(hash_param as u8);
39        res[511].write((hash_param >> 8) as u8);
40        let base_table = base_table.iter().copied().map(|c| {
41            if c == '?' { return 0; }
42            let c: u16 = (c as u32).try_into()
43                .expect("too big char, bit needs to be preremapped");
44            c
45        });
46        let mut first_part = &mut res[.. 256];
47        for byte in base_table.clone().flat_map(|w| [(w >> 8) as u8, w as u8]) {
48            first_part[0].write(byte);
49            first_part = &mut first_part[1 ..];
50        }
51        let second_part = &mut res[256 ..];
52        let mut filled = [Filled::None; 127];
53        for (i, w) in base_table.into_iter().enumerate().filter(|&(_, w)| w != 0) {
54            let hash = hash(w, hash_param);
55            debug_assert!((hash >> 7) == 0 && hash != 0x7F, "invalid hash");
56            let filled = &mut filled[hash as usize];
57            match filled {
58                Filled::None => {
59                    second_part[(2 * hash) as usize].write(i as u8);
60                    *filled = Filled::Half;
61                },
62                Filled::Half => {
63                    second_part[(2 * hash + 1) as usize].write(i as u8);
64                    *filled = Filled::Full;
65                },
66                Filled::Full => unreachable!("invalid hash / base table"),
67            }
68        }
69        for (i, filled) in filled.into_iter().enumerate() {
70            match filled {
71                Filled::None => {
72                    second_part[2 * i].write(128);
73                    second_part[2 * i + 1].write(128);
74                },
75                Filled::Half => {
76                    second_part[2 * i + 1].write(128);
77                },
78                Filled::Full => { }
79            }
80        }
81        CodePage(unsafe { transmute(res) })
82    }
83}
84
85fn base_table_and_hash_param(code_page: u16) -> (&'static [char; 128], u16) {
86    match code_page {
87        437 => (&CP437, 0x9F8D),
88        720 => (&CP720, 0x8EAC),
89        737 => (&CP737, 0x9AF8),
90        808 => (&CP808, 0x8398),
91        850 => (&CP850, 0x80F1),
92        852 => (&CP852, 0xF5F4),
93        855 => (&CP855, 0x808F),
94        857 => (&CP857, 0x80EE),
95        858 => (&CP858, 0x80F1),
96        860 => (&CP860, 0x9FCD),
97        861 => (&CP861, 0x83AD),
98        862 => (&CP862, 0xBB95),
99        863 => (&CP863, 0xEAC8),
100        864 => (&CP864, 0x80A2),
101        865 => (&CP865, 0x9F8D),
102        866 => (&CP866, 0x8398),
103        869 => (&CP869, 0x8B8F),
104        874 => (&CP874, 0x8080),
105        912 => (&CP912, 0x8086),
106        915 => (&CP915, 0x8080),
107        _ => panic!("unknow code page"),
108    }
109}
110 
111const CP437: [char; 128] = [
112    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
113    'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
114    'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù',
115    'ÿ', 'Ö', 'Ü', '¢', '£', '¥', '₧', 'ƒ',
116    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
117    '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
118    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
119    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
120    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
121    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
122    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
123    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
124    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
125    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
126    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
127    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
128];
129
130const CP720: [char; 128] = [
131    '\u{003F}', '\u{003F}', '\u{00E9}', '\u{00E2}', '\u{003F}', '\u{00E0}', '\u{003F}', '\u{00E7}',
132    '\u{00EA}', '\u{00EB}', '\u{00E8}', '\u{00EF}', '\u{00EE}', '\u{003F}', '\u{003F}', '\u{003F}',
133    '\u{003F}', '\u{0651}', '\u{0652}', '\u{00F4}', '\u{00A4}', '\u{0640}', '\u{00FB}', '\u{00F9}',
134    '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{00A3}', '\u{0625}', '\u{0626}', '\u{0627}',
135    '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}',
136    '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{00AB}', '\u{00BB}',
137    '\u{2591}', '\u{2592}', '\u{2593}', '\u{2502}', '\u{2524}', '\u{2561}', '\u{2562}', '\u{2556}',
138    '\u{2555}', '\u{2563}', '\u{2551}', '\u{2557}', '\u{255D}', '\u{255C}', '\u{255B}', '\u{2510}',
139    '\u{2514}', '\u{2534}', '\u{252C}', '\u{251C}', '\u{2500}', '\u{253C}', '\u{255E}', '\u{255F}',
140    '\u{255A}', '\u{2554}', '\u{2569}', '\u{2566}', '\u{2560}', '\u{2550}', '\u{256C}', '\u{2567}',
141    '\u{2568}', '\u{2564}', '\u{2565}', '\u{2559}', '\u{2558}', '\u{2552}', '\u{2553}', '\u{256B}',
142    '\u{256A}', '\u{2518}', '\u{250C}', '\u{2588}', '\u{2584}', '\u{258C}', '\u{2590}', '\u{2580}',
143    '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{0641}', '\u{00B5}', '\u{0642}',
144    '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}',
145    '\u{2261}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{2248}',
146    '\u{00B0}', '\u{2219}', '\u{00B7}', '\u{221A}', '\u{207F}', '\u{00B2}', '\u{25A0}', '\u{00A0}',
147];
148
149const CP737: [char; 128] = [
150    'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ',
151    'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π',
152    'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω',
153    'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ',
154    'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π',
155    'ρ', 'σ', 'ς', 'τ', 'υ', 'φ', 'χ', 'ψ',
156    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
157    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
158    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
159    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
160    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
161    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
162    'ω', 'ά', 'έ', 'ή', 'ϊ', 'ί', 'ό', 'ύ',
163    'ϋ', 'ώ', 'Ά', 'Έ', 'Ή', 'Ί', 'Ό', 'Ύ',
164    'Ώ', '±', '≥', '≤', 'Ϊ', 'Ϋ', '÷', '≈',
165    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
166];
167
168const CP808: [char; 128] = [
169    'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З',
170    'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П',
171    'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч',
172    'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
173    'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з',
174    'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',
175    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
176    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
177    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
178    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
179    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
180    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
181    'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч',
182    'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я',
183    'Ё', 'ё', 'Є', 'є', 'Ї', 'ї', 'Ў', 'ў',
184    '°', '∙', '·', '√', '№', '€', '■', ' ',
185];
186
187const CP850: [char; 128] = [
188    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
189    'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
190    'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù',
191    'ÿ', 'Ö', 'Ü', 'ø', '£', 'Ø', '×', 'ƒ',
192    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
193    '¿', '®', '¬', '½', '¼', '¡', '«', '»',
194    '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'À',
195    '©', '╣', '║', '╗', '╝', '¢', '¥', '┐',
196    '└', '┴', '┬', '├', '─', '┼', 'ã', 'Ã',
197    '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
198    'ð', 'Ð', 'Ê', 'Ë', 'È', 'ı', 'Í', 'Î',
199    'Ï', '┘', '┌', '█', '▄', '¦', 'Ì', '▀',
200    'Ó', 'ß', 'Ô', 'Ò', 'õ', 'Õ', 'µ', 'þ',
201    'Þ', 'Ú', 'Û', 'Ù', 'ý', 'Ý', '¯', '´',
202    '­', '±', '‗', '¾', '¶', '§', '÷', '¸',
203    '°', '¨', '·', '¹', '³', '²', '■', ' ',
204];
205
206const CP852: [char; 128] = [
207    'Ç', 'ü', 'é', 'â', 'ä', 'ů', 'ć', 'ç',
208    'ł', 'ë', 'Ő', 'ő', 'î', 'Ź', 'Ä', 'Ć',
209    'É', 'Ĺ', 'ĺ', 'ô', 'ö', 'Ľ', 'ľ', 'Ś',
210    'ś', 'Ö', 'Ü', 'Ť', 'ť', 'Ł', '×', 'č',
211    'á', 'í', 'ó', 'ú', 'Ą', 'ą', 'Ž', 'ž',
212    'Ę', 'ę', '¬', 'ź', 'Č', 'ş', '«', '»',
213    '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'Ě',
214    'Ş', '╣', '║', '╗', '╝', 'Ż', 'ż', '┐',
215    '└', '┴', '┬', '├', '─', '┼', 'Ă', 'ă',
216    '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
217    'đ', 'Đ', 'Ď', 'Ë', 'ď', 'Ň', 'Í', 'Î',
218    'ě', '┘', '┌', '█', '▄', 'Ţ', 'Ů', '▀',
219    'Ó', 'ß', 'Ô', 'Ń', 'ń', 'ň', 'Š', 'š',
220    'Ŕ', 'Ú', 'ŕ', 'Ű', 'ý', 'Ý', 'ţ', '´',
221    '­', '˝', '˛', 'ˇ', '˘', '§', '÷', '¸',
222    '°', '¨', '˙', 'ű', 'Ř', 'ř', '■', ' ',
223];
224
225const CP855: [char; 128] = [
226    'ђ', 'Ђ', 'ѓ', 'Ѓ', 'ё', 'Ё', 'є', 'Є',
227    'ѕ', 'Ѕ', 'і', 'І', 'ї', 'Ї', 'ј', 'Ј',
228    'љ', 'Љ', 'њ', 'Њ', 'ћ', 'Ћ', 'ќ', 'Ќ',
229    'ў', 'Ў', 'џ', 'Џ', 'ю', 'Ю', 'ъ', 'Ъ',
230    'а', 'А', 'б', 'Б', 'ц', 'Ц', 'д', 'Д',
231    'е', 'Е', 'ф', 'Ф', 'г', 'Г', '«', '»',
232    '░', '▒', '▓', '│', '┤', 'х', 'Х', 'и',
233    'И', '╣', '║', '╗', '╝', 'й', 'Й', '┐',
234    '└', '┴', '┬', '├', '─', '┼', 'к', 'К',
235    '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
236    'л', 'Л', 'м', 'М', 'н', 'Н', 'о', 'О',
237    'п', '┘', '┌', '█', '▄', 'П', 'я', '▀',
238    'Я', 'р', 'Р', 'с', 'С', 'т', 'Т', 'у',
239    'У', 'ж', 'Ж', 'в', 'В', 'ь', 'Ь', '№',
240    '­', 'ы', 'Ы', 'з', 'З', 'ш', 'Ш', 'э',
241    'Э', 'щ', 'Щ', 'ч', 'Ч', '§', '■', ' ',
242];
243
244const CP857: [char; 128] = [
245    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
246    'ê', 'ë', 'è', 'ï', 'î', 'ı', 'Ä', 'Å',
247    'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù',
248    'İ', 'Ö', 'Ü', 'ø', '£', 'Ø', 'Ş', 'ş',
249    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'Ğ', 'ğ',
250    '¿', '®', '¬', '½', '¼', '¡', '«', '»',
251    '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'À',
252    '©', '╣', '║', '╗', '╝', '¢', '¥', '┐',
253    '└', '┴', '┬', '├', '─', '┼', 'ã', 'Ã',
254    '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
255    'º', 'ª', 'Ê', 'Ë', 'È', '?', 'Í', 'Î',
256    'Ï', '┘', '┌', '█', '▄', '¦', 'Ì', '▀',
257    'Ó', 'ß', 'Ô', 'Ò', 'õ', 'Õ', 'µ', '?',
258    '×', 'Ú', 'Û', 'Ù', 'ì', 'ÿ', '¯', '´',
259    '­', '±', '?', '¾', '¶', '§', '÷', '¸',
260    '°', '¨', '·', '¹', '³', '²', '■', ' ',
261];
262
263const CP858: [char; 128] = [
264    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
265    'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
266    'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù',
267    'ÿ', 'Ö', 'Ü', 'ø', '£', 'Ø', '×', 'ƒ',
268    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
269    '¿', '®', '¬', '½', '¼', '¡', '«', '»',
270    '░', '▒', '▓', '│', '┤', 'Á', 'Â', 'À',
271    '©', '╣', '║', '╗', '╝', '¢', '¥', '┐',
272    '└', '┴', '┬', '├', '─', '┼', 'ã', 'Ã',
273    '╚', '╔', '╩', '╦', '╠', '═', '╬', '¤',
274    'ð', 'Ð', 'Ê', 'Ë', 'È', '€', 'Í', 'Î',
275    'Ï', '┘', '┌', '█', '▄', '¦', 'Ì', '▀',
276    'Ó', 'ß', 'Ô', 'Ò', 'õ', 'Õ', 'µ', 'þ',
277    'Þ', 'Ú', 'Û', 'Ù', 'ý', 'Ý', '¯', '´',
278    '­', '±', '‗', '¾', '¶', '§', '÷', '¸',
279    '°', '¨', '·', '¹', '³', '²', '■', ' ',
280];
281
282const CP860: [char; 128] = [
283    'Ç', 'ü', 'é', 'â', 'ã', 'à', 'Á', 'ç',
284    'ê', 'Ê', 'è', 'Í', 'Ô', 'ì', 'Ã', 'Â',
285    'É', 'À', 'È', 'ô', 'õ', 'ò', 'Ú', 'ù',
286    'Ì', 'Õ', 'Ü', '¢', '£', 'Ù', '₧', 'Ó',
287    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
288    '¿', 'Ò', '¬', '½', '¼', '¡', '«', '»',
289    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
290    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
291    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
292    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
293    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
294    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
295    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
296    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
297    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
298    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
299];
300
301const CP861: [char; 128] = [
302    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
303    'ê', 'ë', 'è', 'Ð', 'ð', 'Þ', 'Ä', 'Å',
304    'É', 'æ', 'Æ', 'ô', 'ö', 'þ', 'û', 'Ý',
305    'ý', 'Ö', 'Ü', 'ø', '£', 'Ø', '₧', 'ƒ',
306    'á', 'í', 'ó', 'ú', 'Á', 'Í', 'Ó', 'Ú',
307    '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
308    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
309    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
310    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
311    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
312    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
313    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
314    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
315    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
316    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
317    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
318];
319
320const CP862: [char; 128] = [
321    'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח',
322    'ט', 'י', 'ך', 'כ', 'ל', 'ם', 'מ', 'ן',
323    'נ', 'ס', 'ע', 'ף', 'פ', 'ץ', 'צ', 'ק',
324    'ר', 'ש', 'ת', '¢', '£', '¥', '₧', 'ƒ',
325    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
326    '¿', '⌐', '¬', '½', '¼', '¡', '«', '»',
327    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
328    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
329    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
330    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
331    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
332    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
333    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
334    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
335    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
336    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
337];
338
339const CP863: [char; 128] = [
340    'Ç', 'ü', 'é', 'â', 'Â', 'à', '¶', 'ç',
341    'ê', 'ë', 'è', 'ï', 'î', '‗', 'À', '§',
342    'É', 'È', 'Ê', 'ô', 'Ë', 'Ï', 'û', 'ù',
343    '¤', 'Ô', 'Ü', '¢', '£', 'Ù', 'Û', 'ƒ',
344    '¦', '´', 'ó', 'ú', '¨', '¸', '³', '¯',
345    'Î', '⌐', '¬', '½', '¼', '¾', '«', '»',
346    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
347    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
348    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
349    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
350    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
351    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
352    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
353    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
354    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
355    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
356];
357
358const CP864: [char; 128] = [
359    '\u{00B0}', '\u{00B7}', '\u{2219}', '\u{221A}', '\u{2592}', '\u{2500}', '\u{2502}', '\u{253C}',
360    '\u{2524}', '\u{252C}', '\u{251C}', '\u{2534}', '\u{2510}', '\u{250C}', '\u{2514}', '\u{2518}',
361    '\u{03B2}', '\u{221E}', '\u{03C6}', '\u{00B1}', '\u{00BD}', '\u{00BC}', '\u{2248}', '\u{00AB}',
362    '\u{00BB}', '\u{FEF7}', '\u{FEF8}', '\u{003F}', '\u{003F}', '\u{FEFB}', '\u{FEFC}', '\u{003F}',
363    '\u{00A0}', '\u{00AD}', '\u{FE82}', '\u{00A3}', '\u{00A4}', '\u{FE84}', '\u{003F}', '\u{003F}',
364    '\u{FE8E}', '\u{FE8F}', '\u{FE95}', '\u{FE99}', '\u{060C}', '\u{FE9D}', '\u{FEA1}', '\u{FEA5}',
365    '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}',
366    '\u{0668}', '\u{0669}', '\u{FED1}', '\u{061B}', '\u{FEB1}', '\u{FEB5}', '\u{FEB9}', '\u{061F}',
367    '\u{00A2}', '\u{FE80}', '\u{FE81}', '\u{FE83}', '\u{FE85}', '\u{FECA}', '\u{FE8B}', '\u{FE8D}',
368    '\u{FE91}', '\u{FE93}', '\u{FE97}', '\u{FE9B}', '\u{FE9F}', '\u{FEA3}', '\u{FEA7}', '\u{FEA9}',
369    '\u{FEAB}', '\u{FEAD}', '\u{FEAF}', '\u{FEB3}', '\u{FEB7}', '\u{FEBB}', '\u{FEBF}', '\u{FEC1}',
370    '\u{FEC5}', '\u{FECB}', '\u{FECF}', '\u{00A6}', '\u{00AC}', '\u{00F7}', '\u{00D7}', '\u{FEC9}',
371    '\u{0640}', '\u{FED3}', '\u{FED7}', '\u{FEDB}', '\u{FEDF}', '\u{FEE3}', '\u{FEE7}', '\u{FEEB}',
372    '\u{FEED}', '\u{FEEF}', '\u{FEF3}', '\u{FEBD}', '\u{FECC}', '\u{FECE}', '\u{FECD}', '\u{FEE1}',
373    '\u{FE7D}', '\u{0651}', '\u{FEE5}', '\u{FEE9}', '\u{FEEC}', '\u{FEF0}', '\u{FEF2}', '\u{FED0}',
374    '\u{FED5}', '\u{FEF5}', '\u{FEF6}', '\u{FEDD}', '\u{FED9}', '\u{FEF1}', '\u{25A0}', '\u{003F}',
375];
376
377const CP865: [char; 128] = [
378    'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç',
379    'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å',
380    'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù',
381    'ÿ', 'Ö', 'Ü', 'ø', '£', 'Ø', '₧', 'ƒ',
382    'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º',
383    '¿', '⌐', '¬', '½', '¼', '¡', '«', '¤',
384    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
385    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
386    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
387    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
388    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
389    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
390    'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ',
391    'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
392    '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈',
393    '°', '∙', '·', '√', 'ⁿ', '²', '■', ' ',
394];
395
396const CP866: [char; 128] = [
397    'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З',
398    'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П',
399    'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч',
400    'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
401    'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з',
402    'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',
403    '░', '▒', '▓', '│', '┤', '╡', '╢', '╖',
404    '╕', '╣', '║', '╗', '╝', '╜', '╛', '┐',
405    '└', '┴', '┬', '├', '─', '┼', '╞', '╟',
406    '╚', '╔', '╩', '╦', '╠', '═', '╬', '╧',
407    '╨', '╤', '╥', '╙', '╘', '╒', '╓', '╫',
408    '╪', '┘', '┌', '█', '▄', '▌', '▐', '▀',
409    'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч',
410    'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я',
411    'Ё', 'ё', 'Є', 'є', 'Ї', 'ї', 'Ў', 'ў',
412    '°', '∙', '·', '√', '№', '¤', '■', ' ',
413];
414
415const CP869: [char; 128] = [
416    '?', '?', '?', '?', '?', '?', 'Ά', '?',
417    '·', '¬', '¦', '‘', '’', 'Έ', '―', 'Ή',
418    'Ί', 'Ϊ', 'Ό', '?', '?', 'Ύ', 'Ϋ', '©',
419    'Ώ', '²', '³', 'ά', '£', 'έ', 'ή', 'ί',
420    'ϊ', 'ΐ', 'ό', 'ύ', 'Α', 'Β', 'Γ', 'Δ',
421    'Ε', 'Ζ', 'Η', '½', 'Θ', 'Ι', '«', '»',
422    '░', '▒', '▓', '│', '┤', 'Κ', 'Λ', 'Μ',
423    'Ν', '╣', '║', '╗', '╝', 'Ξ', 'Ο', '┐',
424    '└', '┴', '┬', '├', '─', '┼', 'Π', 'Ρ',
425    '╚', '╔', '╩', '╦', '╠', '═', '╬', 'Σ',
426    'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β',
427    'γ', '┘', '┌', '█', '▄', 'δ', 'ε', '▀',
428    'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν',
429    'ξ', 'ο', 'π', 'ρ', 'σ', 'ς', 'τ', '΄',
430    '­', '±', 'υ', 'φ', 'χ', '§', 'ψ', '΅',
431    '°', '¨', 'ω', 'ϋ', 'ΰ', 'ώ', '■', ' ',
432];
433
434const CP874: [char; 128] = [
435    '\u{20AC}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{2026}', '\u{003F}', '\u{003F}',
436    '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}',
437    '\u{003F}', '\u{2018}', '\u{2019}', '\u{201C}', '\u{201D}', '\u{2022}', '\u{2013}', '\u{2014}',
438    '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}',
439    '\u{00A0}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}',
440    '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}',
441    '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}',
442    '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}',
443    '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}',
444    '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}',
445    '\u{0E30}', '\u{0E31}', '\u{0E32}', '\u{0E33}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}',
446    '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{0E3F}',
447    '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E46}', '\u{0E47}',
448    '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0E4F}',
449    '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}',
450    '\u{0E58}', '\u{0E59}', '\u{0E5A}', '\u{0E5B}', '\u{003F}', '\u{003F}', '\u{003F}', '\u{003F}',
451];
452
453const CP912: [char; 128] = [
454    '€', '', '‚', 'ƒ', '„', '…', '†', '‡',
455    'ˆ', '‰', 'Š', '‹', 'Œ', '', 'Ž', '',
456    '', '‘', '’', '“', '”', '•', '–', '—',
457    '˜', '™', 'š', '›', 'œ', '', 'ž', 'Ÿ',
458    ' ', 'Ą', '˘', 'Ł', '¤', 'Ľ', 'Ś', '§',
459    '¨', 'Š', 'Ş', 'Ť', 'Ź', '­', 'Ž', 'Ż',
460    '°', 'ą', '˛', 'ł', '´', 'ľ', 'ś', 'ˇ',
461    '¸', 'š', 'ş', 'ť', 'ź', '˝', 'ž', 'ż',
462    'Ŕ', 'Á', 'Â', 'Ă', 'Ä', 'Ĺ', 'Ć', 'Ç',
463    'Č', 'É', 'Ę', 'Ë', 'Ě', 'Í', 'Î', 'Ď',
464    'Đ', 'Ń', 'Ň', 'Ó', 'Ô', 'Ő', 'Ö', '×',
465    'Ř', 'Ů', 'Ú', 'Ű', 'Ü', 'Ý', 'Ţ', 'ß',
466    'ŕ', 'á', 'â', 'ă', 'ä', 'ĺ', 'ć', 'ç',
467    'č', 'é', 'ę', 'ë', 'ě', 'í', 'î', 'ď',
468    'đ', 'ń', 'ň', 'ó', 'ô', 'ő', 'ö', '÷',
469    'ř', 'ů', 'ú', 'ű', 'ü', 'ý', 'ţ', '˙',
470];
471
472const CP915: [char; 128] = [
473    '€', '', '‚', 'ƒ', '„', '…', '†', '‡',
474    'ˆ', '‰', 'Š', '‹', 'Œ', '', 'Ž', '',
475    '', '‘', '’', '“', '”', '•', '–', '—',
476    '˜', '™', 'š', '›', 'œ', '', 'ž', 'Ÿ',
477    ' ', 'Ё', 'Ђ', 'Ѓ', 'Є', 'Ѕ', 'І', 'Ї',
478    'Ј', 'Љ', 'Њ', 'Ћ', 'Ќ', '­', 'Ў', 'Џ',
479    'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З',
480    'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П',
481    'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч',
482    'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я',
483    'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з',
484    'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',
485    'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч',
486    'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я',
487    '№', 'ё', 'ђ', 'ѓ', 'є', 'ѕ', 'і', 'ї',
488    'ј', 'љ', 'њ', 'ћ', 'ќ', '§', 'ў', 'џ',
489];
490
491#[cfg(test)]
492mod test {
493    use crate::*;
494    use quickcheck::{Arbitrary, Gen, TestResult};
495    use quickcheck_macros::quickcheck;
496
497    #[derive(Debug, Copy, Clone)]
498    struct KnownCodePage(u8);
499
500    impl Arbitrary for KnownCodePage {
501        fn arbitrary(g: &mut Gen) -> Self {
502            KnownCodePage(unsafe {
503                (g.choose(KNOWN_CODE_PAGES).unwrap() as *const u16)
504                    .offset_from(KNOWN_CODE_PAGES.as_ptr())
505            } as u8)
506        }
507
508        fn shrink(&self) -> Box<dyn Iterator<Item=Self>> {
509            Box::new((0 .. self.0).into_iter().rev().map(KnownCodePage))
510        }
511    }
512
513    #[quickcheck]
514    fn low_half_transform_is_trivial(code_page: KnownCodePage) -> bool {
515        let code_page = CodePage::generate(KNOWN_CODE_PAGES[code_page.0 as usize]);
516        (0 .. 128).all(|a| {
517            let u = a as char;
518            let u_ = char::from_u32(a as u32).unwrap();
519            let a_t = code_page.to_char(a).unwrap();
520            let u_t = code_page.from_char(u).unwrap();
521            u == u_ && u == a_t && a == u_t
522        })
523    }
524
525    #[quickcheck]
526    fn to_char_is_from_char_inverse(c: char, code_page: KnownCodePage) -> TestResult {
527        let code_page = CodePage::generate(KNOWN_CODE_PAGES[code_page.0 as usize]);
528        if let Some(b) = code_page.from_char(c) {
529            TestResult::from_bool(code_page.to_char(b) == Some(c))
530        } else {
531            TestResult::discard()
532        }
533    }
534
535    #[quickcheck]
536    fn from_char_is_to_char_inverse(c: u8, code_page: KnownCodePage) -> TestResult {
537        let code_page = CodePage::generate(KNOWN_CODE_PAGES[code_page.0 as usize]);
538        if let Some(u) = code_page.to_char(c) {
539            TestResult::from_bool(code_page.from_char(u) == Some(c))
540        } else {
541            TestResult::discard()
542        }
543    }
544}