Line | Count | Source (jump to first uncovered line) |
1 | | //! Convert a string in IBM codepage 437 to UTF-8 |
2 | | |
3 | | /// Trait to convert IBM codepage 437 to the target type |
4 | | pub trait FromCp437 { |
5 | | /// Target type |
6 | | type Target; |
7 | | |
8 | | /// Function that does the conversion from cp437. |
9 | | /// Generally allocations will be avoided if all data falls into the ASCII range. |
10 | | #[allow(clippy::wrong_self_convention)] |
11 | | fn from_cp437(self) -> Self::Target; |
12 | | } |
13 | | |
14 | | impl<'a> FromCp437 for &'a [u8] { |
15 | | type Target = ::std::borrow::Cow<'a, str>; |
16 | | |
17 | 0 | fn from_cp437(self) -> Self::Target { |
18 | 0 | if self.iter().all(|c| *c < 0x80) { |
19 | 0 | ::std::str::from_utf8(self).unwrap().into() |
20 | | } else { |
21 | 0 | self.iter().map(|c| to_char(*c)).collect::<String>().into() |
22 | | } |
23 | 0 | } |
24 | | } |
25 | | |
26 | | impl FromCp437 for Vec<u8> { |
27 | | type Target = String; |
28 | | |
29 | 318k | fn from_cp437(self) -> Self::Target { |
30 | 16.3M | if self.iter().all(|c| *c < 0x80) { |
31 | 242k | String::from_utf8(self).unwrap() |
32 | | } else { |
33 | 75.4k | self.into_iter().map(to_char).collect() |
34 | | } |
35 | 318k | } |
36 | | } |
37 | | |
38 | 9.04M | fn to_char(input: u8) -> char { |
39 | 9.04M | let output = match input { |
40 | 9.04M | 0x00..=0x7f => input as u32, |
41 | 30.5k | 0x80 => 0x00c7, |
42 | 33.9k | 0x81 => 0x00fc, |
43 | 4.36k | 0x82 => 0x00e9, |
44 | 836 | 0x83 => 0x00e2, |
45 | 3.57k | 0x84 => 0x00e4, |
46 | 11.6k | 0x85 => 0x00e0, |
47 | 16.8k | 0x86 => 0x00e5, |
48 | 6.83k | 0x87 => 0x00e7, |
49 | 2.23k | 0x88 => 0x00ea, |
50 | 3.84k | 0x89 => 0x00eb, |
51 | 20.0k | 0x8a => 0x00e8, |
52 | 1.16k | 0x8b => 0x00ef, |
53 | 5.11k | 0x8c => 0x00ee, |
54 | 8.70k | 0x8d => 0x00ec, |
55 | 1.60k | 0x8e => 0x00c4, |
56 | 2.01k | 0x8f => 0x00c5, |
57 | 1.54k | 0x90 => 0x00c9, |
58 | 1.32k | 0x91 => 0x00e6, |
59 | 737 | 0x92 => 0x00c6, |
60 | 1.71k | 0x93 => 0x00f4, |
61 | 1.62k | 0x94 => 0x00f6, |
62 | 4.06k | 0x95 => 0x00f2, |
63 | 10.2k | 0x96 => 0x00fb, |
64 | 2.33k | 0x97 => 0x00f9, |
65 | 1.80k | 0x98 => 0x00ff, |
66 | 7.87k | 0x99 => 0x00d6, |
67 | 17.6k | 0x9a => 0x00dc, |
68 | 2.36k | 0x9b => 0x00a2, |
69 | 5.60k | 0x9c => 0x00a3, |
70 | 1.73k | 0x9d => 0x00a5, |
71 | 2.17k | 0x9e => 0x20a7, |
72 | 1.50k | 0x9f => 0x0192, |
73 | 15.7k | 0xa0 => 0x00e1, |
74 | 848 | 0xa1 => 0x00ed, |
75 | 22.4k | 0xa2 => 0x00f3, |
76 | 2.02k | 0xa3 => 0x00fa, |
77 | 9.07k | 0xa4 => 0x00f1, |
78 | 1.94k | 0xa5 => 0x00d1, |
79 | 6.07k | 0xa6 => 0x00aa, |
80 | 2.99k | 0xa7 => 0x00ba, |
81 | 2.03k | 0xa8 => 0x00bf, |
82 | 3.82k | 0xa9 => 0x2310, |
83 | 3.71k | 0xaa => 0x00ac, |
84 | 3.49k | 0xab => 0x00bd, |
85 | 18.2k | 0xac => 0x00bc, |
86 | 3.00k | 0xad => 0x00a1, |
87 | 12.2k | 0xae => 0x00ab, |
88 | 13.3k | 0xaf => 0x00bb, |
89 | 6.15k | 0xb0 => 0x2591, |
90 | 4.76k | 0xb1 => 0x2592, |
91 | 9.94k | 0xb2 => 0x2593, |
92 | 3.17k | 0xb3 => 0x2502, |
93 | 18.1k | 0xb4 => 0x2524, |
94 | 14.1k | 0xb5 => 0x2561, |
95 | 4.53k | 0xb6 => 0x2562, |
96 | 4.13k | 0xb7 => 0x2556, |
97 | 2.35k | 0xb8 => 0x2555, |
98 | 14.9k | 0xb9 => 0x2563, |
99 | 1.91k | 0xba => 0x2551, |
100 | 41.7k | 0xbb => 0x2557, |
101 | 98.7k | 0xbc => 0x255d, |
102 | 16.0k | 0xbd => 0x255c, |
103 | 2.41k | 0xbe => 0x255b, |
104 | 20.7k | 0xbf => 0x2510, |
105 | 7.45k | 0xc0 => 0x2514, |
106 | 5.69k | 0xc1 => 0x2534, |
107 | 9.19k | 0xc2 => 0x252c, |
108 | 53.5k | 0xc3 => 0x251c, |
109 | 16.9k | 0xc4 => 0x2500, |
110 | 2.86k | 0xc5 => 0x253c, |
111 | 718k | 0xc6 => 0x255e, |
112 | 1.98k | 0xc7 => 0x255f, |
113 | 1.81k | 0xc8 => 0x255a, |
114 | 4.67k | 0xc9 => 0x2554, |
115 | 1.46k | 0xca => 0x2569, |
116 | 16.1k | 0xcb => 0x2566, |
117 | 2.34k | 0xcc => 0x2560, |
118 | 21.1k | 0xcd => 0x2550, |
119 | 2.69k | 0xce => 0x256c, |
120 | 4.50k | 0xcf => 0x2567, |
121 | 3.93k | 0xd0 => 0x2568, |
122 | 813k | 0xd1 => 0x2564, |
123 | 2.46k | 0xd2 => 0x2565, |
124 | 10.2k | 0xd3 => 0x2559, |
125 | 12.1k | 0xd4 => 0x2558, |
126 | 3.38k | 0xd5 => 0x2552, |
127 | 3.01k | 0xd6 => 0x2553, |
128 | 2.15k | 0xd7 => 0x256b, |
129 | 1.85k | 0xd8 => 0x256a, |
130 | 4.80k | 0xd9 => 0x2518, |
131 | 3.52k | 0xda => 0x250c, |
132 | 5.45k | 0xdb => 0x2588, |
133 | 3.59k | 0xdc => 0x2584, |
134 | 1.94k | 0xdd => 0x258c, |
135 | 1.54k | 0xde => 0x2590, |
136 | 3.60k | 0xdf => 0x2580, |
137 | 7.65k | 0xe0 => 0x03b1, |
138 | 1.69k | 0xe1 => 0x00df, |
139 | 6.42k | 0xe2 => 0x0393, |
140 | 1.52k | 0xe3 => 0x03c0, |
141 | 2.06k | 0xe4 => 0x03a3, |
142 | 2.07k | 0xe5 => 0x03c3, |
143 | 9.66k | 0xe6 => 0x00b5, |
144 | 1.82k | 0xe7 => 0x03c4, |
145 | 8.63k | 0xe8 => 0x03a6, |
146 | 2.42k | 0xe9 => 0x0398, |
147 | 11.4k | 0xea => 0x03a9, |
148 | 1.19k | 0xeb => 0x03b4, |
149 | 1.10k | 0xec => 0x221e, |
150 | 2.50k | 0xed => 0x03c6, |
151 | 2.09k | 0xee => 0x03b5, |
152 | 20.2k | 0xef => 0x2229, |
153 | 1.79k | 0xf0 => 0x2261, |
154 | 9.26k | 0xf1 => 0x00b1, |
155 | 3.65k | 0xf2 => 0x2265, |
156 | 6.01k | 0xf3 => 0x2264, |
157 | 11.9k | 0xf4 => 0x2320, |
158 | 14.3k | 0xf5 => 0x2321, |
159 | 7.51k | 0xf6 => 0x00f7, |
160 | 16.1k | 0xf7 => 0x2248, |
161 | 10.4k | 0xf8 => 0x00b0, |
162 | 15.6k | 0xf9 => 0x2219, |
163 | 11.5k | 0xfa => 0x00b7, |
164 | 17.2k | 0xfb => 0x221a, |
165 | 12.7k | 0xfc => 0x207f, |
166 | 17.4k | 0xfd => 0x00b2, |
167 | 30.2k | 0xfe => 0x25a0, |
168 | 1.01M | 0xff => 0x00a0, |
169 | | }; |
170 | 9.04M | ::std::char::from_u32(output).unwrap() |
171 | 9.04M | } |
172 | | |
173 | | #[cfg(test)] |
174 | | mod test { |
175 | | #[test] |
176 | | fn to_char_valid() { |
177 | | for i in 0x00_u32..0x100 { |
178 | | super::to_char(i as u8); |
179 | | } |
180 | | } |
181 | | |
182 | | #[test] |
183 | | fn ascii() { |
184 | | for i in 0x00..0x80 { |
185 | | assert_eq!(super::to_char(i), i as char); |
186 | | } |
187 | | } |
188 | | |
189 | | #[test] |
190 | | fn example_slice() { |
191 | | use super::FromCp437; |
192 | | let data = b"Cura\x87ao"; |
193 | | assert!(::std::str::from_utf8(data).is_err()); |
194 | | assert_eq!(data.from_cp437(), "Curaçao"); |
195 | | } |
196 | | |
197 | | #[test] |
198 | | fn example_vec() { |
199 | | use super::FromCp437; |
200 | | let data = vec![0xCC, 0xCD, 0xCD, 0xB9]; |
201 | | assert!(String::from_utf8(data.clone()).is_err()); |
202 | | assert_eq!(&data.from_cp437(), "╠══╣"); |
203 | | } |
204 | | } |