only 13 failing encoder tests

This commit is contained in:
Henry Schimke
2022-10-04 18:08:19 -05:00
parent bf0a83c688
commit 86f6bd0c69
5 changed files with 823 additions and 553 deletions

View File

@@ -20,6 +20,7 @@ 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"

View File

@@ -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<EncodingRef>;
@@ -2928,20 +2930,22 @@ impl ECIEncoderSet {
let mut neededEncoders: Vec<EncodingRef> = Vec::new();
let stringToEncode = stringToEncodeMain.graphemes(true).collect::<Vec<&str>>();
//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<u8> {
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Vec<u8> {
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<u16>,
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::<Vec<&str>>();
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<Vec<Option<Rc<InputEdge>>>>,
from: usize,
previous: Option<Rc<InputEdge>>,
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<u16> {
let inputLength = stringToEncode.len();
@@ -3395,7 +3401,7 @@ impl MinimalECIInput {
intsAL.splice(0..0, [1000]);
} else {
let bytes: Vec<u16> = 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<Rc<InputEdge>>,
cachedTotalSize: usize,
}
impl InputEdge {
pub fn new(
c: i16,
c: &str,
encoderSet: &ECIEncoderSet,
encoderIndex: usize,
previous: Option<Rc<InputEdge>>,
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}"
}
}

View File

@@ -16,7 +16,14 @@
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;
@@ -43,7 +50,10 @@ lazy_static! {
// 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));
assert_eq!(
i as i8,
encoder::getAlphanumericCode((b'A' + i - 10) as u32)
);
}
// Others are symbol letters
@@ -70,8 +80,10 @@ lazy_static! {
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() {
let qrCode = encoder::encode("ABCDEF", ErrorCorrectionLevel::H).expect("encode");
let expected =
r"<<
let expected = r"<<
mode: ALPHANUMERIC
ecLevel: H
version: 1
@@ -130,8 +149,12 @@ r"<<
#[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"));
}
@@ -139,17 +162,28 @@ r"<<
#[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");
hints.insert(
EncodeHintType::QR_VERSION,
EncodeHintValue::QrVersion("3".to_owned()),
);
encoder::encode_with_hints(
"THISMESSAGEISTOOLONGFORAQRCODEVERSION3",
ErrorCorrectionLevel::H,
&hints,
)
.expect("encode");
}
#[test]
fn testSimpleUTF8ECI() {
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"<<
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
@@ -185,11 +219,14 @@ r"<<
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
@@ -225,11 +262,14 @@ r"<<
fn testEncodeShiftjisNumeric() {
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()),
);
let qrCode = encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, &hints).expect("encode");
let expected =
r"<<
let qrCode =
encoder::encode_with_hints("0123", ErrorCorrectionLevel::M, &hints).expect("encode");
let expected = r"<<
mode: NUMERIC
ecLevel: M
version: 1
@@ -265,8 +305,12 @@ r"<<
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);
}
@@ -274,8 +318,12 @@ r"<<
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);
}
@@ -283,9 +331,13 @@ r"<<
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);
}
@@ -293,8 +345,12 @@ r"<<
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);
}
@@ -302,11 +358,17 @@ r"<<
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
@@ -348,28 +410,36 @@ r"<<
#[test]
fn testAppendLengthInfo() {
let mut bits = BitArray::new();
encoder::appendLengthInfo(1, // 1 letter (1/1).
encoder::appendLengthInfo(
1, // 1 letter (1/1).
Version::getVersionForNumber(1).unwrap(),
Mode::NUMERIC,
&mut bits);
&mut bits,
);
assert_eq!(" ........ .X", bits.to_string()); // 10 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(2, // 2 letters (2/1).
encoder::appendLengthInfo(
2, // 2 letters (2/1).
Version::getVersionForNumber(10).unwrap(),
Mode::ALPHANUMERIC,
&mut bits);
&mut bits,
);
assert_eq!(" ........ .X.", bits.to_string()); // 11 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(255, // 255 letter (255/1).
encoder::appendLengthInfo(
255, // 255 letter (255/1).
Version::getVersionForNumber(27).unwrap(),
Mode::BYTE,
&mut bits);
&mut bits,
);
assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(512, // 512 letters (1024/2).
encoder::appendLengthInfo(
512, // 512 letters (1024/2).
Version::getVersionForNumber(40).unwrap(),
Mode::KANJI,
&mut bits);
&mut bits,
);
assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits.
}
@@ -378,16 +448,33 @@ r"<<
// 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);
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);
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) {
@@ -396,15 +483,29 @@ r"<<
// Should use append8BitBytes.
// 0x61, 0x62, 0x63
let mut bits = BitArray::new();
encoder::appendBytes("abc", Mode::BYTE, &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
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);
encoder::appendBytes(
&shiftJISString(&[0x93, 0x5f]),
Mode::KANJI,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
);
assert_eq!(" .XX.XX.. XXXXX", bits.to_string());
}
@@ -442,34 +543,90 @@ r"<<
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]);
}
@@ -485,10 +642,8 @@ r"<<
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()];
@@ -500,12 +655,10 @@ r"<<
}
// 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 {
@@ -516,20 +669,14 @@ r"<<
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()];
@@ -629,17 +776,19 @@ r"<<
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);
}
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() {
@@ -650,7 +799,7 @@ r"<<
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() {
@@ -814,7 +963,12 @@ r"<<
#[test]
fn testMinimalEncoder24() {
verifyMinimalEncoding("A1234567890", "ALPHANUMERIC(A1),NUMERIC(234567890)", None, false);
verifyMinimalEncoding(
"A1234567890",
"ALPHANUMERIC(A1),NUMERIC(234567890)",
None,
false,
);
}
#[test]
@@ -854,75 +1008,115 @@ 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]
fn testMinimalEncoder34() {
verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781",
"NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", None, false);
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);
verifyMinimalEncoding("\u{0150}", "ECI(iso-8859-2),BYTE(.)", None, false);
}
#[test]
fn testMinimalEncoder36() {
verifyMinimalEncoding("\u{015C}", "ECI(ISO-8859-3),BYTE(.)", None, false);
verifyMinimalEncoding("\u{015C}", "ECI(iso-8859-3),BYTE(.)", None, false);
}
#[test]
fn testMinimalEncoder37() {
verifyMinimalEncoding("\u{0150}\u{015C}", "ECI(UTF-8),BYTE(..)", None, false);
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);
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);
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);
verifyMinimalEncoding(
"1001114670010%01201220%107211220%140045003267781",
"FNC1_FIRST_POSITION(),NUMERIC(100111\
4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)",
None,
true,
);
}
#[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() {
// 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]
@@ -930,20 +1124,33 @@ 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<EncodingRef>, 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<EncodingRef>,
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"<<
let expected = r"<<
mode: ALPHANUMERIC
ecLevel: H
version: 2
@@ -980,8 +1187,7 @@ r"<<
}
fn verifyNotGS1EncodedData(qrCode: &QRCode) {
let expected =
r"<<
let expected = r"<<
mode: ALPHANUMERIC
ecLevel: H
version: 1
@@ -1014,6 +1220,8 @@ r"<<
}
fn shiftJISString(bytes: &[u8]) -> String {
SHIFT_JIS_CHARSET.decode(bytes,encoding::DecoderTrap::Strict).expect("decode should be ok")
SHIFT_JIS_CHARSET
.decode(bytes, encoding::DecoderTrap::Strict)
.expect("decode should be ok")
// return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
}

View File

@@ -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;
}

View File

@@ -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<String>,
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::<Vec<String>>(),
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::<String>() //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<Rc<Edge>>,
cachedTotalSize: u32,
encoders: ECIEncoderSet,
stringToEncode: String,
stringToEncode: Vec<String>,
}
impl Edge {
pub fn new(
@@ -615,7 +628,7 @@ impl Edge {
previous: Option<Rc<Edge>>,
version: VersionRef,
encoders: ECIEncoderSet,
stringToEncode: &'_ str,
stringToEncode: Vec<String>,
) -> 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<String>,
) -> 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(
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,
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<String>,
}
impl RXingResultNode {
@@ -947,7 +987,7 @@ impl RXingResultNode {
charsetEncoderIndex: usize,
characterLength: u32,
encoders: ECIEncoderSet,
stringToEncode: &str,
stringToEncode: Vec<String>,
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(')');