From 86f6bd0c690a6db08a2ba341193ab5106c174b41 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Tue, 4 Oct 2022 18:08:19 -0500 Subject: [PATCH] only 13 failing encoder tests --- Cargo.toml | 3 +- src/common/mod.rs | 74 +- src/qrcode/encoder/EncoderTestCase.rs | 1104 +++++++++++++++---------- src/qrcode/encoder/encoder.rs | 11 +- src/qrcode/encoder/minimal_encoder.rs | 184 +++-- 5 files changed, 823 insertions(+), 553 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1002671..5892a3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,10 +20,11 @@ chrono = "0.4" chrono-tz = "0.4" image = {version = "0.24.3", optional = true} imageproc = {version = "0.23.0", optional = true} +unicode-segmentation = "1.10.0" [dev-dependencies] java-properties = "1.4.1" [features] default = ["image"] -image = ["dep:image", "dep:imageproc"] \ No newline at end of file +image = ["dep:image", "dep:imageproc"] diff --git a/src/common/mod.rs b/src/common/mod.rs index 9ca5dab..a1d3cd2 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -18,6 +18,8 @@ use encoding::EncodingRef; use lazy_static::lazy_static; +use unicode_segmentation::UnicodeSegmentation; + #[cfg(test)] mod StringUtilsTestCase; @@ -2920,7 +2922,7 @@ 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(stringToEncodeMain: &str, priorityCharset: EncodingRef, fnc1: Option<&str>) -> Self { // List of encoders that potentially encode characters not in ISO-8859-1 in one byte. let mut encoders: Vec; @@ -2928,20 +2930,22 @@ impl ECIEncoderSet { let mut neededEncoders: Vec = Vec::new(); + let stringToEncode = stringToEncodeMain.graphemes(true).collect::>(); + //we always need the ISO-8859-1 encoder. It is the default encoding neededEncoders.push(encoding::all::ISO_8859_1); 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 - for i in 0..stringToEncode.chars().count() { + for i in 0..stringToEncode.len() { // for (int i = 0; i < stringToEncode.length(); i++) { let mut canEncode = false; for encoder in &neededEncoders { // for (CharsetEncoder encoder : neededEncoders) { - let c = stringToEncode.chars().nth(i).unwrap(); - if c == fnc1 as u8 as char + let c = stringToEncode.get(i).unwrap(); + if (fnc1.is_some() && c == fnc1.as_ref().unwrap()) || encoder - .encode(&c.to_string(), encoding::EncoderTrap::Strict) + .encode(c, encoding::EncoderTrap::Strict) .is_ok() { canEncode = true; @@ -2950,13 +2954,13 @@ impl ECIEncoderSet { } if !canEncode { //for the character at position i we don't yet have an encoder in the list - for i in 0..ENCODERS.len() { + for i_encoder in 0..ENCODERS.len() { // for encoder in ENCODERS { - let encoder = ENCODERS.get(i).unwrap(); + let encoder = ENCODERS.get(i_encoder).unwrap(); // for (CharsetEncoder encoder : ENCODERS) { if encoder .encode( - &stringToEncode.chars().nth(i).unwrap().to_string(), + &stringToEncode.get(i).unwrap(), encoding::EncoderTrap::Strict, ) .is_ok() @@ -3044,15 +3048,15 @@ impl ECIEncoderSet { return self.priorityEncoderIndex; } - pub fn canEncode(&self, c: i16, encoderIndex: usize) -> bool { + pub fn canEncode(&self, c: &str, encoderIndex: usize) -> bool { assert!(encoderIndex < self.len()); let encoder = self.encoders[encoderIndex]; - let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict); + let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict); enc_data.is_ok() } - pub fn encode_char(&self, c: char, encoderIndex: usize) -> Vec { + pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Vec { assert!(encoderIndex < self.len()); let encoder = self.encoders[encoderIndex]; let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict); @@ -3101,7 +3105,7 @@ static COST_PER_ECI: usize = 3; */ pub struct MinimalECIInput { bytes: Vec, - fnc1: i16, + fnc1: u16, } impl ECIInput for MinimalECIInput { @@ -3260,28 +3264,29 @@ impl MinimalECIInput { * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1 * input. */ - pub fn new(stringToEncode: &str, priorityCharset: EncodingRef, fnc1: i16) -> Self { - let encoderSet = ECIEncoderSet::new(stringToEncode, priorityCharset, fnc1); + pub fn new(stringToEncodeInput: &str, priorityCharset: EncodingRef, fnc1: Option<&str>) -> Self { + let stringToEncode = stringToEncodeInput.graphemes(true).collect::>(); + let encoderSet = ECIEncoderSet::new(stringToEncodeInput, priorityCharset, fnc1); let bytes = if encoderSet.len() == 1 { //optimization for the case when all can be encoded without ECI in ISO-8859-1 let mut bytes_hld = vec![0; stringToEncode.len()]; for i in 0..stringToEncode.len() { // for (int i = 0; i < bytes.length; i++) { - let c = stringToEncode.chars().nth(i).unwrap(); - bytes_hld[i] = if c as i16 == fnc1 { 1000 } else { c as u16 }; + let c = stringToEncode.get(i).unwrap(); + bytes_hld[i] = if fnc1.is_some() && c == fnc1.as_ref().unwrap() { 1000 } else { c.chars().nth(0).unwrap() as u16 }; } bytes_hld } else { - Self::encodeMinimally(stringToEncode, &encoderSet, fnc1) + Self::encodeMinimally(stringToEncodeInput, &encoderSet, fnc1.as_ref().unwrap().chars().nth(0).unwrap() as u16) }; Self { bytes: bytes, - fnc1: fnc1, + fnc1: fnc1.as_ref().unwrap().chars().nth(0).unwrap() as u16, } } - pub fn getFNC1Character(&self) -> i16 { + pub fn getFNC1Character(&self) -> u16 { self.fnc1 } @@ -3321,14 +3326,15 @@ impl MinimalECIInput { edges: &mut Vec>>>, from: usize, previous: Option>, - fnc1: i16, + fnc1: u16, ) { - let ch = stringToEncode.chars().nth(from).unwrap() as i16; + // let ch = stringToEncode.chars().nth(from).unwrap() as i16; + let ch = stringToEncode.graphemes(true).nth(from).unwrap(); let mut start = 0; let mut end = encoderSet.len(); if encoderSet.getPriorityEncoderIndex() >= 0 - && (ch as i16 == fnc1 || encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex())) + && (ch.chars().nth(0).unwrap() as u16 == fnc1 || encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex())) { start = encoderSet.getPriorityEncoderIndex(); end = start + 1; @@ -3336,7 +3342,7 @@ impl MinimalECIInput { for i in start..end { // for (int i = start; i < end; i++) { - if ch as i16 == fnc1 || encoderSet.canEncode(ch, i) { + if ch.chars().nth(0).unwrap() as u16 == fnc1 || encoderSet.canEncode(ch, i) { Self::addEdge( edges, from + 1, @@ -3349,7 +3355,7 @@ impl MinimalECIInput { pub fn encodeMinimally( stringToEncode: &str, encoderSet: &ECIEncoderSet, - fnc1: i16, + fnc1: u16, ) -> Vec { let inputLength = stringToEncode.len(); @@ -3395,7 +3401,7 @@ impl MinimalECIInput { intsAL.splice(0..0, [1000]); } else { let bytes: Vec = encoderSet - .encode_char(c.c as u8 as char, c.encoderIndex) + .encode_char(&c.c , c.encoderIndex) .iter() .map(|x| *x as u16) .collect(); @@ -3429,25 +3435,27 @@ impl MinimalECIInput { } struct InputEdge { - c: i16, + c: String, encoderIndex: usize, //the encoding of this edge previous: Option>, cachedTotalSize: usize, } impl InputEdge { pub fn new( - c: i16, + c: &str, encoderSet: &ECIEncoderSet, encoderIndex: usize, previous: Option>, - fnc1: i16, + fnc1: u16, ) -> Self { - let mut size = if c == 1000 { + let mut size = if c == "\u{1000}" { 1 } else { - encoderSet.encode_char(c as u8 as char, encoderIndex).len() + encoderSet.encode_char(c, encoderIndex).len() }; + let fnc1Str = String::from_utf16(&[fnc1]).unwrap(); + if let Some(prev) = previous { let previousEncoderIndex = prev.encoderIndex; if previousEncoderIndex != encoderIndex { @@ -3456,7 +3464,7 @@ impl InputEdge { size += prev.cachedTotalSize; Self { - c: if c as i16 == fnc1 { 1000 } else { c as i16 }, + c: if c == fnc1Str { String::from("\u{1000}") } else { String::from(c) }, encoderIndex, previous: Some(prev.clone()), cachedTotalSize: size, @@ -3468,7 +3476,7 @@ impl InputEdge { } Self { - c: if c as i16 == fnc1 { 1000 } else { c as i16 }, + c: if c == fnc1Str { String::from("\u{1000}") } else { String::from(c) }, encoderIndex, previous: None, cachedTotalSize: size, @@ -3502,7 +3510,7 @@ impl InputEdge { } pub fn isFNC1(&self) -> bool { - self.c == 1000 + self.c == "\u{1000}" } } diff --git a/src/qrcode/encoder/EncoderTestCase.rs b/src/qrcode/encoder/EncoderTestCase.rs index 766beda..4a91eca 100644 --- a/src/qrcode/encoder/EncoderTestCase.rs +++ b/src/qrcode/encoder/EncoderTestCase.rs @@ -16,15 +16,22 @@ use std::collections::HashMap; -use crate::{qrcode::{encoder::{encoder, MinimalEncoder}, decoder::{Mode, ErrorCorrectionLevel, Version}}, EncodeHintType, EncodeHintValue, common::BitArray}; +use crate::{ + common::BitArray, + qrcode::{ + decoder::{ErrorCorrectionLevel, Mode, Version}, + encoder::{encoder, MinimalEncoder}, + }, + EncodeHintType, EncodeHintValue, +}; use encoding::EncodingRef; use lazy_static::lazy_static; use super::QRCode; lazy_static! { - static ref SHIFT_JIS_CHARSET: EncodingRef = - encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); + static ref SHIFT_JIS_CHARSET: EncodingRef = + encoding::label::encoding_from_whatwg_label("SJIS").unwrap(); } /** @@ -32,18 +39,21 @@ lazy_static! { * @author mysen@google.com (Chris Mysen) - ported from C++ */ - #[test] - fn testGetAlphanumericCode() { +#[test] +fn testGetAlphanumericCode() { // The first ten code points are numbers. for i in 0..10u8 { - // for (int i = 0; i < 10; ++i) { - assert_eq!(i as i8, encoder::getAlphanumericCode((b'0' + i) as u32)); + // for (int i = 0; i < 10; ++i) { + assert_eq!(i as i8, encoder::getAlphanumericCode((b'0' + i) as u32)); } // The next 26 code points are capital alphabet letters. for i in 10..36 { - // for (int i = 10; i < 36; ++i) { - assert_eq!(i as i8, encoder::getAlphanumericCode((b'A' + i - 10) as u32)); + // for (int i = 10; i < 36; ++i) { + assert_eq!( + i as i8, + encoder::getAlphanumericCode((b'A' + i - 10) as u32) + ); } // Others are symbol letters @@ -61,17 +71,19 @@ lazy_static! { assert_eq!(-1, encoder::getAlphanumericCode(b'a' as u32)); assert_eq!(-1, encoder::getAlphanumericCode(b'#' as u32)); assert_eq!(-1, encoder::getAlphanumericCode(b'\0' as u32)); - } +} - #[test] - fn testChooseMode() { +#[test] +fn testChooseMode() { // Numeric Mode:: assert_eq!(Mode::NUMERIC, encoder::chooseMode("0")); assert_eq!(Mode::NUMERIC, encoder::chooseMode("0123456789")); // Alphanumeric Mode:: assert_eq!(Mode::ALPHANUMERIC, encoder::chooseMode("A")); - assert_eq!(Mode::ALPHANUMERIC, - encoder::chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")); + assert_eq!( + Mode::ALPHANUMERIC, + encoder::chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:") + ); // 8-bit byte Mode:: assert_eq!(Mode::BYTE, encoder::chooseMode("a")); assert_eq!(Mode::BYTE, encoder::chooseMode("#")); @@ -81,21 +93,28 @@ lazy_static! { // from data bytes alone. See also comments in qrcode_encoder::h. // AIUE in Hiragana in Shift_JIS - assert_eq!(Mode::BYTE, - encoder::chooseMode(&shiftJISString(&[0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6]))); + assert_eq!( + Mode::BYTE, + encoder::chooseMode(&shiftJISString(&[0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6])) + ); // Nihon in Kanji in Shift_JIS. - assert_eq!(Mode::BYTE, encoder::chooseMode(&shiftJISString(&[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(&[0xe, 0x4, 0x9, 0x5, 0x9, 0x61]))); - } + assert_eq!( + Mode::BYTE, + encoder::chooseMode(&shiftJISString(&[0xe, 0x4, 0x9, 0x5, 0x9, 0x61])) + ); +} - #[test] - fn testEncode() { +#[test] +fn testEncode() { let qrCode = encoder::encode("ABCDEF", ErrorCorrectionLevel::H).expect("encode"); - let expected = -r"<< + let expected = r"<< mode: ALPHANUMERIC ecLevel: H version: 1 @@ -125,31 +144,46 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - #[test] - fn testEncodeWithVersion() { +#[test] +fn testEncodeWithVersion() { 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"); + 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")); - } +} - #[test] - #[should_panic] - fn testEncodeWithVersionTooSmall() { - 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] +#[should_panic] +fn testEncodeWithVersionTooSmall() { + 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 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"<< +#[test] +fn testSimpleutf8ECI() { + 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 ecLevel: H version: 1 @@ -179,17 +213,20 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - #[test] - fn testEncodeKanjiMode() { - let mut hints = HashMap::new(); +#[test] +fn testEncodeKanjiMode() { + let mut hints = HashMap::new(); - hints.insert(EncodeHintType::CHARACTER_SET, EncodeHintValue::CharacterSet("Shift_JIS".to_owned())); + 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).expect("encode"); - let expected = -r"<< + let qrCode = encoder::encode_with_hints("\u{65e5}\u{672c}", ErrorCorrectionLevel::M, &hints) + .expect("encode"); + let expected = r"<< mode: KANJI ecLevel: M version: 1 @@ -219,17 +256,20 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - #[test] - fn testEncodeShiftjisNumeric() { - let mut hints = HashMap::new(); +#[test] +fn testEncodeShiftjisNumeric() { + let mut hints = HashMap::new(); - 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"<< + 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 ecLevel: M version: 1 @@ -259,54 +299,76 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - #[test] - fn testEncodeGS1WithStringTypeHint() { - let mut hints = HashMap::new(); +#[test] +fn testEncodeGS1WithStringTypeHint() { + let mut hints = HashMap::new(); - hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned())); - let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode"); + 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 mut hints = HashMap::new(); +#[test] +fn testEncodeGS1WithBooleanTypeHint() { + let mut hints = HashMap::new(); - hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("true".to_owned())); - let qrCode = encoder::encode_with_hints("100001%11171218", ErrorCorrectionLevel::H, &hints).expect("encode"); + 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 mut hints = HashMap::new(); +#[test] +fn testDoesNotEncodeGS1WhenBooleanTypeHintExplicitlyFalse() { + let mut hints = HashMap::new(); - hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned())); + hints.insert( + EncodeHintType::GS1_FORMAT, + EncodeHintValue::Gs1Format("false".to_owned()), + ); - let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); + let qrCode = + encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); verifyNotGS1EncodedData(&qrCode); - } +} - #[test] - fn testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() { - let mut hints = HashMap::new(); +#[test] +fn testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() { + let mut hints = HashMap::new(); - hints.insert(EncodeHintType::GS1_FORMAT, EncodeHintValue::Gs1Format("false".to_owned())); - let qrCode = encoder::encode_with_hints("ABCDEF", ErrorCorrectionLevel::H, &hints).expect("encode"); + 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 mut hints = HashMap::new(); +#[test] +fn testGS1ModeHeaderWithECI() { + let mut hints = HashMap::new(); - 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"<< + 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 ecLevel: H version: 1 @@ -336,331 +398,418 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - #[test] - fn testAppendModeInfo() { - let mut bits = BitArray::new(); +#[test] +fn testAppendModeInfo() { + let mut bits = BitArray::new(); encoder::appendModeInfo(Mode::NUMERIC, &mut bits); assert_eq!(" ...X", bits.to_string()); - } +} - #[test] - fn testAppendLengthInfo() { - let mut bits = BitArray::new(); - encoder::appendLengthInfo(1, // 1 letter (1/1). - Version::getVersionForNumber(1).unwrap(), - Mode::NUMERIC, - &mut bits); - assert_eq!(" ........ .X", bits.to_string()); // 10 bits. - let mut bits = BitArray::new(); - encoder::appendLengthInfo(2, // 2 letters (2/1). - Version::getVersionForNumber(10).unwrap(), - Mode::ALPHANUMERIC, - &mut bits); - assert_eq!(" ........ .X.", bits.to_string()); // 11 bits. - let mut bits = BitArray::new(); - encoder::appendLengthInfo(255, // 255 letter (255/1). - Version::getVersionForNumber(27).unwrap(), - Mode::BYTE, - &mut bits); - assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits. - let mut bits = BitArray::new(); - encoder::appendLengthInfo(512, // 512 letters (1024/2). - Version::getVersionForNumber(40).unwrap(), - Mode::KANJI, - &mut bits); - assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits. - } +#[test] +fn testAppendLengthInfo() { + let mut bits = BitArray::new(); + encoder::appendLengthInfo( + 1, // 1 letter (1/1). + Version::getVersionForNumber(1).unwrap(), + Mode::NUMERIC, + &mut bits, + ); + assert_eq!(" ........ .X", bits.to_string()); // 10 bits. + let mut bits = BitArray::new(); + encoder::appendLengthInfo( + 2, // 2 letters (2/1). + Version::getVersionForNumber(10).unwrap(), + Mode::ALPHANUMERIC, + &mut bits, + ); + assert_eq!(" ........ .X.", bits.to_string()); // 11 bits. + let mut bits = BitArray::new(); + encoder::appendLengthInfo( + 255, // 255 letter (255/1). + Version::getVersionForNumber(27).unwrap(), + Mode::BYTE, + &mut bits, + ); + assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits. + let mut bits = BitArray::new(); + encoder::appendLengthInfo( + 512, // 512 letters (1024/2). + Version::getVersionForNumber(40).unwrap(), + Mode::KANJI, + &mut bits, + ); + assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits. +} - #[test] - fn testAppendBytes() { +#[test] +fn testAppendBytes() { // Should use appendNumericBytes. // 1 = 01 = 0001 in 4 bits. - let mut bits = BitArray::new(); - encoder::appendBytes("1", Mode::NUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); - assert_eq!(" ...X" , bits.to_string()); + 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 mut bits = BitArray::new(); - encoder::appendBytes("A", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); - assert_eq!(" ..X.X." , bits.to_string()); + 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 { - if encoder::appendBytes("a", Mode::ALPHANUMERIC, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).is_ok(){ + if encoder::appendBytes( + "a", + Mode::ALPHANUMERIC, + &mut bits, + encoder::DEFAULT_BYTE_MODE_ENCODING, + ) + .is_ok() + { panic!("should never be ok"); - } + } //} catch (WriterException we) { - // good + // good //} // Should use append8BitBytes. // 0x61, 0x62, 0x63 - let mut bits = BitArray::new(); - encoder::appendBytes("abc", Mode::BYTE, &mut 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, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); + encoder::appendBytes( + "\0", + Mode::BYTE, + &mut bits, + encoder::DEFAULT_BYTE_MODE_ENCODING, + ); // Should use appendKanjiBytes. // 0x93, 0x5f - let mut bits = BitArray::new(); - encoder::appendBytes(&shiftJISString(&[0x93, 0x5f]), Mode::KANJI, &mut bits, - encoder::DEFAULT_BYTE_MODE_ENCODING); + 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 mut v = BitArray::new(); +#[test] +fn testTerminateBits() { + let mut v = BitArray::new(); encoder::terminateBits(0, &mut v).expect("terminate"); assert_eq!("", v.to_string()); - let mut v = BitArray::new(); + let mut v = BitArray::new(); encoder::terminateBits(1, &mut v).expect("terminate"); assert_eq!(" ........", v.to_string()); - let mut v = BitArray::new(); - v.appendBits(0, 3).expect("terminate"); // Append 000 + 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 mut v = BitArray::new(); - v.appendBits(0, 5).expect("terminate"); // Append 00000 + 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 mut v = BitArray::new(); - v.appendBits(0, 8).expect("terminate"); // Append 00000000 + 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 mut v = BitArray::new(); + let mut v = BitArray::new(); encoder::terminateBits(2, &mut v).expect("terminate"); assert_eq!(" ........ XXX.XX..", v.to_string()); - let mut v = BitArray::new(); - v.appendBits(0, 1).expect("terminate"); // Append 0 + 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() { - let mut numDataBytes = vec![0;1]; - let mut numEcBytes = vec![0;1]; +#[test] +fn testGetNumDataBytesAndNumECBytesForBlockID() { + let mut numDataBytes = vec![0; 1]; + let mut numEcBytes = vec![0; 1]; // Version 1-H. - encoder::getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut 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, &mut numDataBytes, &mut numEcBytes); + encoder::getNumDataBytesAndNumECBytesForBlockID( + 3706, + 1276, + 81, + 80, + &mut numDataBytes, + &mut numEcBytes, + ); assert_eq!(16, numDataBytes[0]); assert_eq!(30, numEcBytes[0]); - } +} - #[test] - fn testInterleaveWithECBytes() { +#[test] +fn testInterleaveWithECBytes() { 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); + // for (byte dataByte: dataBytes) { + in_.appendBits(*dataByte, 8); } 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 + 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.len(), out.getSizeInBytes()); - let mut outArray = vec![0u8;expected.len()]; + 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 x in 0..expected.len() { - // for (int x = 0; x < expected.length; x++) { - assert_eq!(expected[x], outArray[x]); + // for (int x = 0; x < expected.length; x++) { + assert_eq!(expected[x], outArray[x]); } // Numbers are from http://www.swetake.com/qr/qr8.html 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 + 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_ = BitArray::new(); - for dataByte in dataBytes{ - // for (byte dataByte: dataBytes) { - in_.appendBits(*dataByte, 8); + in_ = BitArray::new(); + for dataByte in dataBytes { + // for (byte dataByte: dataBytes) { + in_.appendBits(*dataByte, 8); } 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, - 160, 118, 103, 182, 236, 134, 119, 198, 17, 150, - 135, 214, 236, 166, 151, 230, 17, 182, - 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39, - 17, - // Error correction bytes. - 175, 155, 245, 236, 80, 146, 56, 74, 155, 165, - 133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45, - 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, - 190, 82, 51, 209, 199, 171, 54, 12, 112, 57, 113, 155, 117, - 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 + 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, 160, 118, 103, 182, 236, 134, 119, 198, 17, 150, + 135, 214, 236, 166, 151, 230, 17, 182, 166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39, + 17, // Error correction bytes. + 175, 155, 245, 236, 80, 146, 56, 74, 155, 165, 133, 142, 64, 183, 132, 13, 178, 54, 132, + 108, 45, 113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65, 190, 82, 51, 209, 199, 171, + 54, 12, 112, 57, 113, 155, 117, 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.len(), out.getSizeInBytes()); - outArray = vec![0u8;expected.len()]; + 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]); + for x in 0..expected.len() { + // for (int x = 0; x < expected.length; x++) { + assert_eq!(expected[x], outArray[x]); } - } +} - // fn bytes(int... ints) -> Vec{ - // byte[] bytes = new byte[ints.length]; - // for (int i = 0; i < ints.length; i++) { - // bytes[i] = (byte) ints[i]; - // } - // return bytes; - // } +// fn bytes(int... ints) -> Vec{ +// byte[] bytes = new byte[ints.length]; +// for (int i = 0; i < ints.length; i++) { +// bytes[i] = (byte) ints[i]; +// } +// return bytes; +// } - #[test] - fn testAppendNumericBytes() { +#[test] +fn testAppendNumericBytes() { // 1 = 01 = 0001 in 4 bits. - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendNumericBytes("1", &mut bits); - assert_eq!(" ...X" , bits.to_string()); + assert_eq!(" ...X", bits.to_string()); // 12 = 0xc = 0001100 in 7 bits. - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendNumericBytes("12", &mut bits); - assert_eq!(" ...XX.." , bits.to_string()); + assert_eq!(" ...XX..", bits.to_string()); // 123 = 0x7b = 0001111011 in 10 bits. - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendNumericBytes("123", &mut bits); - assert_eq!(" ...XXXX. XX" , bits.to_string()); + assert_eq!(" ...XXXX. XX", bits.to_string()); // 1234 = "123" + "4" = 0001111011 + 0100 - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendNumericBytes("1234", &mut bits); - assert_eq!(" ...XXXX. XX.X.." , bits.to_string()); + assert_eq!(" ...XXXX. XX.X..", bits.to_string()); // Empty. - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendNumericBytes("", &mut bits); - assert_eq!("" , bits.to_string()); - } + assert_eq!("", bits.to_string()); +} - #[test] - fn testAppendAlphanumericBytes() { +#[test] +fn testAppendAlphanumericBytes() { // A = 10 = 0xa = 001010 in 6 bits - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendAlphanumericBytes("A", &mut bits); - assert_eq!(" ..X.X." , bits.to_string()); + assert_eq!(" ..X.X.", bits.to_string()); // AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendAlphanumericBytes("AB", &mut bits); assert_eq!(" ..XXX..X X.X", bits.to_string()); // ABC = "AB" + "C" = 00111001101 + 001100 - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendAlphanumericBytes("ABC", &mut bits); - assert_eq!(" ..XXX..X X.X..XX. ." , bits.to_string()); + assert_eq!(" ..XXX..X X.X..XX. .", bits.to_string()); // Empty. - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); encoder::appendAlphanumericBytes("", &mut bits); - assert_eq!("" , bits.to_string()); + assert_eq!("", bits.to_string()); // Invalid data. // try { - if encoder::appendAlphanumericBytes("abc", &mut BitArray::new()).is_ok() { + if encoder::appendAlphanumericBytes("abc", &mut BitArray::new()).is_ok() { panic!("should not be ok"); - } + } // } catch (WriterException we) { - // good + // good // } - } +} - #[test] - fn testAppend8BitBytes() { +#[test] +fn testAppend8BitBytes() { // 0x61, 0x62, 0x63 - let mut bits = BitArray::new(); + let mut bits = BitArray::new(); 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(); + let mut bits = BitArray::new(); encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING); assert_eq!("", bits.to_string()); - } +} - // Numbers are from page 21 of JISX0510:2004 - #[test] - fn testAppendKanjiBytes() { - let mut bits = BitArray::new(); +// Numbers are from page 21 of JISX0510:2004 +#[test] +fn testAppendKanjiBytes() { + let mut bits = BitArray::new(); encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits); assert_eq!(" .XX.XX.. XXXXX", bits.to_string()); encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits); assert_eq!(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.to_string()); - } +} - // Numbers are from http://www.swetake.com/qr/qr3.html and - // http://www.swetake.com/qr/qr9.html - #[test] - fn testGenerateECBytes() { +// Numbers are from http://www.swetake.com/qr/qr3.html and +// http://www.swetake.com/qr/qr9.html +#[test] +fn testGenerateECBytes() { 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 + 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61, ]; 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); + // for (int x = 0; x < expected.length; x++) { + assert_eq!(expected[x], ecBytes[x] & 0xFF); } - let dataBytes = &[67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214]; + 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 + 175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187, ]; 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); + // for (int x = 0; x < expected.length; x++) { + assert_eq!(expected[x], ecBytes[x] & 0xFF); } // High-order zero coefficient case. 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 + 0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213, ]; 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); + // for (int x = 0; x < expected.length; x++) { + assert_eq!(expected[x], ecBytes[x] & 0xFF); } - } +} - #[test] - fn testBugInBitVectorNumBytes() { +#[test] +fn testBugInBitVectorNumBytes() { // There was a bug in BitVector.sizeInBytes() that caused it to return a // smaller-by-one value (ex. 1465 instead of 1466) if the number of bits // in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(), @@ -689,261 +838,319 @@ 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 mut 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'); + // for (int x = 0; x < 3518; x++) { + builder.push('0'); } encoder::encode(&builder, ErrorCorrectionLevel::L); - } +} - #[test] - fn testMinimalEncoder1() { +#[test] +fn testMinimalEncoder1() { verifyMinimalEncoding("A", "ALPHANUMERIC(A)", None, false); - } +} - #[test] - fn testMinimalEncoder2() { +#[test] +fn testMinimalEncoder2() { verifyMinimalEncoding("AB", "ALPHANUMERIC(AB)", None, false); - } +} - #[test] - fn testMinimalEncoder3() { +#[test] +fn testMinimalEncoder3() { verifyMinimalEncoding("ABC", "ALPHANUMERIC(ABC)", None, false); - } +} - #[test] - fn testMinimalEncoder4() { +#[test] +fn testMinimalEncoder4() { verifyMinimalEncoding("ABCD", "ALPHANUMERIC(ABCD)", None, false); - } +} - #[test] - fn testMinimalEncoder5() { +#[test] +fn testMinimalEncoder5() { verifyMinimalEncoding("ABCDE", "ALPHANUMERIC(ABCDE)", None, false); - } +} - #[test] - fn testMinimalEncoder6() { +#[test] +fn testMinimalEncoder6() { verifyMinimalEncoding("ABCDEF", "ALPHANUMERIC(ABCDEF)", None, false); - } +} - #[test] - fn testMinimalEncoder7() { +#[test] +fn testMinimalEncoder7() { verifyMinimalEncoding("ABCDEFG", "ALPHANUMERIC(ABCDEFG)", None, false); - } +} - #[test] - fn testMinimalEncoder8() { +#[test] +fn testMinimalEncoder8() { verifyMinimalEncoding("1", "NUMERIC(1)", None, false); - } +} - #[test] - fn testMinimalEncoder9() { +#[test] +fn testMinimalEncoder9() { verifyMinimalEncoding("12", "NUMERIC(12)", None, false); - } +} - #[test] - fn testMinimalEncoder10() { +#[test] +fn testMinimalEncoder10() { verifyMinimalEncoding("123", "NUMERIC(123)", None, false); - } +} - #[test] - fn testMinimalEncoder11() { +#[test] +fn testMinimalEncoder11() { verifyMinimalEncoding("1234", "NUMERIC(1234)", None, false); - } +} - #[test] - fn testMinimalEncoder12() { +#[test] +fn testMinimalEncoder12() { verifyMinimalEncoding("12345", "NUMERIC(12345)", None, false); - } +} - #[test] - fn testMinimalEncoder13() { +#[test] +fn testMinimalEncoder13() { verifyMinimalEncoding("123456", "NUMERIC(123456)", None, false); - } +} - #[test] - fn testMinimalEncoder14() { +#[test] +fn testMinimalEncoder14() { verifyMinimalEncoding("123A", "ALPHANUMERIC(123A)", None, false); - } +} - #[test] - fn testMinimalEncoder15() { +#[test] +fn testMinimalEncoder15() { verifyMinimalEncoding("A1", "ALPHANUMERIC(A1)", None, false); - } +} - #[test] - fn testMinimalEncoder16() { +#[test] +fn testMinimalEncoder16() { verifyMinimalEncoding("A12", "ALPHANUMERIC(A12)", None, false); - } +} - #[test] - fn testMinimalEncoder17() { +#[test] +fn testMinimalEncoder17() { verifyMinimalEncoding("A123", "ALPHANUMERIC(A123)", None, false); - } +} - #[test] - fn testMinimalEncoder18() { +#[test] +fn testMinimalEncoder18() { verifyMinimalEncoding("A1234", "ALPHANUMERIC(A1234)", None, false); - } +} - #[test] - fn testMinimalEncoder19() { +#[test] +fn testMinimalEncoder19() { verifyMinimalEncoding("A12345", "ALPHANUMERIC(A12345)", None, false); - } +} - #[test] - fn testMinimalEncoder20() { +#[test] +fn testMinimalEncoder20() { verifyMinimalEncoding("A123456", "ALPHANUMERIC(A123456)", None, false); - } +} - #[test] - fn testMinimalEncoder21() { +#[test] +fn testMinimalEncoder21() { verifyMinimalEncoding("A1234567", "ALPHANUMERIC(A1234567)", None, false); - } +} - #[test] - fn testMinimalEncoder22() { +#[test] +fn testMinimalEncoder22() { verifyMinimalEncoding("A12345678", "BYTE(A),NUMERIC(12345678)", None, false); - } +} - #[test] - fn testMinimalEncoder23() { +#[test] +fn testMinimalEncoder23() { verifyMinimalEncoding("A123456789", "BYTE(A),NUMERIC(123456789)", None, false); - } +} - #[test] - fn testMinimalEncoder24() { - verifyMinimalEncoding("A1234567890", "ALPHANUMERIC(A1),NUMERIC(234567890)", None, false); - } +#[test] +fn testMinimalEncoder24() { + verifyMinimalEncoding( + "A1234567890", + "ALPHANUMERIC(A1),NUMERIC(234567890)", + None, + false, + ); +} - #[test] - fn testMinimalEncoder25() { +#[test] +fn testMinimalEncoder25() { verifyMinimalEncoding("AB1", "ALPHANUMERIC(AB1)", None, false); - } +} - #[test] - fn testMinimalEncoder26() { +#[test] +fn testMinimalEncoder26() { verifyMinimalEncoding("AB12", "ALPHANUMERIC(AB12)", None, false); - } +} - #[test] - fn testMinimalEncoder27() { +#[test] +fn testMinimalEncoder27() { verifyMinimalEncoding("AB123", "ALPHANUMERIC(AB123)", None, false); - } +} - #[test] - fn testMinimalEncoder28() { +#[test] +fn testMinimalEncoder28() { verifyMinimalEncoding("AB1234", "ALPHANUMERIC(AB1234)", None, false); - } +} - #[test] - fn testMinimalEncoder29() { +#[test] +fn testMinimalEncoder29() { verifyMinimalEncoding("ABC1", "ALPHANUMERIC(ABC1)", None, false); - } +} - #[test] - fn testMinimalEncoder30() { +#[test] +fn testMinimalEncoder30() { verifyMinimalEncoding("ABC12", "ALPHANUMERIC(ABC12)", None, false); - } +} - #[test] - fn testMinimalEncoder31() { +#[test] +fn testMinimalEncoder31() { verifyMinimalEncoding("ABC1234", "ALPHANUMERIC(ABC1234)", None, false); - } +} - #[test] - fn testMinimalEncoder32() { - verifyMinimalEncoding("http://foo.com", "BYTE(http://foo.com)\ - ", None, false); - } +#[test] +fn testMinimalEncoder32() { + verifyMinimalEncoding( + "http://foo.com", + "BYTE(http://foo.com)\ + ", + None, + false, + ); +} - #[test] - fn testMinimalEncoder33() { - verifyMinimalEncoding("HTTP://FOO.COM", "ALPHANUMERIC(HTTP://FOO.COM\ - )", None, false); - } +#[test] +fn testMinimalEncoder33() { + verifyMinimalEncoding( + "HTTP://FOO.COM", + "ALPHANUMERIC(HTTP://FOO.COM\ + )", + None, + false, + ); +} - #[test] - fn testMinimalEncoder34() { - verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", - "NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, false); - } +#[test] +fn testMinimalEncoder34() { + verifyMinimalEncoding( + "1001114670010%01201220%107211220%140045003267781", + "NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", + None, + false, + ); +} - #[test] - fn testMinimalEncoder35() { - verifyMinimalEncoding("\u{0150}", "ECI(ISO-8859-2),BYTE(.)", None, false); - } +#[test] +fn testMinimalEncoder35() { + verifyMinimalEncoding("\u{0150}", "ECI(iso-8859-2),BYTE(.)", None, false); +} - #[test] - fn testMinimalEncoder36() { - verifyMinimalEncoding("\u{015C}", "ECI(ISO-8859-3),BYTE(.)", None, false); - } +#[test] +fn testMinimalEncoder36() { + verifyMinimalEncoding("\u{015C}", "ECI(iso-8859-3),BYTE(.)", None, false); +} - #[test] - fn testMinimalEncoder37() { - verifyMinimalEncoding("\u{0150}\u{015C}", "ECI(UTF-8),BYTE(..)", None, false); - } +#[test] +fn testMinimalEncoder37() { + verifyMinimalEncoding("\u{0150}\u{015C}", "ECI(utf-8),BYTE(..)", None, false); +} - #[test] - fn testMinimalEncoder38() { - verifyMinimalEncoding("\u{0150}\u{0150}\u{015C}\u{015C}", "ECI(ISO-8859-2),BYTE(.\ - .),ECI(ISO-8859-3),BYTE(..)", None, false); - } +#[test] +fn testMinimalEncoder38() { + 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); - } +#[test] +fn testMinimalEncoder39() { + 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); - } +#[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, + ); +} - #[test] - fn testMinimalEncoder41() { - verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", "FNC1_FIRST_POSITION(),NUMERIC(100111\ - 4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, - true); - } +#[test] +fn testMinimalEncoder41() { + verifyMinimalEncoding( + "1001114670010%01201220%107211220%140045003267781", + "FNC1_FIRST_POSITION(),NUMERIC(100111\ + 4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", + None, + true, + ); +} - #[test] - fn testMinimalEncoder42() { +#[test] +fn testMinimalEncoder42() { // test halfwidth Katakana character (they are single byte encoded in Shift_JIS) - verifyMinimalEncoding("Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}", "ECI(Shift_JIS),BYTE(Katakana:......)", None - , false); - } + verifyMinimalEncoding( + "Katakana:\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}\u{FF66}", + "ECI(Shift_JIS),BYTE(Katakana:......)", + None, + false, + ); +} - #[test] - fn testMinimalEncoder43() { +#[test] +fn testMinimalEncoder43() { // The character \u30A2 encodes as double byte in Shift_JIS so KANJI is more compact in this case - verifyMinimalEncoding("Katakana:\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}", "BYTE(Katakana:),KANJI(......)", None, - false); - } + verifyMinimalEncoding( + "Katakana:\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}\u{30A2}", + "BYTE(Katakana:),KANJI(......)", + None, + false, + ); +} - #[test] - fn testMinimalEncoder44() { +#[test] +fn testMinimalEncoder44() { // 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_with_details(input, None, priorityCharset.unwrap_or(encoding::all::ISO_8859_1), isGS1, - ErrorCorrectionLevel::L).expect("encode"); +fn verifyMinimalEncoding( + input: &str, + expectedRXingResult: &str, + priorityCharset: Option, + isGS1: bool, +) { + 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); - } +} - fn verifyGS1EncodedData( qrCode:&QRCode) { - let expected = -r"<< +fn verifyGS1EncodedData(qrCode: &QRCode) { + let expected = r"<< mode: ALPHANUMERIC ecLevel: H version: 2 @@ -977,11 +1184,10 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - fn verifyNotGS1EncodedData( qrCode:&QRCode) { - let expected = -r"<< +fn verifyNotGS1EncodedData(qrCode: &QRCode) { + let expected = r"<< mode: ALPHANUMERIC ecLevel: H version: 1 @@ -1011,9 +1217,11 @@ r"<< >> "; assert_eq!(expected, qrCode.to_string()); - } +} - fn shiftJISString( bytes:&[u8]) -> String{ - SHIFT_JIS_CHARSET.decode(bytes,encoding::DecoderTrap::Strict).expect("decode should be ok") +fn shiftJISString(bytes: &[u8]) -> String { + SHIFT_JIS_CHARSET + .decode(bytes, encoding::DecoderTrap::Strict) + .expect("decode should be ok") // return new String(bytes, StringUtils.SHIFT_JIS_CHARSET); - } +} diff --git a/src/qrcode/encoder/encoder.rs b/src/qrcode/encoder/encoder.rs index b21912e..782d8aa 100644 --- a/src/qrcode/encoder/encoder.rs +++ b/src/qrcode/encoder/encoder.rs @@ -357,9 +357,12 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode { } pub fn isOnlyDoubleByteKanji(content: &str) -> bool { - let bytes = SHIFT_JIS_CHARSET - .encode(content, encoding::EncoderTrap::Strict) - .expect("encode"); + let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET + .encode(content, encoding::EncoderTrap::Strict) { + byt + }else { + return false + }; let length = bytes.len(); if length % 2 != 0 { return false; @@ -367,7 +370,7 @@ pub fn isOnlyDoubleByteKanji(content: &str) -> bool { let mut i = 0; while i < length { // for (int i = 0; i < length; i += 2) { - let byte1 = bytes[i] & 0xFF; + let byte1 = bytes[i]; if (byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB) { return false; } diff --git a/src/qrcode/encoder/minimal_encoder.rs b/src/qrcode/encoder/minimal_encoder.rs index aa09180..52e1f58 100644 --- a/src/qrcode/encoder/minimal_encoder.rs +++ b/src/qrcode/encoder/minimal_encoder.rs @@ -24,6 +24,8 @@ use crate::{ Exceptions, }; +use unicode_segmentation::{Graphemes, UnicodeSegmentation}; + use super::encoder; pub enum VersionSize { @@ -84,7 +86,7 @@ impl fmt::Display for VersionSize { * @author Alex Geller */ pub struct MinimalEncoder { - stringToEncode: String, + stringToEncode: Vec, isGS1: bool, encoders: ECIEncoderSet, ecLevel: ErrorCorrectionLevel, @@ -110,9 +112,12 @@ impl MinimalEncoder { ecLevel: ErrorCorrectionLevel, ) -> Self { Self { - stringToEncode: String::from(stringToEncode), + stringToEncode: stringToEncode + .graphemes(true) + .map(|p| p.to_owned()) + .collect::>(), isGS1, - encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, -1), + encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, None), ecLevel, } @@ -222,23 +227,34 @@ impl MinimalEncoder { // } } - pub fn isNumeric(c: char) -> bool { - return c >= '0' && c <= '9'; + pub fn isNumeric(c: &str) -> bool { + if c.len() == 1 { + let ch = c.chars().nth(0).unwrap(); + ch >= '0' && ch <= '9' + } else { + false + } + // return c >= '0' && c <= '9'; } - pub fn isDoubleByteKanji(c: char) -> bool { - return encoder::isOnlyDoubleByteKanji(&String::from(c)); + pub fn isDoubleByteKanji(c: &str) -> bool { + return encoder::isOnlyDoubleByteKanji(&c); } - pub fn isAlphanumeric(c: char) -> bool { - return encoder::getAlphanumericCode(c as u8 as u32) != -1; + pub fn isAlphanumeric(c: &str) -> bool { + if c.len() == 1 { + let ch = c.chars().nth(0).unwrap(); + encoder::getAlphanumericCode(ch as u32) != -1 + } else { + false + } + // return encoder::getAlphanumericCode(c as u8 as u32) != -1; } - pub fn canEncode(&self, mode: &Mode, c: char) -> bool { + pub fn canEncode(&self, mode: &Mode, c: &str) -> bool { match mode { Mode::NUMERIC => Self::isNumeric(c), Mode::ALPHANUMERIC => Self::isAlphanumeric(c), - Mode::STRUCTURED_APPEND => todo!(), Mode::BYTE => true, Mode::KANJI => Self::isDoubleByteKanji(c), _ => false, // any character can be encoded as byte(s). Up to the caller to manage splitting into @@ -305,7 +321,8 @@ impl MinimalEncoder { let priorityEncoderIndex = self.encoders.getPriorityEncoderIndex(); if priorityEncoderIndex >= 0 && self.encoders.canEncode( - self.stringToEncode.chars().nth(from as usize).unwrap() as i16, + // self.stringToEncode.chars().nth(from as usize).unwrap() as i16, + &self.stringToEncode[from as usize], priorityEncoderIndex, ) { @@ -317,7 +334,7 @@ impl MinimalEncoder { // for (int i = start; i < end; i++) { if self .encoders - .canEncode(self.stringToEncode.chars().nth(from).unwrap() as i16, i) + .canEncode(&self.stringToEncode.get(from).unwrap(), i) { self.addEdge( edges, @@ -330,13 +347,13 @@ impl MinimalEncoder { previous.clone(), version, self.encoders.clone(), - &self.stringToEncode, + self.stringToEncode.clone(), ))), ); } } - if self.canEncode(&Mode::KANJI, self.stringToEncode.chars().nth(from).unwrap()) { + if self.canEncode(&Mode::KANJI, &self.stringToEncode.get(from).unwrap()) { self.addEdge( edges, from, @@ -348,16 +365,13 @@ impl MinimalEncoder { previous.clone(), version, self.encoders.clone(), - &self.stringToEncode, + self.stringToEncode.clone(), ))), ); } let inputLength = self.stringToEncode.len(); - if self.canEncode( - &Mode::ALPHANUMERIC, - self.stringToEncode.chars().nth(from).unwrap(), - ) { + if self.canEncode(&Mode::ALPHANUMERIC, self.stringToEncode.get(from).unwrap()) { self.addEdge( edges, from, @@ -368,7 +382,7 @@ impl MinimalEncoder { if from + 1 >= inputLength || !self.canEncode( &Mode::ALPHANUMERIC, - self.stringToEncode.chars().nth(from + 1).unwrap(), + self.stringToEncode.get(from + 1).unwrap(), ) { 1 @@ -378,15 +392,12 @@ impl MinimalEncoder { previous.clone(), version, self.encoders.clone(), - &self.stringToEncode, + self.stringToEncode.clone(), ))), ); } - if self.canEncode( - &Mode::NUMERIC, - self.stringToEncode.chars().nth(from).unwrap(), - ) { + if self.canEncode(&Mode::NUMERIC, self.stringToEncode.get(from).unwrap()) { self.addEdge( edges, from, @@ -395,17 +406,15 @@ impl MinimalEncoder { from, 0, if from + 1 >= inputLength - || !self.canEncode( - &Mode::NUMERIC, - self.stringToEncode.chars().nth(from + 1).unwrap(), - ) + || !self + .canEncode(&Mode::NUMERIC, self.stringToEncode.get(from + 1).unwrap()) { 1 } else { if from + 2 >= inputLength || !self.canEncode( &Mode::NUMERIC, - self.stringToEncode.chars().nth(from + 2).unwrap(), + self.stringToEncode.get(from + 2).unwrap(), ) { 2 @@ -416,7 +425,7 @@ impl MinimalEncoder { previous.clone(), version, self.encoders.clone(), - &self.stringToEncode, + self.stringToEncode.clone(), ))), ); } @@ -535,6 +544,7 @@ impl MinimalEncoder { * The encodation ECI(UTF-8),BYTE(XXYY) is longer with a size of 88. */ + // let inputLength = self.stringToEncode.chars().count(); let inputLength = self.stringToEncode.len(); // Array that represents vertices. There is a vertex for every character, encoding and mode. The vertex contains @@ -580,6 +590,9 @@ impl MinimalEncoder { return Err(Exceptions::WriterException(format!( r#"Internal error: failed to encode "{}"#, self.stringToEncode + .iter() + .map(|x| String::from(x)) + .collect::() //fold("", |acc,x| [acc,&x].concat()) ))); } Ok(RXingResultList::new( @@ -591,7 +604,7 @@ impl MinimalEncoder { self.isGS1, &self.ecLevel, self.encoders.clone(), - &self.stringToEncode, + self.stringToEncode.clone(), )) } } @@ -604,7 +617,7 @@ pub struct Edge { previous: Option>, cachedTotalSize: u32, encoders: ECIEncoderSet, - stringToEncode: String, + stringToEncode: Vec, } impl Edge { pub fn new( @@ -615,7 +628,7 @@ impl Edge { previous: Option>, version: VersionRef, encoders: ECIEncoderSet, - stringToEncode: &'_ str, + stringToEncode: Vec, ) -> Self { let nci = if mode == Mode::BYTE || previous.is_none() { charsetEncoderIndex @@ -628,7 +641,7 @@ impl Edge { charsetEncoderIndex: nci, characterLength, previous: previous.clone(), - stringToEncode: String::from(stringToEncode), + stringToEncode: stringToEncode.clone(), cachedTotalSize: { let mut size = if previous.is_some() { previous.as_ref().unwrap().cachedTotalSize @@ -657,13 +670,22 @@ impl Edge { } Mode::ALPHANUMERIC => size += if characterLength == 1 { 6 } else { 11 }, Mode::BYTE => { + let n: String = stringToEncode + .iter() + .skip(fromPosition as usize) + .take(characterLength as usize) + .map(|x| String::from(x)) + .collect(); size += 8 * encoders - .encode_string( - &stringToEncode[fromPosition as usize - ..(fromPosition + characterLength as usize)], - charsetEncoderIndex as usize, - ) + .encode_string(&n, charsetEncoderIndex as usize) .len() as u32; + // size += 8 * encoders + // .encode_string( + // &stringToEncode[fromPosition as usize + // ..(fromPosition + characterLength as usize)], + // charsetEncoderIndex as usize, + // ) + // .len() as u32; if needECI { size += 4 + 8; // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long } @@ -743,7 +765,7 @@ impl RXingResultList { isGS1: bool, ecLevel: &ErrorCorrectionLevel, encoders: ECIEncoderSet, - stringToEncode: &str, + stringToEncode: Vec, ) -> Self { let mut length = 0; let mut current = Some(solution); @@ -772,7 +794,7 @@ impl RXingResultList { current.as_ref().unwrap().charsetEncoderIndex, length, encoders.clone(), - stringToEncode, + stringToEncode.clone(), version, )); length = 0; @@ -785,7 +807,7 @@ impl RXingResultList { current.as_ref().unwrap().charsetEncoderIndex, 0, encoders.clone(), - stringToEncode, + stringToEncode.clone(), version, )); } @@ -805,23 +827,41 @@ impl RXingResultList { 0, 0, encoders.clone(), - stringToEncode, + stringToEncode.clone(), version, )); } } let first = list.get(0); // prepend or insert a FNC1_FIRST_POSITION after the ECI (if any) - 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, - )); + if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI {//&& containsECI { + list.insert( + if first.as_ref().unwrap().mode != Mode::ECI { + //first + list.len() + } else { + //second + list.len()-1 + }, + RXingResultNode::new( + Mode::FNC1_FIRST_POSITION, + 0, + 0, + 0, + encoders.clone(), + stringToEncode.clone(), + version, + ), + ); + // list.push(RXingResultNode::new( + // Mode::FNC1_FIRST_POSITION, + // 0, + // 0, + // 0, + // encoders.clone(), + // stringToEncode.clone(), + // version, + // )); } } @@ -937,7 +977,7 @@ struct RXingResultNode { characterLength: u32, encoders: ECIEncoderSet, version: VersionRef, - stringToEncode: String, + stringToEncode: Vec, } impl RXingResultNode { @@ -947,7 +987,7 @@ impl RXingResultNode { charsetEncoderIndex: usize, characterLength: u32, encoders: ECIEncoderSet, - stringToEncode: &str, + stringToEncode: Vec, version: VersionRef, ) -> Self { Self { @@ -956,7 +996,7 @@ impl RXingResultNode { charsetEncoderIndex, characterLength, encoders, - stringToEncode: String::from(stringToEncode), + stringToEncode, version, } } @@ -1023,8 +1063,9 @@ impl RXingResultNode { if self.mode == Mode::BYTE { self.encoders .encode_string( - &self.stringToEncode[self.fromPosition as usize - ..(self.fromPosition + self.characterLength as usize)], + // &self.stringToEncode[self.fromPosition as usize + // ..(self.fromPosition + self.characterLength as usize)], + &self.stringToEncode.get(self.fromPosition as usize).unwrap(), self.charsetEncoderIndex as usize, ) .len() as u32 @@ -1053,8 +1094,9 @@ impl RXingResultNode { } else if self.characterLength > 0 { // append data encoder::appendBytes( - &self.stringToEncode[self.fromPosition as usize - ..(self.fromPosition + self.characterLength as usize)], + // &self.stringToEncode[self.fromPosition as usize + // ..(self.fromPosition + self.characterLength as usize)], + &self.stringToEncode.get(self.fromPosition).unwrap(), self.mode, bits, self.encoders.getCharset(self.charsetEncoderIndex as usize), @@ -1067,7 +1109,7 @@ impl RXingResultNode { let mut result = String::new(); for i in 0..s.chars().count() { // for (int i = 0; i < s.length(); i++) { - if (s.chars().nth(i).unwrap() as u8) < 32 || (s.chars().nth(i).unwrap() as u8) > 126 { + if (s.chars().nth(i).unwrap() as u32) < 32 || (s.chars().nth(i).unwrap() as u32) > 126 { result.push('.'); } else { result.push(s.chars().nth(i).unwrap()); @@ -1089,10 +1131,18 @@ impl fmt::Display for RXingResultNode { .name(), ); } else { - result.push_str(&Self::makePrintable( - &self.stringToEncode[self.fromPosition as usize - ..(self.fromPosition + self.characterLength as usize)], - )); + let sub_string: String = self + .stringToEncode + .iter() + .skip(self.fromPosition as usize) + .take(self.characterLength as usize) + .map(|x| String::from(x)) + .collect(); + // result.push_str(&Self::makePrintable( + // &self.stringToEncode[self.fromPosition as usize + // ..(self.fromPosition + self.characterLength as usize)], + // )); + result.push_str(&Self::makePrintable(&sub_string)); } result.push(')');