use std::convert::Into;
use std::default::Default;
use util::StrCharIndex;
use index_japanese as index;
use types::*;
use self::ISO2022JPState::{ASCII,Katakana,Lead};
#[derive(Clone, Copy)]
pub struct EUCJPEncoding;
impl Encoding for EUCJPEncoding {
fn name(&self) -> &'static str { "euc-jp" }
fn whatwg_name(&self) -> Option<&'static str> { Some("euc-jp") }
fn raw_encoder(&self) -> Box<RawEncoder> { EUCJPEncoder::new() }
fn raw_decoder(&self) -> Box<RawDecoder> { EUCJP0212Decoder::new() }
}
#[derive(Clone, Copy)]
pub struct EUCJPEncoder;
impl EUCJPEncoder {
pub fn new() -> Box<RawEncoder> { Box::new(EUCJPEncoder) }
}
impl RawEncoder for EUCJPEncoder {
fn from_self(&self) -> Box<RawEncoder> { EUCJPEncoder::new() }
fn is_ascii_compatible(&self) -> bool { true }
fn raw_feed(&mut self, input: &str, output: &mut ByteWriter) -> (usize, Option<CodecError>) {
output.writer_hint(input.len());
for ((i,j), ch) in input.index_iter() {
match ch {
'\u{0}'...'\u{7f}' => { output.write_byte(ch as u8); }
'\u{a5}' => { output.write_byte(0x5c); }
'\u{203e}' => { output.write_byte(0x7e); }
'\u{ff61}'...'\u{ff9f}' => {
output.write_byte(0x8e);
output.write_byte((ch as usize - 0xff61 + 0xa1) as u8);
}
_ => {
let ptr = index::jis0208::backward(ch as u32);
if ptr == 0xffff {
return (i, Some(CodecError {
upto: j as isize, cause: "unrepresentable character".into()
}));
} else {
let lead = ptr / 94 + 0xa1;
let trail = ptr % 94 + 0xa1;
output.write_byte(lead as u8);
output.write_byte(trail as u8);
}
}
}
}
(input.len(), None)
}
fn raw_finish(&mut self, _output: &mut ByteWriter) -> Option<CodecError> {
None
}
}
#[derive(Clone, Copy)]
struct EUCJP0212Decoder {
st: eucjp::State,
}
impl EUCJP0212Decoder {
pub fn new() -> Box<RawDecoder> {
Box::new(EUCJP0212Decoder { st: Default::default() })
}
}
impl RawDecoder for EUCJP0212Decoder {
fn from_self(&self) -> Box<RawDecoder> { EUCJP0212Decoder::new() }
fn is_ascii_compatible(&self) -> bool { true }
fn raw_feed(&mut self, input: &[u8], output: &mut StringWriter) -> (usize, Option<CodecError>) {
let (st, processed, err) = eucjp::raw_feed(self.st, input, output, &());
self.st = st;
(processed, err)
}
fn raw_finish(&mut self, output: &mut StringWriter) -> Option<CodecError> {
let (st, err) = eucjp::raw_finish(self.st, output, &());
self.st = st;
err
}
}
stateful_decoder! {
module eucjp;
internal pub fn map_two_0208_bytes(lead: u8, trail: u8) -> u32 {
use index_japanese as index;
let lead = lead as u16;
let trail = trail as u16;
let index = match (lead, trail) {
(0xa1...0xfe, 0xa1...0xfe) => (lead - 0xa1) * 94 + trail - 0xa1,
_ => 0xffff,
};
index::jis0208::forward(index)
}
internal pub fn map_two_0212_bytes(lead: u8, trail: u8) -> u32 {
use index_japanese as index;
let lead = lead as u16;
let trail = trail as u16;
let index = match (lead, trail) {
(0xa1...0xfe, 0xa1...0xfe) => (lead - 0xa1) * 94 + trail - 0xa1,
_ => 0xffff,
};
index::jis0212::forward(index)
}
initial:
state S0(ctx: Context) {
case b @ 0x00...0x7f => ctx.emit(b as u32);
case 0x8e => S1(ctx);
case 0x8f => S2(ctx);
case b @ 0xa1...0xfe => S3(ctx, b);
case _ => ctx.err("invalid sequence");
}
transient:
state S1(ctx: Context) {
case b @ 0xa1...0xdf => ctx.emit(0xff61 + b as u32 - 0xa1);
case 0xa1...0xfe => ctx.err("invalid sequence");
case _ => ctx.backup_and_err(1, "invalid sequence");
}
state S2(ctx: Context) {
case b @ 0xa1...0xfe => S4(ctx, b);
case _ => ctx.backup_and_err(1, "invalid sequence");
}
state S3(ctx: Context, lead: u8) {
case b @ 0xa1...0xfe => match map_two_0208_bytes(lead, b) {
0xffff => ctx.err("invalid sequence"),
ch => ctx.emit(ch as u32)
};
case _ => ctx.backup_and_err(1, "invalid sequence");
}
state S4(ctx: Context, lead: u8) {
case b @ 0xa1...0xfe => match map_two_0212_bytes(lead, b) {
0xffff => ctx.err("invalid sequence"),
ch => ctx.emit(ch as u32)
};
case _ => ctx.backup_and_err(1, "invalid sequence");
}
}
#[cfg(test)]
mod eucjp_tests {
extern crate test;
use super::EUCJPEncoding;
use testutils;
use types::*;
#[test]
fn test_encoder_valid() {
let mut e = EUCJPEncoding.raw_encoder();
assert_feed_ok!(e, "A", "", [0x41]);
assert_feed_ok!(e, "BC", "", [0x42, 0x43]);
assert_feed_ok!(e, "", "", []);
assert_feed_ok!(e, "\u{a5}", "", [0x5c]);
assert_feed_ok!(e, "\u{203e}", "", [0x7e]);
assert_feed_ok!(e, "\u{306b}\u{307b}\u{3093}", "", [0xa4, 0xcb, 0xa4, 0xdb, 0xa4, 0xf3]);
assert_feed_ok!(e, "\u{ff86}\u{ff8e}\u{ff9d}", "", [0x8e, 0xc6, 0x8e, 0xce, 0x8e, 0xdd]);
assert_feed_ok!(e, "\u{65e5}\u{672c}", "", [0xc6, 0xfc, 0xcb, 0xdc]);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_double_mapped() {
let mut e = EUCJPEncoding.raw_encoder();
assert_feed_ok!(e, "\u{9ed1}\u{2170}\u{ffe2}", "", [0xfc, 0xee, 0xfc, 0xf1, 0xa2, 0xcc]);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_invalid() {
let mut e = EUCJPEncoding.raw_encoder();
assert_feed_err!(e, "", "\u{ffff}", "", []);
assert_feed_err!(e, "?", "\u{ffff}", "!", [0x3f]);
assert_feed_err!(e, "", "\u{736c}", "\u{8c78}", []);
assert_finish_ok!(e, []);
}
#[test]
fn test_decoder_valid() {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [0x41], [], "A");
assert_feed_ok!(d, [0x42, 0x43], [], "BC");
assert_feed_ok!(d, [], [], "");
assert_feed_ok!(d, [0x5c], [], "\\");
assert_feed_ok!(d, [0x7e], [], "~");
assert_feed_ok!(d, [0xa4, 0xcb, 0xa4, 0xdb, 0xa4, 0xf3], [], "\u{306b}\u{307b}\u{3093}");
assert_feed_ok!(d, [0x8e, 0xc6, 0x8e, 0xce, 0x8e, 0xdd], [], "\u{ff86}\u{ff8e}\u{ff9d}");
assert_feed_ok!(d, [0xc6, 0xfc, 0xcb, 0xdc], [], "\u{65e5}\u{672c}");
assert_feed_ok!(d, [0x8f, 0xcb, 0xc6, 0xec, 0xb8], [], "\u{736c}\u{8c78}");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_valid_partial() {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0xa4], "");
assert_feed_ok!(d, [0xcb], [0xa4], "\u{306b}");
assert_feed_ok!(d, [0xdb], [0xa4], "\u{307b}");
assert_feed_ok!(d, [0xf3], [], "\u{3093}");
assert_feed_ok!(d, [], [0x8e], "");
assert_feed_ok!(d, [0xc6], [0x8e], "\u{ff86}");
assert_feed_ok!(d, [0xce], [0x8e], "\u{ff8e}");
assert_feed_ok!(d, [0xdd], [], "\u{ff9d}");
assert_feed_ok!(d, [], [0xc6], "");
assert_feed_ok!(d, [0xfc], [0xcb], "\u{65e5}");
assert_feed_ok!(d, [0xdc], [], "\u{672c}");
assert_feed_ok!(d, [], [0x8f], "");
assert_feed_ok!(d, [], [0xcb], "");
assert_feed_ok!(d, [0xc6], [0xec], "\u{736c}");
assert_feed_ok!(d, [0xb8], [], "\u{8c78}");
assert_feed_ok!(d, [], [0x8f, 0xcb], "");
assert_feed_ok!(d, [0xc6, 0xec, 0xb8], [], "\u{736c}\u{8c78}");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_lone_lead_immediate_test_finish() {
for i in 0x8e..0x90 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], ""); assert_finish_err!(d, "");
}
for i in 0xa1..0xff {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], ""); assert_finish_err!(d, "");
}
let mut d = EUCJPEncoding.raw_decoder();
for i in 0x80..0x8e {
assert_feed_err!(d, [], [i], [], "");
}
for i in 0x90..0xa1 {
assert_feed_err!(d, [], [i], [], "");
}
assert_feed_err!(d, [], [0xff], [], "");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_lone_lead_followed_by_space() {
for i in 0x80..0x100 {
let i = i as u8;
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x20], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_lead_followed_by_invalid_trail() {
for i in 0x80..0x100 {
let i = i as u8;
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x80], "");
assert_feed_err!(d, [], [i], [0xff], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_lone_lead_for_0212_immediate_test_finish() {
for i in 0xa1..0xff {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8f, i], ""); assert_finish_err!(d, "");
}
}
#[test]
fn test_decoder_invalid_lone_lead_for_0212_immediate_test_finish_partial() {
for i in 0xa1..0xff {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8f], "");
assert_feed_ok!(d, [], [i], ""); assert_finish_err!(d, "");
}
}
#[test]
fn test_decoder_invalid_trail_for_0201() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [0x8e], [i], "");
assert_finish_ok!(d, "");
}
for i in 0xe0..0xff {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [0x8e, i], [], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_trail_for_0201_partial() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8e], "");
assert_feed_err!(d, [], [], [i], "");
assert_finish_ok!(d, "");
}
for i in 0xe0..0xff {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8e], "");
assert_feed_err!(d, [], [i], [], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_middle_for_0212() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [0x8f], [i], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_middle_for_0212_partial() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8f], "");
assert_feed_err!(d, [], [], [i], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_trail_for_0212() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_err!(d, [], [0x8f, 0xa1], [i], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_trail_for_0212_partial() {
for i in 0..0xa1 {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x8f], "");
assert_feed_ok!(d, [], [0xa1], "");
assert_feed_err!(d, [], [], [i], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_feed_after_finish() {
let mut d = EUCJPEncoding.raw_decoder();
assert_feed_ok!(d, [0xa4, 0xa2], [0xa4], "\u{3042}");
assert_finish_err!(d, "");
assert_feed_ok!(d, [0xa4, 0xa2], [], "\u{3042}");
assert_finish_ok!(d, "");
}
#[bench]
fn bench_encode_short_text(bencher: &mut test::Bencher) {
let s = testutils::JAPANESE_TEXT;
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
EUCJPEncoding.encode(&s, EncoderTrap::Strict)
}))
}
#[bench]
fn bench_decode_short_text(bencher: &mut test::Bencher) {
let s = EUCJPEncoding.encode(testutils::JAPANESE_TEXT,
EncoderTrap::Strict).ok().unwrap();
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
EUCJPEncoding.decode(&s, DecoderTrap::Strict)
}))
}
}
#[derive(Clone, Copy)]
pub struct Windows31JEncoding;
impl Encoding for Windows31JEncoding {
fn name(&self) -> &'static str { "windows-31j" }
fn whatwg_name(&self) -> Option<&'static str> { Some("shift_jis") } fn raw_encoder(&self) -> Box<RawEncoder> { Windows31JEncoder::new() }
fn raw_decoder(&self) -> Box<RawDecoder> { Windows31JDecoder::new() }
}
#[derive(Clone, Copy)]
pub struct Windows31JEncoder;
impl Windows31JEncoder {
pub fn new() -> Box<RawEncoder> { Box::new(Windows31JEncoder) }
}
impl RawEncoder for Windows31JEncoder {
fn from_self(&self) -> Box<RawEncoder> { Windows31JEncoder::new() }
fn is_ascii_compatible(&self) -> bool { true }
fn raw_feed(&mut self, input: &str, output: &mut ByteWriter) -> (usize, Option<CodecError>) {
output.writer_hint(input.len());
for ((i,j), ch) in input.index_iter() {
match ch {
'\u{0}'...'\u{80}' => { output.write_byte(ch as u8); }
'\u{a5}' => { output.write_byte(0x5c); }
'\u{203e}' => { output.write_byte(0x7e); }
'\u{ff61}'...'\u{ff9f}' => {
output.write_byte((ch as usize - 0xff61 + 0xa1) as u8);
}
_ => {
let ptr = index::jis0208::backward_remapped(ch as u32);
if ptr == 0xffff {
return (i, Some(CodecError {
upto: j as isize, cause: "unrepresentable character".into(),
}));
} else {
let lead = ptr / 188;
let leadoffset = if lead < 0x1f {0x81} else {0xc1};
let trail = ptr % 188;
let trailoffset = if trail < 0x3f {0x40} else {0x41};
output.write_byte((lead + leadoffset) as u8);
output.write_byte((trail + trailoffset) as u8);
}
}
}
}
(input.len(), None)
}
fn raw_finish(&mut self, _output: &mut ByteWriter) -> Option<CodecError> {
None
}
}
#[derive(Clone, Copy)]
struct Windows31JDecoder {
st: windows31j::State,
}
impl Windows31JDecoder {
pub fn new() -> Box<RawDecoder> {
Box::new(Windows31JDecoder { st: Default::default() })
}
}
impl RawDecoder for Windows31JDecoder {
fn from_self(&self) -> Box<RawDecoder> { Windows31JDecoder::new() }
fn is_ascii_compatible(&self) -> bool { true }
fn raw_feed(&mut self, input: &[u8], output: &mut StringWriter) -> (usize, Option<CodecError>) {
let (st, processed, err) = windows31j::raw_feed(self.st, input, output, &());
self.st = st;
(processed, err)
}
fn raw_finish(&mut self, output: &mut StringWriter) -> Option<CodecError> {
let (st, err) = windows31j::raw_finish(self.st, output, &());
self.st = st;
err
}
}
stateful_decoder! {
module windows31j;
internal pub fn map_two_0208_bytes(lead: u8, trail: u8) -> u32 {
use index_japanese as index;
let lead = lead as u16;
let trail = trail as u16;
let leadoffset = if lead < 0xa0 {0x81} else {0xc1};
let trailoffset = if trail < 0x7f {0x40} else {0x41};
let index = match (lead, trail) {
(0xf0...0xf9, 0x40...0x7e) | (0xf0...0xf9, 0x80...0xfc) =>
return (0xe000 + (lead - 0xf0) * 188 + trail - trailoffset) as u32,
(0x81...0x9f, 0x40...0x7e) | (0x81...0x9f, 0x80...0xfc) |
(0xe0...0xfc, 0x40...0x7e) | (0xe0...0xfc, 0x80...0xfc) =>
(lead - leadoffset) * 188 + trail - trailoffset,
_ => 0xffff,
};
index::jis0208::forward(index)
}
initial:
state S0(ctx: Context) {
case b @ 0x00...0x80 => ctx.emit(b as u32);
case b @ 0xa1...0xdf => ctx.emit(0xff61 + b as u32 - 0xa1);
case b @ 0x81...0x9f, b @ 0xe0...0xfc => S1(ctx, b);
case _ => ctx.err("invalid sequence");
}
transient:
state S1(ctx: Context, lead: u8) {
case b => match map_two_0208_bytes(lead, b) {
0xffff => ctx.backup_and_err(1, "invalid sequence"), ch => ctx.emit(ch)
};
}
}
#[cfg(test)]
mod windows31j_tests {
extern crate test;
use super::Windows31JEncoding;
use testutils;
use types::*;
#[test]
fn test_encoder_valid() {
let mut e = Windows31JEncoding.raw_encoder();
assert_feed_ok!(e, "A", "", [0x41]);
assert_feed_ok!(e, "BC", "", [0x42, 0x43]);
assert_feed_ok!(e, "", "", []);
assert_feed_ok!(e, "\u{a5}", "", [0x5c]);
assert_feed_ok!(e, "\u{203e}", "", [0x7e]);
assert_feed_ok!(e, "\u{306b}\u{307b}\u{3093}", "", [0x82, 0xc9, 0x82, 0xd9, 0x82, 0xf1]);
assert_feed_ok!(e, "\u{ff86}\u{ff8e}\u{ff9d}", "", [0xc6, 0xce, 0xdd]);
assert_feed_ok!(e, "\u{65e5}\u{672c}", "", [0x93, 0xfa, 0x96, 0x7b]);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_no_eudc() {
let mut e = Windows31JEncoding.raw_encoder();
assert_feed_err!(e, "", "\u{e000}", "", []);
assert_feed_err!(e, "", "\u{e757}", "", []);
assert_feed_err!(e, "", "\u{e758}", "", []);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_double_mapped() {
let mut e = Windows31JEncoding.raw_encoder();
assert_feed_ok!(e, "\u{9ed1}\u{2170}\u{ffe2}", "", [0xfc, 0x4b, 0xfa, 0x40, 0x81, 0xca]);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_invalid() {
let mut e = Windows31JEncoding.raw_encoder();
assert_feed_err!(e, "", "\u{ffff}", "", []);
assert_feed_err!(e, "?", "\u{ffff}", "!", [0x3f]);
assert_feed_err!(e, "", "\u{736c}", "\u{8c78}", []);
assert_finish_ok!(e, []);
}
#[test]
fn test_decoder_valid() {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [0x41], [], "A");
assert_feed_ok!(d, [0x42, 0x43], [], "BC");
assert_feed_ok!(d, [], [], "");
assert_feed_ok!(d, [0x5c], [], "\\");
assert_feed_ok!(d, [0x7e], [], "~");
assert_feed_ok!(d, [0x80], [], "\u{80}"); assert_feed_ok!(d, [0x82, 0xc9, 0x82, 0xd9, 0x82, 0xf1], [], "\u{306b}\u{307b}\u{3093}");
assert_feed_ok!(d, [0xc6, 0xce, 0xdd], [], "\u{ff86}\u{ff8e}\u{ff9d}");
assert_feed_ok!(d, [0x93, 0xfa, 0x96, 0x7b], [], "\u{65e5}\u{672c}");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_eudc() {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [], [0xf0], "");
assert_feed_ok!(d, [0x40], [], "\u{e000}");
assert_feed_ok!(d, [0xf9, 0xfc], [], "\u{e757}");
assert_feed_err!(d, [], [0xf0], [0x00], "");
assert_feed_err!(d, [], [0xf0], [0xff], "");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_lone_lead_immediate_test_finish() {
for i in 0x81..0xa0 {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], ""); assert_finish_err!(d, "");
}
for i in 0xe0..0xfd {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], ""); assert_finish_err!(d, "");
}
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_err!(d, [], [0xa0], [], "");
assert_feed_err!(d, [], [0xfd], [], "");
assert_feed_err!(d, [], [0xfe], [], "");
assert_feed_err!(d, [], [0xff], [], "");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_lone_lead_followed_by_space() {
for i in 0x81..0xa0 {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x20], "");
assert_finish_ok!(d, "");
}
for i in 0xe0..0xfd {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x20], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_lead_followed_by_invalid_trail() {
for i in 0x81..0xa0 {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x3f], "");
assert_feed_err!(d, [], [i], [0x7f], "");
assert_feed_err!(d, [], [i], [0xfd], "");
assert_feed_err!(d, [], [i], [0xfe], "");
assert_feed_err!(d, [], [i], [0xff], "");
assert_finish_ok!(d, "");
}
for i in 0xe0..0xfd {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_err!(d, [], [i], [0x3f], "");
assert_feed_err!(d, [], [i], [0x7f], "");
assert_feed_err!(d, [], [i], [0xfd], "");
assert_feed_err!(d, [], [i], [0xfe], "");
assert_feed_err!(d, [], [i], [0xff], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_invalid_lead_followed_by_invalid_trail_partial() {
for i in 0x81..0xa0 {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], "");
assert_feed_err!(d, [], [], [0xff], "");
assert_finish_ok!(d, "");
}
for i in 0xe0..0xfd {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [], [i], "");
assert_feed_err!(d, [], [], [0xff], "");
assert_finish_ok!(d, "");
}
}
#[test]
fn test_decoder_feed_after_finish() {
let mut d = Windows31JEncoding.raw_decoder();
assert_feed_ok!(d, [0x82, 0xa0], [0x82], "\u{3042}");
assert_finish_err!(d, "");
assert_feed_ok!(d, [0x82, 0xa0], [], "\u{3042}");
assert_finish_ok!(d, "");
}
#[bench]
fn bench_encode_short_text(bencher: &mut test::Bencher) {
let s = testutils::JAPANESE_TEXT;
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
Windows31JEncoding.encode(&s, EncoderTrap::Strict)
}))
}
#[bench]
fn bench_decode_short_text(bencher: &mut test::Bencher) {
let s = Windows31JEncoding.encode(testutils::JAPANESE_TEXT,
EncoderTrap::Strict).ok().unwrap();
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
Windows31JEncoding.decode(&s, DecoderTrap::Strict)
}))
}
}
#[derive(Clone, Copy)]
pub struct ISO2022JPEncoding;
impl Encoding for ISO2022JPEncoding {
fn name(&self) -> &'static str { "iso-2022-jp" }
fn whatwg_name(&self) -> Option<&'static str> { Some("iso-2022-jp") }
fn raw_encoder(&self) -> Box<RawEncoder> { ISO2022JPEncoder::new() }
fn raw_decoder(&self) -> Box<RawDecoder> { ISO2022JPDecoder::new() }
}
#[derive(PartialEq,Clone,Copy)]
enum ISO2022JPState {
ASCII, Katakana, Lead, }
#[derive(Clone, Copy)]
pub struct ISO2022JPEncoder {
st: ISO2022JPState
}
impl ISO2022JPEncoder {
pub fn new() -> Box<RawEncoder> { Box::new(ISO2022JPEncoder { st: ASCII }) }
}
impl RawEncoder for ISO2022JPEncoder {
fn from_self(&self) -> Box<RawEncoder> { ISO2022JPEncoder::new() }
fn is_ascii_compatible(&self) -> bool { true }
fn raw_feed(&mut self, input: &str, output: &mut ByteWriter) -> (usize, Option<CodecError>) {
output.writer_hint(input.len());
let mut st = self.st;
macro_rules! ensure_ASCII(
() => (if st != ASCII { output.write_bytes(b"\x1b(B"); st = ASCII; })
);
macro_rules! ensure_Katakana(
() => (if st != Katakana { output.write_bytes(b"\x1b(I"); st = Katakana; })
);
macro_rules! ensure_Lead(
() => (if st != Lead { output.write_bytes(b"\x1b$B"); st = Lead; })
);
for ((i,j), ch) in input.index_iter() {
match ch {
'\u{0}'...'\u{7f}' => { ensure_ASCII!(); output.write_byte(ch as u8); }
'\u{a5}' => { ensure_ASCII!(); output.write_byte(0x5c); }
'\u{203e}' => { ensure_ASCII!(); output.write_byte(0x7e); }
'\u{ff61}'...'\u{ff9f}' => {
ensure_Katakana!();
output.write_byte((ch as usize - 0xff61 + 0x21) as u8);
}
_ => {
let ptr = index::jis0208::backward(ch as u32);
if ptr == 0xffff {
self.st = st; return (i, Some(CodecError {
upto: j as isize, cause: "unrepresentable character".into()
}));
} else {
ensure_Lead!();
let lead = ptr / 94 + 0x21;
let trail = ptr % 94 + 0x21;
output.write_byte(lead as u8);
output.write_byte(trail as u8);
}
}
}
}
self.st = st;
(input.len(), None)
}
fn raw_finish(&mut self, _output: &mut ByteWriter) -> Option<CodecError> {
None
}
}
#[derive(Clone, Copy)]
struct ISO2022JPDecoder {
st: iso2022jp::State,
}
impl ISO2022JPDecoder {
pub fn new() -> Box<RawDecoder> {
Box::new(ISO2022JPDecoder { st: Default::default() })
}
}
impl RawDecoder for ISO2022JPDecoder {
fn from_self(&self) -> Box<RawDecoder> { ISO2022JPDecoder::new() }
fn is_ascii_compatible(&self) -> bool { false }
fn raw_feed(&mut self, input: &[u8], output: &mut StringWriter) -> (usize, Option<CodecError>) {
let (st, processed, err) = iso2022jp::raw_feed(self.st, input, output, &());
self.st = st;
(processed, err)
}
fn raw_finish(&mut self, output: &mut StringWriter) -> Option<CodecError> {
let (st, err) = iso2022jp::raw_finish(self.st, output, &());
self.st = st;
err
}
}
stateful_decoder! {
module iso2022jp;
internal pub fn map_two_0208_bytes(lead: u8, trail: u8) -> u32 {
use index_japanese as index;
let lead = lead as u16;
let trail = trail as u16;
let index = match (lead, trail) {
(0x21...0x7e, 0x21...0x7e) => (lead - 0x21) * 94 + trail - 0x21,
_ => 0xffff,
};
index::jis0208::forward(index)
}
internal pub fn map_two_0212_bytes(lead: u8, trail: u8) -> u32 {
use index_japanese as index;
let lead = lead as u16;
let trail = trail as u16;
let index = match (lead, trail) {
(0x21...0x7e, 0x21...0x7e) => (lead - 0x21) * 94 + trail - 0x21,
_ => 0xffff,
};
index::jis0212::forward(index)
}
initial:
state ASCII(ctx: Context) {
case 0x1b => EscapeStart(ctx);
case b @ 0x00...0x7f => ctx.emit(b as u32), ASCII(ctx);
case _ => ctx.err("invalid sequence"), ASCII(ctx);
final => ctx.reset();
}
checkpoint:
state Lead0208(ctx: Context) {
case 0x0a => ctx.emit(0x000a); case 0x1b => EscapeStart(ctx);
case b => Trail0208(ctx, b);
final => ctx.reset();
}
state Lead0212(ctx: Context) {
case 0x0a => ctx.emit(0x000a); case 0x1b => EscapeStart(ctx);
case b => Trail0212(ctx, b);
final => ctx.reset();
}
state Katakana(ctx: Context) {
case 0x1b => EscapeStart(ctx);
case b @ 0x21...0x5f => ctx.emit(0xff61 + b as u32 - 0x21), Katakana(ctx);
case _ => ctx.err("invalid sequence"), Katakana(ctx);
final => ctx.reset();
}
transient:
state EscapeStart(ctx: Context) {
case 0x24 => EscapeMiddle24(ctx); case 0x28 => EscapeMiddle28(ctx); case _ => ctx.backup_and_err(1, "invalid sequence");
final => ctx.err("incomplete sequence");
}
state EscapeMiddle24(ctx: Context) {
case 0x40, 0x42 => Lead0208(ctx); case 0x28 => EscapeFinal(ctx); case _ => ctx.backup_and_err(2, "invalid sequence");
final => ctx.err("incomplete sequence");
}
state EscapeMiddle28(ctx: Context) {
case 0x42, 0x4a => ctx.reset(); case 0x49 => Katakana(ctx); case _ => ctx.backup_and_err(2, "invalid sequence");
final => ctx.err("incomplete sequence");
}
state EscapeFinal(ctx: Context) {
case 0x44 => Lead0212(ctx); case _ => ctx.backup_and_err(3, "invalid sequence");
final => ctx.backup_and_err(1, "incomplete sequence");
}
state Trail0208(ctx: Context, lead: u8) {
case b =>
match map_two_0208_bytes(lead, b) {
0xffff => ctx.err("invalid sequence"),
ch => ctx.emit(ch as u32)
},
Lead0208(ctx);
final => ctx.err("incomplete sequence");
}
state Trail0212(ctx: Context, lead: u8) {
case b =>
match map_two_0212_bytes(lead, b) {
0xffff => ctx.err("invalid sequence"),
ch => ctx.emit(ch as u32)
},
Lead0212(ctx);
final => ctx.err("incomplete sequence");
}
}
#[cfg(test)]
mod iso2022jp_tests {
extern crate test;
use super::ISO2022JPEncoding;
use testutils;
use types::*;
#[test]
fn test_encoder_valid() {
let mut e = ISO2022JPEncoding.raw_encoder();
assert_feed_ok!(e, "A", "", [0x41]);
assert_feed_ok!(e, "BC", "", [0x42, 0x43]);
assert_feed_ok!(e, "\x1b\x24\x42", "", [0x1b, 0x24, 0x42]); assert_feed_ok!(e, "", "", []);
assert_feed_ok!(e, "\u{a5}", "", [0x5c]);
assert_feed_ok!(e, "\u{203e}", "", [0x7e]);
assert_feed_ok!(e, "\u{306b}\u{307b}\u{3093}", "", [0x1b, 0x24, 0x42,
0x24, 0x4b, 0x24, 0x5b, 0x24, 0x73]);
assert_feed_ok!(e, "\u{65e5}\u{672c}", "", [0x46, 0x7c, 0x4b, 0x5c]);
assert_feed_ok!(e, "\u{ff86}\u{ff8e}\u{ff9d}", "", [0x1b, 0x28, 0x49,
0x46, 0x4e, 0x5d]);
assert_feed_ok!(e, "XYZ", "", [0x1b, 0x28, 0x42,
0x58, 0x59, 0x5a]);
assert_finish_ok!(e, []);
const AD: &'static str = "\x20";
const BD: &'static str = "\u{30cd}";
const CD: &'static str = "\u{ff88}";
const AE: &'static [u8] = &[0x1b, 0x28, 0x42, 0x20];
const BE: &'static [u8] = &[0x1b, 0x24, 0x42, 0x25, 0x4d];
const CE: &'static [u8] = &[0x1b, 0x28, 0x49, 0x48];
let mut e = ISO2022JPEncoding.raw_encoder();
let decoded: String = ["\x20", BD, CD, AD, CD, BD, AD].concat();
let encoded: Vec<_> = [&[0x20][..], BE, CE, AE, CE, BE, AE].concat();
assert_feed_ok!(e, decoded, "", encoded);
assert_finish_ok!(e, []);
}
#[test]
fn test_encoder_invalid() {
let mut e = ISO2022JPEncoding.raw_encoder();
assert_feed_err!(e, "", "\u{ffff}", "", []);
assert_feed_err!(e, "?", "\u{ffff}", "!", [0x3f]);
assert_feed_err!(e, "", "\u{736c}", "\u{8c78}", []);
assert_finish_ok!(e, []);
}
#[test]
fn test_decoder_valid() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x41], [], "A");
assert_feed_ok!(d, [0x42, 0x43], [], "BC");
assert_feed_ok!(d, [0x1b, 0x28, 0x4a,
0x44, 0x45, 0x46], [], "DEF");
assert_feed_ok!(d, [], [], "");
assert_feed_ok!(d, [0x5c], [], "\\");
assert_feed_ok!(d, [0x7e], [], "~");
assert_feed_ok!(d, [0x1b, 0x24, 0x42,
0x24, 0x4b,
0x1b, 0x24, 0x42,
0x24, 0x5b, 0x24, 0x73], [], "\u{306b}\u{307b}\u{3093}");
assert_feed_ok!(d, [0x46, 0x7c, 0x4b, 0x5c], [], "\u{65e5}\u{672c}");
assert_feed_ok!(d, [0x1b, 0x28, 0x49,
0x46, 0x4e, 0x5d], [], "\u{ff86}\u{ff8e}\u{ff9d}");
assert_feed_ok!(d, [0x1b, 0x24, 0x28, 0x44,
0x4b, 0x46,
0x1b, 0x24, 0x40,
0x6c, 0x38], [], "\u{736c}\u{8c78}");
assert_feed_ok!(d, [0x1b, 0x28, 0x42,
0x58, 0x59, 0x5a], [], "XYZ");
assert_finish_ok!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x24, 0x42,
0x24, 0x4b, 0x24, 0x5b, 0x24, 0x73], [], "\u{306b}\u{307b}\u{3093}");
assert_finish_ok!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x28, 0x49,
0x46, 0x4e, 0x5d], [], "\u{ff86}\u{ff8e}\u{ff9d}");
assert_finish_ok!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x24, 0x28, 0x44,
0x4b, 0x46], [], "\u{736c}");
assert_finish_ok!(d, "");
const AD: &'static str = "\x20";
const BD: &'static str = "\u{30cd}";
const CD: &'static str = "\u{ff88}";
const DD: &'static str = "\u{793b}";
const AE: &'static [u8] = &[0x1b, 0x28, 0x42, 0x20];
const BE: &'static [u8] = &[0x1b, 0x24, 0x42, 0x25, 0x4d];
const CE: &'static [u8] = &[0x1b, 0x28, 0x49, 0x48];
const DE: &'static [u8] = &[0x1b, 0x24, 0x28, 0x44, 0x50, 0x4b];
let mut d = ISO2022JPEncoding.raw_decoder();
let dec: String = ["\x20", AD,BD,BD,CD,CD,AD,CD,BD,AD,DD,DD,BD,DD,CD,DD,AD].concat();
let enc: Vec<_> = [&[0x20][..],AE,BE,BE,CE,CE,AE,CE,BE,AE,DE,DE,BE,DE,CE,DE,AE].concat();
assert_feed_ok!(d, enc, [], dec);
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_valid_partial() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x1b], "");
assert_feed_ok!(d, [], [0x28], "");
assert_feed_ok!(d, [0x4a, 0x41], [], "A");
assert_feed_ok!(d, [], [0x1b, 0x28], "");
assert_feed_ok!(d, [0x4a, 0x42], [0x1b], "B");
assert_feed_ok!(d, [0x28, 0x4a, 0x43], [], "C");
assert_feed_ok!(d, [], [0x1b], "");
assert_feed_ok!(d, [], [0x24], "");
assert_feed_ok!(d, [0x42], [0x24], "");
assert_feed_ok!(d, [0x4b], [0x1b, 0x24], "\u{306b}");
assert_feed_ok!(d, [0x42, 0x24, 0x5b], [], "\u{307b}");
assert_feed_ok!(d, [], [0x1b], "");
assert_feed_ok!(d, [0x24, 0x42, 0x24, 0x73], [], "\u{3093}");
assert_feed_ok!(d, [], [0x1b], "");
assert_feed_ok!(d, [], [0x28], "");
assert_feed_ok!(d, [0x49, 0x46], [], "\u{ff86}");
assert_feed_ok!(d, [], [0x1b, 0x28], "");
assert_feed_ok!(d, [0x49, 0x4e], [0x1b], "\u{ff8e}");
assert_feed_ok!(d, [0x28, 0x49, 0x5d], [], "\u{ff9d}");
assert_feed_ok!(d, [], [0x1b, 0x24], "");
assert_feed_ok!(d, [], [0x28], "");
assert_feed_ok!(d, [0x44], [0x4b], "");
assert_feed_ok!(d, [0x46], [0x1b, 0x24, 0x28], "\u{736c}");
assert_feed_ok!(d, [0x44, 0x4b, 0x46], [], "\u{736c}");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_carriage_return() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x24, 0x42,
0x25, 0x4d,
0x0a,
0x25, 0x4d], [], "\u{30cd}\n\x25\x4d");
assert_feed_ok!(d, [0x1b, 0x24, 0x28, 0x44,
0x50, 0x4b,
0x0a,
0x50, 0x4b], [], "\u{793b}\n\x50\x4b");
assert_finish_ok!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_err!(d, [0x1b, 0x28, 0x49, 0x48], [0x0a], [], "\u{ff88}"); assert_feed_err!(d, [0x1b, 0x24, 0x42], [0x25, 0x0a], [], ""); assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_partial() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x24, 0x42, 0x24, 0x4b], [0x24], "\u{306b}");
assert_finish_err!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x1b, 0x24, 0x28, 0x44, 0x4b, 0x46], [0x50], "\u{736c}");
assert_finish_err!(d, "");
}
#[test]
fn test_decoder_invalid_partial_escape() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x1b], "");
assert_finish_err!(d, "");
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x1b, 0x24], "");
assert_finish_err!(d, ""); let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x1b, 0x24, 0x28], "");
assert_finish_err!(d, -1, ""); let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [], [0x1b, 0x28], "");
assert_finish_err!(d, ""); assert_eq!(ISO2022JPEncoding.decode(&[0x1b], DecoderTrap::Replace),
Ok("\u{fffd}".to_string()));
assert_eq!(ISO2022JPEncoding.decode(&[0x1b, 0x24], DecoderTrap::Replace),
Ok("\u{fffd}".to_string()));
assert_eq!(ISO2022JPEncoding.decode(&[0x1b, 0x24, 0x28], DecoderTrap::Replace),
Ok("\u{fffd}\x28".to_string()));
assert_eq!(ISO2022JPEncoding.decode(&[0x1b, 0x28], DecoderTrap::Replace),
Ok("\u{fffd}".to_string()));
}
#[test]
fn test_decoder_invalid_escape() {
let mut d = ISO2022JPEncoding.raw_decoder();
macro_rules! reset(() => (
assert_feed_ok!(d, [0x41, 0x42, 0x43, 0x1b, 0x24, 0x42, 0x21, 0x21], [],
"ABC\u{3000}")
));
reset!();
assert_feed_ok!(d, [], [0x1b], "");
assert_feed_err!(d, [], [], [0x00], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x0a], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x20], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x21, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x22, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x5a], ""); reset!();
assert_feed_ok!(d, [], [0x1b, 0x24], "");
assert_feed_err!(d, -1, [], [], [0x24, 0x5a], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x28, 0x5a], ""); reset!();
assert_feed_ok!(d, [], [0x1b, 0x24, 0x28], "");
assert_feed_err!(d, -2, [], [], [0x24, 0x28, 0x5a], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x29, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x2a, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x2b, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x2d, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x2e, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x24, 0x2f, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x25, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x25, 0x2f, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x28, 0x5a], ""); reset!();
assert_feed_ok!(d, [], [0x1b, 0x28], "");
assert_feed_err!(d, -1, [], [], [0x28, 0x5a], "");
reset!();
assert_feed_err!(d, [], [0x1b], [0x29, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x2a, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x2b, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x2d, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x2e, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x2f, 0x5a], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x4e], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x4f], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x6e], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x6f], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x7c], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x7d], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0x7e], ""); reset!();
assert_feed_err!(d, [], [0x1b], [0xff], "");
reset!();
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_invalid_out_or_range() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_err!(d, [], [0x80], [], "");
assert_feed_err!(d, [], [0xff], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x42], [0x80, 0x21], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x42], [0x21, 0x80], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x42], [0x20, 0x21], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x42], [0x21, 0x20], [], "");
assert_feed_err!(d, [0x1b, 0x28, 0x49], [0x20], [], "");
assert_feed_err!(d, [0x1b, 0x28, 0x49], [0x60], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x28, 0x44], [0x80, 0x21], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x28, 0x44], [0x21, 0x80], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x28, 0x44], [0x20, 0x21], [], "");
assert_feed_err!(d, [0x1b, 0x24, 0x28, 0x44], [0x21, 0x20], [], "");
assert_finish_ok!(d, "");
}
#[test]
fn test_decoder_feed_after_finish() {
let mut d = ISO2022JPEncoding.raw_decoder();
assert_feed_ok!(d, [0x24, 0x22,
0x1b, 0x24, 0x42,
0x24, 0x22], [0x24], "\x24\x22\u{3042}");
assert_finish_err!(d, "");
assert_feed_ok!(d, [0x24, 0x22,
0x1b, 0x24, 0x42,
0x24, 0x22], [], "\x24\x22\u{3042}");
assert_finish_ok!(d, "");
}
#[bench]
fn bench_encode_short_text(bencher: &mut test::Bencher) {
let s = testutils::JAPANESE_TEXT;
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
ISO2022JPEncoding.encode(&s, EncoderTrap::Strict)
}))
}
#[bench]
fn bench_decode_short_text(bencher: &mut test::Bencher) {
let s = ISO2022JPEncoding.encode(testutils::JAPANESE_TEXT,
EncoderTrap::Strict).ok().unwrap();
bencher.bytes = s.len() as u64;
bencher.iter(|| test::black_box({
ISO2022JPEncoding.decode(&s, DecoderTrap::Strict)
}))
}
}