Skip to main content

anyxml_encoding/
euc.rs

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