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,10 +20,11 @@ chrono = "0.4"
chrono-tz = "0.4" chrono-tz = "0.4"
image = {version = "0.24.3", optional = true} image = {version = "0.24.3", optional = true}
imageproc = {version = "0.23.0", optional = true} imageproc = {version = "0.23.0", optional = true}
unicode-segmentation = "1.10.0"
[dev-dependencies] [dev-dependencies]
java-properties = "1.4.1" java-properties = "1.4.1"
[features] [features]
default = ["image"] default = ["image"]
image = ["dep:image", "dep:imageproc"] image = ["dep:image", "dep:imageproc"]

View File

@@ -18,6 +18,8 @@ use encoding::EncodingRef;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use unicode_segmentation::UnicodeSegmentation;
#[cfg(test)] #[cfg(test)]
mod StringUtilsTestCase; 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 * @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(). * 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. // List of encoders that potentially encode characters not in ISO-8859-1 in one byte.
let mut encoders: Vec<EncodingRef>; let mut encoders: Vec<EncodingRef>;
@@ -2928,20 +2930,22 @@ impl ECIEncoderSet {
let mut neededEncoders: Vec<EncodingRef> = Vec::new(); 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 //we always need the ISO-8859-1 encoder. It is the default encoding
neededEncoders.push(encoding::all::ISO_8859_1); neededEncoders.push(encoding::all::ISO_8859_1);
let mut needUnicodeEncoder = priorityCharset.name().starts_with("UTF"); 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 //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++) { // for (int i = 0; i < stringToEncode.length(); i++) {
let mut canEncode = false; let mut canEncode = false;
for encoder in &neededEncoders { for encoder in &neededEncoders {
// for (CharsetEncoder encoder : neededEncoders) { // for (CharsetEncoder encoder : neededEncoders) {
let c = stringToEncode.chars().nth(i).unwrap(); let c = stringToEncode.get(i).unwrap();
if c == fnc1 as u8 as char if (fnc1.is_some() && c == fnc1.as_ref().unwrap())
|| encoder || encoder
.encode(&c.to_string(), encoding::EncoderTrap::Strict) .encode(c, encoding::EncoderTrap::Strict)
.is_ok() .is_ok()
{ {
canEncode = true; canEncode = true;
@@ -2950,13 +2954,13 @@ impl ECIEncoderSet {
} }
if !canEncode { if !canEncode {
//for the character at position i we don't yet have an encoder in the list //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 { // for encoder in ENCODERS {
let encoder = ENCODERS.get(i).unwrap(); let encoder = ENCODERS.get(i_encoder).unwrap();
// for (CharsetEncoder encoder : ENCODERS) { // for (CharsetEncoder encoder : ENCODERS) {
if encoder if encoder
.encode( .encode(
&stringToEncode.chars().nth(i).unwrap().to_string(), &stringToEncode.get(i).unwrap(),
encoding::EncoderTrap::Strict, encoding::EncoderTrap::Strict,
) )
.is_ok() .is_ok()
@@ -3044,15 +3048,15 @@ impl ECIEncoderSet {
return self.priorityEncoderIndex; 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()); assert!(encoderIndex < self.len());
let encoder = self.encoders[encoderIndex]; 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() 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()); assert!(encoderIndex < self.len());
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict); let enc_data = encoder.encode(&c.to_string(), encoding::EncoderTrap::Strict);
@@ -3101,7 +3105,7 @@ static COST_PER_ECI: usize = 3;
*/ */
pub struct MinimalECIInput { pub struct MinimalECIInput {
bytes: Vec<u16>, bytes: Vec<u16>,
fnc1: i16, fnc1: u16,
} }
impl ECIInput for MinimalECIInput { 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 * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1
* input. * input.
*/ */
pub fn new(stringToEncode: &str, priorityCharset: EncodingRef, fnc1: i16) -> Self { pub fn new(stringToEncodeInput: &str, priorityCharset: EncodingRef, fnc1: Option<&str>) -> Self {
let encoderSet = ECIEncoderSet::new(stringToEncode, priorityCharset, fnc1); let stringToEncode = stringToEncodeInput.graphemes(true).collect::<Vec<&str>>();
let encoderSet = ECIEncoderSet::new(stringToEncodeInput, priorityCharset, fnc1);
let bytes = if encoderSet.len() == 1 { let bytes = if encoderSet.len() == 1 {
//optimization for the case when all can be encoded without ECI in ISO-8859-1 //optimization for the case when all can be encoded without ECI in ISO-8859-1
let mut bytes_hld = vec![0; stringToEncode.len()]; let mut bytes_hld = vec![0; stringToEncode.len()];
for i in 0..stringToEncode.len() { for i in 0..stringToEncode.len() {
// for (int i = 0; i < bytes.length; i++) { // for (int i = 0; i < bytes.length; i++) {
let c = stringToEncode.chars().nth(i).unwrap(); let c = stringToEncode.get(i).unwrap();
bytes_hld[i] = if c as i16 == fnc1 { 1000 } else { c as u16 }; bytes_hld[i] = if fnc1.is_some() && c == fnc1.as_ref().unwrap() { 1000 } else { c.chars().nth(0).unwrap() as u16 };
} }
bytes_hld bytes_hld
} else { } else {
Self::encodeMinimally(stringToEncode, &encoderSet, fnc1) Self::encodeMinimally(stringToEncodeInput, &encoderSet, fnc1.as_ref().unwrap().chars().nth(0).unwrap() as u16)
}; };
Self { Self {
bytes: bytes, 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 self.fnc1
} }
@@ -3321,14 +3326,15 @@ impl MinimalECIInput {
edges: &mut Vec<Vec<Option<Rc<InputEdge>>>>, edges: &mut Vec<Vec<Option<Rc<InputEdge>>>>,
from: usize, from: usize,
previous: Option<Rc<InputEdge>>, 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 start = 0;
let mut end = encoderSet.len(); let mut end = encoderSet.len();
if encoderSet.getPriorityEncoderIndex() >= 0 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(); start = encoderSet.getPriorityEncoderIndex();
end = start + 1; end = start + 1;
@@ -3336,7 +3342,7 @@ impl MinimalECIInput {
for i in start..end { for i in start..end {
// for (int i = start; i < end; i++) { // 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( Self::addEdge(
edges, edges,
from + 1, from + 1,
@@ -3349,7 +3355,7 @@ impl MinimalECIInput {
pub fn encodeMinimally( pub fn encodeMinimally(
stringToEncode: &str, stringToEncode: &str,
encoderSet: &ECIEncoderSet, encoderSet: &ECIEncoderSet,
fnc1: i16, fnc1: u16,
) -> Vec<u16> { ) -> Vec<u16> {
let inputLength = stringToEncode.len(); let inputLength = stringToEncode.len();
@@ -3395,7 +3401,7 @@ impl MinimalECIInput {
intsAL.splice(0..0, [1000]); intsAL.splice(0..0, [1000]);
} else { } else {
let bytes: Vec<u16> = encoderSet let bytes: Vec<u16> = encoderSet
.encode_char(c.c as u8 as char, c.encoderIndex) .encode_char(&c.c , c.encoderIndex)
.iter() .iter()
.map(|x| *x as u16) .map(|x| *x as u16)
.collect(); .collect();
@@ -3429,25 +3435,27 @@ impl MinimalECIInput {
} }
struct InputEdge { struct InputEdge {
c: i16, c: String,
encoderIndex: usize, //the encoding of this edge encoderIndex: usize, //the encoding of this edge
previous: Option<Rc<InputEdge>>, previous: Option<Rc<InputEdge>>,
cachedTotalSize: usize, cachedTotalSize: usize,
} }
impl InputEdge { impl InputEdge {
pub fn new( pub fn new(
c: i16, c: &str,
encoderSet: &ECIEncoderSet, encoderSet: &ECIEncoderSet,
encoderIndex: usize, encoderIndex: usize,
previous: Option<Rc<InputEdge>>, previous: Option<Rc<InputEdge>>,
fnc1: i16, fnc1: u16,
) -> Self { ) -> Self {
let mut size = if c == 1000 { let mut size = if c == "\u{1000}" {
1 1
} else { } 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 { if let Some(prev) = previous {
let previousEncoderIndex = prev.encoderIndex; let previousEncoderIndex = prev.encoderIndex;
if previousEncoderIndex != encoderIndex { if previousEncoderIndex != encoderIndex {
@@ -3456,7 +3464,7 @@ impl InputEdge {
size += prev.cachedTotalSize; size += prev.cachedTotalSize;
Self { 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, encoderIndex,
previous: Some(prev.clone()), previous: Some(prev.clone()),
cachedTotalSize: size, cachedTotalSize: size,
@@ -3468,7 +3476,7 @@ impl InputEdge {
} }
Self { 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, encoderIndex,
previous: None, previous: None,
cachedTotalSize: size, cachedTotalSize: size,
@@ -3502,7 +3510,7 @@ impl InputEdge {
} }
pub fn isFNC1(&self) -> bool { pub fn isFNC1(&self) -> bool {
self.c == 1000 self.c == "\u{1000}"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -357,9 +357,12 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
} }
pub fn isOnlyDoubleByteKanji(content: &str) -> bool { pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
let bytes = SHIFT_JIS_CHARSET let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET
.encode(content, encoding::EncoderTrap::Strict) .encode(content, encoding::EncoderTrap::Strict) {
.expect("encode"); byt
}else {
return false
};
let length = bytes.len(); let length = bytes.len();
if length % 2 != 0 { if length % 2 != 0 {
return false; return false;
@@ -367,7 +370,7 @@ pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
let mut i = 0; let mut i = 0;
while i < length { while i < length {
// for (int i = 0; i < length; i += 2) { // 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) { if (byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB) {
return false; return false;
} }

View File

@@ -24,6 +24,8 @@ use crate::{
Exceptions, Exceptions,
}; };
use unicode_segmentation::{Graphemes, UnicodeSegmentation};
use super::encoder; use super::encoder;
pub enum VersionSize { pub enum VersionSize {
@@ -84,7 +86,7 @@ impl fmt::Display for VersionSize {
* @author Alex Geller * @author Alex Geller
*/ */
pub struct MinimalEncoder { pub struct MinimalEncoder {
stringToEncode: String, stringToEncode: Vec<String>,
isGS1: bool, isGS1: bool,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
ecLevel: ErrorCorrectionLevel, ecLevel: ErrorCorrectionLevel,
@@ -110,9 +112,12 @@ impl MinimalEncoder {
ecLevel: ErrorCorrectionLevel, ecLevel: ErrorCorrectionLevel,
) -> Self { ) -> Self {
Self { Self {
stringToEncode: String::from(stringToEncode), stringToEncode: stringToEncode
.graphemes(true)
.map(|p| p.to_owned())
.collect::<Vec<String>>(),
isGS1, isGS1,
encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, -1), encoders: ECIEncoderSet::new(&stringToEncode, priorityCharset, None),
ecLevel, ecLevel,
} }
@@ -222,23 +227,34 @@ impl MinimalEncoder {
// } // }
} }
pub fn isNumeric(c: char) -> bool { pub fn isNumeric(c: &str) -> bool {
return c >= '0' && c <= '9'; 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 { pub fn isDoubleByteKanji(c: &str) -> bool {
return encoder::isOnlyDoubleByteKanji(&String::from(c)); return encoder::isOnlyDoubleByteKanji(&c);
} }
pub fn isAlphanumeric(c: char) -> bool { pub fn isAlphanumeric(c: &str) -> bool {
return encoder::getAlphanumericCode(c as u8 as u32) != -1; 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 { match mode {
Mode::NUMERIC => Self::isNumeric(c), Mode::NUMERIC => Self::isNumeric(c),
Mode::ALPHANUMERIC => Self::isAlphanumeric(c), Mode::ALPHANUMERIC => Self::isAlphanumeric(c),
Mode::STRUCTURED_APPEND => todo!(),
Mode::BYTE => true, Mode::BYTE => true,
Mode::KANJI => Self::isDoubleByteKanji(c), Mode::KANJI => Self::isDoubleByteKanji(c),
_ => false, // any character can be encoded as byte(s). Up to the caller to manage splitting into _ => 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(); let priorityEncoderIndex = self.encoders.getPriorityEncoderIndex();
if priorityEncoderIndex >= 0 if priorityEncoderIndex >= 0
&& self.encoders.canEncode( && 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, priorityEncoderIndex,
) )
{ {
@@ -317,7 +334,7 @@ impl MinimalEncoder {
// for (int i = start; i < end; i++) { // for (int i = start; i < end; i++) {
if self if self
.encoders .encoders
.canEncode(self.stringToEncode.chars().nth(from).unwrap() as i16, i) .canEncode(&self.stringToEncode.get(from).unwrap(), i)
{ {
self.addEdge( self.addEdge(
edges, edges,
@@ -330,13 +347,13 @@ impl MinimalEncoder {
previous.clone(), previous.clone(),
version, version,
self.encoders.clone(), 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( self.addEdge(
edges, edges,
from, from,
@@ -348,16 +365,13 @@ impl MinimalEncoder {
previous.clone(), previous.clone(),
version, version,
self.encoders.clone(), self.encoders.clone(),
&self.stringToEncode, self.stringToEncode.clone(),
))), ))),
); );
} }
let inputLength = self.stringToEncode.len(); let inputLength = self.stringToEncode.len();
if self.canEncode( if self.canEncode(&Mode::ALPHANUMERIC, self.stringToEncode.get(from).unwrap()) {
&Mode::ALPHANUMERIC,
self.stringToEncode.chars().nth(from).unwrap(),
) {
self.addEdge( self.addEdge(
edges, edges,
from, from,
@@ -368,7 +382,7 @@ impl MinimalEncoder {
if from + 1 >= inputLength if from + 1 >= inputLength
|| !self.canEncode( || !self.canEncode(
&Mode::ALPHANUMERIC, &Mode::ALPHANUMERIC,
self.stringToEncode.chars().nth(from + 1).unwrap(), self.stringToEncode.get(from + 1).unwrap(),
) )
{ {
1 1
@@ -378,15 +392,12 @@ impl MinimalEncoder {
previous.clone(), previous.clone(),
version, version,
self.encoders.clone(), self.encoders.clone(),
&self.stringToEncode, self.stringToEncode.clone(),
))), ))),
); );
} }
if self.canEncode( if self.canEncode(&Mode::NUMERIC, self.stringToEncode.get(from).unwrap()) {
&Mode::NUMERIC,
self.stringToEncode.chars().nth(from).unwrap(),
) {
self.addEdge( self.addEdge(
edges, edges,
from, from,
@@ -395,17 +406,15 @@ impl MinimalEncoder {
from, from,
0, 0,
if from + 1 >= inputLength if from + 1 >= inputLength
|| !self.canEncode( || !self
&Mode::NUMERIC, .canEncode(&Mode::NUMERIC, self.stringToEncode.get(from + 1).unwrap())
self.stringToEncode.chars().nth(from + 1).unwrap(),
)
{ {
1 1
} else { } else {
if from + 2 >= inputLength if from + 2 >= inputLength
|| !self.canEncode( || !self.canEncode(
&Mode::NUMERIC, &Mode::NUMERIC,
self.stringToEncode.chars().nth(from + 2).unwrap(), self.stringToEncode.get(from + 2).unwrap(),
) )
{ {
2 2
@@ -416,7 +425,7 @@ impl MinimalEncoder {
previous.clone(), previous.clone(),
version, version,
self.encoders.clone(), 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. * 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(); let inputLength = self.stringToEncode.len();
// Array that represents vertices. There is a vertex for every character, encoding and mode. The vertex contains // 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!( return Err(Exceptions::WriterException(format!(
r#"Internal error: failed to encode "{}"#, r#"Internal error: failed to encode "{}"#,
self.stringToEncode self.stringToEncode
.iter()
.map(|x| String::from(x))
.collect::<String>() //fold("", |acc,x| [acc,&x].concat())
))); )));
} }
Ok(RXingResultList::new( Ok(RXingResultList::new(
@@ -591,7 +604,7 @@ impl MinimalEncoder {
self.isGS1, self.isGS1,
&self.ecLevel, &self.ecLevel,
self.encoders.clone(), self.encoders.clone(),
&self.stringToEncode, self.stringToEncode.clone(),
)) ))
} }
} }
@@ -604,7 +617,7 @@ pub struct Edge {
previous: Option<Rc<Edge>>, previous: Option<Rc<Edge>>,
cachedTotalSize: u32, cachedTotalSize: u32,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
stringToEncode: String, stringToEncode: Vec<String>,
} }
impl Edge { impl Edge {
pub fn new( pub fn new(
@@ -615,7 +628,7 @@ impl Edge {
previous: Option<Rc<Edge>>, previous: Option<Rc<Edge>>,
version: VersionRef, version: VersionRef,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
stringToEncode: &'_ str, stringToEncode: Vec<String>,
) -> Self { ) -> Self {
let nci = if mode == Mode::BYTE || previous.is_none() { let nci = if mode == Mode::BYTE || previous.is_none() {
charsetEncoderIndex charsetEncoderIndex
@@ -628,7 +641,7 @@ impl Edge {
charsetEncoderIndex: nci, charsetEncoderIndex: nci,
characterLength, characterLength,
previous: previous.clone(), previous: previous.clone(),
stringToEncode: String::from(stringToEncode), stringToEncode: stringToEncode.clone(),
cachedTotalSize: { cachedTotalSize: {
let mut size = if previous.is_some() { let mut size = if previous.is_some() {
previous.as_ref().unwrap().cachedTotalSize previous.as_ref().unwrap().cachedTotalSize
@@ -657,13 +670,22 @@ impl Edge {
} }
Mode::ALPHANUMERIC => size += if characterLength == 1 { 6 } else { 11 }, Mode::ALPHANUMERIC => size += if characterLength == 1 { 6 } else { 11 },
Mode::BYTE => { Mode::BYTE => {
let n: String = stringToEncode
.iter()
.skip(fromPosition as usize)
.take(characterLength as usize)
.map(|x| String::from(x))
.collect();
size += 8 * encoders size += 8 * encoders
.encode_string( .encode_string(&n, charsetEncoderIndex as usize)
&stringToEncode[fromPosition as usize
..(fromPosition + characterLength as usize)],
charsetEncoderIndex as usize,
)
.len() as u32; .len() as u32;
// size += 8 * encoders
// .encode_string(
// &stringToEncode[fromPosition as usize
// ..(fromPosition + characterLength as usize)],
// charsetEncoderIndex as usize,
// )
// .len() as u32;
if needECI { if needECI {
size += 4 + 8; // the ECI assignment numbers for ISO-8859-x, UTF-8 and UTF-16 are all 8 bit long 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, isGS1: bool,
ecLevel: &ErrorCorrectionLevel, ecLevel: &ErrorCorrectionLevel,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
stringToEncode: &str, stringToEncode: Vec<String>,
) -> Self { ) -> Self {
let mut length = 0; let mut length = 0;
let mut current = Some(solution); let mut current = Some(solution);
@@ -772,7 +794,7 @@ impl RXingResultList {
current.as_ref().unwrap().charsetEncoderIndex, current.as_ref().unwrap().charsetEncoderIndex,
length, length,
encoders.clone(), encoders.clone(),
stringToEncode, stringToEncode.clone(),
version, version,
)); ));
length = 0; length = 0;
@@ -785,7 +807,7 @@ impl RXingResultList {
current.as_ref().unwrap().charsetEncoderIndex, current.as_ref().unwrap().charsetEncoderIndex,
0, 0,
encoders.clone(), encoders.clone(),
stringToEncode, stringToEncode.clone(),
version, version,
)); ));
} }
@@ -805,23 +827,41 @@ impl RXingResultList {
0, 0,
0, 0,
encoders.clone(), encoders.clone(),
stringToEncode, stringToEncode.clone(),
version, version,
)); ));
} }
} }
let first = list.get(0); let first = list.get(0);
// prepend or insert a FNC1_FIRST_POSITION after the ECI (if any) // prepend or insert a FNC1_FIRST_POSITION after the ECI (if any)
if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI && containsECI { if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI {//&& containsECI {
list.push(RXingResultNode::new( list.insert(
Mode::FNC1_FIRST_POSITION, if first.as_ref().unwrap().mode != Mode::ECI {
0, //first
0, list.len()
0, } else {
encoders.clone(), //second
stringToEncode, list.len()-1
version, },
)); 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, characterLength: u32,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
version: VersionRef, version: VersionRef,
stringToEncode: String, stringToEncode: Vec<String>,
} }
impl RXingResultNode { impl RXingResultNode {
@@ -947,7 +987,7 @@ impl RXingResultNode {
charsetEncoderIndex: usize, charsetEncoderIndex: usize,
characterLength: u32, characterLength: u32,
encoders: ECIEncoderSet, encoders: ECIEncoderSet,
stringToEncode: &str, stringToEncode: Vec<String>,
version: VersionRef, version: VersionRef,
) -> Self { ) -> Self {
Self { Self {
@@ -956,7 +996,7 @@ impl RXingResultNode {
charsetEncoderIndex, charsetEncoderIndex,
characterLength, characterLength,
encoders, encoders,
stringToEncode: String::from(stringToEncode), stringToEncode,
version, version,
} }
} }
@@ -1023,8 +1063,9 @@ impl RXingResultNode {
if self.mode == Mode::BYTE { if self.mode == Mode::BYTE {
self.encoders self.encoders
.encode_string( .encode_string(
&self.stringToEncode[self.fromPosition as usize // &self.stringToEncode[self.fromPosition as usize
..(self.fromPosition + self.characterLength as usize)], // ..(self.fromPosition + self.characterLength as usize)],
&self.stringToEncode.get(self.fromPosition as usize).unwrap(),
self.charsetEncoderIndex as usize, self.charsetEncoderIndex as usize,
) )
.len() as u32 .len() as u32
@@ -1053,8 +1094,9 @@ impl RXingResultNode {
} else if self.characterLength > 0 { } else if self.characterLength > 0 {
// append data // append data
encoder::appendBytes( encoder::appendBytes(
&self.stringToEncode[self.fromPosition as usize // &self.stringToEncode[self.fromPosition as usize
..(self.fromPosition + self.characterLength as usize)], // ..(self.fromPosition + self.characterLength as usize)],
&self.stringToEncode.get(self.fromPosition).unwrap(),
self.mode, self.mode,
bits, bits,
self.encoders.getCharset(self.charsetEncoderIndex as usize), self.encoders.getCharset(self.charsetEncoderIndex as usize),
@@ -1067,7 +1109,7 @@ impl RXingResultNode {
let mut result = String::new(); let mut result = String::new();
for i in 0..s.chars().count() { for i in 0..s.chars().count() {
// for (int i = 0; i < s.length(); i++) { // 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('.'); result.push('.');
} else { } else {
result.push(s.chars().nth(i).unwrap()); result.push(s.chars().nth(i).unwrap());
@@ -1089,10 +1131,18 @@ impl fmt::Display for RXingResultNode {
.name(), .name(),
); );
} else { } else {
result.push_str(&Self::makePrintable( let sub_string: String = self
&self.stringToEncode[self.fromPosition as usize .stringToEncode
..(self.fromPosition + self.characterLength as usize)], .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(')'); result.push(')');