1use crate::{
2 DecodeError, Decoder, EncodeError, Encoder,
3 gb2312::{GB2312_TO_UCS, UCS_TO_GB2312},
4 jisx, ksx,
5};
6
7pub struct EUCDecoder {
8 g1: &'static [&'static [char]],
13 g2: &'static [&'static [char]],
15 g3: &'static [&'static [char]],
17}
18
19impl EUCDecoder {
20 pub(crate) fn decode(
22 &mut self,
23 src: &[u8],
24 dst: &mut String,
25 finish: bool,
26 ) -> Result<(usize, usize), DecodeError> {
27 if src.is_empty() {
28 return if finish {
29 Ok((0, 0))
30 } else {
31 Err(DecodeError::InputIsEmpty)
32 };
33 }
34 let len = dst.capacity() - dst.len();
35 if len < 4 {
36 return Err(DecodeError::OutputTooShort);
37 }
38
39 let (mut read, mut write) = (0, 0);
40 macro_rules! malformed {
41 ( $length:expr ) => {
42 Err(DecodeError::Malformed {
43 read,
44 write,
45 length: $length,
46 offset: 0,
47 })
48 };
49 }
50
51 while read < src.len() {
52 match src[read..] {
53 [0x8E, ..] | [0x8F, ..] => {
54 let g = if src[read] == 0x8E {
56 &self.g2
57 } else {
58 &self.g3
59 };
60
61 read += 1;
62 if read >= src.len() {
63 if finish {
64 return malformed!(1);
65 }
66 break;
67 }
68
69 if src[read] < 0xA0 {
70 read += 1;
71 return malformed!(1);
72 }
73 let s = src[read] as usize - 0xA0;
74 read += 1;
75 if g.len() == 1 {
76 let c = g[0][s];
77 if g[0].len() <= s || g[0][s] == char::REPLACEMENT_CHARACTER {
78 return malformed!(2);
79 }
80 dst.push(c);
81 write += c.len_utf8();
82 } else {
83 if read >= src.len() {
84 if finish {
85 return malformed!(2);
86 }
87 break;
88 }
89 if src[read] < 0xA0 {
90 read += 1;
91 return malformed!(3);
92 }
93 let t = src[read] as usize - 0xA0;
94 read += 1;
95 if g.len() <= s || g[s].len() <= t || g[s][t] == char::REPLACEMENT_CHARACTER
96 {
97 return malformed!(3);
98 }
99 let c = g[s][t];
100 dst.push(c);
101 write += c.len_utf8();
102 }
103 }
104 _ => {
105 if src[read] < 0xA0 {
106 let c = src[read] as char;
112 dst.push(c);
113 read += 1;
114 write += c.len_utf8();
115 } else {
116 if self.g1.len() > 1 {
118 if read + 1 == src.len() {
120 if finish {
122 read += 1;
123 return malformed!(1);
124 }
125 break;
126 }
127 let s = src[read] as usize - 0xA0;
128 if src[read + 1] < 0xA0 {
129 read += 2;
130 return malformed!(2);
131 }
132 let t = src[read + 1] as usize - 0xA0;
133 read += 2;
134 if self.g1.len() <= s
135 || self.g1[s].len() <= t
136 || self.g1[s][t] == char::REPLACEMENT_CHARACTER
137 {
138 return malformed!(2);
139 }
140 let c = self.g1[s][t];
141 dst.push(c);
142 write += c.len_utf8();
143 } else {
144 let c = self.g1[0][src[read] as usize - 0xA0];
146 read += 1;
147 if c == char::REPLACEMENT_CHARACTER {
148 return malformed!(1);
149 } else {
150 dst.push(c);
151 write += c.len_utf8();
152 }
153 }
154 }
155 }
156 }
157
158 if dst.capacity() - dst.len() < 4 {
159 break;
160 }
161 }
162
163 Ok((read, write))
164 }
165}
166
167pub struct EUCEncoder<
168 G1From,
169 G1To,
170 G2From,
171 G2To,
172 G3From,
173 G3To,
174 const G1DIM: u8,
175 const G2DIM: u8,
176 const G3DIM: u8,
177> where
178 G1From: Into<u32> + 'static,
179 G1To: Into<u32> + 'static,
180 G2From: Into<u32> + 'static,
181 G2To: Into<u32> + 'static,
182 G3From: Into<u32> + 'static,
183 G3To: Into<u32> + 'static,
184{
185 g1: &'static [(G1From, G1To)],
189 g2: &'static [(G2From, G2To)],
191 g3: &'static [(G3From, G3To)],
193}
194
195impl<G1From, G1To, G2From, G2To, G3From, G3To, const G1DIM: u8, const G2DIM: u8, const G3DIM: u8>
196 EUCEncoder<G1From, G1To, G2From, G2To, G3From, G3To, G1DIM, G2DIM, G3DIM>
197where
198 G1From: Into<u32> + Copy,
199 G1To: Into<u32> + Copy,
200 G2From: Into<u32> + Copy,
201 G2To: Into<u32> + Copy,
202 G3From: Into<u32> + Copy,
203 G3To: Into<u32> + Copy,
204{
205 pub(crate) fn encode(
207 &mut self,
208 src: &str,
209 dst: &mut [u8],
210 finish: bool,
211 ) -> Result<(usize, usize), EncodeError> {
212 assert!(0 < G1DIM && G1DIM <= 2 && 0 < G2DIM && G2DIM <= 2 && 0 < G3DIM && G3DIM <= 2);
213 if src.is_empty() {
214 return if finish {
215 Ok((0, 0))
216 } else {
217 Err(EncodeError::InputIsEmpty)
218 };
219 }
220
221 if dst.len() < 3 {
222 return Err(EncodeError::OutputTooShort);
223 }
224
225 let (mut read, mut write) = (0, 0);
226 macro_rules! write_buffer {
227 ( $dim:expr, $to:expr ) => {
228 if $dim == 1 {
229 assert!($to < u8::MAX as u32);
230 dst[write] = $to as u8 + 0xA0;
231 write += 1;
232 } else if $dim == 2 {
233 let to = $to + 0x8080;
234 dst[write] = (to >> 8) as u8;
235 dst[write + 1] = (to & 0xFF) as u8;
236 write += 2;
237 } else {
238 unreachable!();
239 }
240 };
241 }
242 for c in src.chars() {
243 read += c.len_utf8();
244 if c.is_ascii() || ((..'\u{A0}').contains(&c) && c != '\u{8E}' && c != '\u{8F}') {
245 dst[write] = c as u8;
246 write += 1;
247 } else if let Ok(pos) = self.g1.binary_search_by_key(&(c as u32), |e| e.0.into()) {
248 let to: u32 = self.g1[pos].1.into();
249 write_buffer!(G1DIM, to);
250 } else if let Ok(pos) = self.g2.binary_search_by_key(&(c as u32), |e| e.0.into()) {
251 dst[write] = 0x8E;
252 write += 1;
253 let to: u32 = self.g2[pos].1.into();
254 write_buffer!(G2DIM, to);
255 } else if let Ok(pos) = self.g3.binary_search_by_key(&(c as u32), |e| e.0.into()) {
256 dst[write] = 0x8F;
257 write += 1;
258 let to: u32 = self.g3[pos].1.into();
259 write_buffer!(G3DIM, to);
260 } else {
261 return Err(EncodeError::Unmappable { read, write, c });
262 }
263
264 if dst[write..].len() < 3 {
265 break;
266 }
267 }
268
269 Ok((read, write))
270 }
271}
272
273pub const EUCJP_NAME: &str = "EUC-JP";
275pub struct EUCJPDecoder {
277 decoder: EUCDecoder,
278}
279
280pub(crate) fn eucjp_decoder_factory() -> Box<dyn Decoder> {
281 static G2: &[&[char]] = &[jisx::JIS_X_0201_KATAKANA_DECODE_TABLE];
282 Box::new(EUCJPDecoder {
283 decoder: EUCDecoder {
284 g1: &jisx::JIS_X_0208_DECODE_TABLE,
285 g2: G2,
286 g3: &jisx::JIS_X_0212_DECODE_TABLE,
287 },
288 })
289}
290
291impl Decoder for EUCJPDecoder {
292 fn name(&self) -> &'static str {
293 EUCJP_NAME
294 }
295
296 fn decode(
297 &mut self,
298 src: &[u8],
299 dst: &mut String,
300 finish: bool,
301 ) -> Result<(usize, usize), DecodeError> {
302 self.decoder.decode(src, dst, finish)
303 }
304}
305
306pub struct EUCJPEncoder {
308 encoder: EUCEncoder<u16, u16, u16, u8, u16, u16, 2, 1, 2>,
309}
310
311pub(crate) fn eucjp_encoder_factory() -> Box<dyn Encoder> {
312 Box::new(EUCJPEncoder {
313 encoder: EUCEncoder {
314 g1: jisx::JIS_X_0208_ENCODE_TABLE,
315 g2: jisx::JIS_X_0201_KATAKANA_ENCODE_TABLE,
316 g3: jisx::JIS_X_0212_ENCODE_TABLE,
317 },
318 })
319}
320
321impl Encoder for EUCJPEncoder {
322 fn name(&self) -> &'static str {
323 EUCJP_NAME
324 }
325
326 fn encode(
327 &mut self,
328 src: &str,
329 dst: &mut [u8],
330 finish: bool,
331 ) -> Result<(usize, usize), EncodeError> {
332 self.encoder.encode(src, dst, finish)
333 }
334}
335
336pub const EUCKR_NAME: &str = "EUC-KR";
338pub struct EUCKRDecoder {
340 decoder: EUCDecoder,
341}
342
343pub(crate) fn euckr_decoder_factory() -> Box<dyn Decoder> {
344 Box::new(EUCKRDecoder {
345 decoder: EUCDecoder {
346 g1: &ksx::KS_X_1001_DECODE_TABLE,
347 g2: &[&[]],
348 g3: &[&[]],
349 },
350 })
351}
352
353impl Decoder for EUCKRDecoder {
354 fn name(&self) -> &'static str {
355 EUCKR_NAME
356 }
357
358 fn decode(
359 &mut self,
360 src: &[u8],
361 dst: &mut String,
362 finish: bool,
363 ) -> Result<(usize, usize), DecodeError> {
364 self.decoder.decode(src, dst, finish)
365 }
366}
367
368pub struct EUCKREncoder {
370 encoder: EUCEncoder<u16, u16, u8, u8, u8, u8, 2, 1, 1>,
371}
372
373pub(crate) fn euckr_encoder_factory() -> Box<dyn Encoder> {
374 Box::new(EUCKREncoder {
375 encoder: EUCEncoder {
376 g1: ksx::KS_X_1001_ENCODE_TABLE,
377 g2: &[],
378 g3: &[],
379 },
380 })
381}
382
383impl Encoder for EUCKREncoder {
384 fn name(&self) -> &'static str {
385 EUCKR_NAME
386 }
387
388 fn encode(
389 &mut self,
390 src: &str,
391 dst: &mut [u8],
392 finish: bool,
393 ) -> Result<(usize, usize), EncodeError> {
394 self.encoder.encode(src, dst, finish)
395 }
396}
397
398pub const GB2312_NAME: &str = "GB2312";
400
401pub struct GB2312Encoder {
403 encoder: EUCEncoder<u16, u16, u8, u8, u8, u8, 2, 1, 1>,
404}
405
406impl Encoder for GB2312Encoder {
407 fn name(&self) -> &'static str {
408 GB2312_NAME
409 }
410
411 fn encode(
412 &mut self,
413 src: &str,
414 dst: &mut [u8],
415 finish: bool,
416 ) -> Result<(usize, usize), crate::EncodeError> {
417 self.encoder.encode(src, dst, finish)
418 }
419}
420
421pub(crate) fn gb2312_encoder_factory() -> Box<dyn Encoder> {
422 Box::new(GB2312Encoder {
423 encoder: EUCEncoder {
424 g1: UCS_TO_GB2312,
425 g2: &[],
426 g3: &[],
427 },
428 })
429}
430
431pub struct GB2312Decoder {
433 decoder: EUCDecoder,
434}
435
436impl Decoder for GB2312Decoder {
437 fn name(&self) -> &'static str {
438 GB2312_NAME
439 }
440
441 fn decode(
442 &mut self,
443 src: &[u8],
444 dst: &mut String,
445 finish: bool,
446 ) -> Result<(usize, usize), crate::DecodeError> {
447 self.decoder.decode(src, dst, finish)
448 }
449}
450
451pub(crate) fn gb2312_decoder_factory() -> Box<dyn Decoder> {
452 Box::new(GB2312Decoder {
453 decoder: EUCDecoder {
454 g1: &GB2312_TO_UCS,
455 g2: &[&[]],
456 g3: &[&[]],
457 },
458 })
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464
465 #[test]
466 fn eucjp_katakana_tests() {
467 let bytes = &[
468 0x8e, 0xb1, 0x8e, 0xb2, 0x8e, 0xb3, 0x8e, 0xb4, 0x8e, 0xb5, 0x8e, 0xb6, 0x8e, 0xb7,
469 0x8e, 0xb8, 0x8e, 0xb9, 0x8e, 0xba, 0x8e, 0xbb, 0x8e, 0xbc, 0x8e, 0xbd, 0x8e, 0xbe,
470 0x8e, 0xbf, 0x8e, 0xc0, 0x8e, 0xc1, 0x8e, 0xc2, 0x8e, 0xc3, 0x8e, 0xc4, 0x8e, 0xc5,
471 0x8e, 0xc6, 0x8e, 0xc7, 0x8e, 0xc8, 0x8e, 0xc9, 0x8e, 0xca, 0x8e, 0xcb, 0x8e, 0xcc,
472 0x8e, 0xcd, 0x8e, 0xce, 0x8e, 0xcf, 0x8e, 0xd0, 0x8e, 0xd1, 0x8e, 0xd2, 0x8e, 0xd3,
473 0x8e, 0xd4, 0x8e, 0xd5, 0x8e, 0xd6, 0x8e, 0xd7, 0x8e, 0xd8, 0x8e, 0xd9, 0x8e, 0xda,
474 0x8e, 0xdb, 0x8e, 0xdc, 0x8e, 0xa6, 0x8e, 0xdd,
475 ];
476 let mut buf = String::with_capacity(512);
477 eucjp_decoder_factory()
478 .decode(bytes, &mut buf, true)
479 .unwrap();
480 assert_eq!(buf, "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン");
481 }
482
483 #[test]
484 fn eucjp_kanji_tests() {
485 let bytes = &[
486 0xc4, 0xbf, 0xb9, 0xf1, 0xb2, 0xc8, 0xa5, 0xce, 0xce, 0xb4, 0xbe, 0xbb, 0xa5, 0xc8,
487 0xbf, 0xc3, 0xcc, 0xb1, 0xa5, 0xce, 0xb7, 0xc4, 0xca, 0xa1, 0xa5, 0xc8, 0xa5, 0xf2,
488 0xb0, 0xca, 0xa5, 0xc6, 0xc3, 0xe6, 0xbf, 0xb4, 0xa5, 0xce, 0xb6, 0xd5, 0xb1, 0xc9,
489 0xa5, 0xc8, 0xa5, 0xb7, 0xc4, 0xbf, 0xa5, 0xab, 0xc1, 0xc4, 0xbd, 0xa1, 0xa5, 0xcb,
490 0xbe, 0xb5, 0xa5, 0xaf, 0xa5, 0xeb, 0xa5, 0xce, 0xc2, 0xe7, 0xb8, 0xa2, 0xa5, 0xcb,
491 0xb0, 0xcd, 0xa5, 0xea, 0xb8, 0xbd, 0xba, 0xdf, 0xb5, 0xda, 0xbe, 0xad, 0xcd, 0xe8,
492 0xa5, 0xce, 0xbf, 0xc3, 0xcc, 0xb1, 0xa5, 0xcb, 0xc2, 0xd0, 0xa5, 0xb7, 0xba, 0xa1,
493 0xa5, 0xce, 0xc9, 0xd4, 0xcb, 0xe1, 0xa5, 0xce, 0xc2, 0xe7, 0xc5, 0xb5, 0xa5, 0xf2,
494 0xc0, 0xeb, 0xc9, 0xdb, 0xa5, 0xb9, 0x0a, 0xb0, 0xd4, 0xa5, 0xd5, 0xa5, 0xcb, 0xb2,
495 0xe6, 0xa5, 0xab, 0xc1, 0xc4, 0xb2, 0xe6, 0xa5, 0xab, 0xbd, 0xa1, 0xa5, 0xcf, 0xb2,
496 0xe6, 0xa5, 0xab, 0xbf, 0xc3, 0xcc, 0xb1, 0xc1, 0xc4, 0xc0, 0xe8, 0xa5, 0xce, 0xb6,
497 0xa8, 0xce, 0xcf, 0xca, 0xe5, 0xcd, 0xe3, 0xa5, 0xcb, 0xd0, 0xe1, 0xa5, 0xea, 0xb2,
498 0xe6, 0xa5, 0xab, 0xc4, 0xeb, 0xb9, 0xf1, 0xa5, 0xf2, 0xc8, 0xa5, 0xc2, 0xa4, 0xa5,
499 0xb7, 0xb0, 0xca, 0xa5, 0xc6, 0xcc, 0xb5, 0xb5, 0xe7, 0xa5, 0xcb, 0xbf, 0xe2, 0xa5,
500 0xec, 0xa5, 0xbf, 0xa5, 0xea, 0xba, 0xa1, 0xa5, 0xec, 0xb2, 0xe6, 0xa5, 0xab, 0xbf,
501 0xc0, 0xc0, 0xbb, 0xa5, 0xca, 0xa5, 0xeb, 0xc1, 0xc4, 0xbd, 0xa1, 0xa5, 0xce, 0xb0,
502 0xd2, 0xc6, 0xc1, 0xa5, 0xc8, 0xca, 0xc2, 0xa5, 0xcb, 0xbf, 0xc3, 0xcc, 0xb1, 0xa5,
503 0xce, 0xc3, 0xe9, 0xbc, 0xc2, 0xcd, 0xa6, 0xc9, 0xf0, 0xa5, 0xcb, 0xa5, 0xb7, 0xa5,
504 0xc6, 0xb9, 0xf1, 0xa5, 0xf2, 0xb0, 0xa6, 0xa5, 0xb7, 0xb8, 0xf8, 0xa5, 0xcb, 0xbd,
505 0xde, 0xa5, 0xd2, 0xb0, 0xca, 0xa5, 0xc6, 0xba, 0xa1, 0xa5, 0xce, 0xb8, 0xf7, 0xb5,
506 0xb1, 0xa5, 0xa2, 0xa5, 0xeb, 0xb9, 0xf1, 0xbb, 0xcb, 0xa5, 0xce, 0xc0, 0xae, 0xc0,
507 0xd7, 0xa5, 0xf2, 0xec, 0xc6, 0xa5, 0xb7, 0xa5, 0xbf, 0xa5, 0xeb, 0xa5, 0xca, 0xa5,
508 0xea, 0xc4, 0xbf, 0xb2, 0xe6, 0xa5, 0xab, 0xbf, 0xc3, 0xcc, 0xb1, 0xa5, 0xcf, 0xc2,
509 0xa8, 0xa5, 0xc1, 0xc1, 0xc4, 0xbd, 0xa1, 0xa5, 0xce, 0xc3, 0xe9, 0xce, 0xc9, 0xa5,
510 0xca, 0xa5, 0xeb, 0xbf, 0xc3, 0xcc, 0xb1, 0xa5, 0xce, 0xbb, 0xd2, 0xc2, 0xb9, 0xa5,
511 0xca, 0xa5, 0xeb, 0xa5, 0xf2, 0xb2, 0xf3, 0xc1, 0xdb, 0xa5, 0xb7, 0xc2, 0xb6, 0xa5,
512 0xce, 0xc4, 0xbf, 0xa5, 0xab, 0xb0, 0xd5, 0xa5, 0xf2, 0xca, 0xf4, 0xc2, 0xce, 0xa5,
513 0xb7, 0xc4, 0xbf, 0xa5, 0xab, 0xbb, 0xf6, 0xa5, 0xf2, 0xbe, 0xa9, 0xbd, 0xe7, 0xa5,
514 0xb7, 0xc1, 0xea, 0xcd, 0xbf, 0xa5, 0xcb, 0xcf, 0xc2, 0xc3, 0xef, 0xb6, 0xa8, 0xc6,
515 0xb1, 0xa5, 0xb7, 0xb1, 0xd7, 0xa1, 0xb9, 0xb2, 0xe6, 0xa5, 0xab, 0xc4, 0xeb, 0xb9,
516 0xf1, 0xa5, 0xce, 0xb8, 0xf7, 0xb1, 0xc9, 0xa5, 0xf2, 0xc3, 0xe6, 0xb3, 0xb0, 0xa5,
517 0xcb, 0xc0, 0xeb, 0xcd, 0xc8, 0xa5, 0xb7, 0xc1, 0xc4, 0xbd, 0xa1, 0xa5, 0xce, 0xb0,
518 0xe4, 0xb6, 0xc8, 0xa5, 0xf2, 0xb1, 0xca, 0xb5, 0xd7, 0xa5, 0xcb, 0xf0, 0xdf, 0xb8,
519 0xc7, 0xa5, 0xca, 0xa5, 0xe9, 0xa5, 0xb7, 0xa5, 0xe0, 0xa5, 0xeb, 0xa5, 0xce, 0xb4,
520 0xf5, 0xcb, 0xbe, 0xa5, 0xf2, 0xc6, 0xb1, 0xa5, 0xaf, 0xa5, 0xb7, 0xba, 0xa1, 0xa5,
521 0xce, 0xc9, 0xe9, 0xc3, 0xb4, 0xa5, 0xf2, 0xca, 0xac, 0xa5, 0xc4, 0xa5, 0xcb, 0xb4,
522 0xae, 0xa5, 0xd5, 0xa5, 0xeb, 0xa5, 0xb3, 0xa5, 0xc8, 0xa5, 0xf2, 0xb5, 0xbf, 0xa5,
523 0xcf, 0xa5, 0xb5, 0xa5, 0xeb, 0xa5, 0xca, 0xa5, 0xea,
524 ];
525
526 let mut buf = String::with_capacity(1024);
527 let (read, _) = eucjp_decoder_factory()
528 .decode(bytes, &mut buf, true)
529 .unwrap();
530 assert_eq!(read, bytes.len());
531 assert_eq!(
532 buf,
533 "朕国家ノ隆昌ト臣民ノ慶福トヲ以テ中心ノ欣栄トシ朕カ祖宗ニ承クルノ大権ニ依リ現在及将来ノ臣民ニ対シ此ノ不磨ノ大典ヲ宣布ス\n惟フニ我カ祖我カ宗ハ我カ臣民祖先ノ協力輔翼ニ倚リ我カ帝国ヲ肇造シ以テ無窮ニ垂レタリ此レ我カ神聖ナル祖宗ノ威徳ト並ニ臣民ノ忠実勇武ニシテ国ヲ愛シ公ニ殉ヒ以テ此ノ光輝アル国史ノ成跡ヲ貽シタルナリ朕我カ臣民ハ即チ祖宗ノ忠良ナル臣民ノ子孫ナルヲ回想シ其ノ朕カ意ヲ奉体シ朕カ事ヲ奨順シ相与ニ和衷協同シ益々我カ帝国ノ光栄ヲ中外ニ宣揚シ祖宗ノ遺業ヲ永久ニ鞏固ナラシムルノ希望ヲ同クシ此ノ負担ヲ分ツニ堪フルコトヲ疑ハサルナリ"
534 );
535 }
536
537 #[test]
538 fn euckr_kanji_hangul_tests() {
539 let bytes = &[
540 0xea, 0xed, 0xce, 0xf9, 0xc7, 0xd1, 0x20, 0xd5, 0xf6, 0xde, 0xc8, 0xbf, 0xcd, 0x20,
541 0xee, 0xee, 0xf7, 0xd6, 0xbf, 0xa1, 0x20, 0xba, 0xfb, 0xb3, 0xaa, 0xb4, 0xc2, 0x20,
542 0xbf, 0xec, 0xb8, 0xae, 0x20, 0xd3, 0xde, 0xf9, 0xdb, 0xcf, 0xd0, 0xda, 0xc5, 0xc0,
543 0xba, 0x20, 0x33, 0xa1, 0xa4, 0x31, 0x20, 0xea, 0xa1, 0xd4, 0xd1, 0xc0, 0xb8, 0xb7,
544 0xce, 0x20, 0xcb, 0xef, 0xd8, 0xa1, 0xb5, 0xc8, 0x20, 0xd3, 0xde, 0xf9, 0xdb, 0xda,
545 0xc5, 0xcf, 0xd0, 0xd7, 0xfc, 0xe3, 0xc1, 0xef, 0xd9, 0xdd, 0xa4, 0xc0, 0xc7, 0x20,
546 0xdb, 0xf6, 0xf7, 0xd6, 0xb0, 0xfa, 0x20, 0xdc, 0xf4, 0xeb, 0xf9, 0xbf, 0xa1, 0x20,
547 0xf9, 0xf7, 0xcb, 0xde, 0xc7, 0xd1, 0x20, 0x34, 0xa1, 0xa4, 0x31, 0x39, 0x20, 0xda,
548 0xc5, 0xf1, 0xab, 0xd7, 0xe2, 0xd2, 0xb7, 0xc0, 0xbb, 0x20, 0xcd, 0xa9, 0xe3, 0xaf,
549 0xc7, 0xcf, 0xb0, 0xed, 0x2c, 0x20, 0xf0, 0xd3, 0xcf, 0xd0, 0xc0, 0xc7, 0x20, 0xda,
550 0xc5, 0xf1, 0xab, 0xcb, 0xc7, 0xfa, 0xd4, 0xb0, 0xfa, 0x20, 0xf8, 0xc1, 0xfb, 0xfa,
551 0xee, 0xdc, 0xf7, 0xd6, 0xec, 0xe9, 0xc0, 0xc7, 0x20, 0xde, 0xc5, 0xd9, 0xa4, 0xbf,
552 0xa1, 0x20, 0xd8, 0xa1, 0xca, 0xc5, 0xc7, 0xcf, 0xbf, 0xa9, 0x20, 0xef, 0xe1, 0xeb,
553 0xf9, 0xa1, 0xa4, 0xec, 0xd1, 0xd4, 0xb3, 0xbf, 0xcd, 0x20, 0xd4, 0xd2, 0xf8, 0xe0,
554 0xe4, 0xf1, 0xb7, 0xce, 0xbd, 0xe1, 0x20, 0xda, 0xc5, 0xf0, 0xe9, 0xc0, 0xc7, 0x20,
555 0xd3, 0xa5, 0xcc, 0xbf, 0xc0, 0xbb, 0x20, 0xcd, 0xf9, 0xcd, 0xb3, 0xc8, 0xf7, 0x20,
556 0xc7, 0xcf, 0xb0, 0xed, 0x2c, 0x20, 0xb8, 0xf0, 0xb5, 0xe7, 0x20, 0xde, 0xe4, 0xfc,
557 0xe5, 0xee, 0xdc, 0xf8, 0xc9, 0xe3, 0xa7, 0xb0, 0xfa, 0x20, 0xdc, 0xf4, 0xeb, 0xf9,
558 0xb8, 0xa6, 0x20, 0xf6, 0xe8, 0xf7, 0xf2, 0xc7, 0xcf, 0xb8, 0xe7, 0x2c, 0x20, 0xed,
559 0xbb, 0xd7, 0xc8, 0xb0, 0xfa, 0x20, 0xf0, 0xe0, 0xfb, 0xfa, 0xb8, 0xa6, 0x20, 0xb9,
560 0xd9, 0xc5, 0xc1, 0xc0, 0xb8, 0xb7, 0xce, 0x20, 0xed, 0xbb, 0xeb, 0xa6, 0xda, 0xc5,
561 0xf1, 0xab, 0xee, 0xdc, 0xd0, 0xf1, 0xdc, 0xe2, 0xf2, 0xf1, 0xdf, 0xed, 0xb8, 0xa6,
562 0x20, 0xb4, 0xf5, 0xbf, 0xed, 0x20, 0xfc, 0xac, 0xcd, 0xb3, 0xc8, 0xf7, 0x20, 0xc7,
563 0xcf, 0xbf, 0xa9, 0x20, 0xef, 0xd9, 0xf6, 0xbd, 0xa1, 0xa4, 0xcc, 0xe8, 0xf0, 0xad,
564 0xa1, 0xa4, 0xde, 0xe4, 0xfc, 0xe5, 0xa1, 0xa4, 0xd9, 0xfe, 0xfb, 0xf9, 0xc0, 0xc7,
565 0x20, 0xb8, 0xf0, 0xb5, 0xe7, 0x20, 0xd6, 0xc5, 0xe6, 0xb4, 0xbf, 0xa1, 0x20, 0xc0,
566 0xd6, 0xbe, 0xee, 0xbc, 0xad, 0x20, 0xca, 0xc0, 0xec, 0xd1, 0xc0, 0xc7, 0x20, 0xd1,
567 0xa6, 0xfc, 0xe5, 0xb8, 0xa6, 0x20, 0xd0, 0xb3, 0xd4, 0xf5, 0xc8, 0xf7, 0x20, 0xc7,
568 0xcf, 0xb0, 0xed, 0x2c, 0x20, 0xd2, 0xf6, 0xd5, 0xf4, 0xc0, 0xbb, 0x20, 0xf5, 0xcc,
569 0xcd, 0xd4, 0xd3, 0xf8, 0xb7, 0xce, 0x20, 0xdb, 0xa1, 0xfd, 0xc6, 0xc7, 0xcf, 0xb0,
570 0xd4, 0x20, 0xc7, 0xcf, 0xb8, 0xe7, 0x2c, 0x20, 0xed, 0xbb, 0xeb, 0xa6, 0xbf, 0xcd,
571 0x20, 0xcf, 0xed, 0xd7, 0xd7, 0xbf, 0xa1, 0x20, 0xb5, 0xfb, 0xb8, 0xa3, 0xb4, 0xc2,
572 0x20, 0xf4, 0xa1, 0xec, 0xf2, 0xb0, 0xfa, 0x20, 0xeb, 0xf9, 0xd9, 0xe2, 0xb8, 0xa6,
573 0x20, 0xe8, 0xc7, 0xe2, 0xc4, 0xc7, 0xcf, 0xb0, 0xd4, 0x20, 0xc7, 0xcf, 0xbf, 0xa9,
574 0x2c, 0x20, 0xbe, 0xc8, 0xc0, 0xb8, 0xb7, 0xce, 0xb4, 0xc2, 0x20, 0xcf, 0xd0, 0xda,
575 0xc5, 0xdf, 0xe6, 0xfc, 0xc0, 0xc0, 0xc7, 0x20, 0xd0, 0xb3, 0xd4, 0xf5, 0xc7, 0xd1,
576 0x20, 0xfa, 0xbe, 0xdf, 0xbe, 0xc0, 0xbb, 0x20, 0xd1, 0xa2, 0xc7, 0xcf, 0xb0, 0xed,
577 0x20, 0xb9, 0xdb, 0xc0, 0xb8, 0xb7, 0xce, 0xb4, 0xc2, 0x20, 0xf9, 0xf6, 0xce, 0xf9,
578 0xee, 0xdc, 0xc0, 0xce, 0x20, 0xe1, 0xa6, 0xcd, 0xa3, 0xf8, 0xc1, 0xfb, 0xfa, 0xbf,
579 0xcd, 0x20, 0xec, 0xd1, 0xd7, 0xbe, 0xcd, 0xec, 0xe7, 0xb4, 0xbf, 0xa1, 0x20, 0xc0,
580 0xcc, 0xb9, 0xd9, 0xc1, 0xf6, 0xc7, 0xd4, 0xc0, 0xb8, 0xb7, 0xce, 0xbd, 0xe1, 0x20,
581 0xbf, 0xec, 0xb8, 0xae, 0xb5, 0xe9, 0xb0, 0xfa, 0x20, 0xbf, 0xec, 0xb8, 0xae, 0xb5,
582 0xe9, 0xc0, 0xc7, 0x20, 0xed, 0xad, 0xe1, 0xdd, 0xc0, 0xc7, 0x20, 0xe4, 0xcc, 0xee,
583 0xef, 0xb0, 0xfa, 0x20, 0xed, 0xbb, 0xeb, 0xa6, 0xbf, 0xcd, 0x20, 0xfa, 0xb9, 0xdc,
584 0xd8, 0xc0, 0xbb, 0x20, 0xe7, 0xb5, 0xea, 0xc0, 0xc8, 0xf7, 0x20, 0xfc, 0xac, 0xdc,
585 0xc1, 0xc7, 0xd2, 0x20, 0xb0, 0xcd, 0xc0, 0xbb, 0x20, 0xb4, 0xd9, 0xc1, 0xfc, 0xc7,
586 0xcf, 0xb8, 0xe9, 0xbc, 0xad, 0x20, 0x31, 0x39, 0x34, 0x38, 0xd2, 0xb4, 0x20, 0x37,
587 0xea, 0xc5, 0x20, 0x31, 0x32, 0xec, 0xed, 0xbf, 0xa1, 0x20, 0xf0, 0xa4, 0xef, 0xd2,
588 0xb5, 0xc7, 0xb0, 0xed, 0x20, 0x38, 0xf3, 0xad, 0xbf, 0xa1, 0x20, 0xb0, 0xc9, 0xc3,
589 0xc4, 0x20, 0xcb, 0xc7, 0xef, 0xe1, 0xb5, 0xc8, 0x20, 0xfa, 0xca, 0xdb, 0xf6, 0xc0,
590 0xbb, 0x20, 0xc0, 0xcc, 0xc1, 0xa6, 0x20, 0xcf, 0xd0, 0xfc, 0xe5, 0xc0, 0xc7, 0x20,
591 0xec, 0xa1, 0xcc, 0xbd, 0xc0, 0xbb, 0x20, 0xb0, 0xc5, 0xc3, 0xc4, 0x20, 0xcf, 0xd0,
592 0xda, 0xc5, 0xf7, 0xe1, 0xf8, 0xf9, 0xbf, 0xa1, 0x20, 0xeb, 0xee, 0xc7, 0xcf, 0xbf,
593 0xa9, 0x20, 0xcb, 0xc7, 0xef, 0xe1, 0xc7, 0xd1, 0xb4, 0xd9, 0x2e,
594 ];
595
596 let mut buf = String::with_capacity(2048);
597 let (read, _) = euckr_decoder_factory()
598 .decode(bytes, &mut buf, true)
599 .unwrap();
600 assert_eq!(read, bytes.len());
601 assert_eq!(
602 buf,
603 "悠久한 歷史와 傳統에 빛나는 우리 大韓國民은 3·1 運動으로 建立된 大韓民國臨時政府의 法統과 不義에 抗拒한 4·19 民主理念을 繼承하고, 祖國의 民主改革과 平和的統一의 使命에 立脚하여 正義·人道와 同胞愛로써 民族의 團結을 鞏固히 하고, 모든 社會的弊習과 不義를 打破하며, 自律과 調和를 바탕으로 自由民主的基本秩序를 더욱 確固히 하여 政治·經濟·社會·文化의 모든 領域에 있어서 各人의 機會를 均等히 하고, 能力을 最高度로 發揮하게 하며, 自由와 權利에 따르는 責任과 義務를 完遂하게 하여, 안으로는 國民生活의 均等한 向上을 期하고 밖으로는 恒久的인 世界平和와 人類共榮에 이바지함으로써 우리들과 우리들의 子孫의 安全과 自由와 幸福을 永遠히 確保할 것을 다짐하면서 1948年 7月 12日에 制定되고 8次에 걸쳐 改正된 憲法을 이제 國會의 議決을 거쳐 國民投票에 依하여 改正한다."
604 );
605 }
606
607 #[test]
608 fn gb2312_tests() {
609 let src = include_str!("../resources/gb2312tests/邓小平南巡讲话_unicode.txt");
610 let mut buf = vec![0; 1 << 15];
611 let (_, write) = gb2312_encoder_factory()
612 .encode(src, &mut buf, true)
613 .unwrap();
614 assert!(buf.len() >= write);
615 buf.truncate(write);
616
617 let bytes = include_bytes!("../resources/gb2312tests/邓小平南巡讲话_GB2312.txt").as_slice();
618 assert_eq!(buf.as_slice(), bytes);
619
620 let mut unicode = String::with_capacity(src.len() * 2);
621 gb2312_decoder_factory()
622 .decode(&buf, &mut unicode, true)
623 .unwrap();
624 assert_eq!(src, unicode);
625 }
626}