From 9ec895ecc532de5e16d7aece1c4573a3a9338d49 Mon Sep 17 00:00:00 2001 From: Henry Date: Mon, 3 Oct 2022 20:17:41 -0500 Subject: [PATCH] partially passing encoder tests --- src/common/mod.rs | 121 ++++----- src/qrcode/encoder/EncoderTestCase.rs | 345 +++++++++++++------------- src/qrcode/encoder/encoder.rs | 37 +-- src/qrcode/encoder/minimal_encoder.rs | 33 +-- 4 files changed, 279 insertions(+), 257 deletions(-) diff --git a/src/common/mod.rs b/src/common/mod.rs index 92e0c57..c4cb972 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -84,10 +84,10 @@ const ASSUME_SHIFT_JIS: bool = false; static SHIFT_JIS: &'static str = "SJIS"; static GB2312: &'static str = "GB2312"; lazy_static! { - pub static ref SHIFT_JIS_CHARSET: EncodingRef = encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); + pub static ref SHIFT_JIS_CHARSET: EncodingRef = + encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); } - // private static final boolean ASSUME_SHIFT_JIS = // SHIFT_JIS_CHARSET.equals(PLATFORM_DEFAULT_ENCODING) || // EUC_JP.equals(PLATFORM_DEFAULT_ENCODING); @@ -558,27 +558,27 @@ impl BitArray { * @param value {@code int} containing bits to append * @param numBits bits from value to append */ - pub fn appendBits(&mut self, value: u32, numBits: usize) -> Result<(), Exceptions> { - if numBits > 32 { + pub fn appendBits(&mut self, value: u32, num_bits: usize) -> Result<(), Exceptions> { + if num_bits > 32 { return Err(Exceptions::IllegalArgumentException( "Num bits must be between 0 and 32".to_owned(), )); } - if numBits == 0 { + if num_bits == 0 { return Ok(()); } - let mut nextSize = self.size; - self.ensure_capacity(nextSize + numBits); - for numBitsLeft in (0..(numBits)).rev() { + let mut next_size = self.size; + self.ensure_capacity(next_size + num_bits); + for numBitsLeft in (0..num_bits).rev() { //for (int numBitsLeft = numBits - 1; numBitsLeft >= 0; numBitsLeft--) { if (value & (1 << numBitsLeft)) != 0 { - self.bits[nextSize / 32] |= 1 << (nextSize & 0x1F); + self.bits[next_size / 32] |= 1 << (next_size & 0x1F); } - nextSize += 1; + next_size += 1; } - self.size = nextSize; + self.size = next_size; Ok(()) } @@ -1670,7 +1670,7 @@ impl PerspectiveTransform { x3p: f32, y3p: f32, ) -> Self { - let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); + let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); let s_to_q = PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); return s_to_q.times(&q_to_s); @@ -2473,7 +2473,7 @@ impl CharacterSetECI { // this.otherEncodingNames = otherEncodingNames; // } - pub fn getValueSelf(&self) -> u32{ + pub fn getValueSelf(&self) -> u32 { Self::getValue(self) } @@ -2550,7 +2550,7 @@ impl CharacterSetECI { pub fn getCharacterSetECI(charset: &'static dyn Encoding) -> Option { let name = if let Some(nm) = charset.whatwg_name() { nm - }else { + } else { charset.name() }; match name { @@ -2853,6 +2853,44 @@ impl fmt::Display for ECIStringBuilder { // import java.util.ArrayList; // import java.util.List; +lazy_static! { + static ref ENCODERS : Vec = { + let mut enc_vec = Vec::new(); + for name in NAMES { + if let Some(enc) = CharacterSetECI::getCharacterSetECIByName(name) { + // try { + enc_vec.push(CharacterSetECI::getCharset(&enc)); + // } catch (UnsupportedCharsetException e) { + // continue + // } + } + } + enc_vec + }; +} +const NAMES: [&str; 20] = [ + "IBM437", + "ISO-8859-2", + "ISO-8859-3", + "ISO-8859-4", + "ISO-8859-5", + "ISO-8859-6", + "ISO-8859-7", + "ISO-8859-8", + "ISO-8859-9", + "ISO-8859-10", + "ISO-8859-11", + "ISO-8859-13", + "ISO-8859-14", + "ISO-8859-15", + "ISO-8859-16", + "windows-1250", + "windows-1251", + "windows-1252", + "windows-1256", + "Shift_JIS", +]; + /** * Set of CharsetEncoders for a given input string * @@ -2882,45 +2920,8 @@ impl ECIEncoderSet { * @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar * code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode(). */ - pub fn new( - stringToEncode: &str, - priorityCharset: EncodingRef, - fnc1: i16, - ) -> Self { + pub fn new(stringToEncode: &str, priorityCharset: EncodingRef, fnc1: i16) -> Self { // List of encoders that potentially encode characters not in ISO-8859-1 in one byte. - let mut ENCODERS :Vec = Vec::new(); - - let names = [ - "IBM437", - "ISO-8859-2", - "ISO-8859-3", - "ISO-8859-4", - "ISO-8859-5", - "ISO-8859-6", - "ISO-8859-7", - "ISO-8859-8", - "ISO-8859-9", - "ISO-8859-10", - "ISO-8859-11", - "ISO-8859-13", - "ISO-8859-14", - "ISO-8859-15", - "ISO-8859-16", - "windows-1250", - "windows-1251", - "windows-1252", - "windows-1256", - "Shift_JIS", - ]; - for name in names { - if let Some(enc) = CharacterSetECI::getCharacterSetECIByName(name) { - // try { - ENCODERS.push(CharacterSetECI::getCharset(&enc)); - // } catch (UnsupportedCharsetException e) { - // continue - // } - } - } let mut encoders: Vec; let mut priorityEncoderIndexValue = 0; @@ -2929,7 +2930,6 @@ impl ECIEncoderSet { //we always need the ISO-8859-1 encoder. It is the default encoding neededEncoders.push(encoding::all::ISO_8859_1); - neededEncoders.push(encoding::all::UTF_8); let mut needUnicodeEncoder = priorityCharset.name().starts_with("UTF"); //Walk over the input string and see if all characters can be encoded with the list of encoders @@ -2950,7 +2950,9 @@ impl ECIEncoderSet { } if !canEncode { //for the character at position i we don't yet have an encoder in the list - for encoder in &ENCODERS { + for i in 0..ENCODERS.len() { + // for encoder in ENCODERS { + let encoder = ENCODERS.get(i).unwrap(); // for (CharsetEncoder encoder : ENCODERS) { if encoder .encode( @@ -4034,19 +4036,19 @@ impl HybridBinarizer { if (max - min) as usize > HybridBinarizer::MIN_DYNAMIC_RANGE { // finish the rest of the rows quickly offset += width; - yy+=1; - while yy < HybridBinarizer::BLOCK_SIZE { + yy += 1; + while yy < HybridBinarizer::BLOCK_SIZE { // for (yy++, offset += width; yy < HybridBinarizer::BLOCK_SIZE; yy++, offset += width) { for xx in 0..HybridBinarizer::BLOCK_SIZE { // for (int xx = 0; xx < BLOCK_SIZE; xx++) { sum += luminances[offset as usize + xx] as u32; } - yy+=1; + yy += 1; offset += width; } break; } - yy+=1; + yy += 1; offset += width; } @@ -4069,7 +4071,8 @@ impl HybridBinarizer { // the boundaries is used for the interior. // The (min < bp) is arbitrary but works better than other heuristics that were tried. - let average_neighbor_black_point:u32 = (blackPoints[y as usize - 1][x as usize] + let average_neighbor_black_point: u32 = (blackPoints[y as usize - 1] + [x as usize] + (2 * blackPoints[y as usize][x as usize - 1]) + blackPoints[y as usize - 1][x as usize - 1]) / 4; diff --git a/src/qrcode/encoder/EncoderTestCase.rs b/src/qrcode/encoder/EncoderTestCase.rs index f5dd260..766beda 100644 --- a/src/qrcode/encoder/EncoderTestCase.rs +++ b/src/qrcode/encoder/EncoderTestCase.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; -use crate::{qrcode::{encoder::encoder, decoder::{Mode, ErrorCorrectionLevel}}, EncodeHintType, EncodeHintValue, common::BitArray}; +use crate::{qrcode::{encoder::{encoder, MinimalEncoder}, decoder::{Mode, ErrorCorrectionLevel, Version}}, EncodeHintType, EncodeHintValue, common::BitArray}; use encoding::EncodingRef; use lazy_static::lazy_static; @@ -82,13 +82,13 @@ lazy_static! { // AIUE in Hiragana in Shift_JIS assert_eq!(Mode::BYTE, - encoder::chooseMode(&shiftJISString(bytes(0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6)))); + encoder::chooseMode(&shiftJISString(&[0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6]))); // Nihon in Kanji in Shift_JIS. - assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(bytes(0x9, 0xf, 0x9, 0x7b)))); + assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(&[0x9, 0xf, 0x9, 0x7b]))); // Sou-Utsu-Byou in Kanji in Shift_JIS. - assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(bytes(0xe, 0x4, 0x9, 0x5, 0x9, 0x61)))); + assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(&[0xe, 0x4, 0x9, 0x5, 0x9, 0x61]))); } #[test] @@ -129,7 +129,7 @@ r"<< #[test] fn testEncodeWithVersion() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); hints.insert(EncodeHintType::QR_VERSION, EncodeHintValue::QrVersion("7".to_owned())); let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); assert!(qrCode.to_string().contains(" version: 7\n")); @@ -138,16 +138,16 @@ r"<< #[test] #[should_panic] fn testEncodeWithVersionTooSmall() { - let hints = HashMap::new(); - hints.put(EncodeHintType::QR_VERSION, 3); - encoder::encode_with_hints("THISMESSAGEISTOOLONGFORAQRCODEVERSION3", ErrorCorrectionLevel::H, &hints); + let mut hints = HashMap::new(); + hints.insert(EncodeHintType::QR_VERSION, EncodeHintValue::QrVersion("3".to_owned())); + encoder::encode_with_hints("THISMESSAGEISTOOLONGFORAQRCODEVERSION3", ErrorCorrectionLevel::H, &hints).expect("encode"); } #[test] fn testSimpleUTF8ECI() { - let hints = HashMap::new(); - hints.put(EncodeHintType::CHARACTER_SET, "UTF8"); - let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints); + let mut hints = HashMap::new(); + hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("UTF8".to_owned())); + let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode"); let expected = r"<< mode: BYTE @@ -183,11 +183,11 @@ r"<< #[test] fn testEncodeKanjiMode() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::CHARACTER_SET, "Shift_JIS"); + hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("Shift_JIS".to_owned())); // Nihon in Kanji - let qrCode = encoder::encode_with_hints("\u{65e5}\u{672c}", ErrorCorrectionLevel::M, hints); + let qrCode = encoder::encode_with_hints("\u{65e5}\u{672c}", ErrorCorrectionLevel::M, &hints).expect("encode"); let expected = r"<< mode: KANJI @@ -223,10 +223,11 @@ r"<< #[test] fn testEncodeShiftjisNumeric() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::CHARACTER_SET, "Shift_JIS"); - let qrCode = encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, hints); + hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("Shift_JIS".to_owned())); + + let qrCode = encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, &hints).expect("encode"); let expected = r"<< mode: NUMERIC @@ -262,47 +263,48 @@ r"<< #[test] fn testEncodeGS1WithStringTypeHint() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::GS1_FORMAT, "true"); - let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, hints); - verifyGS1EncodedData(qrCode); + hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned())); + let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode"); + verifyGS1EncodedData(&qrCode); } #[test] fn testEncodeGS1WithBooleanTypeHint() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::GS1_FORMAT, true); - let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, hints); - verifyGS1EncodedData(qrCode); + hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned())); + let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode"); + verifyGS1EncodedData(&qrCode); } #[test] fn testDoesNotEncodeGS1WhenBooleanTypeHintExplicitlyFalse() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::GS1_FORMAT, false); - let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, hints); - verifyNotGS1EncodedData(qrCode); + hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned())); + + let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); + verifyNotGS1EncodedData(&qrCode); } #[test] fn testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::GS1_FORMAT, "false"); - let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, hints); - verifyNotGS1EncodedData(qrCode); + hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned())); + let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); + verifyNotGS1EncodedData(&qrCode); } #[test] fn testGS1ModeHeaderWithECI() { - let hints = HashMap::new(); + let mut hints = HashMap::new(); - hints.put(EncodeHintType::CHARACTER_SET, "UTF8"); - hints.put(EncodeHintType::GS1_FORMAT, true); - let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, hints); + hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("UTF8".to_owned())); + hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned())); + let qrCode = encoder::encode_with_hints("hello", ErrorCorrectionLevel::H, &hints).expect("encode"); let expected = r"<< mode: BYTE @@ -338,36 +340,36 @@ r"<< #[test] fn testAppendModeInfo() { - let bits = BitArray::new(); - encoder::appendModeInfo(Mode::NUMERIC, bits); + let mut bits = BitArray::new(); + encoder::appendModeInfo(Mode::NUMERIC, &mut bits); assert_eq!(" ...X", bits.to_string()); } #[test] fn testAppendLengthInfo() { - let bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendLengthInfo(1, // 1 letter (1/1). - Version::getVersionForNumber(1), + Version::getVersionForNumber(1).unwrap(), Mode::NUMERIC, - bits); + &mut bits); assert_eq!(" ........ .X", bits.to_string()); // 10 bits. - let bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendLengthInfo(2, // 2 letters (2/1). - Version::getVersionForNumber(10), + Version::getVersionForNumber(10).unwrap(), Mode::ALPHANUMERIC, - bits); + &mut bits); assert_eq!(" ........ .X.", bits.to_string()); // 11 bits. - let bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendLengthInfo(255, // 255 letter (255/1). - Version::getVersionForNumber(27), + Version::getVersionForNumber(27).unwrap(), Mode::BYTE, - bits); + &mut bits); assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits. - let bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendLengthInfo(512, // 512 letters (1024/2). - Version::getVersionForNumber(40), + Version::getVersionForNumber(40).unwrap(), Mode::KANJI, - bits); + &mut bits); assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits. } @@ -375,139 +377,144 @@ r"<< fn testAppendBytes() { // Should use appendNumericBytes. // 1 = 01 = 0001 in 4 bits. - let bits = BitArray::new(); - encoder::appendBytes("1", Mode::NUMERIC, bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + let mut bits = BitArray::new(); + encoder::appendBytes("1", Mode::NUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!(" ...X" , bits.to_string()); // Should use appendAlphanumericBytes. // A = 10 = 0xa = 001010 in 6 bits - let bits = BitArray::new(); - encoder::appendBytes("A", Mode::ALPHANUMERIC, bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + let mut bits = BitArray::new(); + encoder::appendBytes("A", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!(" ..X.X." , bits.to_string()); // Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC. - try { - encoder::appendBytes("a", Mode::ALPHANUMERIC, bits, encoder::DEFAULT_BYTE_MODE_ENCODING); - } catch (WriterException we) { + //try { + if encoder::appendBytes("a", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).is_ok(){ + panic!("should never be ok"); + } + //} catch (WriterException we) { // good - } + //} // Should use append8BitBytes. // 0x61, 0x62, 0x63 - let bits = BitArray::new(); - encoder::appendBytes("abc", Mode::BYTE, bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + let mut bits = BitArray::new(); + encoder::appendBytes("abc", Mode::BYTE, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string()); // Anything can be encoded in QRCode.MODE_8BIT_BYTE. - encoder::appendBytes("\0", Mode::BYTE, bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::appendBytes("\0", Mode::BYTE, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); // Should use appendKanjiBytes. // 0x93, 0x5f - let bits = BitArray::new(); - encoder::appendBytes(&shiftJISString(bytes(0x93, 0x5f)), Mode::KANJI, bits, + let mut bits = BitArray::new(); + encoder::appendBytes(&shiftJISString(&[0x93, 0x5f]), Mode::KANJI, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!(" .XX.XX.. XXXXX", bits.to_string()); } #[test] fn testTerminateBits() { - let v = BitArray::new(); - encoder::terminateBits(0, v); + let mut v = BitArray::new(); + encoder::terminateBits(0, &mut v).expect("terminate"); assert_eq!("", v.to_string()); - let v = BitArray::new(); - encoder::terminateBits(1, v); + let mut v = BitArray::new(); + encoder::terminateBits(1, &mut v).expect("terminate"); assert_eq!(" ........", v.to_string()); - let v = BitArray::new(); - v.appendBits(0, 3); // Append 000 - encoder::terminateBits(1, v); + let mut v = BitArray::new(); + v.appendBits(0, 3).expect("terminate"); // Append 000 + encoder::terminateBits(1, &mut v).expect("terminate"); assert_eq!(" ........", v.to_string()); - let v = BitArray::new(); - v.appendBits(0, 5); // Append 00000 - encoder::terminateBits(1, v); + let mut v = BitArray::new(); + v.appendBits(0, 5).expect("terminate"); // Append 00000 + encoder::terminateBits(1, &mut v).expect("terminate"); assert_eq!(" ........", v.to_string()); - let v = BitArray::new(); - v.appendBits(0, 8); // Append 00000000 - encoder::terminateBits(1, v); + let mut v = BitArray::new(); + v.appendBits(0, 8).expect("terminate"); // Append 00000000 + encoder::terminateBits(1, &mut v).expect("terminate"); assert_eq!(" ........", v.to_string()); - let v = BitArray::new(); - encoder::terminateBits(2, v); + let mut v = BitArray::new(); + encoder::terminateBits(2, &mut v).expect("terminate"); assert_eq!(" ........ XXX.XX..", v.to_string()); - let v = BitArray::new(); - v.appendBits(0, 1); // Append 0 - encoder::terminateBits(3, v); + let mut v = BitArray::new(); + v.appendBits(0, 1).expect("terminate"); // Append 0 + encoder::terminateBits(3, &mut v).expect("terminate"); assert_eq!(" ........ XXX.XX.. ...X...X", v.to_string()); } #[test] fn testGetNumDataBytesAndNumECBytesForBlockID() { - int[] numDataBytes = new int[1]; - int[] numEcBytes = new int[1]; + let mut numDataBytes = vec![0;1]; + let mut numEcBytes = vec![0;1]; // Version 1-H. - encoder::getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, &mut numDataBytes, &mut numEcBytes); assert_eq!(9, numDataBytes[0]); assert_eq!(17, numEcBytes[0]); // Version 3-H. 2 blocks. - encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, &mut numDataBytes, &mut numEcBytes); assert_eq!(13, numDataBytes[0]); assert_eq!(22, numEcBytes[0]); - encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, &mut numDataBytes, &mut numEcBytes); assert_eq!(13, numDataBytes[0]); assert_eq!(22, numEcBytes[0]); // Version 7-H. (4 + 1) blocks. - encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, &mut numDataBytes, &mut numEcBytes); assert_eq!(13, numDataBytes[0]); assert_eq!(26, numEcBytes[0]); - encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, &mut numDataBytes, &mut numEcBytes); assert_eq!(14, numDataBytes[0]); assert_eq!(26, numEcBytes[0]); // Version 40-H. (20 + 61) blocks. - encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, &mut numDataBytes, &mut numEcBytes); assert_eq!(15, numDataBytes[0]); assert_eq!(30, numEcBytes[0]); - encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, &mut numDataBytes, &mut numEcBytes); assert_eq!(16, numDataBytes[0]); assert_eq!(30, numEcBytes[0]); - encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, &mut numDataBytes, &mut numEcBytes); assert_eq!(16, numDataBytes[0]); assert_eq!(30, numEcBytes[0]); } #[test] fn testInterleaveWithECBytes() { - byte[] dataBytes = bytes(32, 65, 205, 69, 41, 220, 46, 128, 236); - BitArray in = new BitArray(); - for (byte dataByte: dataBytes) { - in.appendBits(dataByte, 8); + let dataBytes = &[32u32, 65, 205, 69, 41, 220, 46, 128, 236]; + let mut in_ = BitArray::new(); + for dataByte in dataBytes { + // for (byte dataByte: dataBytes) { + in_.appendBits(*dataByte, 8); } - BitArray out = encoder::interleaveWithECBytes(in, 26, 9, 1); - byte[] expected = bytes( + let out = encoder::interleaveWithECBytes(&in_, 26, 9, 1).expect("encode"); + let expected = &[ // Data bytes. 32, 65, 205, 69, 41, 220, 46, 128, 236, // Error correction bytes. 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 - ); - assert_eq!(expected.length, out.getSizeInBytes()); - byte[] outArray = new byte[expected.length]; - out.toBytes(0, outArray, 0, expected.length); + ]; + assert_eq!(expected.len(), out.getSizeInBytes()); + let mut outArray = vec![0u8;expected.len()]; + out.toBytes(0, &mut outArray, 0, expected.len()); // Can't use Arrays.equals(), because outArray may be longer than out.sizeInBytes() - for (int x = 0; x < expected.length; x++) { + for x in 0..expected.len() { + // for (int x = 0; x < expected.length; x++) { assert_eq!(expected[x], outArray[x]); } // Numbers are from http://www.swetake.com/qr/qr8.html - dataBytes = bytes( - 67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, + let dataBytes = &[ + 67u32, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, 160, 236, 17, 236, 17, 236, 17, 236, 17 - ); - in = new BitArray(); - for (byte dataByte: dataBytes) { - in.appendBits(dataByte, 8); + ]; + in_ = BitArray::new(); + for dataByte in dataBytes{ + // for (byte dataByte: dataBytes) { + in_.appendBits(*dataByte, 8); } - out = encoder::interleaveWithECBytes(in, 134, 62, 4); - expected = bytes( + let out = encoder::interleaveWithECBytes(&in_, 134, 62, 4).expect("interleave ok"); + let expected = &[ // Data bytes. 67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39, 118, 119, 70, 55, 134, 135, 86, 71, 150, 151, 102, 87, 166, @@ -523,11 +530,12 @@ r"<< 211, 164, 117, 30, 158, 225, 31, 190, 242, 38, 140, 61, 179, 154, 214, 138, 147, 87, 27, 96, 77, 47, 187, 49, 156, 214 - ); - assert_eq!(expected.length, out.getSizeInBytes()); - outArray = new byte[expected.length]; - out.toBytes(0, outArray, 0, expected.length); - for (int x = 0; x < expected.length; x++) { + ]; + assert_eq!(expected.len(), out.getSizeInBytes()); + outArray = vec![0u8;expected.len()]; + out.toBytes(0, &mut outArray, 0, expected.len()); + for x in 0..expected.len(){ + // for (int x = 0; x < expected.length; x++) { assert_eq!(expected[x], outArray[x]); } } @@ -544,23 +552,23 @@ r"<< fn testAppendNumericBytes() { // 1 = 01 = 0001 in 4 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("1", bits); + encoder::appendNumericBytes("1", &mut bits); assert_eq!(" ...X" , bits.to_string()); // 12 = 0xc = 0001100 in 7 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("12", bits); + encoder::appendNumericBytes("12", &mut bits); assert_eq!(" ...XX.." , bits.to_string()); // 123 = 0x7b = 0001111011 in 10 bits. let mut bits = BitArray::new(); - encoder::appendNumericBytes("123", bits); + encoder::appendNumericBytes("123", &mut bits); assert_eq!(" ...XXXX. XX" , bits.to_string()); // 1234 = "123" + "4" = 0001111011 + 0100 let mut bits = BitArray::new(); - encoder::appendNumericBytes("1234", bits); + encoder::appendNumericBytes("1234", &mut bits); assert_eq!(" ...XXXX. XX.X.." , bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::appendNumericBytes("", bits); + encoder::appendNumericBytes("", &mut bits); assert_eq!("" , bits.to_string()); } @@ -568,37 +576,39 @@ r"<< fn testAppendAlphanumericBytes() { // A = 10 = 0xa = 001010 in 6 bits let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("A", bits); + encoder::appendAlphanumericBytes("A", &mut bits); assert_eq!(" ..X.X." , bits.to_string()); // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("AB", bits); + encoder::appendAlphanumericBytes("AB", &mut bits); assert_eq!(" ..XXX..X X.X", bits.to_string()); // ABC = "AB" + "C" = 00111001101 + 001100 let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("ABC", bits); + encoder::appendAlphanumericBytes("ABC", &mut bits); assert_eq!(" ..XXX..X X.X..XX. ." , bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::appendAlphanumericBytes("", bits); + encoder::appendAlphanumericBytes("", &mut bits); assert_eq!("" , bits.to_string()); // Invalid data. - try { - encoder::appendAlphanumericBytes("abc", BitArray::new()); - } catch (WriterException we) { + // try { + if encoder::appendAlphanumericBytes("abc", &mut BitArray::new()).is_ok() { + panic!("should not be ok"); + } + // } catch (WriterException we) { // good - } + // } } #[test] fn testAppend8BitBytes() { // 0x61, 0x62, 0x63 let mut bits = BitArray::new(); - encoder::append8BitBytes("abc", bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string()); // Empty. let mut bits = BitArray::new(); - encoder::append8BitBytes("", bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!("", bits.to_string()); } @@ -606,9 +616,9 @@ r"<< #[test] fn testAppendKanjiBytes() { let mut bits = BitArray::new(); - encoder::appendKanjiBytes(shiftJISString(bytes(0x93, 0x5f)), bits); + encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits); assert_eq!(" .XX.XX.. XXXXX", bits.to_string()); - encoder::appendKanjiBytes(shiftJISString(bytes(0xe4, 0xaa)), bits); + encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits); assert_eq!(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.to_string()); } @@ -616,32 +626,35 @@ r"<< // http://www.swetake.com/qr/qr9.html #[test] fn testGenerateECBytes() { - let dataBytes = bytes(32, 65, 205, 69, 41, 220, 46, 128, 236); + let dataBytes = &[32, 65, 205, 69, 41, 220, 46, 128, 236]; let ecBytes = encoder::generateECBytes(dataBytes, 17); let expected = [ 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 ]; - assert_eq!(expected.length, ecBytes.length); - for (int x = 0; x < expected.length; x++) { + assert_eq!(expected.len(), ecBytes.len()); + for x in 0..expected.len() { + // for (int x = 0; x < expected.length; x++) { assert_eq!(expected[x], ecBytes[x] & 0xFF); } - dataBytes = bytes(67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214); - ecBytes = encoder::generateECBytes(dataBytes, 18); - expected = new int[] { + let dataBytes = &[67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214]; + let ecBytes = encoder::generateECBytes(dataBytes, 18); + let expected = &[ 175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187 - }; - assert_eq!(expected.length, ecBytes.length); - for (int x = 0; x < expected.length; x++) { + ]; + assert_eq!(expected.len(), ecBytes.len()); + for x in 0..expected.len() { + // for (int x = 0; x < expected.length; x++) { assert_eq!(expected[x], ecBytes[x] & 0xFF); } // High-order zero coefficient case. - dataBytes = bytes(32, 49, 205, 69, 42, 20, 0, 236, 17); - ecBytes = encoder::generateECBytes(dataBytes, 17); - expected = new int[] { + let dataBytes = &[32, 49, 205, 69, 42, 20, 0, 236, 17]; + let ecBytes = encoder::generateECBytes(dataBytes, 17); + let expected = &[ 0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213 - }; - assert_eq!(expected.length, ecBytes.length); - for (int x = 0; x < expected.length; x++) { + ]; + assert_eq!(expected.len(), ecBytes.len()); + for x in 0..expected.len() { + // for (int x = 0; x < expected.length; x++) { assert_eq!(expected[x], ecBytes[x] & 0xFF); } } @@ -676,12 +689,12 @@ r"<< // - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) = // 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468 // bytes). - let builder = String::with_capacity(3518); + let mut builder = String::with_capacity(3518); for x in 0..3518 { // for (int x = 0; x < 3518; x++) { builder.push('0'); } - encoder::encode(builder.to_string(), ErrorCorrectionLevel::L); + encoder::encode(&builder, ErrorCorrectionLevel::L); } #[test] @@ -841,14 +854,14 @@ r"<< #[test] fn testMinimalEncoder32() { - verifyMinimalEncoding("http://foo.com", "BYTE(http://foo.com)" + - "", None, false); + verifyMinimalEncoding("http://foo.com", "BYTE(http://foo.com)\ + ", None, false); } #[test] fn testMinimalEncoder33() { - verifyMinimalEncoding("HTTP://FOO.COM", "ALPHANUMERIC(HTTP://FOO.COM" + - ")", None, false); + verifyMinimalEncoding("HTTP://FOO.COM", "ALPHANUMERIC(HTTP://FOO.COM\ + )", None, false); } #[test] @@ -874,27 +887,27 @@ r"<< #[test] fn testMinimalEncoder38() { - verifyMinimalEncoding("\u{0150}\u{0150}\u{015C}\u{015C}", "ECI(ISO-8859-2),BYTE(." + - ".),ECI(ISO-8859-3),BYTE(..)", None, false); + verifyMinimalEncoding("\u{0150}\u{0150}\u{015C}\u{015C}", "ECI(ISO-8859-2),BYTE(.\ + .),ECI(ISO-8859-3),BYTE(..)", None, false); } #[test] fn testMinimalEncoder39() { - verifyMinimalEncoding("abcdef\u{0150}ghij", "ECI(ISO-8859-2),BYTE(abcde" + - "f.ghij)", None, false); + verifyMinimalEncoding("abcdef\u{0150}ghij", "ECI(ISO-8859-2),BYTE(abcde\ + f.ghij)", None, false); } #[test] fn testMinimalEncoder40() { verifyMinimalEncoding("2938928329832983\u{0150}2938928329832983\u{015C}2938928329832983", - "NUMERIC(2938928329832983),ECI(ISO-8859-2),BYTE(.),NUMERIC(2938928329832983),ECI(ISO-8" + - "859-3),BYTE(.),NUMERIC(2938928329832983)", None, false); + "NUMERIC(2938928329832983),ECI(ISO-8859-2),BYTE(.),NUMERIC(2938928329832983),ECI(ISO-8\ + 859-3),BYTE(.),NUMERIC(2938928329832983)", None, false); } #[test] fn testMinimalEncoder41() { - verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", "FNC1_FIRST_POSITION(),NUMERIC(100111" + - "4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, + verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", "FNC1_FIRST_POSITION(),NUMERIC(100111\ + 4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, true); } @@ -917,14 +930,14 @@ r"<< // The character \u30A2 encodes as double byte in Shift_JIS but KANJI is not more compact in this case because // KANJI is only more compact when it encodes pairs of characters. In the case of mixed text it can however be // that Shift_JIS encoding is more compact as in this example - verifyMinimalEncoding("Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}", "ECI(Shift_JIS),BYTE(Katakana:.a.a.a" + - ".a.a.)", None, false); + verifyMinimalEncoding("Katakana:\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}a\u{30A2}", "ECI(Shift_JIS),BYTE(Katakana:.a.a.a\ + .a.a.)", None, false); } fn verifyMinimalEncoding( input:&str, expectedRXingResult:&str, priorityCharset:Option, isGS1:bool) { - let result = Minimalencoder::encode(input, None, priorityCharset, isGS1, - ErrorCorrectionLevel::L); + let result = MinimalEncoder::encode_with_details(input, None, priorityCharset.unwrap_or(encoding::all::ISO_8859_1), isGS1, + ErrorCorrectionLevel::L).expect("encode"); assert_eq!(result.to_string(), expectedRXingResult); } diff --git a/src/qrcode/encoder/encoder.rs b/src/qrcode/encoder/encoder.rs index ff33001..b21912e 100644 --- a/src/qrcode/encoder/encoder.rs +++ b/src/qrcode/encoder/encoder.rs @@ -70,7 +70,7 @@ const ALPHANUMERIC_TABLE: [i8; 96] = [ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f ]; -const DEFAULT_BYTE_MODE_ENCODING: EncodingRef = encoding::all::ISO_8859_1; +pub const DEFAULT_BYTE_MODE_ENCODING: EncodingRef = encoding::all::ISO_8859_1; // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. // Basically it applies four rules and summate all penalties. @@ -89,13 +89,13 @@ pub fn calculateMaskPenalty(matrix: &ByteMatrix) -> u32 { * or configuration */ pub fn encode(content: &str, ecLevel: ErrorCorrectionLevel) -> Result { - return encode_with_hints(content, ecLevel, HashMap::new()); + return encode_with_hints(content, ecLevel, &HashMap::new()); } pub fn encode_with_hints( content: &str, ecLevel: ErrorCorrectionLevel, - hints: EncodingHintDictionary, + hints: &EncodingHintDictionary, ) -> Result { let version; let mut headerAndDataBits; @@ -431,8 +431,8 @@ pub fn willFit(numInputBits: u32, version: VersionRef, ecLevel: &ErrorCorrection /** * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). */ -pub fn terminateBits(numDataBytes: u32, bits: &mut BitArray) -> Result<(), Exceptions> { - let capacity = numDataBytes * 8; +pub fn terminateBits(num_data_bytes: u32, bits: &mut BitArray) -> Result<(), Exceptions> { + let capacity = num_data_bytes * 8; if bits.getSize() > capacity as usize { return Err(Exceptions::WriterException(format!( "data bits cannot fit in the QR Code{} > ", @@ -442,8 +442,8 @@ pub fn terminateBits(numDataBytes: u32, bits: &mut BitArray) -> Result<(), Excep // capacity); } // Append Mode.TERMINATE if there is enough space (value is 0000) - for i in 0..4 { - if bits.getSize() > 0 { + for _i in 0..4 { + if bits.getSize() >= capacity as usize { break; } // } @@ -452,18 +452,19 @@ pub fn terminateBits(numDataBytes: u32, bits: &mut BitArray) -> Result<(), Excep } // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. // If the last byte isn't 8-bit aligned, we'll add padding bits. - let numBitsInLastByte = bits.getSize() & 0x07; - if numBitsInLastByte > 0 { - for i in numBitsInLastByte..8 { + let num_bits_in_last_byte = bits.getSize() & 0x07; + if num_bits_in_last_byte > 0 { + for _i in num_bits_in_last_byte..8 { // for (int i = numBitsInLastByte; i < 8; i++) { bits.appendBit(false); } } // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). - let numPaddingBytes = numDataBytes as usize - bits.getSizeInBytes(); - for i in 0..numPaddingBytes { + let num_padding_bytes = num_data_bytes as isize - bits.getSizeInBytes() as isize; + for i in 0..num_padding_bytes { + if i >= num_padding_bytes{ break } // for (int i = 0; i < numPaddingBytes; ++i) { - bits.appendBits(if (i & 0x01) == 0 { 0xEC } else { 0x11 }, 8); + bits.appendBits(if (i & 0x01) == 0 { 0xEC } else { 0x11 }, 8)?; } if bits.getSize() != capacity as usize { return Err(Exceptions::WriterException( @@ -757,22 +758,22 @@ pub fn appendAlphanumericBytes(content: &str, bits: &mut BitArray) -> Result<(), } if i + 1 < length { let code2 = getAlphanumericCode(content.chars().nth(i + 1).unwrap() as u32); - if (code2 == -1) { + if code2 == -1 { return Err(Exceptions::WriterException("".to_owned())); } // Encode two alphanumeric letters in 11 bits. - bits.appendBits((code1 * 45 + code2) as u32, 11); + bits.appendBits((code1 as i16 * 45 + code2 as i16) as u32, 11)?; i += 2; } else { // Encode one alphanumeric letter in six bits. - bits.appendBits(code1 as u32, 6); + bits.appendBits(code1 as u32, 6)?; i += 1; } } Ok(()) } -fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) { +pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) { let bytes = encoding .encode(content, encoding::EncoderTrap::Strict) .expect("should encode"); @@ -783,7 +784,7 @@ fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) { } } -fn appendKanjiBytes(content: &str, bits: &mut BitArray) -> Result<(), Exceptions> { +pub fn appendKanjiBytes(content: &str, bits: &mut BitArray) -> Result<(), Exceptions> { let sjis = &SHIFT_JIS_CHARSET; //encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); let bytes = sjis diff --git a/src/qrcode/encoder/minimal_encoder.rs b/src/qrcode/encoder/minimal_encoder.rs index cef8ff9..aa09180 100644 --- a/src/qrcode/encoder/minimal_encoder.rs +++ b/src/qrcode/encoder/minimal_encoder.rs @@ -108,7 +108,7 @@ impl MinimalEncoder { priorityCharset: EncodingRef, isGS1: bool, ecLevel: ErrorCorrectionLevel, - ) -> Self { + ) -> Self { Self { stringToEncode: String::from(stringToEncode), isGS1, @@ -553,7 +553,7 @@ impl MinimalEncoder { for k in 0..4 { // for (int k = 0; k < 4; k++) { if edges[i][j][k].is_some() && i < inputLength { - let e = edges[i][j][k].clone(); + let e = edges[i][j][k].clone(); self.addEdges(version, &mut edges, i, e); } } @@ -584,7 +584,10 @@ impl MinimalEncoder { } Ok(RXingResultList::new( version, - edges[inputLength][minimalJ.unwrap()][minimalK.unwrap()].as_ref().unwrap().clone(), + edges[inputLength][minimalJ.unwrap()][minimalK.unwrap()] + .as_ref() + .unwrap() + .clone(), self.isGS1, &self.ecLevel, self.encoders.clone(), @@ -807,18 +810,19 @@ impl RXingResultList { )); } } - let first = list.get(0).unwrap(); + let first = list.get(0); // prepend or insert a FNC1_FIRST_POSITION after the ECI (if any) - // if first != null && first.mode != Mode.ECI && containsECI { - list.push(RXingResultNode::new( - Mode::FNC1_FIRST_POSITION, - 0, - 0, - 0, - encoders.clone(), - stringToEncode, - version, - )); + if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI && containsECI { + list.push(RXingResultNode::new( + Mode::FNC1_FIRST_POSITION, + 0, + 0, + 0, + encoders.clone(), + stringToEncode, + version, + )); + } } // set version to smallest version into which the bits fit. @@ -867,6 +871,7 @@ impl RXingResultList { versionNumber -= 1; } let version = Version::getVersionForNumber(versionNumber).unwrap(); + list.reverse(); Self { list, version } }