From fb8d534f9edd6638cecbea31edf919399807bac9 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Sun, 29 Jan 2023 16:07:37 -0600 Subject: [PATCH] fix some high level eci parsing --- src/common/eci_string_builder.rs | 55 ++++---- .../decoder/decoded_bit_stream_parser.rs | 124 ++++++++++-------- .../blackbox/datamatrix-1/eci-mixed.txt | 1 + 3 files changed, 97 insertions(+), 83 deletions(-) create mode 100644 test_resources/blackbox/datamatrix-1/eci-mixed.txt diff --git a/src/common/eci_string_builder.rs b/src/common/eci_string_builder.rs index 2db4055..f27de9e 100644 --- a/src/common/eci_string_builder.rs +++ b/src/common/eci_string_builder.rs @@ -105,10 +105,11 @@ impl ECIStringBuilder { */ pub fn appendECI(&mut self, value: u32) -> Result<(), Exceptions> { self.encodeCurrentBytesIfAny(); - + if let Ok(character_set_eci) = CharacterSetECI::getCharacterSetECIByValue(value) { + dbg!(character_set_eci, CharacterSetECI::getCharset(&character_set_eci).name(), CharacterSetECI::getCharset(&character_set_eci).whatwg_name()); self.current_charset = Some(CharacterSetECI::getCharset(&character_set_eci)); - }else { + } else { self.current_charset = None } @@ -118,35 +119,35 @@ impl ECIStringBuilder { pub fn encodeCurrentBytesIfAny(&mut self) { if let Some(encoder) = self.current_charset { - if encoder.name() == encoding::all::UTF_8.name() { - if !self.current_bytes.is_empty() { - // if result == null { - // result = currentBytes; - // currentBytes = new StringBuilder(); - // } else { - self.result - .push_str(&String::from_utf8(self.current_bytes.clone()).unwrap()); + if encoder.name() == encoding::all::UTF_8.name() { + if !self.current_bytes.is_empty() { + // if result == null { + // result = currentBytes; + // currentBytes = new StringBuilder(); + // } else { + self.result + .push_str(&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap()); + self.current_bytes.clear(); + // } + } + } else if !self.current_bytes.is_empty() { + let bytes = std::mem::take(&mut self.current_bytes); self.current_bytes.clear(); - // } + // if (result == null) { + // result = new StringBuilder(new String(bytes, currentCharset)); + // } else { + let encoded_value = encoder + .decode(&bytes, encoding::DecoderTrap::Strict) + .unwrap(); + self.result.push_str(&encoded_value); + // } + } + } else { + for byte in &self.current_bytes { + self.result.push(char::from(*byte)) } - } else if !self.current_bytes.is_empty() { - let bytes = self.current_bytes.clone(); self.current_bytes.clear(); - // if (result == null) { - // result = new StringBuilder(new String(bytes, currentCharset)); - // } else { - let encoded_value = encoder - .decode(&bytes, encoding::DecoderTrap::Replace) - .unwrap(); - self.result.push_str(&encoded_value); - // } } - }else { - for byte in &self.current_bytes { - self.result.push(char::from(*byte)) - } - self.current_bytes.clear(); - } } /** diff --git a/src/datamatrix/decoder/decoded_bit_stream_parser.rs b/src/datamatrix/decoder/decoded_bit_stream_parser.rs index 8dbe246..c117f5b 100644 --- a/src/datamatrix/decoder/decoded_bit_stream_parser.rs +++ b/src/datamatrix/decoder/decoded_bit_stream_parser.rs @@ -121,30 +121,43 @@ pub fn decode(bytes: &[u8]) -> Result { let symbologyModifier; let mut isECIencoded = false; loop { - if mode == Mode::ASCII_ENCODE { - mode = decodeAsciiSegment( - &mut bits, - &mut result, - &mut resultTrailer, - &mut fnc1Positions, - )?; - } else { - match mode { - Mode::C40_ENCODE => decodeC40Segment(&mut bits, &mut result, &mut fnc1Positions)?, - Mode::TEXT_ENCODE => decodeTextSegment(&mut bits, &mut result, &mut fnc1Positions)?, - Mode::ANSIX12_ENCODE => decodeAnsiX12Segment(&mut bits, &mut result)?, - Mode::EDIFACT_ENCODE => decodeEdifactSegment(&mut bits, &mut result)?, - Mode::BASE256_ENCODE => { - decodeBase256Segment(&mut bits, &mut result, &mut byteSegments)? - } - Mode::ECI_ENCODE => { - decodeECISegment(&mut bits, &mut result)?; - isECIencoded = true; // ECI detection only, atm continue decoding as ASCII - } - _ => return Err(Exceptions::FormatException(None)), - }; - mode = Mode::ASCII_ENCODE; + match mode { + Mode::ASCII_ENCODE => { + mode = decodeAsciiSegment( + &mut bits, + &mut result, + &mut resultTrailer, + &mut fnc1Positions, + )? + } + Mode::C40_ENCODE => { + decodeC40Segment(&mut bits, &mut result, &mut fnc1Positions)?; + mode = Mode::ASCII_ENCODE; + } + Mode::TEXT_ENCODE => { + decodeTextSegment(&mut bits, &mut result, &mut fnc1Positions)?; + mode = Mode::ASCII_ENCODE; + } + Mode::ANSIX12_ENCODE => { + decodeAnsiX12Segment(&mut bits, &mut result)?; + mode = Mode::ASCII_ENCODE; + } + Mode::EDIFACT_ENCODE => { + decodeEdifactSegment(&mut bits, &mut result)?; + mode = Mode::ASCII_ENCODE; + } + Mode::BASE256_ENCODE => { + decodeBase256Segment(&mut bits, &mut result, &mut byteSegments)?; + mode = Mode::ASCII_ENCODE; + } + Mode::ECI_ENCODE => { + decodeECISegment(&mut bits, &mut result)?; + isECIencoded = true; // ECI detection only, atm continue decoding as ASCII + mode = Mode::ASCII_ENCODE; + } + _ => return Err(Exceptions::FormatException(None)), } + if !(mode != Mode::PAD_ENCODE && bits.available() > 0) { break; } @@ -200,31 +213,29 @@ fn decodeAsciiSegment( let mut sai = StructuredAppendInfo::default(); loop { let mut oneByte = bits.readBits(8)?; - if oneByte == 0 { - return Err(Exceptions::FormatException(None)); - } else if oneByte <= 128 { - // ASCII data (ASCII value + 1) - if upperShift { - oneByte += 128; - //upperShift = false; - } - result.append_char(char::from_u32(oneByte - 1).unwrap()); - return Ok(Mode::ASCII_ENCODE); - } else if oneByte == 129 { - // Pad - return Ok(Mode::PAD_ENCODE); - } else if oneByte <= 229 { - // 2-digit data 00-99 (Numeric Value + 130) - let value = oneByte - 130; - if value < 10 { - // pad with '0' for single digit values - result.append_char('0'); - } - //result.append_char(char::from_u32(value).unwrap()); - result.append_string(&format!("{value}")); - } else { - match oneByte { - 230=> // Latch to C40 encodation + match oneByte { + 0 => return Err(Exceptions::FormatException(None)), + 1..=128 => { + // ASCII data (ASCII value + 1) + if upperShift { + oneByte += 128; + //upperShift = false; + } + result.append_char(char::from_u32(oneByte - 1).unwrap()); + return Ok(Mode::ASCII_ENCODE); + }, + 129 => return Ok(Mode::PAD_ENCODE), // Pad + 129..=229 => { + // 2-digit data 00-99 (Numeric Value + 130) + let value = oneByte - 130; + if value < 10 { + // pad with '0' for single digit values + result.append_char('0'); + } + //result.append_char(char::from_u32(value).unwrap()); + result.append_string(&format!("{value}")); + }, + 230=> // Latch to C40 encodation return Ok(Mode::C40_ENCODE), 231=> // Latch to Base 256 encodation return Ok(Mode::BASE256_ENCODE), @@ -237,16 +248,17 @@ fn decodeAsciiSegment( {fnc1positions.push(result.len()); result.append_char( 29 as char); }// translate as ASCII 29 }, - 233| // Structured Append + 233 => // Structured Append + { + if !firstCodeword // Must be first ISO 16022:2006 5.6.1 + {return Err(Exceptions::FormatException(Some("structured append tag must be first code word".to_owned())));} + parse_structured_append(bits, &mut sai)?; + firstFNC1Position = 5; + }, 234=> // Reader Programming // Ignore these symbols for now //throw ReaderException.getInstance(); - { - if !firstCodeword // Must be first ISO 16022:2006 5.6.1 - {return Err(Exceptions::FormatException(Some("structured append tag must be first code word".to_owned())));} - parse_structured_append(bits, &mut sai)?; - firstFNC1Position = 5; - }, + {}, 235=> // Upper Shift (shift to Extended ASCII) upperShift = true, 236=> {// 05 Macro @@ -274,7 +286,7 @@ fn decodeAsciiSegment( return Err(Exceptions::FormatException(None)) }}, } - } + if bits.available() == 0 { break; } diff --git a/test_resources/blackbox/datamatrix-1/eci-mixed.txt b/test_resources/blackbox/datamatrix-1/eci-mixed.txt new file mode 100644 index 0000000..93bb3a1 --- /dev/null +++ b/test_resources/blackbox/datamatrix-1/eci-mixed.txt @@ -0,0 +1 @@ +á¡¡ĦĦͱ𐌶@@@@@@@@@@_ \ No newline at end of file