1use super::*;
11use crate::data::*;
12use crate::handles::*;
13use crate::variant::*;
14use super::in_inclusive_range16;
16
17#[derive(Copy, Clone, PartialEq)]
18enum Iso2022JpDecoderState {
19 Ascii,
20 Roman,
21 Katakana,
22 LeadByte,
23 TrailByte,
24 EscapeStart,
25 Escape,
26}
27
28pub struct Iso2022JpDecoder {
29 decoder_state: Iso2022JpDecoderState,
30 output_state: Iso2022JpDecoderState, lead: u8,
32 output_flag: bool,
33 pending_prepended: bool,
34}
35
36impl Iso2022JpDecoder {
37 pub fn new() -> VariantDecoder {
38 VariantDecoder::Iso2022Jp(Iso2022JpDecoder {
39 decoder_state: Iso2022JpDecoderState::Ascii,
40 output_state: Iso2022JpDecoderState::Ascii,
41 lead: 0u8,
42 output_flag: false,
43 pending_prepended: false,
44 })
45 }
46
47 pub fn in_neutral_state(&self) -> bool {
48 self.decoder_state == Iso2022JpDecoderState::Ascii
49 && self.output_state == Iso2022JpDecoderState::Ascii
50 && self.lead == 0u8
51 && !self.output_flag
52 && !self.pending_prepended
53 }
54
55 fn extra_to_input_from_state(&self, byte_length: usize) -> Option<usize> {
56 byte_length.checked_add(
57 if self.lead == 0 || self.pending_prepended {
58 0
59 } else {
60 1
61 } + match self.decoder_state {
62 Iso2022JpDecoderState::Escape | Iso2022JpDecoderState::EscapeStart => 1,
63 _ => 0,
64 },
65 )
66 }
67
68 fn extra_to_output_from_state(&self) -> usize {
69 if self.lead != 0 && self.pending_prepended {
70 1 + self.output_flag as usize
71 } else {
72 self.output_flag as usize
73 }
74 }
75
76 pub fn max_utf16_buffer_length(&self, byte_length: usize) -> Option<usize> {
77 checked_add(
78 self.extra_to_output_from_state(),
79 self.extra_to_input_from_state(byte_length),
80 )
81 }
82
83 pub fn max_utf8_buffer_length_without_replacement(&self, byte_length: usize) -> Option<usize> {
84 self.max_utf8_buffer_length(byte_length)
86 }
87
88 pub fn max_utf8_buffer_length(&self, byte_length: usize) -> Option<usize> {
89 checked_mul(
90 3,
91 checked_add(
92 self.extra_to_output_from_state(),
93 self.extra_to_input_from_state(byte_length),
94 ),
95 )
96 }
97
98 decoder_functions!(
99 preamble = {
100 if self.pending_prepended {
101 debug_assert!(self.lead == 0x24u8 || self.lead == 0x28u8);
104 match dest.check_space_bmp() {
105 Space::Full(_) => {
106 return (DecoderResult::OutputFull, 0, 0);
107 }
108 Space::Available(destination_handle) => {
109 self.pending_prepended = false;
110 self.output_flag = false;
111 match self.decoder_state {
112 Iso2022JpDecoderState::Ascii | Iso2022JpDecoderState::Roman => {
113 destination_handle.write_ascii(self.lead);
114 self.lead = 0x0u8;
115 }
116 Iso2022JpDecoderState::Katakana => {
117 destination_handle
118 .write_upper_bmp(u16::from(self.lead) - 0x21u16 + 0xFF61u16);
119 self.lead = 0x0u8;
120 }
121 Iso2022JpDecoderState::LeadByte => {
122 self.decoder_state = Iso2022JpDecoderState::TrailByte;
123 }
124 _ => unreachable!(),
125 }
126 }
127 }
128 }
129 },
130 loop_preamble = {},
131 eof = {
132 match self.decoder_state {
133 Iso2022JpDecoderState::TrailByte | Iso2022JpDecoderState::EscapeStart => {
134 self.decoder_state = self.output_state;
135 return (DecoderResult::Malformed(1, 0), src_consumed, dest.written());
136 }
137 Iso2022JpDecoderState::Escape => {
138 self.pending_prepended = true;
139 self.decoder_state = self.output_state;
140 return (DecoderResult::Malformed(1, 1), src_consumed, dest.written());
141 }
142 _ => {}
143 }
144 },
145 body = {
146 match self.decoder_state {
147 Iso2022JpDecoderState::Ascii => {
148 if b == 0x1Bu8 {
149 self.decoder_state = Iso2022JpDecoderState::EscapeStart;
150 continue;
151 }
152 self.output_flag = false;
153 if b > 0x7Fu8 || b == 0x0Eu8 || b == 0x0Fu8 {
154 return (
155 DecoderResult::Malformed(1, 0),
156 unread_handle.consumed(),
157 destination_handle.written(),
158 );
159 }
160 destination_handle.write_ascii(b);
161 continue;
162 }
163 Iso2022JpDecoderState::Roman => {
164 if b == 0x1Bu8 {
165 self.decoder_state = Iso2022JpDecoderState::EscapeStart;
166 continue;
167 }
168 self.output_flag = false;
169 if b == 0x5Cu8 {
170 destination_handle.write_mid_bmp(0x00A5u16);
171 continue;
172 }
173 if b == 0x7Eu8 {
174 destination_handle.write_upper_bmp(0x203Eu16);
175 continue;
176 }
177 if b > 0x7Fu8 || b == 0x0Eu8 || b == 0x0Fu8 {
178 return (
179 DecoderResult::Malformed(1, 0),
180 unread_handle.consumed(),
181 destination_handle.written(),
182 );
183 }
184 destination_handle.write_ascii(b);
185 continue;
186 }
187 Iso2022JpDecoderState::Katakana => {
188 if b == 0x1Bu8 {
189 self.decoder_state = Iso2022JpDecoderState::EscapeStart;
190 continue;
191 }
192 self.output_flag = false;
193 if (0x21u8..=0x5Fu8).contains(&b) {
194 destination_handle.write_upper_bmp(u16::from(b) - 0x21u16 + 0xFF61u16);
195 continue;
196 }
197 return (
198 DecoderResult::Malformed(1, 0),
199 unread_handle.consumed(),
200 destination_handle.written(),
201 );
202 }
203 Iso2022JpDecoderState::LeadByte => {
204 if b == 0x1Bu8 {
205 self.decoder_state = Iso2022JpDecoderState::EscapeStart;
206 continue;
207 }
208 self.output_flag = false;
209 if (0x21u8..=0x7Eu8).contains(&b) {
210 self.lead = b;
211 self.decoder_state = Iso2022JpDecoderState::TrailByte;
212 continue;
213 }
214 return (
215 DecoderResult::Malformed(1, 0),
216 unread_handle.consumed(),
217 destination_handle.written(),
218 );
219 }
220 Iso2022JpDecoderState::TrailByte => {
221 if b == 0x1Bu8 {
222 self.decoder_state = Iso2022JpDecoderState::EscapeStart;
223 return (
226 DecoderResult::Malformed(1, 1),
227 unread_handle.consumed(),
228 destination_handle.written(),
229 );
230 }
231 self.decoder_state = Iso2022JpDecoderState::LeadByte;
232 let jis0208_lead_minus_offset = self.lead - 0x21;
233 let byte = b;
234 let handle = destination_handle;
235 let trail_minus_offset = byte.wrapping_sub(0x21);
238 if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 {
241 handle.write_upper_bmp(0x3041 + u16::from(trail_minus_offset));
243 continue;
244 } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 {
245 handle.write_upper_bmp(0x30A1 + u16::from(trail_minus_offset));
247 continue;
248 } else if trail_minus_offset > (0xFE - 0xA1) {
249 return (
250 DecoderResult::Malformed(2, 0),
251 unread_handle.consumed(),
252 handle.written(),
253 );
254 } else {
255 let pointer =
256 mul_94(jis0208_lead_minus_offset) + trail_minus_offset as usize;
257 let level1_pointer = pointer.wrapping_sub(1410);
258 if level1_pointer < JIS0208_LEVEL1_KANJI.len() {
259 handle.write_upper_bmp(JIS0208_LEVEL1_KANJI[level1_pointer]);
260 continue;
261 } else {
262 let level2_pointer = pointer.wrapping_sub(4418);
263 if level2_pointer < JIS0208_LEVEL2_AND_ADDITIONAL_KANJI.len() {
264 handle.write_upper_bmp(
265 JIS0208_LEVEL2_AND_ADDITIONAL_KANJI[level2_pointer],
266 );
267 continue;
268 } else {
269 let ibm_pointer = pointer.wrapping_sub(8272);
270 if ibm_pointer < IBM_KANJI.len() {
271 handle.write_upper_bmp(IBM_KANJI[ibm_pointer]);
272 continue;
273 } else if let Some(bmp) = jis0208_symbol_decode(pointer) {
274 handle.write_bmp_excl_ascii(bmp);
275 continue;
276 } else if let Some(bmp) = jis0208_range_decode(pointer) {
277 handle.write_bmp_excl_ascii(bmp);
278 continue;
279 } else {
280 return (
281 DecoderResult::Malformed(2, 0),
282 unread_handle.consumed(),
283 handle.written(),
284 );
285 }
286 }
287 }
288 }
289 }
290 Iso2022JpDecoderState::EscapeStart => {
291 if b == 0x24u8 || b == 0x28u8 {
292 self.lead = b;
293 self.decoder_state = Iso2022JpDecoderState::Escape;
294 continue;
295 }
296 self.output_flag = false;
297 self.decoder_state = self.output_state;
298 return (
299 DecoderResult::Malformed(1, 0),
300 unread_handle.unread(),
301 destination_handle.written(),
302 );
303 }
304 Iso2022JpDecoderState::Escape => {
305 let mut state: Option<Iso2022JpDecoderState> = None;
306 if self.lead == 0x28u8 && b == 0x42u8 {
307 state = Some(Iso2022JpDecoderState::Ascii);
308 } else if self.lead == 0x28u8 && b == 0x4Au8 {
309 state = Some(Iso2022JpDecoderState::Roman);
310 } else if self.lead == 0x28u8 && b == 0x49u8 {
311 state = Some(Iso2022JpDecoderState::Katakana);
312 } else if self.lead == 0x24u8 && (b == 0x40u8 || b == 0x42u8) {
313 state = Some(Iso2022JpDecoderState::LeadByte);
314 }
315 match state {
316 Some(s) => {
317 self.lead = 0x0u8;
318 self.decoder_state = s;
319 self.output_state = s;
320 let flag = self.output_flag;
321 self.output_flag = true;
322 if flag {
323 return (
329 DecoderResult::Malformed(3, 3),
330 unread_handle.consumed(),
331 destination_handle.written(),
332 );
333 }
334 continue;
335 }
336 None => {
337 self.pending_prepended = true;
341 self.output_flag = false;
342 self.decoder_state = self.output_state;
343 return (
347 DecoderResult::Malformed(1, 1),
348 unread_handle.unread(),
349 destination_handle.written(),
350 );
351 }
352 }
353 }
354 }
355 },
356 self = self,
357 src_consumed = src_consumed,
358 dest = dest,
359 source = source,
360 byte = b,
361 destination_handle = destination_handle,
362 unread_handle = unread_handle,
363 destination_check = check_space_bmp
364 );
365}
366
367#[cfg(feature = "fast-kanji-encode")]
368#[inline(always)]
369fn is_kanji_mapped(bmp: u16) -> bool {
370 jis0208_kanji_shift_jis_encode(bmp).is_some()
373}
374
375#[cfg(not(feature = "fast-kanji-encode"))]
376#[allow(clippy::redundant_pattern_matching, clippy::if_same_then_else)]
377#[inline(always)]
378fn is_kanji_mapped(bmp: u16) -> bool {
379 0x4EDD == bmp
380 || jis0208_level1_kanji_shift_jis_encode(bmp).is_some()
381 || jis0208_level2_and_additional_kanji_encode(bmp).is_some()
384 || position(&IBM_KANJI[..], bmp).is_some()
385}
386
387#[allow(clippy::redundant_pattern_matching, clippy::if_same_then_else)]
388fn is_mapped_for_two_byte_encode(bmp: u16) -> bool {
389 let bmp_minus_hiragana = bmp.wrapping_sub(0x3041);
393 if bmp_minus_hiragana < 0x53 {
394 true
395 } else if in_inclusive_range16(bmp, 0x4E00, 0x9FA0) {
396 is_kanji_mapped(bmp)
397 } else {
398 let bmp_minus_katakana = bmp.wrapping_sub(0x30A1);
399 if bmp_minus_katakana < 0x56 {
400 true
401 } else {
402 let bmp_minus_space = bmp.wrapping_sub(0x3000);
403 bmp_minus_space < 3
405 || in_inclusive_range16(bmp, 0xFF61, 0xFF9F)
406 || bmp == 0x2212
407 || jis0208_range_encode(bmp).is_some()
408 || in_inclusive_range16(bmp, 0xFA0E, 0xFA2D)
409 || bmp == 0xF929
410 || bmp == 0xF9DC
411 || ibm_symbol_encode(bmp).is_some()
412 || jis0208_symbol_encode(bmp).is_some()
413 }
414 }
415}
416
417#[cfg(feature = "fast-kanji-encode")]
418#[inline(always)]
419fn encode_kanji(bmp: u16) -> Option<(u8, u8)> {
420 jis0208_kanji_iso_2022_jp_encode(bmp)
421}
422
423#[cfg(not(feature = "fast-kanji-encode"))]
424#[inline(always)]
425fn encode_kanji(bmp: u16) -> Option<(u8, u8)> {
426 if 0x4EDD == bmp {
427 Some((0x21, 0xB8 - 0x80))
429 } else if let Some((lead, trail)) = jis0208_level1_kanji_iso_2022_jp_encode(bmp) {
430 Some((lead, trail))
431 } else if let Some(pos) = jis0208_level2_and_additional_kanji_encode(bmp) {
432 let lead = (pos / 94) + (0xD0 - 0x80);
433 let trail = (pos % 94) + 0x21;
434 Some((lead as u8, trail as u8))
435 } else if let Some(pos) = position(&IBM_KANJI[..], bmp) {
436 let lead = (pos / 94) + (0xF9 - 0x80);
437 let trail = (pos % 94) + 0x21;
438 Some((lead as u8, trail as u8))
439 } else {
440 None
441 }
442}
443
444enum Iso2022JpEncoderState {
445 Ascii,
446 Roman,
447 Jis0208,
448}
449
450pub struct Iso2022JpEncoder {
451 state: Iso2022JpEncoderState,
452}
453
454impl Iso2022JpEncoder {
455 pub fn new(encoding: &'static Encoding) -> Encoder {
456 Encoder::new(
457 encoding,
458 VariantEncoder::Iso2022Jp(Iso2022JpEncoder {
459 state: Iso2022JpEncoderState::Ascii,
460 }),
461 )
462 }
463
464 pub fn has_pending_state(&self) -> bool {
465 !matches!(self.state, Iso2022JpEncoderState::Ascii)
466 }
467
468 pub fn max_buffer_length_from_utf16_without_replacement(
469 &self,
470 u16_length: usize,
471 ) -> Option<usize> {
472 checked_add_opt(
481 checked_add(3, u16_length.checked_mul(4)),
482 checked_div(u16_length.checked_add(1), 2),
483 )
484 }
485
486 pub fn max_buffer_length_from_utf8_without_replacement(
487 &self,
488 byte_length: usize,
489 ) -> Option<usize> {
490 checked_add(3, byte_length.checked_mul(3))
499 }
500
501 encoder_functions!(
502 eof = {
503 match self.state {
504 Iso2022JpEncoderState::Ascii => {}
505 _ => match dest.check_space_three() {
506 Space::Full(dst_written) => {
507 return (EncoderResult::OutputFull, src_consumed, dst_written);
508 }
509 Space::Available(destination_handle) => {
510 self.state = Iso2022JpEncoderState::Ascii;
511 destination_handle.write_three(0x1Bu8, 0x28u8, 0x42u8);
512 }
513 },
514 }
515 },
516 body = {
517 match self.state {
518 Iso2022JpEncoderState::Ascii => {
519 if c == '\u{0E}' || c == '\u{0F}' || c == '\u{1B}' {
520 return (
521 EncoderResult::Unmappable('\u{FFFD}'),
522 unread_handle.consumed(),
523 destination_handle.written(),
524 );
525 }
526 if c <= '\u{7F}' {
527 destination_handle.write_one(c as u8);
528 continue;
529 }
530 if c == '\u{A5}' || c == '\u{203E}' {
531 self.state = Iso2022JpEncoderState::Roman;
532 destination_handle.write_three(0x1Bu8, 0x28u8, 0x4Au8);
533 unread_handle.unread();
534 continue;
535 }
536 if c > '\u{FFFF}' {
537 return (
538 EncoderResult::Unmappable(c),
539 unread_handle.consumed(),
540 destination_handle.written(),
541 );
542 }
543 if is_mapped_for_two_byte_encode(c as u16) {
547 self.state = Iso2022JpEncoderState::Jis0208;
548 destination_handle.write_three(0x1Bu8, 0x24u8, 0x42u8);
549 unread_handle.unread();
550 continue;
551 }
552 return (
553 EncoderResult::Unmappable(c),
554 unread_handle.consumed(),
555 destination_handle.written(),
556 );
557 }
558 Iso2022JpEncoderState::Roman => {
559 if c == '\u{0E}' || c == '\u{0F}' || c == '\u{1B}' {
560 return (
561 EncoderResult::Unmappable('\u{FFFD}'),
562 unread_handle.consumed(),
563 destination_handle.written(),
564 );
565 }
566 if c == '\u{5C}' || c == '\u{7E}' {
567 self.state = Iso2022JpEncoderState::Ascii;
568 destination_handle.write_three(0x1Bu8, 0x28u8, 0x42u8);
569 unread_handle.unread();
570 continue;
571 }
572 if c <= '\u{7F}' {
573 destination_handle.write_one(c as u8);
574 continue;
575 }
576 if c == '\u{A5}' {
577 destination_handle.write_one(0x5Cu8);
578 continue;
579 }
580 if c == '\u{203E}' {
581 destination_handle.write_one(0x7Eu8);
582 continue;
583 }
584 if c > '\u{FFFF}' {
585 return (
586 EncoderResult::Unmappable(c),
587 unread_handle.consumed(),
588 destination_handle.written(),
589 );
590 }
591 if is_mapped_for_two_byte_encode(c as u16) {
595 self.state = Iso2022JpEncoderState::Jis0208;
596 destination_handle.write_three(0x1Bu8, 0x24u8, 0x42u8);
597 unread_handle.unread();
598 continue;
599 }
600 return (
601 EncoderResult::Unmappable(c),
602 unread_handle.consumed(),
603 destination_handle.written(),
604 );
605 }
606 Iso2022JpEncoderState::Jis0208 => {
607 if c <= '\u{7F}' {
608 self.state = Iso2022JpEncoderState::Ascii;
609 destination_handle.write_three(0x1Bu8, 0x28u8, 0x42u8);
610 unread_handle.unread();
611 continue;
612 }
613 if c == '\u{A5}' || c == '\u{203E}' {
614 self.state = Iso2022JpEncoderState::Roman;
615 destination_handle.write_three(0x1Bu8, 0x28u8, 0x4Au8);
616 unread_handle.unread();
617 continue;
618 }
619 if c > '\u{FFFF}' {
620 self.state = Iso2022JpEncoderState::Ascii;
624 return (
625 EncoderResult::Unmappable(c),
626 unread_handle.consumed(),
627 destination_handle.write_three_return_written(0x1Bu8, 0x28u8, 0x42u8),
628 );
629 }
630 let bmp = c as u16;
631 let handle = destination_handle;
632 let bmp_minus_hiragana = bmp.wrapping_sub(0x3041);
636 if bmp_minus_hiragana < 0x53 {
637 handle.write_two(0x24, 0x21 + bmp_minus_hiragana as u8);
638 continue;
639 } else if in_inclusive_range16(bmp, 0x4E00, 0x9FA0) {
640 if let Some((lead, trail)) = encode_kanji(bmp) {
641 handle.write_two(lead, trail);
642 continue;
643 } else {
644 self.state = Iso2022JpEncoderState::Ascii;
645 return (
646 EncoderResult::Unmappable(c),
647 unread_handle.consumed(),
648 handle.write_three_return_written(0x1Bu8, 0x28u8, 0x42u8),
649 );
650 }
651 } else {
652 let bmp_minus_katakana = bmp.wrapping_sub(0x30A1);
653 if bmp_minus_katakana < 0x56 {
654 handle.write_two(0x25, 0x21 + bmp_minus_katakana as u8);
655 continue;
656 } else {
657 let bmp_minus_space = bmp.wrapping_sub(0x3000);
658 if bmp_minus_space < 3 {
659 handle.write_two(0x21, 0x21 + bmp_minus_space as u8);
661 continue;
662 }
663 let bmp_minus_half_width = bmp.wrapping_sub(0xFF61);
664 if bmp_minus_half_width <= (0xFF9F - 0xFF61) {
665 let lead =
669 if bmp != 0xFF70 && in_inclusive_range16(bmp, 0xFF66, 0xFF9D) {
670 0x25u8
671 } else {
672 0x21u8
673 };
674 let trail =
675 ISO_2022_JP_HALF_WIDTH_TRAIL[bmp_minus_half_width as usize];
676 handle.write_two(lead, trail);
677 continue;
678 } else if bmp == 0x2212 {
679 handle.write_two(0x21, 0x5D);
680 continue;
681 } else if let Some(pointer) = jis0208_range_encode(bmp) {
682 let lead = (pointer / 94) + 0x21;
683 let trail = (pointer % 94) + 0x21;
684 handle.write_two(lead as u8, trail as u8);
685 continue;
686 } else if in_inclusive_range16(bmp, 0xFA0E, 0xFA2D)
687 || bmp == 0xF929
688 || bmp == 0xF9DC
689 {
690 let pos = position(&IBM_KANJI[..], bmp).unwrap();
692 let lead = (pos / 94) + (0xF9 - 0x80);
693 let trail = (pos % 94) + 0x21;
694 handle.write_two(lead as u8, trail as u8);
695 continue;
696 } else if let Some(pointer) = ibm_symbol_encode(bmp) {
697 let lead = (pointer / 94) + 0x21;
698 let trail = (pointer % 94) + 0x21;
699 handle.write_two(lead as u8, trail as u8);
700 continue;
701 } else if let Some(pointer) = jis0208_symbol_encode(bmp) {
702 let lead = (pointer / 94) + 0x21;
703 let trail = (pointer % 94) + 0x21;
704 handle.write_two(lead as u8, trail as u8);
705 continue;
706 } else {
707 self.state = Iso2022JpEncoderState::Ascii;
708 return (
709 EncoderResult::Unmappable(c),
710 unread_handle.consumed(),
711 handle.write_three_return_written(0x1Bu8, 0x28u8, 0x42u8),
712 );
713 }
714 }
715 }
716 }
717 }
718 },
719 self = self,
720 src_consumed = src_consumed,
721 source = source,
722 dest = dest,
723 c = c,
724 destination_handle = destination_handle,
725 unread_handle = unread_handle,
726 destination_check = check_space_three
727 );
728}
729
730#[cfg(all(test, feature = "alloc"))]
734mod tests {
735 use super::super::testing::*;
736 use super::super::*;
737
738 fn decode_iso_2022_jp(bytes: &[u8], expect: &str) {
739 decode(ISO_2022_JP, bytes, expect);
740 }
741
742 fn encode_iso_2022_jp(string: &str, expect: &[u8]) {
743 encode(ISO_2022_JP, string, expect);
744 }
745
746 #[test]
747 fn test_iso_2022_jp_decode() {
748 decode_iso_2022_jp(b"", &"");
750
751 decode_iso_2022_jp(b"\x61\x62", "\u{0061}\u{0062}");
753 decode_iso_2022_jp(b"\x7F\x0E\x0F", "\u{007F}\u{FFFD}\u{FFFD}");
754
755 decode_iso_2022_jp(b"\x1B", "\u{FFFD}");
757 decode_iso_2022_jp(b"\x1B$", "\u{FFFD}$");
758 decode_iso_2022_jp(b"\x1B(", "\u{FFFD}(");
759 decode_iso_2022_jp(b"\x1B.", "\u{FFFD}.");
760
761 decode_iso_2022_jp(b"\x1B(B", ""); decode_iso_2022_jp(b"\x1B(J", ""); decode_iso_2022_jp(b"\x1B$@", ""); decode_iso_2022_jp(b"\x1B$B", ""); decode_iso_2022_jp(b"\x1B$(D", "\u{FFFD}$(D"); decode_iso_2022_jp(b"\x1B$A", "\u{FFFD}$A"); decode_iso_2022_jp(b"\x1B$(C", "\u{FFFD}$(C"); decode_iso_2022_jp(b"\x1B.A", "\u{FFFD}.A"); decode_iso_2022_jp(b"\x1B.F", "\u{FFFD}.F"); decode_iso_2022_jp(b"\x1B(I", ""); decode_iso_2022_jp(b"\x1B$(O", "\u{FFFD}$(O"); decode_iso_2022_jp(b"\x1B$(P", "\u{FFFD}$(P"); decode_iso_2022_jp(b"\x1B$(Q", "\u{FFFD}$(Q"); decode_iso_2022_jp(b"\x1B$)C", "\u{FFFD}$)C"); decode_iso_2022_jp(b"\x1B$)A", "\u{FFFD}$)A"); decode_iso_2022_jp(b"\x1B$)G", "\u{FFFD}$)G"); decode_iso_2022_jp(b"\x1B$*H", "\u{FFFD}$*H"); decode_iso_2022_jp(b"\x1B$)E", "\u{FFFD}$)E"); decode_iso_2022_jp(b"\x1B$+I", "\u{FFFD}$+I"); decode_iso_2022_jp(b"\x1B$+J", "\u{FFFD}$+J"); decode_iso_2022_jp(b"\x1B$+K", "\u{FFFD}$+K"); decode_iso_2022_jp(b"\x1B$+L", "\u{FFFD}$+L"); decode_iso_2022_jp(b"\x1B$+M", "\u{FFFD}$+M"); decode_iso_2022_jp(b"\x1B$(@", "\u{FFFD}$(@"); decode_iso_2022_jp(b"\x1B$(A", "\u{FFFD}$(A"); decode_iso_2022_jp(b"\x1B$(B", "\u{FFFD}$(B"); decode_iso_2022_jp(b"\x1B%G", "\u{FFFD}%G"); decode_iso_2022_jp(b"\x5B", "\u{005B}");
792 decode_iso_2022_jp(b"\x5C", "\u{005C}");
793 decode_iso_2022_jp(b"\x7E", "\u{007E}");
794 decode_iso_2022_jp(b"\x0E", "\u{FFFD}");
795 decode_iso_2022_jp(b"\x0F", "\u{FFFD}");
796 decode_iso_2022_jp(b"\x80", "\u{FFFD}");
797 decode_iso_2022_jp(b"\xFF", "\u{FFFD}");
798 decode_iso_2022_jp(b"\x1B(B\x5B", "\u{005B}");
799 decode_iso_2022_jp(b"\x1B(B\x5C", "\u{005C}");
800 decode_iso_2022_jp(b"\x1B(B\x7E", "\u{007E}");
801 decode_iso_2022_jp(b"\x1B(B\x0E", "\u{FFFD}");
802 decode_iso_2022_jp(b"\x1B(B\x0F", "\u{FFFD}");
803 decode_iso_2022_jp(b"\x1B(B\x80", "\u{FFFD}");
804 decode_iso_2022_jp(b"\x1B(B\xFF", "\u{FFFD}");
805
806 decode_iso_2022_jp(b"\x1B(J\x5B", "\u{005B}");
808 decode_iso_2022_jp(b"\x1B(J\x5C", "\u{00A5}");
809 decode_iso_2022_jp(b"\x1B(J\x7E", "\u{203E}");
810 decode_iso_2022_jp(b"\x1B(J\x0E", "\u{FFFD}");
811 decode_iso_2022_jp(b"\x1B(J\x0F", "\u{FFFD}");
812 decode_iso_2022_jp(b"\x1B(J\x80", "\u{FFFD}");
813 decode_iso_2022_jp(b"\x1B(J\xFF", "\u{FFFD}");
814
815 decode_iso_2022_jp(b"\x1B(I\x20", "\u{FFFD}");
817 decode_iso_2022_jp(b"\x1B(I\x21", "\u{FF61}");
818 decode_iso_2022_jp(b"\x1B(I\x5F", "\u{FF9F}");
819 decode_iso_2022_jp(b"\x1B(I\x60", "\u{FFFD}");
820 decode_iso_2022_jp(b"\x1B(I\x0E", "\u{FFFD}");
821 decode_iso_2022_jp(b"\x1B(I\x0F", "\u{FFFD}");
822 decode_iso_2022_jp(b"\x1B(I\x80", "\u{FFFD}");
823 decode_iso_2022_jp(b"\x1B(I\xFF", "\u{FFFD}");
824
825 decode_iso_2022_jp(b"\x1B$@\x54\x64", "\u{58FA}");
827 decode_iso_2022_jp(b"\x1B$@\x44\x5B", "\u{58F7}");
828 decode_iso_2022_jp(b"\x1B$@\x74\x21", "\u{582F}");
829 decode_iso_2022_jp(b"\x1B$@\x36\x46", "\u{5C2D}");
830 decode_iso_2022_jp(b"\x1B$@\x28\x2E", "\u{250F}");
831 decode_iso_2022_jp(b"\x1B$B\x54\x64", "\u{58FA}");
832 decode_iso_2022_jp(b"\x1B$B\x44\x5B", "\u{58F7}");
833 decode_iso_2022_jp(b"\x1B$B\x74\x21", "\u{582F}");
834 decode_iso_2022_jp(b"\x1B$B\x36\x46", "\u{5C2D}");
835 decode_iso_2022_jp(b"\x1B$B\x28\x2E", "\u{250F}");
836
837 decode_iso_2022_jp(b"\x1B$B\x28\x41", "\u{FFFD}");
839 decode_iso_2022_jp(b"\x1B$@\x80\x54\x64", "\u{FFFD}\u{58FA}");
840 decode_iso_2022_jp(b"\x1B$B\x28\x80", "\u{FFFD}");
841
842 if cfg!(miri) {
843 return;
845 }
846
847 decode_iso_2022_jp(b"\x1B(B\x5C\x1B(J\x5C", "\u{005C}\u{00A5}");
849 decode_iso_2022_jp(b"\x1B(B\x5C\x1B(I\x21", "\u{005C}\u{FF61}");
850 decode_iso_2022_jp(b"\x1B(B\x5C\x1B$@\x54\x64", "\u{005C}\u{58FA}");
851 decode_iso_2022_jp(b"\x1B(B\x5C\x1B$B\x54\x64", "\u{005C}\u{58FA}");
852
853 decode_iso_2022_jp(b"\x1B(J\x5C\x1B(B\x5C", "\u{00A5}\u{005C}");
854 decode_iso_2022_jp(b"\x1B(J\x5C\x1B(I\x21", "\u{00A5}\u{FF61}");
855 decode_iso_2022_jp(b"\x1B(J\x5C\x1B$@\x54\x64", "\u{00A5}\u{58FA}");
856 decode_iso_2022_jp(b"\x1B(J\x5C\x1B$B\x54\x64", "\u{00A5}\u{58FA}");
857
858 decode_iso_2022_jp(b"\x1B(I\x21\x1B(J\x5C", "\u{FF61}\u{00A5}");
859 decode_iso_2022_jp(b"\x1B(I\x21\x1B(B\x5C", "\u{FF61}\u{005C}");
860 decode_iso_2022_jp(b"\x1B(I\x21\x1B$@\x54\x64", "\u{FF61}\u{58FA}");
861 decode_iso_2022_jp(b"\x1B(I\x21\x1B$B\x54\x64", "\u{FF61}\u{58FA}");
862
863 decode_iso_2022_jp(b"\x1B$@\x54\x64\x1B(J\x5C", "\u{58FA}\u{00A5}");
864 decode_iso_2022_jp(b"\x1B$@\x54\x64\x1B(I\x21", "\u{58FA}\u{FF61}");
865 decode_iso_2022_jp(b"\x1B$@\x54\x64\x1B(B\x5C", "\u{58FA}\u{005C}");
866 decode_iso_2022_jp(b"\x1B$@\x54\x64\x1B$B\x54\x64", "\u{58FA}\u{58FA}");
867
868 decode_iso_2022_jp(b"\x1B$B\x54\x64\x1B(J\x5C", "\u{58FA}\u{00A5}");
869 decode_iso_2022_jp(b"\x1B$B\x54\x64\x1B(I\x21", "\u{58FA}\u{FF61}");
870 decode_iso_2022_jp(b"\x1B$B\x54\x64\x1B$@\x54\x64", "\u{58FA}\u{58FA}");
871 decode_iso_2022_jp(b"\x1B$B\x54\x64\x1B(B\x5C", "\u{58FA}\u{005C}");
872
873 decode_iso_2022_jp(b"\x1B(B\x1B(J", "\u{FFFD}");
875 decode_iso_2022_jp(b"\x1B(B\x1B(I", "\u{FFFD}");
876 decode_iso_2022_jp(b"\x1B(B\x1B$@", "\u{FFFD}");
877 decode_iso_2022_jp(b"\x1B(B\x1B$B", "\u{FFFD}");
878
879 decode_iso_2022_jp(b"\x1B(J\x1B(B", "\u{FFFD}");
880 decode_iso_2022_jp(b"\x1B(J\x1B(I", "\u{FFFD}");
881 decode_iso_2022_jp(b"\x1B(J\x1B$@", "\u{FFFD}");
882 decode_iso_2022_jp(b"\x1B(J\x1B$B", "\u{FFFD}");
883
884 decode_iso_2022_jp(b"\x1B(I\x1B(J", "\u{FFFD}");
885 decode_iso_2022_jp(b"\x1B(I\x1B(B", "\u{FFFD}");
886 decode_iso_2022_jp(b"\x1B(I\x1B$@", "\u{FFFD}");
887 decode_iso_2022_jp(b"\x1B(I\x1B$B", "\u{FFFD}");
888
889 decode_iso_2022_jp(b"\x1B$@\x1B(J", "\u{FFFD}");
890 decode_iso_2022_jp(b"\x1B$@\x1B(I", "\u{FFFD}");
891 decode_iso_2022_jp(b"\x1B$@\x1B(B", "\u{FFFD}");
892 decode_iso_2022_jp(b"\x1B$@\x1B$B", "\u{FFFD}");
893
894 decode_iso_2022_jp(b"\x1B$B\x1B(J", "\u{FFFD}");
895 decode_iso_2022_jp(b"\x1B$B\x1B(I", "\u{FFFD}");
896 decode_iso_2022_jp(b"\x1B$B\x1B$@", "\u{FFFD}");
897 decode_iso_2022_jp(b"\x1B$B\x1B(B", "\u{FFFD}");
898
899 decode_iso_2022_jp(b"\x1B(B\x5C\x1B(B\x5C", "\u{005C}\u{005C}");
901 decode_iso_2022_jp(b"\x1B(J\x5C\x1B(J\x5C", "\u{00A5}\u{00A5}");
902 decode_iso_2022_jp(b"\x1B(I\x21\x1B(I\x21", "\u{FF61}\u{FF61}");
903 decode_iso_2022_jp(b"\x1B$@\x54\x64\x1B$@\x54\x64", "\u{58FA}\u{58FA}");
904 decode_iso_2022_jp(b"\x1B$B\x54\x64\x1B$B\x54\x64", "\u{58FA}\u{58FA}");
905 }
906
907 #[test]
908 fn test_iso_2022_jp_encode() {
909 encode_iso_2022_jp("", b"");
911
912 encode_iso_2022_jp("ab", b"ab");
914 encode_iso_2022_jp("\u{1F4A9}", b"💩");
915 encode_iso_2022_jp("\x1B", b"�");
916 encode_iso_2022_jp("\x0E", b"�");
917 encode_iso_2022_jp("\x0F", b"�");
918
919 encode_iso_2022_jp("a\u{00A5}b", b"a\x1B(J\x5Cb\x1B(B");
921 encode_iso_2022_jp("a\u{203E}b", b"a\x1B(J\x7Eb\x1B(B");
922 if !cfg!(miri) {
923 encode_iso_2022_jp("a\u{00A5}b\x5C", b"a\x1B(J\x5Cb\x1B(B\x5C");
925 encode_iso_2022_jp("a\u{203E}b\x7E", b"a\x1B(J\x7Eb\x1B(B\x7E");
926 encode_iso_2022_jp("\u{00A5}\u{1F4A9}", b"\x1B(J\x5C💩\x1B(B");
927 encode_iso_2022_jp("\u{00A5}\x1B", b"\x1B(J\x5C�\x1B(B");
928 encode_iso_2022_jp("\u{00A5}\x0E", b"\x1B(J\x5C�\x1B(B");
929 encode_iso_2022_jp("\u{00A5}\x0F", b"\x1B(J\x5C�\x1B(B");
930 encode_iso_2022_jp("\u{00A5}\u{58FA}", b"\x1B(J\x5C\x1B$B\x54\x64\x1B(B");
931 }
932
933 encode_iso_2022_jp("\u{FF61}", b"\x1B$B\x21\x23\x1B(B");
935 encode_iso_2022_jp("\u{FF65}", b"\x1B$B\x21\x26\x1B(B");
936 if !cfg!(miri) {
937 encode_iso_2022_jp("\u{FF66}", b"\x1B$B\x25\x72\x1B(B");
939 encode_iso_2022_jp("\u{FF70}", b"\x1B$B\x21\x3C\x1B(B");
940 encode_iso_2022_jp("\u{FF9D}", b"\x1B$B\x25\x73\x1B(B");
941 encode_iso_2022_jp("\u{FF9E}", b"\x1B$B\x21\x2B\x1B(B");
942 encode_iso_2022_jp("\u{FF9F}", b"\x1B$B\x21\x2C\x1B(B");
943 }
944
945 encode_iso_2022_jp("\u{58FA}", b"\x1B$B\x54\x64\x1B(B");
947 encode_iso_2022_jp("\u{58FA}\u{250F}", b"\x1B$B\x54\x64\x28\x2E\x1B(B");
948 if !cfg!(miri) {
949 encode_iso_2022_jp("\u{58FA}\u{1F4A9}", b"\x1B$B\x54\x64\x1B(B💩");
951 encode_iso_2022_jp("\u{58FA}\x1B", b"\x1B$B\x54\x64\x1B(B�");
952 encode_iso_2022_jp("\u{58FA}\x0E", b"\x1B$B\x54\x64\x1B(B�");
953 encode_iso_2022_jp("\u{58FA}\x0F", b"\x1B$B\x54\x64\x1B(B�");
954 encode_iso_2022_jp("\u{58FA}\u{00A5}", b"\x1B$B\x54\x64\x1B(J\x5C\x1B(B");
955 encode_iso_2022_jp("\u{58FA}a", b"\x1B$B\x54\x64\x1B(Ba");
956 }
957 }
958
959 #[test]
960 fn test_iso_2022_jp_half_width_katakana_length() {
961 let mut output = [0u8; 20];
962 let mut decoder = ISO_2022_JP.new_decoder();
963 {
964 let (result, read, written) =
965 decoder.decode_to_utf8_without_replacement(b"\x1B\x28\x49", &mut output, false);
966 assert_eq!(result, DecoderResult::InputEmpty);
967 assert_eq!(read, 3);
968 assert_eq!(written, 0);
969 }
970 {
971 let needed = decoder
972 .max_utf8_buffer_length_without_replacement(1)
973 .unwrap();
974 let (result, read, written) =
975 decoder.decode_to_utf8_without_replacement(b"\x21", &mut output[..needed], true);
976 assert_eq!(result, DecoderResult::InputEmpty);
977 assert_eq!(read, 1);
978 assert_eq!(written, 3);
979 assert_eq!(output[0], 0xEF);
980 assert_eq!(output[1], 0xBD);
981 assert_eq!(output[2], 0xA1);
982 }
983 }
984
985 #[test]
986 fn test_iso_2022_jp_length_after_escape() {
987 let mut output = [0u16; 20];
988 let mut decoder = ISO_2022_JP.new_decoder();
989 {
990 let (result, read, written, had_errors) =
991 decoder.decode_to_utf16(b"\x1B", &mut output, false);
992 assert_eq!(result, CoderResult::InputEmpty);
993 assert_eq!(read, 1);
994 assert_eq!(written, 0);
995 assert!(!had_errors);
996 }
997 {
998 let needed = decoder.max_utf16_buffer_length(1).unwrap();
999 let (result, read, written, had_errors) =
1000 decoder.decode_to_utf16(b"A", &mut output[..needed], true);
1001 assert_eq!(result, CoderResult::InputEmpty);
1002 assert_eq!(read, 1);
1003 assert_eq!(written, 2);
1004 assert!(had_errors);
1005 assert_eq!(output[0], 0xFFFD);
1006 assert_eq!(output[1], 0x0041);
1007 }
1008 }
1009
1010 #[test]
1011 fn test_iso_2022_jp_encode_from_two_low_surrogates() {
1012 let expectation = b"��";
1013 let mut output = [0u8; 40];
1014 let mut encoder = ISO_2022_JP.new_encoder();
1015 let (result, read, written, had_errors) =
1016 encoder.encode_from_utf16(&[0xDC00u16, 0xDEDEu16], &mut output[..], true);
1017 assert_eq!(result, CoderResult::InputEmpty);
1018 assert_eq!(read, 2);
1019 assert_eq!(written, expectation.len());
1020 assert!(had_errors);
1021 assert_eq!(&output[..written], expectation);
1022 }
1023}