mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
Cleanup of many components of the code.
Many unwraps, expects, and panics removed or handled. More rustification of the codebase. Squashed commit of the following: commit 80c6483cf8c819496a7b781f9e3a149d1f18d5fe Author: Henry <henry@azule.info> Date: Fri Feb 10 20:36:57 2023 -0600 add other parsed result option commit 412d92ae585e7bf194697f5282dbc045e448bace Author: Henry <henry@azule.info> Date: Fri Feb 10 19:06:34 2023 -0600 fix some panics commit 9108d3e931aadec00fc0bf346ebc52d24e5d8146 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:56:30 2023 -0600 clippy --fix commit 8cd89d314323f54f342f15fc73297b62d418ac79 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:55:45 2023 -0600 some more cleanup in aztec commit fb7f9242e273b85a4bb212f22a185a0dcbfafc36 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:19:54 2023 -0600 cleanup root commit 4fb7c0639830869149332b29be789e891eade3e7 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:50:15 2023 -0600 format commit 3ac271af657b25fbe5ee39cbdf8859e5aa38ea41 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:43:14 2023 -0600 clippy --fix commit 0c5b4c1477159db93a9da9645039f51cd1a7c574 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:04:31 2023 -0600 qrcode cleanup complete commit 70c1d107cc672e45d46567c650c46fece7e7da9c Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:28:25 2023 -0600 clippy --fix commit e13263d0f1f2a13dbb59b6e60d8b871a32babc92 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:27:44 2023 -0600 qrcode detector cleanup commit f7f2855099e469fe1091868c6099196705d0ae83 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:48:13 2023 -0600 qrcode decoder commit bdbaaba597b3479639c2ed3726465a69e3004471 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:13:18 2023 -0600 clippy --fix commit fd6dbcaeb1f45dc91ae98f0e7c58aad48d67df78 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:12:28 2023 -0600 pdf417 cleanup complete commit 7bbd47604c2639a5eb61bdb5533e71be3bce95a1 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:28 2023 -0600 clippy --fix commit 8f4962b7bb5f133524fe4d3d4948e5672a88c545 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:00 2023 -0600 cleanup on pdf417 hie commit 254c8243953776d3c8704dd81529aadd05d5a94e Author: Henry <henry@azule.info> Date: Fri Feb 10 02:51:21 2023 +0000 partway through pdf417 hle commit d4a5b00fde8c0282b0c6e4175a21c1e111b11533 Author: Henry <henry@azule.info> Date: Wed Feb 8 21:35:25 2023 +0000 clippy --fix commit 2bd4a8e218aa963a88997b50bc5a198f9a88205e Author: Henry <henry@azule.info> Date: Wed Feb 8 21:31:55 2023 +0000 pdf417 decode and detect cleanup commit 05130ac54a72c2303045d64507bf6185aa74e531 Author: Henry Schimke <henry@azule.info> Date: Tue Feb 7 08:06:25 2023 -0600 at decodeTextCompaction in decoded_bit_straem_parser commit 924c023a7d2339dfffa6ef0c4a805fb192576796 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:22:02 2023 -0600 clippy --fix commit 5cfb81a885c22b4b5ec937a79be31d0815def211 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:20:22 2023 -0600 oned cleanup commit 0649b64854baf56a8e3314728d4f6cf4063db8b2 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 11:47:28 2023 -0600 rss cleanup commit 2d3127898fc11f7e65d590e983cda799b798b646 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 10:19:56 2023 -0600 multi cleanup commit 7e8b43a159083a2096123e6204d4d1d359c59981 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:59 2023 -0600 cargo fmt commit df8285e8da07b4bffd48ca6e596de3f010eb8d9e Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:29 2023 -0600 maxicode cleanup commit a51f923a14016eb416ca202b2194258808dde3e7 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:57 2023 -0600 cargo fmt commit 332d7eef4a25318611025a3fcb0b70c604d917be Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:48 2023 -0600 cleanup datamatrix commit eb2311c476a9c9993f271ab6cf9fd359aedca26f Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:26 2023 -0600 cargo clippy --fix commit 2abaa4c51d287f619d4c7a438f85ba2a30f159cf Author: Henry <henry@azule.info> Date: Sun Feb 5 19:13:02 2023 -0600 finish cleanup in parsers commit 716aa2fbf728716cff36657a5fd80e7bca5276b7 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 17:44:56 2023 -0600 cleanup continues commit 7d843788a49fa9cc82c4616d226c0f882e73612b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 15:15:09 2023 -0600 common cleanup commit fd251866c68f22d450dd428c93d7a3620bf1be27 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 10:24:54 2023 -0600 cleanup reedsolomon commit 132e27ed1468f5c1ce998516ff5a00687217c3e6 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:52:04 2023 -0600 make MathUtils more generic commit d8352b7fff4cb4f9ecc8e8a969710d26ef410e8b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:29:33 2023 -0600 cleanup some string handling in ResultParser There may still be some edge cases where multi-byte characters break the parser
This commit is contained in:
@@ -18,6 +18,7 @@ use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::common::BitArray;
|
||||
use crate::BarcodeFormat;
|
||||
use crate::DecodeHintValue;
|
||||
use crate::Exceptions;
|
||||
use crate::RXingResult;
|
||||
|
||||
@@ -70,7 +71,7 @@ impl OneDReader for CodaBarReader {
|
||||
// StringBuilder, so that we can access the decoded patterns in
|
||||
// validatePattern. We'll translate to the actual characters later.
|
||||
self.decodeRowRXingResult
|
||||
.push(char::from_u32(charOffset as u32).unwrap());
|
||||
.push(char::from_u32(charOffset as u32).ok_or(Exceptions::ParseException(None))?);
|
||||
nextStart += 8;
|
||||
// Stop as soon as we see the end character.
|
||||
if self.decodeRowRXingResult.chars().count() > 1
|
||||
@@ -81,16 +82,16 @@ impl OneDReader for CodaBarReader {
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// no fixed end pattern so keep on reading while data is available
|
||||
if nextStart >= self.counterLength {
|
||||
break;
|
||||
} // no fixed end pattern so keep on reading while data is available
|
||||
} //while (nextStart < counterLength); // no fixed end pattern so keep on reading while data is available
|
||||
|
||||
}
|
||||
}
|
||||
// Look for whitespace after pattern:
|
||||
let trailingWhitespace = self.counters[nextStart - 1];
|
||||
let mut lastPatternSize = 0;
|
||||
for i in -8isize..-1isize {
|
||||
// for (int i = -8; i < -1; i++) {
|
||||
for i in -8isize..-1 {
|
||||
lastPatternSize += self.counters[(nextStart as isize + i) as usize];
|
||||
}
|
||||
|
||||
@@ -108,13 +109,21 @@ impl OneDReader for CodaBarReader {
|
||||
// for (int i = 0; i < decodeRowRXingResult.length(); i++) {
|
||||
self.decodeRowRXingResult.replace_range(
|
||||
i..=i,
|
||||
&Self::ALPHABET[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]
|
||||
&Self::ALPHABET[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize]
|
||||
.to_string(),
|
||||
);
|
||||
// self.decodeRowRXingResult.setCharAt(i, Self::ALPHABET[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]);
|
||||
}
|
||||
// Ensure a valid start and end character
|
||||
let startchar = self.decodeRowRXingResult.chars().next().unwrap();
|
||||
let startchar = self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if !Self::arrayContains(&Self::STARTEND_ENCODING, startchar) {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -122,7 +131,7 @@ impl OneDReader for CodaBarReader {
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(self.decodeRowRXingResult.chars().count() - 1)
|
||||
.unwrap();
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if !Self::arrayContains(&Self::STARTEND_ENCODING, endchar) {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -133,23 +142,29 @@ impl OneDReader for CodaBarReader {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
if !hints.contains_key(&DecodeHintType::RETURN_CODABAR_START_END) {
|
||||
// self.decodeRowRXingResult.deleteCharAt(self.decodeRowRXingResult.chars().count() - 1);
|
||||
// self.decodeRowRXingResult.deleteCharAt(0);
|
||||
if !matches!(
|
||||
hints.get(&DecodeHintType::RETURN_CODABAR_START_END),
|
||||
Some(DecodeHintValue::ReturnCodabarStartEnd(true))
|
||||
) {
|
||||
self.decodeRowRXingResult =
|
||||
self.decodeRowRXingResult[1..self.decodeRowRXingResult.len() - 1].to_owned();
|
||||
}
|
||||
|
||||
let mut runningCount = 0;
|
||||
for i in 0..startOffset {
|
||||
// for (int i = 0; i < startOffset; i++) {
|
||||
runningCount += self.counters[i];
|
||||
}
|
||||
runningCount += self.counters.iter().take(startOffset).sum::<u32>();
|
||||
// for i in 0..startOffset {
|
||||
// runningCount += self.counters[i];
|
||||
// }
|
||||
let left: f32 = runningCount as f32;
|
||||
for i in startOffset..(nextStart - 1) {
|
||||
// for (int i = startOffset; i < nextStart - 1; i++) {
|
||||
runningCount += self.counters[i];
|
||||
}
|
||||
runningCount += self
|
||||
.counters
|
||||
.iter()
|
||||
.skip(startOffset)
|
||||
.take(nextStart)
|
||||
.sum::<u32>();
|
||||
// for i in startOffset..(nextStart - 1) {
|
||||
// runningCount += self.counters[i];
|
||||
// }
|
||||
let right: f32 = runningCount as f32;
|
||||
|
||||
let mut result = RXingResult::new(
|
||||
@@ -224,10 +239,13 @@ impl CodaBarReader {
|
||||
let mut pos = start;
|
||||
for i in 0..=end {
|
||||
// for (int i = 0; i <= end; i++) {
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS
|
||||
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize];
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize];
|
||||
for j in (0_usize..=6).rev() {
|
||||
// for (int j = 6; j >= 0; j--) {
|
||||
// Even j = bars, while odd j = spaces. Categories 2 and 3 are for
|
||||
// long stripes, while 0 and 1 are for short stripes.
|
||||
let category = (j & 1) + ((pattern as usize) & 1) * 2;
|
||||
@@ -260,10 +278,13 @@ impl CodaBarReader {
|
||||
pos = start;
|
||||
for i in 0..=end {
|
||||
// for (int i = 0; i <= end; i++) {
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS
|
||||
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize];
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize];
|
||||
for j in (0usize..=6).rev() {
|
||||
// for (int j = 6; j >= 0; j--) {
|
||||
// Even j = bars, while odd j = spaces. Categories 2 and 3 are for
|
||||
// long stripes, while 0 and 1 are for short stripes.
|
||||
let category = (j & 1) + ((pattern as usize) & 1) * 2;
|
||||
@@ -312,9 +333,8 @@ impl CodaBarReader {
|
||||
self.counters[self.counterLength] = e;
|
||||
self.counterLength += 1;
|
||||
if self.counterLength >= self.counters.len() {
|
||||
let mut temp = vec![0; self.counterLength * 2]; //new int[counterLength * 2];
|
||||
let mut temp = vec![0; self.counterLength * 2];
|
||||
temp[0..self.counterLength].clone_from_slice(&self.counters[..]);
|
||||
// System.arraycopy(counters, 0, temp, 0, counterLength);
|
||||
self.counters = temp;
|
||||
}
|
||||
}
|
||||
@@ -334,7 +354,6 @@ impl CodaBarReader {
|
||||
// We make an exception if the whitespace is the first element.
|
||||
let mut patternSize = 0;
|
||||
for j in i..(i + 7) {
|
||||
// for (int j = i; j < i + 7; j++) {
|
||||
patternSize += self.counters[j];
|
||||
}
|
||||
if i == 1 || self.counters[i - 1] >= patternSize / 2 {
|
||||
@@ -348,14 +367,7 @@ impl CodaBarReader {
|
||||
}
|
||||
|
||||
pub fn arrayContains(array: &[char], key: char) -> bool {
|
||||
// if (array != null) {
|
||||
for c in array {
|
||||
if c == &key {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// }
|
||||
false
|
||||
array.contains(&key)
|
||||
}
|
||||
|
||||
// Assumes that counters[position] is a bar.
|
||||
@@ -371,7 +383,6 @@ impl CodaBarReader {
|
||||
let mut minBar = u32::MAX;
|
||||
let mut j = position;
|
||||
while j < end {
|
||||
// for (int j = position; j < end; j += 2) {
|
||||
let currentCounter = theCounters[j];
|
||||
if currentCounter < minBar {
|
||||
minBar = currentCounter;
|
||||
@@ -388,14 +399,9 @@ impl CodaBarReader {
|
||||
let mut minSpace = u32::MAX;
|
||||
let mut j = position + 1;
|
||||
while j < end {
|
||||
// for (int j = position + 1; j < end; j += 2) {
|
||||
let currentCounter = theCounters[j];
|
||||
if currentCounter < minSpace {
|
||||
minSpace = currentCounter;
|
||||
}
|
||||
if currentCounter > maxSpace {
|
||||
maxSpace = currentCounter;
|
||||
}
|
||||
minSpace = std::cmp::min(currentCounter, minSpace);
|
||||
maxSpace = std::cmp::max(currentCounter, maxSpace);
|
||||
|
||||
j += 2;
|
||||
}
|
||||
@@ -404,7 +410,6 @@ impl CodaBarReader {
|
||||
let mut bitmask = 1 << 7;
|
||||
let mut pattern = 0;
|
||||
for i in 0..7 {
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
let threshold = if (i & 1) == 0 {
|
||||
thresholdBar
|
||||
} else {
|
||||
@@ -417,7 +422,6 @@ impl CodaBarReader {
|
||||
}
|
||||
|
||||
for i in 0..Self::CHARACTER_ENCODINGS.len() {
|
||||
// for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) {
|
||||
if Self::CHARACTER_ENCODINGS[i] == pattern {
|
||||
return i as i32;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,15 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
format!("{DEFAULT_GUARD}{contents}{DEFAULT_GUARD}")
|
||||
} else {
|
||||
// Verify input and calculate decoded length.
|
||||
let firstChar = contents.chars().next().unwrap().to_ascii_uppercase();
|
||||
let firstChar = contents
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
let lastChar = contents
|
||||
.chars()
|
||||
.nth(contents.chars().count() - 1)
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
let startsNormal = CodaBarReader::arrayContains(&START_END_CHARS, firstChar);
|
||||
let endsNormal = CodaBarReader::arrayContains(&START_END_CHARS, lastChar);
|
||||
@@ -80,9 +84,7 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
|
||||
// The start character and the end character are decoded to 10 length each.
|
||||
let mut resultLength = 20;
|
||||
//for i in 1..contents.chars().count() {
|
||||
for ch in contents[1..contents.chars().count() - 1].chars() {
|
||||
// for (int i = 1; i < contents.length() - 1; i++) {
|
||||
if ch.is_ascii_digit() || ch == '-' || ch == '$' {
|
||||
resultLength += 9;
|
||||
} else if CodaBarReader::arrayContains(
|
||||
@@ -103,7 +105,11 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
let mut position = 0;
|
||||
for index in 0..contents.chars().count() {
|
||||
// for (int index = 0; index < contents.length(); index++) {
|
||||
let mut c = contents.chars().nth(index).unwrap().to_ascii_uppercase();
|
||||
let mut c = contents
|
||||
.chars()
|
||||
.nth(index)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
if index == 0 || index == contents.chars().count() - 1 {
|
||||
// The start/end chars are not in the CodaBarReader.ALPHABET.
|
||||
c = match c {
|
||||
@@ -116,7 +122,6 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
}
|
||||
let mut code = 0;
|
||||
for i in 0..CodaBarReader::ALPHABET.len() {
|
||||
// for (int i = 0; i < CodaBarReader::ALPHABET.length; i++) {
|
||||
// Found any, because I checked above.
|
||||
if c == CodaBarReader::ALPHABET[i] {
|
||||
code = CodaBarReader::CHARACTER_ENCODINGS[i];
|
||||
|
||||
@@ -98,11 +98,6 @@ impl OneDReader for Code128Reader {
|
||||
|
||||
nextStart += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
// for counter in counters {
|
||||
// // for (int counter : counters) {
|
||||
// nextStart += counter;
|
||||
// }
|
||||
|
||||
// Take care of illegal start codes
|
||||
match code {
|
||||
CODE_START_A | CODE_START_B | CODE_START_C => {
|
||||
@@ -328,11 +323,6 @@ impl OneDReader for Code128Reader {
|
||||
};
|
||||
let new_str = result.chars().take(len_trim).collect();
|
||||
result = new_str;
|
||||
// if codeSet == CODE_CODE_C {
|
||||
// result.delete(resultLength - 2, resultLength);
|
||||
// } else {
|
||||
// result.delete(resultLength - 1, resultLength);
|
||||
// }
|
||||
}
|
||||
|
||||
let left: f32 = (startPatternInfo[1] + startPatternInfo[0]) as f32 / 2.0;
|
||||
@@ -341,8 +331,9 @@ impl OneDReader for Code128Reader {
|
||||
let rawCodesSize = rawCodes.len();
|
||||
let mut rawBytes = vec![0u8; rawCodesSize];
|
||||
for (i, rawByte) in rawBytes.iter_mut().enumerate().take(rawCodesSize) {
|
||||
// for (int i = 0; i < rawCodesSize; i++) {
|
||||
*rawByte = *rawCodes.get(i).unwrap();
|
||||
*rawByte = *rawCodes
|
||||
.get(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
}
|
||||
let mut resultObject = RXingResult::new(
|
||||
&result,
|
||||
@@ -374,7 +365,6 @@ impl Code128Reader {
|
||||
let patternLength = counters.len();
|
||||
|
||||
for i in rowOffset..width {
|
||||
// for (int i = rowOffset; i < width; i++) {
|
||||
if row.get(i) != isWhite {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
@@ -382,7 +372,6 @@ impl Code128Reader {
|
||||
let mut bestVariance = MAX_AVG_VARIANCE;
|
||||
let mut bestMatch = -1_isize;
|
||||
for startCode in CODE_START_A..=CODE_START_C {
|
||||
// for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
|
||||
let variance = one_d_reader::patternMatchVariance(
|
||||
&counters,
|
||||
&CODE_PATTERNS[startCode as usize],
|
||||
@@ -407,7 +396,6 @@ impl Code128Reader {
|
||||
patternStart += (counters[0] + counters[1]) as usize;
|
||||
|
||||
counters.copy_within(2..(counterPosition - 1 + 2), 0);
|
||||
// System.arraycopy(counters, 2, counters, 0, counterPosition - 1);
|
||||
counters[counterPosition - 1] = 0;
|
||||
counters[counterPosition] = 0;
|
||||
counterPosition -= 1;
|
||||
@@ -432,7 +420,6 @@ impl Code128Reader {
|
||||
let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
|
||||
let mut bestMatch = -1_isize;
|
||||
for d in 0..CODE_PATTERNS.len() {
|
||||
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
|
||||
let pattern = &CODE_PATTERNS[d];
|
||||
let variance =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
|
||||
@@ -73,13 +73,17 @@ impl OneDimensionalCodeWriter for Code128Writer {
|
||||
) -> Result<Vec<bool>, Exceptions> {
|
||||
let forcedCodeSet = check(contents, hints)?;
|
||||
|
||||
let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) =
|
||||
hints.get(&EncodeHintType::CODE128_COMPACT)
|
||||
{
|
||||
*compat
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let hasCompactionHint = matches!(
|
||||
hints.get(&EncodeHintType::CODE128_COMPACT),
|
||||
Some(EncodeHintValue::Code128Compact(true))
|
||||
);
|
||||
// let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) =
|
||||
// hints.get(&EncodeHintType::CODE128_COMPACT)
|
||||
// {
|
||||
// *compat
|
||||
// } else {
|
||||
// false
|
||||
// };
|
||||
// let hasCompactionHint = hints != null && hints.containsKey(EncodeHintType::CODE128_COMPACT) &&
|
||||
// Boolean.parseBoolean(hints.get(EncodeHintType::CODE128_COMPACT).toString());
|
||||
|
||||
@@ -103,7 +107,7 @@ fn check(contents: &str, hints: &crate::EncodingHintDictionary) -> Result<i32, E
|
||||
// Check for forced code set hint.
|
||||
let mut forcedCodeSet = -1_i32;
|
||||
if hints.contains_key(&EncodeHintType::FORCE_CODE_SET) {
|
||||
let Some(EncodeHintValue::ForceCodeSet(codeSetHint)) = hints.get(&EncodeHintType::FORCE_CODE_SET) else { panic!("This must exist by checks previous")};
|
||||
let Some(EncodeHintValue::ForceCodeSet(codeSetHint)) = hints.get(&EncodeHintType::FORCE_CODE_SET) else { return Err(Exceptions::IllegalStateException(None)) };
|
||||
match codeSetHint.as_str() {
|
||||
"A" => forcedCodeSet = CODE_CODE_A as i32,
|
||||
"B" => forcedCodeSet = CODE_CODE_B as i32,
|
||||
@@ -192,6 +196,7 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
//Select code to use
|
||||
let newCodeSet = if forcedCodeSet == -1 {
|
||||
chooseCode(contents, position, codeSet)
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
} else {
|
||||
forcedCodeSet as usize // THIS IS RISKY
|
||||
};
|
||||
@@ -201,7 +206,11 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
if newCodeSet == codeSet {
|
||||
// Encode the current character
|
||||
// First handle escapes
|
||||
match contents.chars().nth(position).unwrap() {
|
||||
match contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
ESCAPE_FNC_1 => patternIndex = CODE_FNC_1 as isize,
|
||||
ESCAPE_FNC_2 => patternIndex = CODE_FNC_2 as isize,
|
||||
ESCAPE_FNC_3 => patternIndex = CODE_FNC_3 as isize,
|
||||
@@ -217,16 +226,24 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
{
|
||||
match codeSet {
|
||||
CODE_CODE_A => {
|
||||
patternIndex =
|
||||
contents.chars().nth(position).unwrap() as isize - ' ' as isize;
|
||||
patternIndex = contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize;
|
||||
if patternIndex < 0 {
|
||||
// everything below a space character comes behind the underscore in the code patterns table
|
||||
patternIndex += '`' as isize;
|
||||
}
|
||||
}
|
||||
CODE_CODE_B => {
|
||||
patternIndex =
|
||||
contents.chars().nth(position).unwrap() as isize - ' ' as isize
|
||||
patternIndex = contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize
|
||||
}
|
||||
_ => {
|
||||
// CODE_CODE_C
|
||||
@@ -242,9 +259,9 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
.take(2)
|
||||
.map(|(_u, c)| c)
|
||||
.collect();
|
||||
patternIndex = s.parse::<isize>().unwrap();
|
||||
// contents[position..position + 2].parse::<isize>().unwrap();
|
||||
// patternIndex = Integer.parseInt(contents.substring(position, position + 2));
|
||||
patternIndex = s.parse::<isize>().map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!("issue parsing {s}: {e}")))
|
||||
})?;
|
||||
position += 1;
|
||||
} // Also incremented below
|
||||
}
|
||||
@@ -308,11 +325,7 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
|
||||
// Compute code width
|
||||
let mut codeWidth = 0_usize;
|
||||
for pattern in &mut *patterns {
|
||||
// for (int[] pattern : patterns) {
|
||||
for width in pattern {
|
||||
// for (int width : pattern) {
|
||||
codeWidth += *width;
|
||||
}
|
||||
codeWidth += pattern.iter().sum::<usize>();
|
||||
}
|
||||
|
||||
// Compute result
|
||||
@@ -326,99 +339,99 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
|
||||
result
|
||||
}
|
||||
|
||||
fn findCType(value: &str, start: usize) -> CType {
|
||||
fn findCType(value: &str, start: usize) -> Option<CType> {
|
||||
let last = value.chars().count();
|
||||
if start >= last {
|
||||
return CType::Uncodable;
|
||||
return Some(CType::Uncodable);
|
||||
}
|
||||
let c = value.chars().nth(start).unwrap();
|
||||
let c = value.chars().nth(start)?;
|
||||
if c == ESCAPE_FNC_1 {
|
||||
return CType::Fnc1;
|
||||
return Some(CType::Fnc1);
|
||||
}
|
||||
if !('0'..='9').contains(&c) {
|
||||
return CType::Uncodable;
|
||||
return Some(CType::Uncodable);
|
||||
}
|
||||
if start + 1 >= last {
|
||||
return CType::OneDigit;
|
||||
return Some(CType::OneDigit);
|
||||
}
|
||||
let c = value.chars().nth(start + 1).unwrap();
|
||||
let c = value.chars().nth(start + 1)?;
|
||||
if !('0'..='9').contains(&c) {
|
||||
return CType::OneDigit;
|
||||
return Some(CType::OneDigit);
|
||||
}
|
||||
CType::TwoDigits
|
||||
Some(CType::TwoDigits)
|
||||
}
|
||||
|
||||
fn chooseCode(value: &str, start: usize, oldCode: usize) -> usize {
|
||||
let mut lookahead = findCType(value, start);
|
||||
fn chooseCode(value: &str, start: usize, oldCode: usize) -> Option<usize> {
|
||||
let mut lookahead = findCType(value, start)?;
|
||||
if lookahead == CType::OneDigit {
|
||||
if oldCode == CODE_CODE_A {
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
return CODE_CODE_B;
|
||||
return Some(CODE_CODE_B);
|
||||
}
|
||||
if lookahead == CType::Uncodable {
|
||||
if start < value.chars().count() {
|
||||
let c = value.chars().nth(start).unwrap();
|
||||
let c = value.chars().nth(start)?;
|
||||
if c < ' '
|
||||
|| (oldCode == CODE_CODE_A && (c < '`' || (c >= ESCAPE_FNC_1 && c <= ESCAPE_FNC_4)))
|
||||
{
|
||||
// can continue in code A, encodes ASCII 0 to 95 or FNC1 to FNC4
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
}
|
||||
return CODE_CODE_B; // no choice
|
||||
return Some(CODE_CODE_B); // no choice
|
||||
}
|
||||
if oldCode == CODE_CODE_A && lookahead == CType::Fnc1 {
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
if oldCode == CODE_CODE_C {
|
||||
// can continue in code C
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
}
|
||||
if oldCode == CODE_CODE_B {
|
||||
if lookahead == CType::Fnc1 {
|
||||
return CODE_CODE_B; // can continue in code B
|
||||
return Some(CODE_CODE_B); // can continue in code B
|
||||
}
|
||||
// Seen two consecutive digits, see what follows
|
||||
lookahead = findCType(value, start + 2);
|
||||
lookahead = findCType(value, start + 2)?;
|
||||
if lookahead == CType::Uncodable || lookahead == CType::OneDigit {
|
||||
return CODE_CODE_B; // not worth switching now
|
||||
return Some(CODE_CODE_B); // not worth switching now
|
||||
}
|
||||
if lookahead == CType::Fnc1 {
|
||||
// two digits, then FNC_1...
|
||||
lookahead = findCType(value, start + 3);
|
||||
lookahead = findCType(value, start + 3)?;
|
||||
if lookahead == CType::TwoDigits {
|
||||
// then two more digits, switch
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
} else {
|
||||
return CODE_CODE_B; // otherwise not worth switching
|
||||
return Some(CODE_CODE_B); // otherwise not worth switching
|
||||
}
|
||||
}
|
||||
// At this point, there are at least 4 consecutive digits.
|
||||
// Look ahead to choose whether to switch now or on the next round.
|
||||
let mut index = start + 4;
|
||||
let mut lookahead = findCType(value, index);
|
||||
let mut lookahead = findCType(value, index)?;
|
||||
while lookahead == CType::TwoDigits {
|
||||
// while (lookahead = findCType(value, index)) == CType::TWO_DIGITS {
|
||||
index += 2;
|
||||
lookahead = findCType(value, index);
|
||||
lookahead = findCType(value, index)?;
|
||||
}
|
||||
if lookahead == CType::OneDigit {
|
||||
// odd number of digits, switch later
|
||||
return CODE_CODE_B;
|
||||
return Some(CODE_CODE_B);
|
||||
}
|
||||
return CODE_CODE_C; // even number of digits, switch now
|
||||
return Some(CODE_CODE_C); // even number of digits, switch now
|
||||
}
|
||||
// Here oldCode == 0, which means we are choosing the initial code
|
||||
if lookahead == CType::Fnc1 {
|
||||
// ignore FNC_1
|
||||
lookahead = findCType(value, start + 1);
|
||||
lookahead = findCType(value, start + 1)?;
|
||||
}
|
||||
if lookahead == CType::TwoDigits {
|
||||
// at least two digits, start in code C
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
}
|
||||
CODE_CODE_B
|
||||
Some(CODE_CODE_B)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -520,7 +533,12 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
Latch::None => { /* skip */ }
|
||||
}
|
||||
if charset == Charset::C {
|
||||
if contents.chars().nth(i).unwrap() == ESCAPE_FNC_1 {
|
||||
if contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
== ESCAPE_FNC_1
|
||||
{
|
||||
addPattern(
|
||||
&mut patterns,
|
||||
CODE_FNC_1,
|
||||
@@ -537,7 +555,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
.collect();
|
||||
addPattern(
|
||||
&mut patterns,
|
||||
s.parse::<usize>().unwrap(),
|
||||
s.parse::<usize>().map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!("unable to parse {s} {e}")))
|
||||
})?,
|
||||
&mut checkSum,
|
||||
&mut checkWeight,
|
||||
i,
|
||||
@@ -549,7 +569,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
}
|
||||
} else {
|
||||
// charset A or B
|
||||
let mut patternIndex = match contents.chars().nth(i).unwrap() {
|
||||
let mut patternIndex = match contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
ESCAPE_FNC_1 => CODE_FNC_1 as isize,
|
||||
ESCAPE_FNC_2 => CODE_FNC_2 as isize,
|
||||
ESCAPE_FNC_3 => CODE_FNC_3 as isize,
|
||||
@@ -562,7 +586,14 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
CODE_FNC_4_B as isize
|
||||
}
|
||||
}
|
||||
_ => contents.chars().nth(i).unwrap() as isize - ' ' as isize,
|
||||
_ => {
|
||||
contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize
|
||||
}
|
||||
};
|
||||
if ((charset == Charset::A && latch != Latch::Shift)
|
||||
|| (charset == Charset::B && latch == Latch::Shift))
|
||||
@@ -611,7 +642,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
}
|
||||
|
||||
fn canEncode(contents: &str, charset: Charset, position: usize) -> bool {
|
||||
let c = contents.chars().nth(position).unwrap();
|
||||
let Some(c) = contents.chars().nth(position) else {
|
||||
return false;
|
||||
};
|
||||
match charset {
|
||||
Charset::A => {
|
||||
c == ESCAPE_FNC_1
|
||||
@@ -628,10 +661,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
|| B.find(c).is_some()
|
||||
}
|
||||
Charset::C => {
|
||||
let Some(c_p_1) = contents.chars().nth(position + 1) else {
|
||||
return false;
|
||||
};
|
||||
c == ESCAPE_FNC_1
|
||||
|| (position + 1 < contents.chars().count()
|
||||
&& isDigit(c)
|
||||
&& isDigit(contents.chars().nth(position + 1).unwrap()))
|
||||
|| (position + 1 < contents.chars().count() && isDigit(c) && isDigit(c_p_1))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -647,7 +681,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
memoizedCost: &mut Vec<Vec<u32>>,
|
||||
minPath: &mut Vec<Vec<Latch>>,
|
||||
) -> Result<u32, Exceptions> {
|
||||
assert!(position < contents.chars().count());
|
||||
if position >= contents.chars().count() {
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
let mCost = memoizedCost[charset.ordinal()][position];
|
||||
if mCost > 0 {
|
||||
return Ok(mCost);
|
||||
@@ -665,7 +701,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
let mut latch = Latch::None;
|
||||
if charset != sets[i] {
|
||||
cost += 1;
|
||||
latch = sets[i].into(); //Latch::valueOf(sets[i].toString());
|
||||
latch = sets[i].into();
|
||||
}
|
||||
if !atEnd {
|
||||
cost += encode_with_start_position(
|
||||
@@ -707,7 +743,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
cost += 1;
|
||||
latch = Latch::C;
|
||||
}
|
||||
let advance = if contents.chars().nth(position).unwrap() == ESCAPE_FNC_1 {
|
||||
let advance = if contents.chars().nth(position).unwrap_or_default() == ESCAPE_FNC_1 {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
|
||||
@@ -46,11 +46,7 @@ impl OneDReader for Code39Reader {
|
||||
row: &crate::common::BitArray,
|
||||
_hints: &DecodingHintDictionary,
|
||||
) -> Result<crate::RXingResult, Exceptions> {
|
||||
// let theCounters = self.counters;
|
||||
let mut counters = [0_u32; 9];
|
||||
// self.counters.fill(0);
|
||||
// let result = self.decodeRowRXingResult;
|
||||
// result.setLength(0);
|
||||
self.decodeRowRXingResult.clear();
|
||||
|
||||
let start = Self::findAsteriskPattern(row, &mut counters)?;
|
||||
@@ -70,7 +66,6 @@ impl OneDReader for Code39Reader {
|
||||
self.decodeRowRXingResult.push(decodedChar);
|
||||
lastStart = nextStart;
|
||||
for counter in &counters {
|
||||
// for (int counter : theCounters) {
|
||||
nextStart += *counter as usize;
|
||||
}
|
||||
// Read off white space
|
||||
@@ -79,16 +74,13 @@ impl OneDReader for Code39Reader {
|
||||
if decodedChar == '*' {
|
||||
break;
|
||||
}
|
||||
} //(decodedChar != '*');
|
||||
}
|
||||
self.decodeRowRXingResult
|
||||
.truncate(self.decodeRowRXingResult.len() - 1); // remove asterisk
|
||||
|
||||
// Look for whitespace after pattern:
|
||||
let mut lastPatternSize = 0;
|
||||
for counter in &counters {
|
||||
// for (int counter : self.counters) {
|
||||
lastPatternSize += *counter;
|
||||
}
|
||||
let lastPatternSize = counters.iter().sum::<u32>();
|
||||
|
||||
let whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize as usize;
|
||||
// If 50% of last pattern size, following last pattern, is not whitespace, fail
|
||||
// (but if it's whitespace to the very end of the image, that's OK)
|
||||
@@ -100,16 +92,24 @@ impl OneDReader for Code39Reader {
|
||||
let max = self.decodeRowRXingResult.chars().count() - 1;
|
||||
let mut total = 0;
|
||||
for i in 0..max {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
if let Some(pos) =
|
||||
Self::ALPHABET_STRING.find(self.decodeRowRXingResult.chars().nth(i).unwrap())
|
||||
{
|
||||
if let Some(pos) = Self::ALPHABET_STRING.find(
|
||||
self.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
) {
|
||||
total += pos;
|
||||
}
|
||||
// total += Self::ALPHABET_STRING.indexOf(self.decodeRowRXingResult.chars().nth(i).unwrap());
|
||||
}
|
||||
if self.decodeRowRXingResult.chars().nth(max).unwrap()
|
||||
!= Self::ALPHABET_STRING.chars().nth(total % 43).unwrap()
|
||||
if self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(max)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
!= Self::ALPHABET_STRING
|
||||
.chars()
|
||||
.nth(total % 43)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -256,9 +256,8 @@ impl Code39Reader {
|
||||
let mut maxNarrowCounter = 0;
|
||||
let mut wideCounters;
|
||||
loop {
|
||||
let mut minCounter = u32::MAX; //Integer.MAX_VALUE;
|
||||
let mut minCounter = u32::MAX;
|
||||
for counter in counters {
|
||||
// for (int counter : counters) {
|
||||
if counter < &minCounter && counter > &maxNarrowCounter {
|
||||
minCounter = *counter;
|
||||
}
|
||||
@@ -268,7 +267,6 @@ impl Code39Reader {
|
||||
let mut totalWideCountersWidth = 0;
|
||||
let mut pattern = 0;
|
||||
for (i, counter) in counters.iter().enumerate().take(numCounters) {
|
||||
// for (int i = 0; i < numCounters; i++) {
|
||||
if *counter > maxNarrowCounter {
|
||||
pattern |= 1 << (numCounters - 1 - i);
|
||||
wideCounters += 1;
|
||||
@@ -281,7 +279,6 @@ impl Code39Reader {
|
||||
// counter is more than 1.5 times the average:
|
||||
let mut i = 0;
|
||||
while i < numCounters && wideCounters > 0 {
|
||||
// for (int i = 0; i < numCounters && wideCounters > 0; i++) {
|
||||
let counter = counters[i];
|
||||
if counter > maxNarrowCounter {
|
||||
wideCounters -= 1;
|
||||
@@ -299,15 +296,17 @@ impl Code39Reader {
|
||||
if wideCounters <= 3 {
|
||||
break;
|
||||
}
|
||||
} //while ;
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
fn patternToChar(pattern: u32) -> Result<char, Exceptions> {
|
||||
for i in 0..Self::CHARACTER_ENCODINGS.len() {
|
||||
// for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) {
|
||||
if Self::CHARACTER_ENCODINGS[i] == pattern {
|
||||
return Ok(Self::ALPHABET_STRING.chars().nth(i).unwrap());
|
||||
return Self::ALPHABET_STRING
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None));
|
||||
}
|
||||
}
|
||||
if pattern == Self::ASTERISK_ENCODING {
|
||||
@@ -323,15 +322,22 @@ impl Code39Reader {
|
||||
while i < length {
|
||||
// for i in 0..length {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
let c = encoded.chars().nth(i).unwrap();
|
||||
let c = encoded
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if c == '+' || c == '$' || c == '%' || c == '/' {
|
||||
let next = encoded.chars().nth(i + 1).unwrap();
|
||||
let next = encoded
|
||||
.chars()
|
||||
.nth(i + 1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
let mut decodedChar = '\0';
|
||||
match c {
|
||||
'+' => {
|
||||
// +A to +Z map to a to z
|
||||
if ('A'..='Z').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 + 32).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 32)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -339,7 +345,8 @@ impl Code39Reader {
|
||||
'$' => {
|
||||
// $A to $Z map to control codes SH to SB
|
||||
if ('A'..='Z').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 64).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 64)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -347,13 +354,17 @@ impl Code39Reader {
|
||||
'%' => {
|
||||
// %A to %E map to control codes ESC to US
|
||||
if ('A'..='E').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 38).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 38)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else if ('F'..='J').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 11).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 11)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else if ('K'..='O').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 + 16).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 16)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else if ('P'..='T').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 + 43).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 43)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else if next == 'U' {
|
||||
decodedChar = 0 as char;
|
||||
} else if next == 'V' {
|
||||
@@ -369,7 +380,8 @@ impl Code39Reader {
|
||||
'/' => {
|
||||
// /A to /O map to ! to , and /Z maps to :
|
||||
if ('A'..='O').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 32).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 32)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else if next == 'Z' {
|
||||
decodedChar = ':';
|
||||
} else {
|
||||
|
||||
@@ -43,7 +43,12 @@ impl OneDimensionalCodeWriter for Code39Writer {
|
||||
// for i in 0..length {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
if Code39Reader::ALPHABET_STRING
|
||||
.find(contents.chars().nth(i).unwrap())
|
||||
.find(
|
||||
contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
contents = Self::tryToConvertToExtendedMode(&contents)?;
|
||||
@@ -53,15 +58,6 @@ impl OneDimensionalCodeWriter for Code39Writer {
|
||||
}
|
||||
break;
|
||||
}
|
||||
//let indexInString = Code39Reader::ALPHABET_STRING.indexOf(contents.charAt(i));
|
||||
// if indexInString < 0 {
|
||||
// contents = Self::tryToConvertToExtendedMode(&contents);
|
||||
// length = contents.chars().count();
|
||||
// if length > 80 {
|
||||
// return Err(Exceptions::IllegalArgumentException(format!("Requested contents should be less than 80 digits long, but got {} (extended full ASCII mode)",length)));
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
i += 1;
|
||||
}
|
||||
|
||||
@@ -74,11 +70,9 @@ impl OneDimensionalCodeWriter for Code39Writer {
|
||||
pos += Self::appendPattern(&mut result, pos as usize, &narrowWhite, false);
|
||||
//append next character to byte matrix
|
||||
for i in 0..length {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
let Some(indexInString) = Code39Reader::ALPHABET_STRING.find(contents.chars().nth(i).unwrap()) else {
|
||||
let Some(indexInString) = Code39Reader::ALPHABET_STRING.find(contents.chars().nth(i).ok_or(Exceptions::IndexOutOfBoundsException(None))?) else {
|
||||
continue;
|
||||
};
|
||||
// let indexInString = Code39Reader::ALPHABET_STRING.indexOf(contents.charAt(i));
|
||||
Self::toIntArray(
|
||||
Code39Reader::CHARACTER_ENCODINGS[indexInString],
|
||||
&mut widths,
|
||||
@@ -121,38 +115,56 @@ impl Code39Writer {
|
||||
_ => {
|
||||
if (character as u32) <= 26 {
|
||||
extendedContent.push('$');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + (character as u32 - 1)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + (character as u32 - 1))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character < ' ' {
|
||||
extendedContent.push('%');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + (character as u32 - 27)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + (character as u32 - 27))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= ',' || character == '/' || character == ':' {
|
||||
extendedContent.push('/');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + (character as u32 - 33)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + (character as u32 - 33))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= '9' {
|
||||
extendedContent
|
||||
.push(char::from_u32('0' as u32 + (character as u32 - 48)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('0' as u32 + (character as u32 - 48))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= '?' {
|
||||
extendedContent.push('%');
|
||||
extendedContent
|
||||
.push(char::from_u32('F' as u32 + (character as u32 - 59)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('F' as u32 + (character as u32 - 59))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= 'Z' {
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + (character as u32 - 65)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + (character as u32 - 65))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= '_' {
|
||||
extendedContent.push('%');
|
||||
extendedContent
|
||||
.push(char::from_u32('K' as u32 + (character as u32 - 91)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('K' as u32 + (character as u32 - 91))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= 'z' {
|
||||
extendedContent.push('+');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + (character as u32 - 97)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + (character as u32 - 97))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character as u32 <= 127 {
|
||||
extendedContent.push('%');
|
||||
extendedContent
|
||||
.push(char::from_u32('P' as u32 + (character as u32 - 123)).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('P' as u32 + (character as u32 - 123))
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(format!(
|
||||
"Requested content contains a non-encodable character: '{character}'"
|
||||
|
||||
@@ -68,8 +68,8 @@ impl OneDReader for Code93Reader {
|
||||
decodedChar = Self::patternToChar(pattern as u32)?;
|
||||
self.decodeRowRXingResult.push(decodedChar);
|
||||
lastStart = nextStart;
|
||||
|
||||
for counter in theCounters {
|
||||
// for (int counter : theCounters) {
|
||||
nextStart += counter as usize;
|
||||
}
|
||||
// Read off white space
|
||||
@@ -171,7 +171,6 @@ impl Code93Reader {
|
||||
|
||||
let mut counterPosition = 0;
|
||||
for i in rowOffset..width {
|
||||
// for (int i = rowOffset; i < width; i++) {
|
||||
if row.get(i) != isWhite {
|
||||
theCounters[counterPosition] += 1;
|
||||
} else {
|
||||
@@ -182,7 +181,6 @@ impl Code93Reader {
|
||||
patternStart += (theCounters[0] + theCounters[1]) as usize;
|
||||
|
||||
theCounters.copy_within(2..(counterPosition - 1 + 2), 0);
|
||||
// System.arraycopy(theCounters, 2, theCounters, 0, counterPosition - 1);
|
||||
theCounters[counterPosition - 1] = 0;
|
||||
theCounters[counterPosition] = 0;
|
||||
counterPosition -= 1;
|
||||
@@ -197,23 +195,17 @@ impl Code93Reader {
|
||||
}
|
||||
|
||||
fn toPattern(counters: &[u32; 6]) -> i32 {
|
||||
let mut sum = 0;
|
||||
for counter in counters {
|
||||
// for (int counter : counters) {
|
||||
sum += counter;
|
||||
}
|
||||
let sum = counters.iter().sum::<u32>();
|
||||
|
||||
let mut pattern = 0;
|
||||
let max = counters.len();
|
||||
for (i, counter) in counters.iter().enumerate().take(max) {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
let scaled = (*counter as f32 * 9.0 / sum as f32).round() as u32;
|
||||
// let scaled = Math.round(counters[i] * 9.0 / sum);
|
||||
if !(1..=4).contains(&scaled) {
|
||||
return -1;
|
||||
}
|
||||
if (i & 0x01) == 0 {
|
||||
for _j in 0..scaled {
|
||||
// for (int j = 0; j < scaled; j++) {
|
||||
pattern = (pattern << 1) | 0x01;
|
||||
}
|
||||
} else {
|
||||
@@ -225,7 +217,6 @@ impl Code93Reader {
|
||||
|
||||
fn patternToChar(pattern: u32) -> Result<char, Exceptions> {
|
||||
for i in 0..Self::CHARACTER_ENCODINGS.len() {
|
||||
// for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) {
|
||||
if Self::CHARACTER_ENCODINGS[i] == pattern {
|
||||
return Ok(Self::ALPHABET[i]);
|
||||
}
|
||||
@@ -240,18 +231,25 @@ impl Code93Reader {
|
||||
while i < length {
|
||||
// for i in 0..length {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
let c = encoded.chars().nth(i).unwrap();
|
||||
let c = encoded
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if ('a'..='d').contains(&c) {
|
||||
if i >= length - 1 {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
let next = encoded.chars().nth(i + 1).unwrap();
|
||||
let next = encoded
|
||||
.chars()
|
||||
.nth(i + 1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
let mut decodedChar = '\0';
|
||||
match c {
|
||||
'd' => {
|
||||
// +A to +Z map to a to z
|
||||
if ('A'..='Z').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 + 32).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 32)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
@@ -259,7 +257,8 @@ impl Code93Reader {
|
||||
'a' => {
|
||||
// $A to $Z map to control codes SH to SB
|
||||
if ('A'..='Z').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 64).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 64)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
@@ -267,16 +266,20 @@ impl Code93Reader {
|
||||
'b' => {
|
||||
if ('A'..='E').contains(&next) {
|
||||
// %A to %E map to control codes ESC to USep
|
||||
decodedChar = char::from_u32(next as u32 - 38).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 38)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else if ('F'..='J').contains(&next) {
|
||||
// %F to %J map to ; < = > ?
|
||||
decodedChar = char::from_u32(next as u32 - 11).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 11)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else if ('K'..='O').contains(&next) {
|
||||
// %K to %O map to [ \ ] ^ _
|
||||
decodedChar = char::from_u32(next as u32 + 16).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 16)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else if ('P'..='T').contains(&next) {
|
||||
// %P to %T map to { | } ~ DEL
|
||||
decodedChar = char::from_u32(next as u32 + 43).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 + 43)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else if next == 'U' {
|
||||
// %U map to NUL
|
||||
decodedChar = '\0';
|
||||
@@ -296,7 +299,8 @@ impl Code93Reader {
|
||||
'c' => {
|
||||
// /A to /O map to ! to , and /Z maps to :
|
||||
if ('A'..='O').contains(&next) {
|
||||
decodedChar = char::from_u32(next as u32 - 32).unwrap();
|
||||
decodedChar = char::from_u32(next as u32 - 32)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
} else if next == 'Z' {
|
||||
decodedChar = ':';
|
||||
} else {
|
||||
@@ -332,19 +336,26 @@ impl Code93Reader {
|
||||
let mut weight = 1;
|
||||
let mut total = 0;
|
||||
for i in (0..checkPosition).rev() {
|
||||
// for (int i = checkPosition - 1; i >= 0; i--) {
|
||||
total += weight
|
||||
* if let Some(pos) = Self::ALPHABET_STRING.find(result.chars().nth(i).unwrap()) {
|
||||
pos as i32
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
* Self::ALPHABET_STRING
|
||||
.find(
|
||||
result
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)
|
||||
.map_or_else(|| -1_i32, |v| v as i32);
|
||||
weight += 1;
|
||||
if weight > weightMax as i32 {
|
||||
weight = 1;
|
||||
}
|
||||
}
|
||||
if result.chars().nth(checkPosition).unwrap() != Self::ALPHABET[(total as usize) % 47] {
|
||||
if result
|
||||
.chars()
|
||||
.nth(checkPosition)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
!= Self::ALPHABET[(total as usize) % 47]
|
||||
{
|
||||
Err(Exceptions::ChecksumException(None))
|
||||
} else {
|
||||
Ok(())
|
||||
|
||||
@@ -48,7 +48,7 @@ impl OneDimensionalCodeWriter for Code93Writer {
|
||||
|
||||
for i in 0..length {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
let Some(indexInString) = Code93Reader::ALPHABET_STRING.find(contents.chars().nth(i).unwrap()) else {panic!("alphabet")};
|
||||
let Some(indexInString) = Code93Reader::ALPHABET_STRING.find(contents.chars().nth(i).ok_or(Exceptions::IndexOutOfBoundsException(None))?) else {panic!("alphabet")};
|
||||
pos += Self::appendPattern(
|
||||
&mut result,
|
||||
pos,
|
||||
@@ -61,7 +61,12 @@ impl OneDimensionalCodeWriter for Code93Writer {
|
||||
pos += Self::appendPattern(&mut result, pos, Code93Reader::CHARACTER_ENCODINGS[check1]);
|
||||
|
||||
//append the contents to reflect the first checksum added
|
||||
contents.push(Code93Reader::ALPHABET_STRING.chars().nth(check1).unwrap());
|
||||
contents.push(
|
||||
Code93Reader::ALPHABET_STRING
|
||||
.chars()
|
||||
.nth(check1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
);
|
||||
|
||||
let check2 = Self::computeChecksumIndex(&contents, 15);
|
||||
pos += Self::appendPattern(&mut result, pos, Code93Reader::CHARACTER_ENCODINGS[check2]);
|
||||
@@ -110,7 +115,6 @@ impl Code93Writer {
|
||||
|
||||
fn appendPattern(target: &mut [bool], pos: usize, a: u32) -> usize {
|
||||
for i in 0..9 {
|
||||
// for (int i = 0; i < 9; i++) {
|
||||
let temp = a & (1 << (8 - i));
|
||||
target[pos + i] = temp != 0;
|
||||
}
|
||||
@@ -118,6 +122,9 @@ impl Code93Writer {
|
||||
9
|
||||
}
|
||||
|
||||
/// Compute the checksum index
|
||||
///
|
||||
/// Panics if out of bounds or character isn't in the alphabet
|
||||
fn computeChecksumIndex(contents: &str, maxWeight: u32) -> usize {
|
||||
let mut weight = 1_u32;
|
||||
let mut total = 0_u32;
|
||||
@@ -148,19 +155,27 @@ impl Code93Writer {
|
||||
} else if character as u32 <= 26 {
|
||||
// SOH - SUB: ($)A - ($)Z
|
||||
extendedContent.push('a');
|
||||
extendedContent.push(char::from_u32('A' as u32 + character as u32 - 1).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + character as u32 - 1)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character as u32 <= 31 {
|
||||
// ESC - US: (%)A - (%)E
|
||||
extendedContent.push('b');
|
||||
extendedContent.push(char::from_u32('A' as u32 + character as u32 - 27).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + character as u32 - 27)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character == ' ' || character == '$' || character == '%' || character == '+' {
|
||||
// space $ % +
|
||||
extendedContent.push(character);
|
||||
} else if character <= ',' {
|
||||
// ! " # & ' ( ) * ,: (/)A - (/)L
|
||||
extendedContent.push('c');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + character as u32 - '!' as u32).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + character as u32 - '!' as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character <= '9' {
|
||||
extendedContent.push(character);
|
||||
} else if character == ':' {
|
||||
@@ -169,8 +184,10 @@ impl Code93Writer {
|
||||
} else if character <= '?' {
|
||||
// ; - ?: (%)F - (%)J
|
||||
extendedContent.push('b');
|
||||
extendedContent
|
||||
.push(char::from_u32('F' as u32 + character as u32 - ';' as u32).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('F' as u32 + character as u32 - ';' as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character == '@' {
|
||||
// @: (%)V
|
||||
extendedContent.push_str("bV");
|
||||
@@ -180,21 +197,27 @@ impl Code93Writer {
|
||||
} else if character <= '_' {
|
||||
// [ - _: (%)K - (%)O
|
||||
extendedContent.push('b');
|
||||
extendedContent
|
||||
.push(char::from_u32('K' as u32 + character as u32 - '[' as u32).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('K' as u32 + character as u32 - '[' as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character == '`' {
|
||||
// `: (%)W
|
||||
extendedContent.push_str("bW");
|
||||
} else if character <= 'z' {
|
||||
// a - z: (*)A - (*)Z
|
||||
extendedContent.push('d');
|
||||
extendedContent
|
||||
.push(char::from_u32('A' as u32 + character as u32 - 'a' as u32).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('A' as u32 + character as u32 - 'a' as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if character as u32 <= 127 {
|
||||
// { - DEL: (%)P - (%)T
|
||||
extendedContent.push('b');
|
||||
extendedContent
|
||||
.push(char::from_u32('P' as u32 + character as u32 - '{' as u32).unwrap());
|
||||
extendedContent.push(
|
||||
char::from_u32('P' as u32 + character as u32 - '{' as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(format!(
|
||||
"Requested content contains a non-encodable character: '{character}'"
|
||||
|
||||
@@ -64,11 +64,13 @@ impl UPCEANReader for EAN13Reader {
|
||||
rowOffset,
|
||||
&upc_ean_reader::L_AND_G_PATTERNS,
|
||||
)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32 % 10).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32 % 10)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
if bestMatch >= 10 {
|
||||
lgPatternFound |= 1 << (5 - x);
|
||||
}
|
||||
@@ -85,13 +87,13 @@ impl UPCEANReader for EAN13Reader {
|
||||
let mut x = 0;
|
||||
|
||||
while x < 6 && rowOffset < end {
|
||||
// for (int x = 0; x < 6 && rowOffset < end; x++) {
|
||||
let bestMatch =
|
||||
self.decodeDigit(row, &mut counters, rowOffset, &upc_ean_reader::L_PATTERNS)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
x += 1;
|
||||
@@ -150,7 +152,11 @@ impl EAN13Reader {
|
||||
for d in 0..10 {
|
||||
// for (int d = 0; d < 10; d++) {
|
||||
if lgPatternFound == Self::FIRST_DIGIT_ENCODINGS[d] {
|
||||
resultString.insert(0, char::from_u32('0' as u32 + d as u32).unwrap());
|
||||
resultString.insert(
|
||||
0,
|
||||
char::from_u32('0' as u32 + d as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,24 +40,15 @@ impl OneDimensionalCodeWriter for EAN13Writer {
|
||||
match length {
|
||||
12 => {
|
||||
// No check digit present, calculate it and add it
|
||||
|
||||
// try {
|
||||
let check = reader.getStandardUPCEANChecksum(&contents)?;
|
||||
// } catch (FormatException fe) {
|
||||
// throw new IllegalArgumentException(fe);
|
||||
// }
|
||||
contents.push_str(&check.to_string());
|
||||
}
|
||||
13 => {
|
||||
//try {
|
||||
if !reader.checkStandardUPCEANChecksum(&contents)? {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Contents do not pass checksum".to_owned(),
|
||||
)));
|
||||
}
|
||||
//} catch (FormatException ignored) {
|
||||
//return Err( Exceptions::IllegalArgumentException("Illegal contents".to_owned()));
|
||||
//}
|
||||
}
|
||||
_ => {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(format!(
|
||||
@@ -68,7 +59,12 @@ impl OneDimensionalCodeWriter for EAN13Writer {
|
||||
|
||||
EAN13Writer::checkNumeric(&contents)?;
|
||||
|
||||
let firstDigit = contents.chars().next().unwrap().to_digit(10).unwrap() as usize; //, 10);
|
||||
let firstDigit = contents
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize;
|
||||
let parities = EAN13Reader::FIRST_DIGIT_ENCODINGS[firstDigit];
|
||||
let mut result = [false; CODE_WIDTH];
|
||||
let mut pos = 0;
|
||||
@@ -80,7 +76,12 @@ impl OneDimensionalCodeWriter for EAN13Writer {
|
||||
// See EAN13Reader for a description of how the first digit & left bars are encoded
|
||||
for i in 1..=6 {
|
||||
// for (int i = 1; i <= 6; i++) {
|
||||
let mut digit = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(i), 10);
|
||||
let mut digit = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize;
|
||||
if (parities >> (6 - i) & 1) == 1 {
|
||||
digit += 10;
|
||||
}
|
||||
@@ -96,9 +97,12 @@ impl OneDimensionalCodeWriter for EAN13Writer {
|
||||
as usize;
|
||||
|
||||
for i in 7..=12 {
|
||||
// for (int i = 7; i <= 12; i++) {
|
||||
// let digit = Character.digit(contents.charAt(i), 10);
|
||||
let digit = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(i), 10);
|
||||
let digit = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize;
|
||||
|
||||
pos += EAN13Writer::appendPattern(
|
||||
&mut result,
|
||||
|
||||
@@ -50,13 +50,12 @@ impl UPCEANReader for EAN8Reader {
|
||||
|
||||
let mut x = 0;
|
||||
while x < 4 && rowOffset < end {
|
||||
// for (int x = 0; x < 4 && rowOffset < end; x++) {
|
||||
let bestMatch =
|
||||
self.decodeDigit(row, &mut counters, rowOffset, &upc_ean_reader::L_PATTERNS)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
@@ -69,13 +68,13 @@ impl UPCEANReader for EAN8Reader {
|
||||
|
||||
let mut x = 0;
|
||||
while x < 4 && rowOffset < end {
|
||||
// for (int x = 0; x < 4 && rowOffset < end; x++) {
|
||||
let bestMatch =
|
||||
self.decodeDigit(row, &mut counters, rowOffset, &upc_ean_reader::L_PATTERNS)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
x += 1;
|
||||
}
|
||||
|
||||
@@ -50,25 +50,16 @@ impl OneDimensionalCodeWriter for EAN8Writer {
|
||||
7 => {
|
||||
// No check digit present, calculate it and add it
|
||||
let check = reader.getStandardUPCEANChecksum(&contents)?;
|
||||
// try {
|
||||
// check = UPCEANReader.getStandardUPCEANChecksum(contents);
|
||||
// } catch (FormatException fe) {
|
||||
// throw new IllegalArgumentException(fe);
|
||||
// }
|
||||
|
||||
contents.push_str(&check.to_string());
|
||||
}
|
||||
8 =>
|
||||
// try {
|
||||
{
|
||||
8 => {
|
||||
if !EAN8Reader.checkStandardUPCEANChecksum(&contents)? {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Contents do not pass checksum".to_owned(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
// } catch (FormatException ignored) {
|
||||
// throw new IllegalArgumentException("Illegal contents");
|
||||
// }},
|
||||
_ => {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(format!(
|
||||
"Requested contents should be 7 or 8 digits long, but got {length}"
|
||||
@@ -78,7 +69,7 @@ impl OneDimensionalCodeWriter for EAN8Writer {
|
||||
|
||||
Self::checkNumeric(&contents)?;
|
||||
|
||||
let mut result = [false; CODE_WIDTH]; //new boolean[CODE_WIDTH];
|
||||
let mut result = [false; CODE_WIDTH];
|
||||
let mut pos = 0;
|
||||
|
||||
pos += Self::appendPattern(&mut result, pos, &upc_ean_reader::START_END_PATTERN, true)
|
||||
@@ -86,7 +77,13 @@ impl OneDimensionalCodeWriter for EAN8Writer {
|
||||
|
||||
for i in 0..=3 {
|
||||
// for (int i = 0; i <= 3; i++) {
|
||||
let digit = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(i), 10);
|
||||
let digit = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize;
|
||||
pos += Self::appendPattern(&mut result, pos, &upc_ean_reader::L_PATTERNS[digit], false)
|
||||
as usize;
|
||||
}
|
||||
@@ -96,7 +93,13 @@ impl OneDimensionalCodeWriter for EAN8Writer {
|
||||
|
||||
for i in 4..=7 {
|
||||
// for (int i = 4; i <= 7; i++) {
|
||||
let digit = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(i), 10);
|
||||
let digit = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize;
|
||||
pos += Self::appendPattern(&mut result, pos, &upc_ean_reader::L_PATTERNS[digit], true)
|
||||
as usize;
|
||||
}
|
||||
|
||||
@@ -43,23 +43,15 @@ impl Default for EANManufacturerOrgSupport {
|
||||
impl EANManufacturerOrgSupport {
|
||||
pub fn lookupCountryIdentifier(&self, productCode: &str) -> Option<&str> {
|
||||
let prefix = productCode[0..3].parse::<u32>().expect("must parse prefix");
|
||||
// let prefix = Integer.parseInt(productCode.substring(0, 3));
|
||||
let max = self.ranges.len();
|
||||
for (i, range) in self.ranges.iter().enumerate().take(max) {
|
||||
// for i in 0..max {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
// let range = self.ranges.get(i).expect("must have index i or fail");
|
||||
let start = range[0];
|
||||
if prefix < start {
|
||||
return None;
|
||||
}
|
||||
let end = if range.len() == 1 { start } else { range[1] };
|
||||
if prefix <= end {
|
||||
return Some(
|
||||
self.countryIdentifiers
|
||||
.get(i)
|
||||
.expect("must have index i or fail"), // .clone(),
|
||||
);
|
||||
return Some(self.countryIdentifiers.get(i)?);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,14 +123,6 @@ impl OneDReader for ITFReader {
|
||||
} else {
|
||||
DEFAULT_ALLOWED_LENGTHS.to_vec()
|
||||
};
|
||||
// int[] allowedLengths = null;
|
||||
// if (hints != null) {
|
||||
// allowedLengths = (int[]) hints.get(DecodeHintType.ALLOWED_LENGTHS);
|
||||
|
||||
// }
|
||||
// if (allowedLengths == null) {
|
||||
// allowedLengths = DEFAULT_ALLOWED_LENGTHS;
|
||||
// }
|
||||
|
||||
// To avoid false positives with 2D barcodes (and other patterns), make
|
||||
// an assumption that the decoded string must be a 'standard' length if it's short
|
||||
@@ -138,14 +130,11 @@ impl OneDReader for ITFReader {
|
||||
let mut lengthOK = false;
|
||||
let mut maxAllowedLength = 0;
|
||||
for allowedLength in allowedLengths {
|
||||
// for (int allowedLength : allowedLengths) {
|
||||
if length == allowedLength as usize {
|
||||
lengthOK = true;
|
||||
break;
|
||||
}
|
||||
if allowedLength > maxAllowedLength {
|
||||
maxAllowedLength = allowedLength;
|
||||
}
|
||||
maxAllowedLength = std::cmp::max(allowedLength, maxAllowedLength);
|
||||
}
|
||||
if !lengthOK && length > maxAllowedLength as usize {
|
||||
lengthOK = true;
|
||||
@@ -188,8 +177,7 @@ impl ITFReader {
|
||||
) -> Result<(), Exceptions> {
|
||||
let mut payloadStart = payloadStart;
|
||||
// Digits are interleaved in pairs - 5 black lines for one digit, and the
|
||||
// 5
|
||||
// interleaved white lines for the second digit.
|
||||
// 5 interleaved white lines for the second digit.
|
||||
// Therefore, need to scan 10 lines and then
|
||||
// split these into two arrays
|
||||
let mut counterDigitPair = [0_u32; 10]; //new int[10];
|
||||
@@ -201,23 +189,21 @@ impl ITFReader {
|
||||
one_d_reader::recordPattern(row, payloadStart, &mut counterDigitPair)?;
|
||||
// Split them into each array
|
||||
for k in 0..5 {
|
||||
// for (int k = 0; k < 5; k++) {
|
||||
let twoK = 2 * k;
|
||||
counterBlack[k] = counterDigitPair[twoK];
|
||||
counterWhite[k] = counterDigitPair[twoK + 1];
|
||||
}
|
||||
|
||||
let mut bestMatch = self.decodeDigit(&counterBlack)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch).unwrap());
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
bestMatch = self.decodeDigit(&counterWhite)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch).unwrap());
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
payloadStart += counterDigitPair.iter().sum::<u32>() as usize;
|
||||
|
||||
// for counterDigit in counterDigitPair {
|
||||
// // for (int counterDigit : counterDigitPair) {
|
||||
// payloadStart += counterDigit;
|
||||
// }
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -267,7 +253,6 @@ impl ITFReader {
|
||||
|
||||
let mut i = startPattern as isize - 1;
|
||||
while quietCount > 0 && i >= 0 {
|
||||
// for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) {
|
||||
if row.get(i as usize) {
|
||||
break;
|
||||
}
|
||||
@@ -313,18 +298,12 @@ impl ITFReader {
|
||||
row.reverse();
|
||||
let interim_function = || -> Result<[usize; 2], Exceptions> {
|
||||
let endStart = Self::skipWhiteSpace(row)?;
|
||||
let mut endPattern;
|
||||
endPattern =
|
||||
let mut endPattern =
|
||||
if let Ok(ptrn) = self.findGuardPattern(row, endStart, &END_PATTERN_REVERSED[0]) {
|
||||
ptrn
|
||||
} else {
|
||||
self.findGuardPattern(row, endStart, &END_PATTERN_REVERSED[1])?
|
||||
};
|
||||
// try {
|
||||
// endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED[0]);
|
||||
// } catch (NotFoundException nfe) {
|
||||
// endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED[1]);
|
||||
// }
|
||||
|
||||
// The start & end patterns must be pre/post fixed by a quiet zone. This
|
||||
// zone must be at least 10 times the width of a narrow line.
|
||||
@@ -332,8 +311,7 @@ impl ITFReader {
|
||||
self.validateQuietZone(row, endPattern[0])?;
|
||||
|
||||
// Now recalculate the indices of where the 'endblock' starts & stops to
|
||||
// accommodate
|
||||
// the reversed nature of the search
|
||||
// accommodate the reversed nature of the search
|
||||
let temp = endPattern[0];
|
||||
endPattern[0] = row.getSize() - endPattern[1];
|
||||
endPattern[1] = row.getSize() - temp;
|
||||
@@ -386,7 +364,6 @@ impl ITFReader {
|
||||
patternStart += (counters[0] + counters[1]) as usize;
|
||||
|
||||
counters.copy_within(2..(counterPosition - 1 + 2), 0);
|
||||
// System.arraycopy(counters, 2, counters, 0, counterPosition - 1);
|
||||
counters[counterPosition - 1] = 0;
|
||||
counters[counterPosition] = 0;
|
||||
counterPosition -= 1;
|
||||
@@ -413,7 +390,6 @@ impl ITFReader {
|
||||
let mut bestMatch = -1_isize;
|
||||
let max = PATTERNS.len();
|
||||
for (i, pattern) in PATTERNS.iter().enumerate().take(max) {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
let variance =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
if variance < bestVariance {
|
||||
|
||||
@@ -48,12 +48,20 @@ impl OneDimensionalCodeWriter for ITFWriter {
|
||||
let mut pos = Self::appendPattern(&mut result, 0, &START_PATTERN, true) as usize;
|
||||
let mut i = 0;
|
||||
while i < length {
|
||||
// for (int i = 0; i < length; i += 2) {
|
||||
let one = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize;
|
||||
let two = contents.chars().nth(i + 1).unwrap().to_digit(10).unwrap() as usize;
|
||||
let mut encoding = [0; 10]; //new int[10];
|
||||
let one = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize;
|
||||
let two = contents
|
||||
.chars()
|
||||
.nth(i + 1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize;
|
||||
let mut encoding = [0; 10];
|
||||
for j in 0..5 {
|
||||
// for (int j = 0; j < 5; j++) {
|
||||
encoding[2 * j] = PATTERNS[one][j];
|
||||
encoding[2 * j + 1] = PATTERNS[two][j];
|
||||
}
|
||||
|
||||
@@ -41,26 +41,20 @@ impl OneDReader for MultiFormatOneDReader {
|
||||
hints: &crate::DecodingHintDictionary,
|
||||
) -> Result<crate::RXingResult, crate::Exceptions> {
|
||||
for reader in self.0.iter_mut() {
|
||||
// for (OneDReader reader : readers) {
|
||||
// try {
|
||||
if let Ok(res) = reader.decodeRow(rowNumber, row, hints) {
|
||||
return Ok(res);
|
||||
}
|
||||
// } catch (ReaderException re) {
|
||||
// continue
|
||||
// }
|
||||
}
|
||||
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
}
|
||||
impl MultiFormatOneDReader {
|
||||
// private static final OneDReader[] EMPTY_ONED_ARRAY = new OneDReader[0];
|
||||
|
||||
// private final OneDReader[] readers;
|
||||
|
||||
pub fn new(hints: &DecodingHintDictionary) -> Self {
|
||||
let useCode39CheckDigit = hints.contains_key(&DecodeHintType::ASSUME_CODE_39_CHECK_DIGIT);
|
||||
let useCode39CheckDigit = matches!(
|
||||
hints.get(&DecodeHintType::ASSUME_CODE_39_CHECK_DIGIT),
|
||||
Some(DecodeHintValue::AssumeCode39CheckDigit(true))
|
||||
);
|
||||
let mut readers: Vec<Box<dyn OneDReader>> = Vec::new();
|
||||
if let Some(DecodeHintValue::PossibleFormats(possibleFormats)) =
|
||||
hints.get(&DecodeHintType::POSSIBLE_FORMATS)
|
||||
@@ -132,60 +126,54 @@ impl Reader for MultiFormatOneDReader {
|
||||
image: &mut crate::BinaryBitmap,
|
||||
hints: &DecodingHintDictionary,
|
||||
) -> Result<crate::RXingResult, Exceptions> {
|
||||
if let Ok(res) = self.doDecode(image, hints) {
|
||||
Ok(res)
|
||||
} else {
|
||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||
let metadata = result.getRXingResultMetadata();
|
||||
let mut orientation = 270;
|
||||
if metadata.contains_key(&RXingResultMetadataType::ORIENTATION) {
|
||||
// But if we found it reversed in doDecode(), add in that result here:
|
||||
orientation = (orientation
|
||||
+ if let Some(crate::RXingResultMetadataValue::Orientation(or)) =
|
||||
metadata.get(&RXingResultMetadataType::ORIENTATION)
|
||||
{
|
||||
*or
|
||||
} else {
|
||||
0
|
||||
})
|
||||
% 360;
|
||||
}
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::ORIENTATION,
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
// let points = result.getRXingResultPoints();
|
||||
// if points != null {
|
||||
let height = rotatedImage.getHeight();
|
||||
// for point in result.getRXingResultPointsMut().iter_mut() {
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
// for i in 0..total_points {
|
||||
// for (int i = 0; i < points.length; i++) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
// points[i] = RXingResultPoint::new(
|
||||
// height as f32 - points[i].getY() - 1.0,
|
||||
// points[i].getX(),
|
||||
// );
|
||||
}
|
||||
// }
|
||||
let first_try = self.doDecode(image, hints);
|
||||
if first_try.is_ok() {
|
||||
return first_try;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
let tryHarder = matches!(
|
||||
hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||
let metadata = result.getRXingResultMetadata();
|
||||
let mut orientation = 270;
|
||||
if metadata.contains_key(&RXingResultMetadataType::ORIENTATION) {
|
||||
// But if we found it reversed in doDecode(), add in that result here:
|
||||
orientation = (orientation
|
||||
+ if let Some(crate::RXingResultMetadataValue::Orientation(or)) =
|
||||
metadata.get(&RXingResultMetadataType::ORIENTATION)
|
||||
{
|
||||
*or
|
||||
} else {
|
||||
0
|
||||
})
|
||||
% 360;
|
||||
}
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::ORIENTATION,
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
for reader in self.0.iter_mut() {
|
||||
// for (Reader reader : readers) {
|
||||
reader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,60 +158,54 @@ impl Reader for MultiFormatUPCEANReader {
|
||||
image: &mut crate::BinaryBitmap,
|
||||
hints: &DecodingHintDictionary,
|
||||
) -> Result<crate::RXingResult, Exceptions> {
|
||||
if let Ok(res) = self.doDecode(image, hints) {
|
||||
Ok(res)
|
||||
} else {
|
||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||
let metadata = result.getRXingResultMetadata();
|
||||
let mut orientation = 270;
|
||||
if metadata.contains_key(&RXingResultMetadataType::ORIENTATION) {
|
||||
// But if we found it reversed in doDecode(), add in that result here:
|
||||
orientation = (orientation
|
||||
+ if let Some(crate::RXingResultMetadataValue::Orientation(or)) =
|
||||
metadata.get(&RXingResultMetadataType::ORIENTATION)
|
||||
{
|
||||
*or
|
||||
} else {
|
||||
0
|
||||
})
|
||||
% 360;
|
||||
}
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::ORIENTATION,
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
// let points = result.getRXingResultPoints();
|
||||
// if points != null {
|
||||
let height = rotatedImage.getHeight();
|
||||
// for point in result.getRXingResultPointsMut().iter_mut() {
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
// for i in 0..total_points {
|
||||
// for (int i = 0; i < points.length; i++) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
// points[i] = RXingResultPoint::new(
|
||||
// height as f32 - points[i].getY() - 1.0,
|
||||
// points[i].getX(),
|
||||
// );
|
||||
}
|
||||
// }
|
||||
let first_try = self.doDecode(image, hints);
|
||||
if first_try.is_ok() {
|
||||
return first_try;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
let tryHarder = matches!(
|
||||
hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
|
||||
let metadata = result.getRXingResultMetadata();
|
||||
let mut orientation = 270;
|
||||
if metadata.contains_key(&RXingResultMetadataType::ORIENTATION) {
|
||||
// But if we found it reversed in doDecode(), add in that result here:
|
||||
orientation = (orientation
|
||||
+ if let Some(crate::RXingResultMetadataValue::Orientation(or)) =
|
||||
metadata.get(&RXingResultMetadataType::ORIENTATION)
|
||||
{
|
||||
*or
|
||||
} else {
|
||||
0
|
||||
})
|
||||
% 360;
|
||||
}
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::ORIENTATION,
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
let height = rotatedImage.getHeight();
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
for reader in self.0.iter_mut() {
|
||||
// for (Reader reader : readers) {
|
||||
reader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ pub trait OneDimensionalCodeWriter: Writer {
|
||||
let mut outputX = leftPadding;
|
||||
|
||||
while inputX < inputWidth {
|
||||
// for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
|
||||
if code[inputX] {
|
||||
output.setRegion(outputX as u32, 0, multiple as u32, outputHeight as u32)?;
|
||||
}
|
||||
@@ -126,9 +125,7 @@ pub trait OneDimensionalCodeWriter: Writer {
|
||||
let mut numAdded = 0;
|
||||
let mut pos = pos;
|
||||
for len in pattern {
|
||||
// for (int len : pattern) {
|
||||
for _j in 0..TryInto::<usize>::try_into(*len).unwrap_or_default() {
|
||||
// for (int j = 0; j < len; j++) {
|
||||
target[pos] = color;
|
||||
pos += 1;
|
||||
}
|
||||
@@ -186,17 +183,17 @@ impl Writer for L {
|
||||
|
||||
let mut sidesMargin = self.getDefaultMargin();
|
||||
if let Some(EncodeHintValue::Margin(margin)) = hints.get(&EncodeHintType::MARGIN) {
|
||||
sidesMargin = margin.parse::<u32>().unwrap();
|
||||
sidesMargin = margin.parse::<u32>().map_err(|e| {
|
||||
Exceptions::IllegalArgumentException(Some(format!("couldnt parse {margin}: {e}")))
|
||||
})?;
|
||||
}
|
||||
// if hints.contains_key(&EncodeHintType::MARGIN) {
|
||||
// sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
|
||||
// }
|
||||
|
||||
let code = self.encode_oned_with_hints(contents, hints)?;
|
||||
|
||||
Self::renderRXingResult(&code, width, height, sidesMargin)
|
||||
}
|
||||
}
|
||||
|
||||
impl OneDimensionalCodeWriter for L {
|
||||
fn encode_oned(&self, _contents: &str) -> Result<Vec<bool>, Exceptions> {
|
||||
todo!()
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
common::BitArray, BinaryBitmap, DecodeHintType, DecodingHintDictionary, Exceptions,
|
||||
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
ResultPoint,
|
||||
common::BitArray, BinaryBitmap, DecodeHintType, DecodeHintValue, DecodingHintDictionary,
|
||||
Exceptions, RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint,
|
||||
Reader, ResultPoint,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -50,9 +50,11 @@ pub trait OneDReader: Reader {
|
||||
let mut hints = hints.clone();
|
||||
let width = image.getWidth();
|
||||
let height = image.getHeight();
|
||||
// let mut row = BitArray::with_size(width);
|
||||
|
||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
let tryHarder = matches!(
|
||||
hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
let rowStep = 1.max(height >> (if tryHarder { 8 } else { 5 }));
|
||||
let maxLines = if tryHarder {
|
||||
height // Look at the whole image, not just the center
|
||||
@@ -62,8 +64,6 @@ pub trait OneDReader: Reader {
|
||||
|
||||
let middle = height / 2;
|
||||
for x in 0..maxLines {
|
||||
// for (int x = 0; x < maxLines; x++) {
|
||||
|
||||
// Scanning from the middle out. Determine which row we're looking at next:
|
||||
let rowStepsAboveOrBelow = (x + 1) / 2;
|
||||
let isAbove = (x & 0x01) == 0; // i.e. is x even?
|
||||
@@ -85,11 +85,6 @@ pub trait OneDReader: Reader {
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
// try {
|
||||
// row = image.getBlackRow(rowNumber, row);
|
||||
// } catch (NotFoundException ignored) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
|
||||
// handle decoding upside down barcodes.
|
||||
@@ -97,21 +92,18 @@ pub trait OneDReader: Reader {
|
||||
// for (int attempt = 0; attempt < 2; attempt++) {
|
||||
if attempt == 1 {
|
||||
// trying again?
|
||||
row.to_mut().reverse(); // reverse the row and continue
|
||||
// This means we will only ever draw result points *once* in the life of this method
|
||||
// since we want to avoid drawing the wrong points after flipping the row, and,
|
||||
// don't want to clutter with noise from every single row scan -- just the scans
|
||||
// that start on the center line.
|
||||
|
||||
// reverse the row and continue
|
||||
// This means we will only ever draw result points *once* in the life of this method
|
||||
// since we want to avoid drawing the wrong points after flipping the row, and,
|
||||
// don't want to clutter with noise from every single row scan -- just the scans
|
||||
// that start on the center line.
|
||||
row.to_mut().reverse();
|
||||
|
||||
if hints.contains_key(&DecodeHintType::NEED_RESULT_POINT_CALLBACK) {
|
||||
// let newHints = HashMap::new();
|
||||
// newHints.putAll(hints);
|
||||
// newHints.remove(&DecodeHintType::NEED_RESULT_POINT_CALLBACK);
|
||||
hints.remove(&DecodeHintType::NEED_RESULT_POINT_CALLBACK);
|
||||
// hints = newHints;
|
||||
}
|
||||
}
|
||||
//try {
|
||||
// Look for a barcode
|
||||
let Ok(mut result) = self.decodeRow(rowNumber as u32, &row, &hints) else {
|
||||
continue
|
||||
};
|
||||
@@ -136,9 +128,6 @@ pub trait OneDReader: Reader {
|
||||
}
|
||||
}
|
||||
return Ok(result);
|
||||
// } catch (ReaderException re) {
|
||||
// // continue -- just couldn't decode this row
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +170,6 @@ pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVari
|
||||
let mut total = 0.0;
|
||||
let mut patternLength = 0;
|
||||
for i in 0..numCounters {
|
||||
// for (int i = 0; i < numCounters; i++) {
|
||||
total += counters[i] as f32;
|
||||
patternLength += pattern[i];
|
||||
}
|
||||
@@ -196,7 +184,6 @@ pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVari
|
||||
|
||||
let mut totalVariance = 0.0;
|
||||
for x in 0..numCounters {
|
||||
// for (int x = 0; x < numCounters; x++) {
|
||||
let counter = counters[x];
|
||||
let scaledPattern = (pattern[x] as f32) * unitBarWidth;
|
||||
let variance = if (counter as f32) > scaledPattern {
|
||||
@@ -227,12 +214,13 @@ pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVari
|
||||
*/
|
||||
pub fn recordPattern(row: &BitArray, start: usize, counters: &mut [u32]) -> Result<(), Exceptions> {
|
||||
let numCounters = counters.len();
|
||||
// Arrays.fill(counters, 0, numCounters, 0);
|
||||
counters.fill(0);
|
||||
|
||||
let end = row.getSize();
|
||||
if start >= end {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
let mut isWhite = !row.get(start);
|
||||
let mut counterPosition = 0;
|
||||
let mut i = start;
|
||||
|
||||
@@ -30,26 +30,8 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
||||
const MIN_FINDER_PATTERN_RATIO: f32 = 9.5 / 12.0;
|
||||
const MAX_FINDER_PATTERN_RATIO: f32 = 12.5 / 14.0;
|
||||
|
||||
// private final int[] decodeFinderCounters;
|
||||
// private final int[] dataCharacterCounters;
|
||||
// private final float[] oddRoundingErrors;
|
||||
// private final float[] evenRoundingErrors;
|
||||
// private final int[] oddCounts;
|
||||
// private final int[] evenCounts;
|
||||
|
||||
// protected AbstractRSSReader() {
|
||||
// decodeFinderCounters = new int[4];
|
||||
// dataCharacterCounters = new int[8];
|
||||
// oddRoundingErrors = new float[4];
|
||||
// evenRoundingErrors = new float[4];
|
||||
// oddCounts = new int[dataCharacterCounters.length / 2];
|
||||
// evenCounts = new int[dataCharacterCounters.length / 2];
|
||||
// }
|
||||
|
||||
fn parseFinderValue(counters: &[u32], finderPatterns: &[[u32; 4]]) -> Result<u32, Exceptions> {
|
||||
for (value, pattern) in finderPatterns.iter().enumerate() {
|
||||
// for value in 0..finderPatterns.len() {
|
||||
// for (int value = 0; value < finderPatterns.length; value++) {
|
||||
if one_d_reader::patternMatchVariance(counters, pattern, Self::MAX_INDIVIDUAL_VARIANCE)
|
||||
< Self::MAX_AVG_VARIANCE
|
||||
{
|
||||
@@ -73,7 +55,6 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
||||
let mut index = 0;
|
||||
let mut biggestError = errors[0];
|
||||
for (i, error) in errors.iter().enumerate().take(array.len()).skip(1) {
|
||||
// for (int i = 1; i < array.length; i++) {
|
||||
if *error > biggestError {
|
||||
biggestError = *error;
|
||||
index = i;
|
||||
@@ -86,8 +67,6 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
||||
let mut index = 0;
|
||||
let mut biggestError = errors[0];
|
||||
for (i, error) in errors.iter().enumerate().take(array.len()).skip(1) {
|
||||
// for i in 1..array.len() {
|
||||
// for (int i = 1; i < array.length; i++) {
|
||||
if *error < biggestError {
|
||||
biggestError = *error;
|
||||
index = i;
|
||||
@@ -102,16 +81,19 @@ pub trait AbstractRSSReaderTrait: OneDReader {
|
||||
let ratio: f32 = (firstTwoSum as f32) / (sum as f32);
|
||||
if ratio >= Self::MIN_FINDER_PATTERN_RATIO && ratio <= Self::MAX_FINDER_PATTERN_RATIO {
|
||||
// passes ratio test in spec, but see if the counts are unreasonable
|
||||
// let minCounter = counters.iter().min();
|
||||
// let maxCounter = counters.iter().max();
|
||||
let mut minCounter = u32::MAX;
|
||||
let mut maxCounter = u32::MIN;
|
||||
for counter in counters {
|
||||
// for (int counter : counters) {
|
||||
if *counter > maxCounter {
|
||||
maxCounter = *counter;
|
||||
}
|
||||
if *counter < minCounter {
|
||||
minCounter = *counter;
|
||||
}
|
||||
maxCounter = std::cmp::max(*counter, maxCounter);
|
||||
minCounter = std::cmp::min(*counter, minCounter);
|
||||
// if *counter > maxCounter {
|
||||
// maxCounter = *counter;
|
||||
// }
|
||||
// if *counter < minCounter {
|
||||
// minCounter = *counter;
|
||||
// }
|
||||
}
|
||||
return maxCounter < 10 * minCounter;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,12 @@ pub fn buildBitArrayFromString(data: &str) -> Result<BitArray, Exceptions> {
|
||||
// for (int i = 0; i < dotsAndXs.length(); ++i) {
|
||||
if i % 9 == 0 {
|
||||
// spaces
|
||||
if dotsAndXs.chars().nth(i).unwrap() != ' ' {
|
||||
if dotsAndXs
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::ParseException(None))?
|
||||
!= ' '
|
||||
{
|
||||
return Err(Exceptions::IllegalStateException(Some(
|
||||
"space expected".to_owned(),
|
||||
)));
|
||||
@@ -58,7 +63,10 @@ pub fn buildBitArrayFromString(data: &str) -> Result<BitArray, Exceptions> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let currentChar = dotsAndXs.chars().nth(i).unwrap();
|
||||
let currentChar = dotsAndXs
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::ParseException(None))?;
|
||||
if currentChar == 'X' || currentChar == 'x' {
|
||||
binary.set(counter);
|
||||
}
|
||||
@@ -75,12 +83,17 @@ pub fn buildBitArrayFromStringWithoutSpaces(data: &str) -> Result<BitArray, Exce
|
||||
.replace_all(&ONE.replace_all(data, "X"), ".")
|
||||
.to_string();
|
||||
let mut current = 0;
|
||||
while current < dotsAndXs.chars().count() {
|
||||
let dotsAndXs_length = dotsAndXs.chars().count();
|
||||
while current < dotsAndXs_length {
|
||||
sb.push(' ');
|
||||
let mut i = 0;
|
||||
while i < 8 && current < dotsAndXs.chars().count() {
|
||||
// for (int i = 0; i < 8 && current < dotsAndXs.length(); ++i) {
|
||||
sb.push(dotsAndXs.chars().nth(current).unwrap());
|
||||
while i < 8 && current < dotsAndXs_length {
|
||||
sb.push(
|
||||
dotsAndXs
|
||||
.chars()
|
||||
.nth(current)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
current += 1;
|
||||
|
||||
i += 1;
|
||||
|
||||
@@ -33,19 +33,24 @@ use super::ExpandedPair;
|
||||
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
|
||||
*/
|
||||
|
||||
pub fn buildBitArray(pairs: &Vec<ExpandedPair>) -> BitArray {
|
||||
pub fn buildBitArray(pairs: &Vec<ExpandedPair>) -> Option<BitArray> {
|
||||
let mut charNumber = (pairs.len() * 2) - 1;
|
||||
if pairs.last().unwrap().getRightChar().is_none() {
|
||||
charNumber -= 1;
|
||||
if let Some(pair) = pairs.last() {
|
||||
if pair.getRightChar().is_none() {
|
||||
charNumber -= 1;
|
||||
}
|
||||
}
|
||||
// if pairs.last().unwrap().getRightChar().is_none() {
|
||||
// charNumber -= 1;
|
||||
// }
|
||||
|
||||
let size = 12 * charNumber;
|
||||
|
||||
let mut binary = BitArray::with_size(size);
|
||||
let mut accPos = 0;
|
||||
|
||||
let firstPair = pairs.get(0).unwrap();
|
||||
let Some(rp) = firstPair.getRightChar() else { panic!("first char must exist");};
|
||||
let firstPair = pairs.get(0)?;
|
||||
let rp = firstPair.getRightChar().as_ref()?;
|
||||
let firstValue = rp.getValue();
|
||||
let mut i = 11;
|
||||
while i >= 0 {
|
||||
@@ -60,8 +65,8 @@ pub fn buildBitArray(pairs: &Vec<ExpandedPair>) -> BitArray {
|
||||
|
||||
for i in 1..pairs.len() {
|
||||
// for (int i = 1; i < pairs.size(); ++i) {
|
||||
let currentPair = pairs.get(i).unwrap();
|
||||
let Some(lv) = currentPair.getLeftChar() else { panic!("I'm not sure how we get here ");};
|
||||
let currentPair = pairs.get(i)?;
|
||||
let lv = currentPair.getLeftChar().as_ref()?;
|
||||
let leftValue = lv.getValue();
|
||||
let mut j = 11;
|
||||
while j >= 0 {
|
||||
@@ -88,7 +93,7 @@ pub fn buildBitArray(pairs: &Vec<ExpandedPair>) -> BitArray {
|
||||
}
|
||||
}
|
||||
}
|
||||
binary
|
||||
Some(binary)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +144,6 @@ mod BitArrayBuilderTest {
|
||||
pairs.push(expandedPair);
|
||||
}
|
||||
|
||||
super::buildBitArray(&pairs)
|
||||
super::buildBitArray(&pairs).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub struct AI01AndOtherAIs<'a>(&'a BitArray, GeneralAppIdDecoder<'a>);
|
||||
impl AI01decoder for AI01AndOtherAIs<'_> {}
|
||||
impl AbstractExpandedDecoder for AI01AndOtherAIs<'_> {
|
||||
fn parseInformation(&mut self) -> Result<String, crate::Exceptions> {
|
||||
let mut buff = String::new(); //new StringBuilder();
|
||||
let mut buff = String::new();
|
||||
|
||||
buff.push_str("(01)");
|
||||
let initialGtinPosition = buff.chars().count();
|
||||
@@ -59,9 +59,7 @@ impl<'a> AI01AndOtherAIs<'_> {
|
||||
AI01AndOtherAIs(information, GeneralAppIdDecoder::new(information))
|
||||
}
|
||||
|
||||
const HEADER_SIZE: usize = 1 + 1 + 2; //first bit encodes the linkage flag,
|
||||
//the second one is the encodation method, and the other two are for the variable length
|
||||
// AI01AndOtherAIs(BitArray information) {
|
||||
// super(information);
|
||||
// }
|
||||
//first bit encodes the linkage flag,
|
||||
//the second one is the encodation method, and the other two are for the variable length
|
||||
const HEADER_SIZE: usize = 1 + 1 + 2;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,12 @@ pub trait AI01decoder: AbstractExpandedDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Append the checkdigit to the string buffer
|
||||
///
|
||||
/// Panics is buf is less than 13 characters in length
|
||||
pub(super) fn appendCheckDigit(buf: &mut String, currentPos: usize) {
|
||||
let mut checkDigit = 0;
|
||||
for i in 0..13 {
|
||||
// for (int i = 0; i < 13; i++) {
|
||||
let digit = buf.chars().nth(i + currentPos).unwrap() as u32 - '0' as u32;
|
||||
checkDigit += if (i & 0x01) == 0 { 3 * digit } else { digit };
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ pub trait AI01weightDecoder: AI01decoder {
|
||||
|
||||
let mut currentDivisor = 100000;
|
||||
for _i in 0..5 {
|
||||
// for (int i = 0; i < 5; ++i) {
|
||||
if weightNumeric / currentDivisor == 0 {
|
||||
buf.push('0');
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ pub fn parseFieldsInGeneralPurpose(rawInformation: &str) -> Result<String, Excep
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
let firstThreeDigits: String = rawInformation.chars().take(3).collect(); //rawInformation.substring(0, 3);
|
||||
let firstThreeDigits: String = rawInformation.chars().take(3).collect();
|
||||
let threeDigitDataLength = THREE_DIGIT_DATA_LENGTH.get(&firstThreeDigits);
|
||||
if let Some(tddl) = threeDigitDataLength {
|
||||
if tddl.variable {
|
||||
@@ -230,7 +230,7 @@ fn processVariableAI(
|
||||
variableFieldSize: usize,
|
||||
rawInformation: &str,
|
||||
) -> Result<String, Exceptions> {
|
||||
let ai: String = rawInformation.chars().take(aiSize).collect(); //rawInformation.substring(0, aiSize);
|
||||
let ai: String = rawInformation.chars().take(aiSize).collect();
|
||||
let maxSize = rawInformation
|
||||
.chars()
|
||||
.count()
|
||||
|
||||
@@ -132,7 +132,6 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
) -> u32 {
|
||||
let mut value = 0;
|
||||
for i in 0..bits {
|
||||
// for (int i = 0; i < bits; ++i) {
|
||||
if information.get(pos + i as usize) {
|
||||
value |= 1 << (bits - i - 1);
|
||||
}
|
||||
@@ -197,8 +196,8 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
}
|
||||
} //while (!isFinished);
|
||||
|
||||
if result.getDecodedInformation().is_some() {
|
||||
Ok(result.getDecodedInformation().as_ref().unwrap().clone())
|
||||
if let Some(r) = result.getDecodedInformation() {
|
||||
Ok(r.clone())
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
@@ -346,7 +345,8 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
if (5..15).contains(&fiveBitValue) {
|
||||
return Ok(DecodedChar::new(
|
||||
pos + 5,
|
||||
char::from_u32('0' as u32 + fiveBitValue - 5).unwrap(),
|
||||
char::from_u32('0' as u32 + fiveBitValue - 5)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -355,14 +355,14 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
if (64..90).contains(&sevenBitValue) {
|
||||
return Ok(DecodedChar::new(
|
||||
pos + 7,
|
||||
char::from_u32(sevenBitValue + 1).unwrap(),
|
||||
char::from_u32(sevenBitValue + 1).ok_or(Exceptions::ParseException(None))?,
|
||||
));
|
||||
}
|
||||
|
||||
if (90..116).contains(&sevenBitValue) {
|
||||
return Ok(DecodedChar::new(
|
||||
pos + 7,
|
||||
char::from_u32(sevenBitValue + 7).unwrap(),
|
||||
char::from_u32(sevenBitValue + 7).ok_or(Exceptions::ParseException(None))?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -424,7 +424,8 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
if (5..15).contains(&fiveBitValue) {
|
||||
return Ok(DecodedChar::new(
|
||||
pos + 5,
|
||||
char::from_u32('0' as u32 + fiveBitValue - 5).unwrap(),
|
||||
char::from_u32('0' as u32 + fiveBitValue - 5)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -433,7 +434,7 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
if (32..58).contains(&sixBitValue) {
|
||||
return Ok(DecodedChar::new(
|
||||
pos + 6,
|
||||
char::from_u32(sixBitValue + 33).unwrap(),
|
||||
char::from_u32(sixBitValue + 33).ok_or(Exceptions::ParseException(None))?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -460,7 +461,6 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
|
||||
let mut i = 0;
|
||||
while i < 5 && i + pos < self.information.getSize() {
|
||||
// for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {
|
||||
if i == 2 {
|
||||
if !self.information.get(pos + 2) {
|
||||
return false;
|
||||
@@ -482,7 +482,6 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
}
|
||||
|
||||
for i in pos..pos + 3 {
|
||||
// for (int i = pos; i < pos + 3; ++i) {
|
||||
if self.information.get(i) {
|
||||
return false;
|
||||
}
|
||||
@@ -500,7 +499,6 @@ impl<'a> GeneralAppIdDecoder<'_> {
|
||||
|
||||
let mut i = 0;
|
||||
while i < 4 && i + pos < self.information.getSize() {
|
||||
// for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {
|
||||
if self.information.get(pos + i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -190,6 +190,6 @@ fn assertCorrectImage2binary(fileName: &str, expected: &str) {
|
||||
// fail(re.toString());
|
||||
// return;
|
||||
// }
|
||||
let binary = bit_array_builder::buildBitArray(&pairs);
|
||||
let binary = bit_array_builder::buildBitArray(&pairs).unwrap();
|
||||
assert_eq!(expected, binary.to_string());
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ use crate::{
|
||||
},
|
||||
OneDReader,
|
||||
},
|
||||
BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult,
|
||||
RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
BarcodeFormat, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, Reader,
|
||||
};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -144,9 +144,9 @@ pub struct RSSExpandedReader {
|
||||
oddCounts: [u32; 4],
|
||||
evenCounts: [u32; 4],
|
||||
|
||||
pub(super) pairs: Vec<ExpandedPair>, //new ArrayList<>(MAX_PAIRS);
|
||||
pub(super) rows: Vec<ExpandedRow>, // new ArrayList<>();
|
||||
startEnd: [u32; 2], // new int[2];
|
||||
pub(super) pairs: Vec<ExpandedPair>,
|
||||
pub(super) rows: Vec<ExpandedRow>,
|
||||
startEnd: [u32; 2],
|
||||
startFromEven: bool,
|
||||
}
|
||||
impl AbstractRSSReaderTrait for RSSExpandedReader {}
|
||||
@@ -161,19 +161,11 @@ impl OneDReader for RSSExpandedReader {
|
||||
// So lets try twice
|
||||
self.pairs.clear();
|
||||
self.startFromEven = false;
|
||||
// try {
|
||||
if let Ok(decoded_two_pairs) = self.decodeRow2pairs(rowNumber, row) {
|
||||
if let Ok(possible_result) = Self::constructRXingResult(&decoded_two_pairs) {
|
||||
return Ok(possible_result);
|
||||
}
|
||||
}
|
||||
// let possible = Self::constructRXingResult(&self.decodeRow2pairs(rowNumber, row)?);
|
||||
// if possible.is_ok() {
|
||||
// return possible;
|
||||
// }
|
||||
// } catch (NotFoundException e) {
|
||||
// OK
|
||||
// }
|
||||
|
||||
self.pairs.clear();
|
||||
self.startFromEven = true;
|
||||
@@ -197,7 +189,10 @@ impl Reader for RSSExpandedReader {
|
||||
if let Ok(res) = self.doDecode(image, hints) {
|
||||
Ok(res)
|
||||
} else {
|
||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
let tryHarder = matches!(
|
||||
hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
@@ -221,23 +216,14 @@ impl Reader for RSSExpandedReader {
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
// let points = result.getRXingResultPoints();
|
||||
// if points != null {
|
||||
let height = rotatedImage.getHeight();
|
||||
// for point in result.getRXingResultPointsMut().iter_mut() {
|
||||
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
// for i in 0..total_points {
|
||||
// for (int i = 0; i < points.length; i++) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0;
|
||||
// points[i] = RXingResultPoint::new(
|
||||
// height as f32 - points[i].getY() - 1.0,
|
||||
// points[i].getX(),
|
||||
// );
|
||||
}
|
||||
// }
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
@@ -311,23 +297,14 @@ impl RSSExpandedReader {
|
||||
if let Ok(to_add) = to_add_res {
|
||||
self.pairs.push(to_add);
|
||||
} else if self.pairs.is_empty() {
|
||||
return Err(to_add_res.err().unwrap());
|
||||
return Err(to_add_res
|
||||
.err()
|
||||
.unwrap_or(Exceptions::IllegalStateException(None)));
|
||||
} else {
|
||||
// exit this loop when retrieveNextPair() fails and throws
|
||||
done = true;
|
||||
}
|
||||
// self.pairs = previousPairs;
|
||||
}
|
||||
// try {
|
||||
// this.pairs.add(retrieveNextPair(row, this.pairs, rowNumber));
|
||||
// } catch (NotFoundException nfe) {
|
||||
// if (this.pairs.isEmpty()) {
|
||||
// throw nfe;
|
||||
// }
|
||||
// // exit this loop when retrieveNextPair() fails and throws
|
||||
// done = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: verify sequence of finder patterns as in checkPairSequence()
|
||||
if self.checkChecksum() {
|
||||
@@ -339,14 +316,19 @@ impl RSSExpandedReader {
|
||||
if tryStackedDecode {
|
||||
// When the image is 180-rotated, then rows are sorted in wrong direction.
|
||||
// Try twice with both the directions.
|
||||
let ps = self.checkRows(false);
|
||||
if let Some(ps) = ps {
|
||||
return Ok(ps);
|
||||
}
|
||||
let ps = self.checkRows(true);
|
||||
let ps = self.checkRows(false).or(self.checkRows(true));
|
||||
if let Some(ps) = ps {
|
||||
return Ok(ps);
|
||||
}
|
||||
|
||||
// let ps = self.checkRows(false);
|
||||
// if let Some(ps) = ps {
|
||||
// return Ok(ps);
|
||||
// }
|
||||
// let ps = self.checkRows(true);
|
||||
// if let Some(ps) = ps {
|
||||
// return Ok(ps);
|
||||
// }
|
||||
}
|
||||
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
@@ -367,11 +349,12 @@ impl RSSExpandedReader {
|
||||
}
|
||||
|
||||
let mut c_rows = Vec::new();
|
||||
let ps = if let Ok(res) = self.checkRowsDetails(&mut c_rows, 0) {
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ps = self.checkRowsDetails(&mut c_rows, 0).ok();
|
||||
// let ps = if let Ok(res) = self.checkRowsDetails(&mut c_rows, 0) {
|
||||
// Some(res)
|
||||
// } else {
|
||||
// None
|
||||
// };
|
||||
// } catch (NotFoundException e) {
|
||||
// OK
|
||||
// }
|
||||
@@ -392,7 +375,10 @@ impl RSSExpandedReader {
|
||||
) -> Result<Vec<ExpandedPair>, Exceptions> {
|
||||
for i in currentRow..self.rows.len() {
|
||||
// for (int i = currentRow; i < rows.size(); i++) {
|
||||
let row = self.rows.get(i).unwrap();
|
||||
let row = self
|
||||
.rows
|
||||
.get(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
self.pairs.clear();
|
||||
for collectedRow in &collectedRows.clone() {
|
||||
// for (ExpandedRow collectedRow : collectedRows) {
|
||||
@@ -423,12 +409,15 @@ impl RSSExpandedReader {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
}
|
||||
|
||||
// Whether the pairs form a valid find pattern sequence,
|
||||
// either complete or a prefix
|
||||
/// Whether the pairs form a valid find pattern sequence,
|
||||
/// either complete or a prefix
|
||||
///
|
||||
/// Could potentially panic in a very out of bounds situation
|
||||
fn isValidSequence(pairs: &[ExpandedPair]) -> bool {
|
||||
for i in 0..FINDER_PATTERN_SEQUENCES.len() {
|
||||
for sequence in FINDER_PATTERN_SEQUENCES.iter() {
|
||||
// for i in 0..FINDER_PATTERN_SEQUENCES.len() {
|
||||
// for sequence in &FINDER_PATTERN_SEQUENCES.iter() {
|
||||
let sequence = FINDER_PATTERN_SEQUENCES.get(i).unwrap();
|
||||
// let sequence = FINDER_PATTERN_SEQUENCES.get(i).unwrap();
|
||||
// for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
|
||||
if pairs.len() <= sequence.len() {
|
||||
let mut stop = true;
|
||||
@@ -462,13 +451,14 @@ impl RSSExpandedReader {
|
||||
let mut prevIsSame = false;
|
||||
let mut nextIsSame = false;
|
||||
while insertPos < self.rows.len() {
|
||||
let erow = self.rows.get(insertPos).unwrap();
|
||||
if erow.getRowNumber() > rowNumber {
|
||||
nextIsSame = erow.isEquivalent(&self.pairs);
|
||||
break;
|
||||
if let Some(erow) = self.rows.get(insertPos) {
|
||||
if erow.getRowNumber() > rowNumber {
|
||||
nextIsSame = erow.isEquivalent(&self.pairs);
|
||||
break;
|
||||
}
|
||||
prevIsSame = erow.isEquivalent(&self.pairs);
|
||||
insertPos += 1;
|
||||
}
|
||||
prevIsSame = erow.isEquivalent(&self.pairs);
|
||||
insertPos += 1;
|
||||
}
|
||||
if nextIsSame || prevIsSame {
|
||||
return;
|
||||
@@ -506,40 +496,15 @@ impl RSSExpandedReader {
|
||||
true
|
||||
}
|
||||
});
|
||||
// let row_search = rows.clone();
|
||||
// for i in 0..row_search.len() {
|
||||
// // for r in rows {
|
||||
// // for (Iterator<ExpandedRow> iterator = rows.iterator(); iterator.hasNext();) {
|
||||
// // ExpandedRow r = iterator.next();
|
||||
// let r = row_search.get(i).unwrap();
|
||||
// if r.getPairs().len() != pairs.len() {
|
||||
// let mut allFound = true;
|
||||
// for p in r.getPairs() {
|
||||
// // for (ExpandedPair p : r.getPairs()) {
|
||||
// if !pairs.contains(p) {
|
||||
// allFound = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if allFound {
|
||||
// // 'pairs' contains all the pairs from the row 'r'
|
||||
// // iterator.remove();
|
||||
// rows.remove(i);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// Returns true when one of the rows already contains all the pairs
|
||||
fn isPartialRow(pairs: &[ExpandedPair], rows: &[ExpandedRow]) -> bool {
|
||||
for r in rows {
|
||||
// for (ExpandedRow r : rows) {
|
||||
let mut allFound = true;
|
||||
for p in pairs {
|
||||
// for (ExpandedPair p : pairs) {
|
||||
let mut found = false;
|
||||
for pp in r.getPairs() {
|
||||
// for (ExpandedPair pp : r.getPairs()) {
|
||||
if p == pp {
|
||||
found = true;
|
||||
break;
|
||||
@@ -571,24 +536,25 @@ impl RSSExpandedReader {
|
||||
|
||||
// Not private for unit testing
|
||||
pub(crate) fn constructRXingResult(pairs: &[ExpandedPair]) -> Result<RXingResult, Exceptions> {
|
||||
let binary = bit_array_builder::buildBitArray(&pairs.to_vec());
|
||||
let binary = bit_array_builder::buildBitArray(&pairs.to_vec())
|
||||
.ok_or(Exceptions::IllegalStateException(None))?;
|
||||
|
||||
let mut decoder = abstract_expanded_decoder::createDecoder(&binary)?;
|
||||
let resultingString = decoder.parseInformation()?;
|
||||
|
||||
let firstPoints = pairs
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.getFinderPattern()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getRXingResultPoints();
|
||||
let lastPoints = pairs
|
||||
.last()
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.getFinderPattern()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getRXingResultPoints();
|
||||
|
||||
let mut result = RXingResult::new(
|
||||
@@ -607,23 +573,24 @@ impl RSSExpandedReader {
|
||||
}
|
||||
|
||||
fn checkChecksum(&self) -> bool {
|
||||
let firstPair = self.pairs.get(0).unwrap();
|
||||
let Some(firstPair) = self.pairs.get(0) else {
|
||||
return false;
|
||||
};
|
||||
let checkCharacter = firstPair.getLeftChar();
|
||||
let Some(firstCharacter) = firstPair.getRightChar() else {
|
||||
return false;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
let mut checksum = firstCharacter.getChecksumPortion();
|
||||
let mut s = 2;
|
||||
|
||||
// for i in 1..self.pairs.len() {
|
||||
// for (int i = 1; i < this.pairs.size(); ++i) {
|
||||
for currentPair in self.pairs.iter().skip(1) {
|
||||
// let currentPair = self.pairs.get(i).unwrap();
|
||||
checksum += currentPair.getLeftChar().unwrap().getChecksumPortion();
|
||||
let Some(currentPairLeftChar) = currentPair.getLeftChar() else {
|
||||
return false;
|
||||
};
|
||||
checksum += currentPairLeftChar.getChecksumPortion();
|
||||
s += 1;
|
||||
if let Some(currentRightChar) = currentPair.getRightChar() {
|
||||
// if (currentRightChar != null) {
|
||||
checksum += currentRightChar.getChecksumPortion();
|
||||
s += 1;
|
||||
}
|
||||
@@ -633,7 +600,11 @@ impl RSSExpandedReader {
|
||||
|
||||
let checkCharacterValue = (211 * (s as i64 - 4) + checksum as i64) as u32;
|
||||
|
||||
checkCharacterValue == checkCharacter.unwrap().getValue()
|
||||
if let Some(checkCharacter) = checkCharacter {
|
||||
checkCharacterValue == checkCharacter.getValue()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn getNextSecondBar(row: &BitArray, initialPos: usize) -> usize {
|
||||
@@ -675,30 +646,39 @@ impl RSSExpandedReader {
|
||||
if !keepFinding {
|
||||
break;
|
||||
}
|
||||
} //while (keepFinding);
|
||||
}
|
||||
|
||||
// When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.
|
||||
// boolean mayBeLast = checkPairSequence(previousPairs, pattern);
|
||||
|
||||
let leftChar =
|
||||
self.decodeDataCharacter(row, pattern.as_ref().unwrap(), isOddPattern, true)?;
|
||||
let leftChar = self.decodeDataCharacter(
|
||||
row,
|
||||
pattern
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::NotFoundException(None))?,
|
||||
isOddPattern,
|
||||
true,
|
||||
)?;
|
||||
|
||||
if !previousPairs.is_empty() && previousPairs.last().unwrap().mustBeLast() {
|
||||
if !previousPairs.is_empty()
|
||||
&& previousPairs
|
||||
.last()
|
||||
.ok_or(Exceptions::NotFoundException(None))?
|
||||
.mustBeLast()
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
let rightChar = if let Ok(ch) =
|
||||
self.decodeDataCharacter(row, pattern.as_ref().unwrap(), isOddPattern, false)
|
||||
{
|
||||
Some(ch)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// try {
|
||||
// rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);
|
||||
// } catch (NotFoundException ignored) {
|
||||
// rightChar = null;
|
||||
// }
|
||||
let rightChar = self
|
||||
.decodeDataCharacter(
|
||||
row,
|
||||
pattern
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::NotFoundException(None))?,
|
||||
isOddPattern,
|
||||
false,
|
||||
)
|
||||
.ok();
|
||||
|
||||
Ok(ExpandedPair::new(Some(leftChar), rightChar, pattern))
|
||||
}
|
||||
@@ -710,10 +690,11 @@ impl RSSExpandedReader {
|
||||
forcedOffset: i32,
|
||||
) -> Result<(), Exceptions> {
|
||||
let counters = &mut self.decodeFinderCounters;
|
||||
counters[0] = 0;
|
||||
counters[1] = 0;
|
||||
counters[2] = 0;
|
||||
counters[3] = 0;
|
||||
counters.fill(0);
|
||||
// counters[0] = 0;
|
||||
// counters[1] = 0;
|
||||
// counters[2] = 0;
|
||||
// counters[3] = 0;
|
||||
|
||||
let width = row.getSize();
|
||||
|
||||
@@ -723,8 +704,14 @@ impl RSSExpandedReader {
|
||||
} else if previousPairs.is_empty() {
|
||||
rowOffset = 0;
|
||||
} else {
|
||||
let lastPair = previousPairs.last().unwrap();
|
||||
rowOffset = lastPair.getFinderPattern().as_ref().unwrap().getStartEnd()[1] as i32;
|
||||
let lastPair = previousPairs
|
||||
.last()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
rowOffset = lastPair
|
||||
.getFinderPattern()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getStartEnd()[1] as i32;
|
||||
}
|
||||
let mut searchingEvenPair = previousPairs.len() % 2 != 0;
|
||||
if self.startFromEven {
|
||||
@@ -779,11 +766,11 @@ impl RSSExpandedReader {
|
||||
}
|
||||
|
||||
fn reverseCounters(counters: &mut [u32]) {
|
||||
let length = counters.len();
|
||||
for i in 0..length / 2 {
|
||||
// for (int i = 0; i < length / 2; ++i) {
|
||||
counters.swap(i, length - i - 1);
|
||||
}
|
||||
counters.reverse();
|
||||
// let length = counters.len();
|
||||
// for i in 0..length / 2 {
|
||||
// counters.swap(i, length - i - 1);
|
||||
// }
|
||||
}
|
||||
|
||||
fn parseFoundFinderPattern(
|
||||
@@ -826,9 +813,7 @@ impl RSSExpandedReader {
|
||||
// System.arraycopy(counters, 0, counters, 1, counters.length - 1);
|
||||
|
||||
counters[0] = firstCounter as u32;
|
||||
let Ok(value) = Self::parseFinderValue(&counters, &Self::FINDER_PATTERNS) else {
|
||||
return None
|
||||
};
|
||||
let value = Self::parseFinderValue(&counters, &Self::FINDER_PATTERNS).ok()?;
|
||||
|
||||
Some(FinderPattern::new(
|
||||
value,
|
||||
@@ -854,34 +839,29 @@ impl RSSExpandedReader {
|
||||
} else {
|
||||
recordPattern(row, pattern.getStartEnd()[1], counters)?;
|
||||
// reverse it
|
||||
let mut i = 0;
|
||||
let mut j = counters.len() - 1;
|
||||
while i < j {
|
||||
// for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
|
||||
counters.reverse();
|
||||
// let mut i = 0;
|
||||
// let mut j = counters.len() - 1;
|
||||
// while i < j {
|
||||
// counters.swap(i, j);
|
||||
|
||||
counters.swap(i, j);
|
||||
|
||||
i += 1;
|
||||
j -= 1;
|
||||
}
|
||||
// i += 1;
|
||||
// j -= 1;
|
||||
// }
|
||||
} //counters[] has the pixels of the module
|
||||
|
||||
let numModules = 17; //left and right data characters have all the same length
|
||||
// let elementWidth: f32 = MathUtils::sum(counters) / numModules;
|
||||
//left and right data characters have all the same length
|
||||
let numModules = 17;
|
||||
|
||||
let elementWidth: f32 = (counters.iter().sum::<u32>() as f32) / numModules as f32;
|
||||
|
||||
// Sanity check: element width for pattern and the character should match
|
||||
// Logic check: element width for pattern and the character should match
|
||||
let expectedElementWidth: f32 =
|
||||
(pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) as f32 / 15.0;
|
||||
if (elementWidth - expectedElementWidth).abs() / expectedElementWidth > 0.3 {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
// let oddCounts = &mut self.oddCounts;
|
||||
// let evenCounts = &mut self.evenCounts;
|
||||
// let oddRoundingErrors = &mut self.oddRoundingErrors;
|
||||
// let evenRoundingErrors = &mut self.evenRoundingErrors;
|
||||
|
||||
for (i, counter) in counters.iter().enumerate() {
|
||||
// for (int i = 0; i < counters.length; i++) {
|
||||
let value: f32 = 1.0 * (*counter as f32) / elementWidth;
|
||||
@@ -911,13 +891,12 @@ impl RSSExpandedReader {
|
||||
|
||||
let weightRowNumber = (4 * pattern.getValue() as isize
|
||||
+ (if isOddPattern { 0 } else { 2 })
|
||||
+ isize::from(!leftChar)//(if leftChar { 0 } else { 1 })
|
||||
+ isize::from(!leftChar)
|
||||
- 1) as usize;
|
||||
|
||||
let mut oddSum = 0;
|
||||
let mut oddChecksumPortion = 0;
|
||||
for i in (0..self.oddCounts.len()).rev() {
|
||||
// for (int i = oddCounts.length - 1; i >= 0; i--) {
|
||||
if Self::isNotA1left(pattern, isOddPattern, leftChar) {
|
||||
let weight = Self::WEIGHTS[weightRowNumber][2 * i];
|
||||
oddChecksumPortion += self.oddCounts[i] * weight;
|
||||
@@ -926,7 +905,6 @@ impl RSSExpandedReader {
|
||||
}
|
||||
let mut evenChecksumPortion = 0;
|
||||
for i in (0..self.evenCounts.len()).rev() {
|
||||
// for (int i = evenCounts.length - 1; i >= 0; i--) {
|
||||
if Self::isNotA1left(pattern, isOddPattern, leftChar) {
|
||||
let weight = Self::WEIGHTS[weightRowNumber][2 * i + 1];
|
||||
evenChecksumPortion += self.evenCounts[i] * weight;
|
||||
@@ -950,14 +928,13 @@ impl RSSExpandedReader {
|
||||
Ok(DataCharacter::new(value, checksumPortion))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn isNotA1left(pattern: &FinderPattern, isOddPattern: bool, leftChar: bool) -> bool {
|
||||
// A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char
|
||||
!(pattern.getValue() == 0 && isOddPattern && leftChar)
|
||||
}
|
||||
|
||||
fn adjustOddEvenCounts(&mut self, numModules: u32) -> Result<(), Exceptions> {
|
||||
// let oddSum = MathUtils::sum(&self.oddCounts);
|
||||
// let evenSum = MathUtils::sum(&self.evenCounts);
|
||||
let oddSum = self.oddCounts.iter().sum::<u32>();
|
||||
let evenSum = self.evenCounts.iter().sum::<u32>();
|
||||
|
||||
|
||||
@@ -59,12 +59,12 @@ impl OneDReader for RSS14Reader {
|
||||
Self::addOrTally(&mut self.possibleRightPairs, rightPair);
|
||||
row.reverse();
|
||||
for left in &self.possibleLeftPairs {
|
||||
// for (Pair left : possibleLeftPairs) {
|
||||
if left.getCount() > 1 {
|
||||
for right in &self.possibleRightPairs {
|
||||
// for (Pair right : possibleRightPairs) {
|
||||
if right.getCount() > 1 && self.checkChecksum(left, right) {
|
||||
return Ok(self.constructRXingResult(left, right));
|
||||
return self
|
||||
.constructRXingResult(left, right)
|
||||
.ok_or(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,10 @@ impl Reader for RSS14Reader {
|
||||
if let Ok(res) = self.doDecode(image, hints) {
|
||||
Ok(res)
|
||||
} else {
|
||||
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
let tryHarder = matches!(
|
||||
hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
if tryHarder && image.isRotateSupported() {
|
||||
let mut rotatedImage = image.rotateCounterClockwise();
|
||||
let mut result = self.doDecode(&mut rotatedImage, hints)?;
|
||||
@@ -113,23 +116,13 @@ impl Reader for RSS14Reader {
|
||||
RXingResultMetadataValue::Orientation(orientation),
|
||||
);
|
||||
// Update result points
|
||||
// let points = result.getRXingResultPoints();
|
||||
// if points != null {
|
||||
let height = rotatedImage.getHeight();
|
||||
// for point in result.getRXingResultPointsMut().iter_mut() {
|
||||
let total_points = result.getRXingResultPoints().len();
|
||||
let points = result.getRXingResultPointsMut();
|
||||
// for i in 0..total_points {
|
||||
for point in points.iter_mut().take(total_points) {
|
||||
// for (int i = 0; i < points.length; i++) {
|
||||
std::mem::swap(&mut point.x, &mut point.y);
|
||||
point.x = height as f32 - point.x - 1.0
|
||||
// points[i] = RXingResultPoint::new(
|
||||
// height as f32 - points[i].getY() - 1.0,
|
||||
// points[i].getX(),
|
||||
// );
|
||||
}
|
||||
// }
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
@@ -172,19 +165,18 @@ impl RSS14Reader {
|
||||
dataCharacterCounters: [0u32; 8],
|
||||
oddRoundingErrors: [0.0; 4],
|
||||
evenRoundingErrors: [0.0; 4],
|
||||
oddCounts: [0u32; 4], //vec![0u32;4],
|
||||
evenCounts: [0u32; 4], //vec![0u32;4],
|
||||
oddCounts: [0u32; 4],
|
||||
evenCounts: [0u32; 4],
|
||||
}
|
||||
}
|
||||
|
||||
fn addOrTally(possiblePairs: &mut Vec<Pair>, pair: Option<Pair>) {
|
||||
let Some(pair) = pair else {
|
||||
return;
|
||||
};
|
||||
return;
|
||||
};
|
||||
|
||||
let mut found = false;
|
||||
for other in possiblePairs.iter_mut() {
|
||||
// for (Pair other : possiblePairs) {
|
||||
if other.getValue() == pair.getValue() {
|
||||
other.incrementCount();
|
||||
found = true;
|
||||
@@ -196,14 +188,13 @@ impl RSS14Reader {
|
||||
}
|
||||
}
|
||||
|
||||
fn constructRXingResult(&self, leftPair: &Pair, rightPair: &Pair) -> RXingResult {
|
||||
fn constructRXingResult(&self, leftPair: &Pair, rightPair: &Pair) -> Option<RXingResult> {
|
||||
let symbolValue: u64 = 4537077 * leftPair.getValue() as u64 + rightPair.getValue() as u64;
|
||||
let text = symbolValue.to_string();
|
||||
|
||||
let mut buffer = String::with_capacity(14);
|
||||
let mut i = 13 - text.chars().count() as isize;
|
||||
while i > 0 {
|
||||
// for (int i = 13 - text.length(); i > 0; i--) {
|
||||
buffer.push('0');
|
||||
|
||||
i -= 1;
|
||||
@@ -212,8 +203,7 @@ impl RSS14Reader {
|
||||
|
||||
let mut checkDigit = 0;
|
||||
for i in 0..13 {
|
||||
// for (int i = 0; i < 13; i++) {
|
||||
let digit = buffer.chars().nth(i).unwrap() as u32 - '0' as u32;
|
||||
let digit = buffer.chars().nth(i)? as u32 - '0' as u32;
|
||||
checkDigit += if (i & 0x01) == 0 { 3 * digit } else { digit };
|
||||
}
|
||||
checkDigit = 10 - (checkDigit % 10);
|
||||
@@ -236,7 +226,7 @@ impl RSS14Reader {
|
||||
RXingResultMetadataValue::SymbologyIdentifier("]e0".to_owned()),
|
||||
);
|
||||
|
||||
result
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn checkChecksum(&self, leftPair: &Pair, rightPair: &Pair) -> bool {
|
||||
@@ -286,11 +276,8 @@ impl RSS14Reader {
|
||||
pattern,
|
||||
))
|
||||
}();
|
||||
if let Ok(ppair) = pos_pair {
|
||||
Some(ppair)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
pos_pair.ok()
|
||||
}
|
||||
|
||||
fn decodeDataCharacter(
|
||||
@@ -299,47 +286,33 @@ impl RSS14Reader {
|
||||
pattern: &FinderPattern,
|
||||
outsideChar: bool,
|
||||
) -> Result<DataCharacter, Exceptions> {
|
||||
let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters();
|
||||
//Arrays.fill(counters, 0);
|
||||
// counters.fill(0);
|
||||
let counters = &mut self.dataCharacterCounters;
|
||||
counters.fill(0);
|
||||
|
||||
if outsideChar {
|
||||
one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?;
|
||||
one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], counters)?;
|
||||
} else {
|
||||
one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?;
|
||||
one_d_reader::recordPattern(row, pattern.getStartEnd()[1], counters)?;
|
||||
// reverse it
|
||||
let mut i = 0;
|
||||
let mut j = counters.len() - 1;
|
||||
while i < j {
|
||||
// for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
|
||||
counters.reverse();
|
||||
// let mut i = 0;
|
||||
// let mut j = counters.len() - 1;
|
||||
// while i < j {
|
||||
// counters.swap(i, j);
|
||||
|
||||
counters.swap(i, j);
|
||||
|
||||
i += 1;
|
||||
j -= 1;
|
||||
}
|
||||
// i += 1;
|
||||
// j -= 1;
|
||||
// }
|
||||
}
|
||||
|
||||
let numModules = if outsideChar { 16 } else { 15 };
|
||||
|
||||
let elementWidth: f32 = counters.iter().sum::<u32>() as f32 / numModules as f32;
|
||||
|
||||
// let oddCounts = &mut self.oddCounts;//[0u32; 4]; //self.getOddCounts();
|
||||
// let evenCounts = //&mut self.evenCounts;//[0u32; 4]; // self.getEvenCounts();
|
||||
// let oddRoundingErrors = //&mut self.oddRoundingErrors;//[0f32; 4]; // self.getOddRoundingErrors();
|
||||
// let evenRoundingErrors = &mut self.evenRoundingErrors;//[0f32; 4]; // self.getEvenRoundingErrors();
|
||||
|
||||
for (i, counter) in counters.iter().enumerate() {
|
||||
// for (int i = 0; i < counters.length; i++) {
|
||||
let value: f32 = *counter as f32 / elementWidth;
|
||||
// let mut count = (value + 0.5) as u32; // Round
|
||||
let count = ((value + 0.5) as u32).clamp(1, 8);
|
||||
// if count < 1 {
|
||||
// count = 1;
|
||||
// } else if count > 8 {
|
||||
// count = 8;
|
||||
// }
|
||||
|
||||
let offset = i / 2;
|
||||
if (i & 0x01) == 0 {
|
||||
self.oddCounts[offset] = count;
|
||||
@@ -355,7 +328,6 @@ impl RSS14Reader {
|
||||
let mut oddSum = 0;
|
||||
let mut oddChecksumPortion = 0;
|
||||
for i in (0..self.oddCounts.len()).rev() {
|
||||
// for (int i = oddCounts.length - 1; i >= 0; i--) {
|
||||
oddChecksumPortion *= 9;
|
||||
oddChecksumPortion += &self.oddCounts[i];
|
||||
oddSum += &self.oddCounts[i];
|
||||
@@ -363,7 +335,6 @@ impl RSS14Reader {
|
||||
let mut evenChecksumPortion = 0;
|
||||
let mut evenSum = 0;
|
||||
for i in (0..self.evenCounts.len()).rev() {
|
||||
// for (int i = evenCounts.length - 1; i >= 0; i--) {
|
||||
evenChecksumPortion *= 9;
|
||||
evenChecksumPortion += self.evenCounts[i];
|
||||
evenSum += self.evenCounts[i];
|
||||
@@ -408,11 +379,6 @@ impl RSS14Reader {
|
||||
row: &BitArray,
|
||||
rightFinderPattern: bool,
|
||||
) -> Result<[usize; 2], Exceptions> {
|
||||
// let counters = self.getDecodeFinderCounters();
|
||||
// counters[0] = 0;
|
||||
// counters[1] = 0;
|
||||
// counters[2] = 0;
|
||||
// counters[3] = 0;
|
||||
let counters = &mut self.decodeFinderCounters;
|
||||
counters.fill(0);
|
||||
|
||||
@@ -431,7 +397,6 @@ impl RSS14Reader {
|
||||
let mut counterPosition = 0;
|
||||
let mut patternStart = rowOffset;
|
||||
for x in rowOffset..width {
|
||||
// for (int x = rowOffset; x < width; x++) {
|
||||
if row.get(x) != isWhite {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
@@ -476,9 +441,6 @@ impl RSS14Reader {
|
||||
|
||||
counters.copy_within(..counter_len - 1, 1);
|
||||
// Make 'counters' hold 1-4
|
||||
// let counters = self.getDecodeFinderCounters();
|
||||
// System.arraycopy(counters, 0, counters, 1, counters.length - 1);
|
||||
// counters.fill(0);
|
||||
|
||||
counters[0] = firstCounter as u32;
|
||||
let value = Self::parseFinderValue(counters, &Self::FINDER_PATTERNS)?;
|
||||
@@ -504,8 +466,8 @@ impl RSS14Reader {
|
||||
outsideChar: bool,
|
||||
numModules: u32,
|
||||
) -> Result<(), Exceptions> {
|
||||
let oddSum = self.oddCounts.iter().sum::<u32>(); //MathUtils.sum(getOddCounts());
|
||||
let evenSum = self.evenCounts.iter().sum::<u32>(); //MathUtils.sum(getEvenCounts());
|
||||
let oddSum = self.oddCounts.iter().sum::<u32>();
|
||||
let evenSum = self.evenCounts.iter().sum::<u32>();
|
||||
|
||||
let mut incrementOdd = false;
|
||||
let mut decrementOdd = false;
|
||||
@@ -537,7 +499,7 @@ impl RSS14Reader {
|
||||
}
|
||||
|
||||
let mismatch = oddSum as i32 + evenSum as i32 - numModules as i32;
|
||||
let oddParityBad = (oddSum & 0x01) == u32::from(outsideChar); //(if outsideChar { 1 } else { 0 });
|
||||
let oddParityBad = (oddSum & 0x01) == u32::from(outsideChar);
|
||||
let evenParityBad = (evenSum & 0x01) == 1;
|
||||
/*if (mismatch == 2) {
|
||||
if (!(oddParityBad && evenParityBad)) {
|
||||
|
||||
@@ -17,25 +17,15 @@
|
||||
/** Adapted from listings in ISO/IEC 24724 Appendix B and Appendix G. */
|
||||
|
||||
pub fn getRSSvalue(widths: &[u32], maxWidth: u32, noNarrow: bool) -> u32 {
|
||||
let mut n = 0;
|
||||
// for width in widths {
|
||||
// // for (int width : widths) {
|
||||
// n += width;
|
||||
// }
|
||||
n += widths.iter().sum::<u32>();
|
||||
let mut n = widths.iter().sum::<u32>();
|
||||
|
||||
let mut val = 0;
|
||||
let mut narrowMask = 0;
|
||||
let elements = widths.len() as u32;
|
||||
for bar in 0..(elements - 1) {
|
||||
// for (int bar = 0; bar < elements - 1; bar++) {
|
||||
// let elmWidth;
|
||||
let mut elmWidth = 1;
|
||||
narrowMask |= 1 << bar;
|
||||
while elmWidth < widths[bar as usize] {
|
||||
// for (elmWidth = 1, narrowMask |= 1 << bar;
|
||||
// elmWidth < widths[bar];
|
||||
// elmWidth++, narrowMask &= ~(1 << bar)) {
|
||||
let mut subVal = combins(n - elmWidth - 1, elements - bar - 2);
|
||||
if noNarrow
|
||||
&& (narrowMask == 0)
|
||||
@@ -47,8 +37,6 @@ pub fn getRSSvalue(widths: &[u32], maxWidth: u32, noNarrow: bool) -> u32 {
|
||||
let mut lessVal = 0;
|
||||
let mut mxwElement = n - elmWidth - (elements - bar - 2);
|
||||
while mxwElement > maxWidth {
|
||||
// for (int mxwElement = n - elmWidth - (elements - bar - 2);
|
||||
// mxwElement > maxWidth; mxwElement--) {
|
||||
lessVal += combins(n - elmWidth - mxwElement - 1, elements - bar - 3);
|
||||
|
||||
mxwElement -= 1;
|
||||
@@ -83,7 +71,6 @@ fn combins(n: u32, r: u32) -> u32 {
|
||||
let mut j = 1;
|
||||
let mut i = n;
|
||||
while i > maxDenom {
|
||||
// for (int i = n; i > maxDenom; i--) {
|
||||
val *= i;
|
||||
if j <= minDenom {
|
||||
val /= j;
|
||||
|
||||
@@ -94,16 +94,14 @@ impl UPCAReader {
|
||||
fn maybeReturnRXingResult(result: RXingResult) -> Result<RXingResult, Exceptions> {
|
||||
let text = result.getText();
|
||||
if let Some(stripped_text) = text.strip_prefix('0') {
|
||||
// if text.starts_with('0') {
|
||||
let mut upcaRXingResult = RXingResult::new(
|
||||
stripped_text,
|
||||
Vec::new(),
|
||||
result.getRXingResultPoints().to_vec(),
|
||||
BarcodeFormat::UPC_A,
|
||||
);
|
||||
// if result.getRXingResultMetadata() != null {
|
||||
upcaRXingResult.putAllMetadata(result.getRXingResultMetadata().clone());
|
||||
// }
|
||||
|
||||
Ok(upcaRXingResult)
|
||||
} else {
|
||||
Err(Exceptions::NotFoundException(None))
|
||||
|
||||
@@ -39,11 +39,8 @@ impl UPCEANReader for UPCEReader {
|
||||
startRange: &[usize; 2],
|
||||
resultString: &mut String,
|
||||
) -> Result<usize, Exceptions> {
|
||||
let mut counters = [0_u32; 4]; //decodeMiddleCounters;
|
||||
// counters[0] = 0;
|
||||
// counters[1] = 0;
|
||||
// counters[2] = 0;
|
||||
// counters[3] = 0;
|
||||
let mut counters = [0_u32; 4];
|
||||
|
||||
let end = row.getSize();
|
||||
let mut rowOffset = startRange[1];
|
||||
|
||||
@@ -51,12 +48,11 @@ impl UPCEANReader for UPCEReader {
|
||||
|
||||
let mut x = 0;
|
||||
while x < 6 && rowOffset < end {
|
||||
// for (int x = 0; x < 6 && rowOffset < end; x++) {
|
||||
let bestMatch = self.decodeDigit(row, &mut counters, rowOffset, &L_AND_G_PATTERNS)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32 % 10).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32 % 10)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
if bestMatch >= 10 {
|
||||
@@ -72,7 +68,9 @@ impl UPCEANReader for UPCEReader {
|
||||
}
|
||||
|
||||
fn checkChecksum(&self, s: &str) -> Result<bool, Exceptions> {
|
||||
self.checkStandardUPCEANChecksum(&convertUPCEtoUPCA(s))
|
||||
self.checkStandardUPCEANChecksum(
|
||||
&convertUPCEtoUPCA(s).ok_or(Exceptions::IllegalArgumentException(None))?,
|
||||
)
|
||||
}
|
||||
|
||||
fn decodeEnd(
|
||||
@@ -130,12 +128,17 @@ impl UPCEReader {
|
||||
lgPatternFound: usize,
|
||||
) -> Result<(), Exceptions> {
|
||||
for numSys in 0..=1 {
|
||||
// for (int numSys = 0; numSys <= 1; numSys++) {
|
||||
for d in 0..10 {
|
||||
// for (int d = 0; d < 10; d++) {
|
||||
if lgPatternFound == Self::NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d] {
|
||||
resultString.insert(0, char::from_u32('0' as u32 + numSys as u32).unwrap());
|
||||
resultString.push(char::from_u32('0' as u32 + d as u32).unwrap());
|
||||
resultString.insert(
|
||||
0,
|
||||
char::from_u32('0' as u32 + numSys as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + d as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -150,12 +153,13 @@ impl UPCEReader {
|
||||
* @param upce UPC-E code as string of digits
|
||||
* @return equivalent UPC-A code as string of digits
|
||||
*/
|
||||
pub fn convertUPCEtoUPCA(upce: &str) -> String {
|
||||
let upceChars = &upce[1..7]; //['0';6];//new char[6];
|
||||
//upce.getChars(1, 7, upceChars, 0);
|
||||
let mut result = String::with_capacity(12); //new StringBuilder(12);
|
||||
result.push(upce.chars().next().unwrap());
|
||||
let lastChar = upceChars.chars().nth(5).unwrap();
|
||||
pub fn convertUPCEtoUPCA(upce: &str) -> Option<String> {
|
||||
let upceChars = &upce[1..7];
|
||||
|
||||
let mut result = String::with_capacity(12);
|
||||
|
||||
result.push(upce.chars().next()?);
|
||||
let lastChar = upceChars.chars().nth(5)?;
|
||||
match lastChar {
|
||||
'0' | '1' | '2' => {
|
||||
result.push_str(&upceChars[0..2]);
|
||||
@@ -172,7 +176,7 @@ pub fn convertUPCEtoUPCA(upce: &str) -> String {
|
||||
'4' => {
|
||||
result.push_str(&upceChars[0..4]);
|
||||
result.push_str("00000");
|
||||
result.push(upceChars.chars().nth(4).unwrap());
|
||||
result.push(upceChars.chars().nth(4)?);
|
||||
}
|
||||
_ => {
|
||||
result.push_str(&upceChars[0..5]);
|
||||
@@ -182,8 +186,8 @@ pub fn convertUPCEtoUPCA(upce: &str) -> String {
|
||||
}
|
||||
// Only append check digit in conversion if supplied
|
||||
if upce.chars().count() >= 8 {
|
||||
result.push(upce.chars().nth(7).unwrap());
|
||||
result.push(upce.chars().nth(7)?);
|
||||
}
|
||||
|
||||
result
|
||||
Some(result)
|
||||
}
|
||||
|
||||
@@ -44,29 +44,22 @@ impl OneDimensionalCodeWriter for UPCEWriter {
|
||||
match length {
|
||||
7 => {
|
||||
// No check digit present, calculate it and add it
|
||||
let check = reader
|
||||
.getStandardUPCEANChecksum(&upc_e_reader::convertUPCEtoUPCA(&contents))?;
|
||||
// try {
|
||||
// check = UPCEANReader.getStandardUPCEANChecksum(UPCEReader.convertUPCEtoUPCA(contents));
|
||||
// } catch (FormatException fe) {
|
||||
// throw new IllegalArgumentException(fe);
|
||||
// }
|
||||
let check = reader.getStandardUPCEANChecksum(
|
||||
&upc_e_reader::convertUPCEtoUPCA(&contents)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?,
|
||||
)?;
|
||||
contents.push_str(&check.to_string());
|
||||
}
|
||||
8 =>
|
||||
// try {
|
||||
{
|
||||
if !reader
|
||||
.checkStandardUPCEANChecksum(&upc_e_reader::convertUPCEtoUPCA(&contents))?
|
||||
{
|
||||
8 => {
|
||||
if !reader.checkStandardUPCEANChecksum(
|
||||
&upc_e_reader::convertUPCEtoUPCA(&contents)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?,
|
||||
)? {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Contents do not pass checksum".to_owned(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
// } catch (FormatException ignored) {
|
||||
// throw new IllegalArgumentException("Illegal contents");
|
||||
// }},
|
||||
_ => {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(format!(
|
||||
"Requested contents should be 7 or 8 digits long, but got {length}"
|
||||
@@ -76,14 +69,24 @@ impl OneDimensionalCodeWriter for UPCEWriter {
|
||||
|
||||
Self::checkNumeric(&contents)?;
|
||||
|
||||
let firstDigit = contents.chars().next().unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(0), 10);
|
||||
let firstDigit = contents
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize; //Character.digit(contents.charAt(0), 10);
|
||||
if firstDigit != 0 && firstDigit != 1 {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Number system must be 0 or 1".to_owned(),
|
||||
)));
|
||||
}
|
||||
|
||||
let checkDigit = contents.chars().nth(7).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(7), 10);
|
||||
let checkDigit = contents
|
||||
.chars()
|
||||
.nth(7)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize; //Character.digit(contents.charAt(7), 10);
|
||||
let parities = UPCEReader::NUMSYS_AND_CHECK_DIGIT_PATTERNS[firstDigit][checkDigit];
|
||||
let mut result = [false; CODE_WIDTH];
|
||||
|
||||
@@ -92,7 +95,12 @@ impl OneDimensionalCodeWriter for UPCEWriter {
|
||||
|
||||
for i in 1..=6 {
|
||||
// for (int i = 1; i <= 6; i++) {
|
||||
let mut digit = contents.chars().nth(i).unwrap().to_digit(10).unwrap() as usize; //Character.digit(contents.charAt(i), 10);
|
||||
let mut digit = contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))? as usize; //Character.digit(contents.charAt(i), 10);
|
||||
if (parities >> (6 - i) & 1) == 1 {
|
||||
digit += 10;
|
||||
}
|
||||
@@ -112,6 +120,7 @@ impl OneDimensionalCodeWriter for UPCEWriter {
|
||||
fn getSupportedWriteFormats(&self) -> Option<Vec<crate::BarcodeFormat>> {
|
||||
Some(vec![BarcodeFormat::UPC_E])
|
||||
}
|
||||
|
||||
fn getDefaultMargin(&self) -> u32 {
|
||||
Self::DEFAULT_MARGIN
|
||||
}
|
||||
|
||||
@@ -70,10 +70,8 @@ impl UPCEANExtension2Support {
|
||||
resultString: &mut String,
|
||||
) -> Result<u32, Exceptions> {
|
||||
let mut counters = self.decodeMiddleCounters;
|
||||
counters[0] = 0;
|
||||
counters[1] = 0;
|
||||
counters[2] = 0;
|
||||
counters[3] = 0;
|
||||
counters.fill(0);
|
||||
|
||||
let end = row.getSize();
|
||||
let mut rowOffset = startRange[1] as usize;
|
||||
|
||||
@@ -88,11 +86,10 @@ impl UPCEANExtension2Support {
|
||||
rowOffset,
|
||||
&upc_ean_reader::L_AND_G_PATTERNS,
|
||||
)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32 % 10).unwrap());
|
||||
// for counter in counters {
|
||||
// // for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32 % 10)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
@@ -111,8 +108,11 @@ impl UPCEANExtension2Support {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
if resultString.parse::<u32>().unwrap() % 4 != checkParity {
|
||||
// if (Integer.parseInt(resultString.toString()) % 4 != checkParity) {
|
||||
if resultString.parse::<u32>().map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!("could not parse {resultString}: {e}")))
|
||||
})? % 4
|
||||
!= checkParity
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ impl UPCEANExtension2Support {
|
||||
|
||||
result.insert(
|
||||
RXingResultMetadataType::ISSUE_NUMBER,
|
||||
RXingResultMetadataValue::IssueNumber(raw.parse::<i32>().unwrap()),
|
||||
RXingResultMetadataValue::IssueNumber(raw.parse::<i32>().ok()?),
|
||||
);
|
||||
|
||||
Some(result)
|
||||
|
||||
@@ -27,10 +27,7 @@ use super::{upc_ean_reader, UPCEANReader, STAND_IN};
|
||||
* @see UPCEANExtension2Support
|
||||
*/
|
||||
#[derive(Default)]
|
||||
pub struct UPCEANExtension5Support {
|
||||
//decodeMiddleCounters : [u32;4],
|
||||
// decodeRowStringBuffer : String,
|
||||
}
|
||||
pub struct UPCEANExtension5Support;
|
||||
|
||||
impl UPCEANExtension5Support {
|
||||
const CHECK_DIGIT_ENCODINGS: [usize; 10] =
|
||||
@@ -42,8 +39,8 @@ impl UPCEANExtension5Support {
|
||||
row: &BitArray,
|
||||
extensionStartRange: &[usize; 2],
|
||||
) -> Result<RXingResult, Exceptions> {
|
||||
let mut result = String::new(); //self.decodeRowStringBuffer;
|
||||
// result.setLength(0);
|
||||
let mut result = String::new();
|
||||
|
||||
let end = Self::decodeMiddle(row, extensionStartRange, &mut result)?;
|
||||
|
||||
let resultString = result;
|
||||
@@ -61,9 +58,11 @@ impl UPCEANExtension5Support {
|
||||
],
|
||||
BarcodeFormat::UPC_EAN_EXTENSION,
|
||||
);
|
||||
|
||||
if let Some(ed) = extensionData {
|
||||
extensionRXingResult.putAllMetadata(ed);
|
||||
}
|
||||
|
||||
Ok(extensionRXingResult)
|
||||
}
|
||||
|
||||
@@ -72,11 +71,7 @@ impl UPCEANExtension5Support {
|
||||
startRange: &[usize; 2],
|
||||
resultString: &mut String,
|
||||
) -> Result<u32, Exceptions> {
|
||||
let mut counters = [0_u32; 4]; //decodeMiddleCounters;
|
||||
// counters[0] = 0;
|
||||
// counters[1] = 0;
|
||||
// counters[2] = 0;
|
||||
// counters[3] = 0;
|
||||
let mut counters = [0_u32; 4];
|
||||
let end = row.getSize();
|
||||
let mut rowOffset = startRange[1];
|
||||
|
||||
@@ -84,17 +79,17 @@ impl UPCEANExtension5Support {
|
||||
|
||||
let mut x = 0;
|
||||
while x < 5 && rowOffset < end {
|
||||
// for (int x = 0; x < 5 && rowOffset < end; x++) {
|
||||
let bestMatch = STAND_IN.decodeDigit(
|
||||
row,
|
||||
&mut counters,
|
||||
rowOffset,
|
||||
&upc_ean_reader::L_AND_G_PATTERNS,
|
||||
)?;
|
||||
resultString.push(char::from_u32('0' as u32 + bestMatch as u32 % 10).unwrap());
|
||||
// for (int counter : counters) {
|
||||
// rowOffset += counter;
|
||||
// }
|
||||
resultString.push(
|
||||
char::from_u32('0' as u32 + bestMatch as u32 % 10)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
|
||||
rowOffset += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
if bestMatch >= 10 {
|
||||
@@ -114,20 +109,23 @@ impl UPCEANExtension5Support {
|
||||
}
|
||||
|
||||
let checkDigit = Self::determineCheckDigit(lgPatternFound)?;
|
||||
if Self::extensionChecksum(resultString) != checkDigit as u32 {
|
||||
if Self::extensionChecksum(resultString)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?
|
||||
!= checkDigit as u32
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
Ok(rowOffset as u32)
|
||||
}
|
||||
|
||||
fn extensionChecksum(s: &str) -> u32 {
|
||||
fn extensionChecksum(s: &str) -> Option<u32> {
|
||||
let length = s.chars().count();
|
||||
let mut sum = 0;
|
||||
let mut i = length as isize - 2;
|
||||
while i >= 0 {
|
||||
// for (int i = length - 2; i >= 0; i -= 2) {
|
||||
sum += s.chars().nth(i as usize).unwrap() as u32 - '0' as u32;
|
||||
sum += s.chars().nth(i as usize)? as u32 - '0' as u32;
|
||||
|
||||
i -= 2;
|
||||
}
|
||||
@@ -136,17 +134,16 @@ impl UPCEANExtension5Support {
|
||||
let mut i = length as isize - 1;
|
||||
while i >= 0 {
|
||||
// for (int i = length - 1; i >= 0; i -= 2) {
|
||||
sum += s.chars().nth(i as usize).unwrap() as u32 - '0' as u32;
|
||||
sum += s.chars().nth(i as usize)? as u32 - '0' as u32;
|
||||
|
||||
i -= 2;
|
||||
}
|
||||
sum *= 3;
|
||||
sum % 10
|
||||
Some(sum % 10)
|
||||
}
|
||||
|
||||
fn determineCheckDigit(lgPatternFound: usize) -> Result<usize, Exceptions> {
|
||||
for d in 0..10 {
|
||||
// for (int d = 0; d < 10; d++) {
|
||||
if lgPatternFound == Self::CHECK_DIGIT_ENCODINGS[d] {
|
||||
return Ok(d);
|
||||
}
|
||||
@@ -166,9 +163,9 @@ impl UPCEANExtension5Support {
|
||||
return None;
|
||||
}
|
||||
let Some(value) = Self::parseExtension5String(raw) else {
|
||||
return None;
|
||||
};
|
||||
// Map<RXingResultMetadataType,Object> result = new EnumMap<>(RXingResultMetadataType.class);
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut result = HashMap::new();
|
||||
result.insert(
|
||||
RXingResultMetadataType::SUGGESTED_PRICE,
|
||||
@@ -179,7 +176,7 @@ impl UPCEANExtension5Support {
|
||||
}
|
||||
|
||||
fn parseExtension5String(raw: &str) -> Option<String> {
|
||||
let currency = match raw.chars().next().unwrap() {
|
||||
let currency = match raw.chars().next()? {
|
||||
'0' => "£",
|
||||
'5' => "$",
|
||||
'9' => {
|
||||
@@ -204,8 +201,7 @@ impl UPCEANExtension5Support {
|
||||
_ => "",
|
||||
};
|
||||
|
||||
let rawAmount = raw[1..].parse::<i32>().unwrap();
|
||||
// let rawAmount = Integer.parseInt(raw.substring(1));
|
||||
let rawAmount = raw[1..].parse::<i32>().ok()?;
|
||||
let unitsString = (rawAmount / 100).to_string();
|
||||
let hundredths = rawAmount % 100;
|
||||
let hundredthsString = if hundredths < 10 {
|
||||
|
||||
@@ -44,11 +44,5 @@ impl UPCEANExtensionSupport {
|
||||
self.twoSupport
|
||||
.decodeRow(rowNumber, row, &Self::EXTENSION_START_PATTERN)
|
||||
}
|
||||
// let res_2 = twoSupport.decodeRow(rowNumber, row, extensionStartRange);
|
||||
// try {
|
||||
// return fiveSupport.decodeRow(rowNumber, row, extensionStartRange);
|
||||
// } catch (ReaderException ignored) {
|
||||
// return twoSupport.decodeRow(rowNumber, row, extensionStartRange);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,22 +67,18 @@ pub const L_PATTERNS: [[u32; 4]; 10] = [
|
||||
* As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
|
||||
*/
|
||||
pub const L_AND_G_PATTERNS: [[u32; 4]; 20] = {
|
||||
let mut new_array = [[0_u32; 4]; 20]; //new int[20][];
|
||||
let mut new_array = [[0_u32; 4]; 20];
|
||||
let mut i = 0;
|
||||
while i < 10 {
|
||||
new_array[i] = L_PATTERNS[i];
|
||||
i += 1;
|
||||
}
|
||||
// new_array[0..10].copy_from_slice(&L_PATTERNS[0..10]);
|
||||
// System.arraycopy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10);
|
||||
let mut i = 10;
|
||||
while i < 20 {
|
||||
// for (int i = 10; i < 20; i++) {
|
||||
let widths = &L_PATTERNS[i - 10];
|
||||
let mut reversedWidths = [0_u32; 4]; //new int[widths.length];
|
||||
let mut reversedWidths = [0_u32; 4];
|
||||
let mut j = 0;
|
||||
while j < 4 {
|
||||
// for (int j = 0; j < widths.length; j++) {
|
||||
reversedWidths[j] = widths[4 - j - 1];
|
||||
|
||||
j += 1;
|
||||
@@ -104,24 +100,14 @@ pub const L_AND_G_PATTERNS: [[u32; 4]; 20] = {
|
||||
* @author alasdair@google.com (Alasdair Mackintosh)
|
||||
*/
|
||||
pub trait UPCEANReader: OneDReader {
|
||||
// private final StringBuilder decodeRowStringBuffer;
|
||||
// private final UPCEANExtensionSupport extensionReader;
|
||||
// private final EANManufacturerOrgSupport eanManSupport;
|
||||
|
||||
// protected UPCEANReader() {
|
||||
// decodeRowStringBuffer = new StringBuilder(20);
|
||||
// extensionReader = new UPCEANExtensionSupport();
|
||||
// eanManSupport = new EANManufacturerOrgSupport();
|
||||
// }
|
||||
|
||||
fn findStartGuardPattern(&self, row: &BitArray) -> Result<[usize; 2], Exceptions> {
|
||||
let mut foundStart = false;
|
||||
let mut startRange = [0; 2]; //= null;
|
||||
let mut startRange = [0; 2];
|
||||
let mut nextStart = 0;
|
||||
let mut counters = [0_u32; 3]; //vec![0_u32;START_END_PATTERN.len()];
|
||||
let mut counters = [0_u32; 3];
|
||||
while !foundStart {
|
||||
counters.fill(0);
|
||||
// Arrays.fill(counters, 0, START_END_PATTERN.len(), 0);
|
||||
|
||||
startRange = self.findGuardPatternWithCounters(
|
||||
row,
|
||||
nextStart,
|
||||
@@ -131,6 +117,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
)?;
|
||||
let start = startRange[0];
|
||||
nextStart = startRange[1];
|
||||
|
||||
// Make sure there is a quiet zone at least as big as the start pattern before the barcode.
|
||||
// If this check would run off the left edge of the image, do not accept this barcode,
|
||||
// as it is very likely to be a false positive.
|
||||
@@ -143,12 +130,6 @@ pub trait UPCEANReader: OneDReader {
|
||||
Ok(startRange)
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public RXingResult decodeRow(int rowNumber, BitArray row, Map<DecodeHintType,?> hints)
|
||||
// throws NotFoundException, ChecksumException, FormatException {
|
||||
// return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
|
||||
// }
|
||||
|
||||
/**
|
||||
* <p>Like {@link #decodeRow(int, BitArray, Map)}, but
|
||||
* allows caller to inform method about where the UPC/EAN start pattern is
|
||||
@@ -180,7 +161,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
));
|
||||
}
|
||||
|
||||
let mut result = String::new(); //decodeRowStringBuffer;
|
||||
let mut result = String::new();
|
||||
let endStart = self.decodeMiddle(row, startGuardRange, &mut result)?;
|
||||
|
||||
if let Some(DecodeHintValue::NeedResultPointCallback(cb)) = resultPointCallback {
|
||||
@@ -205,10 +186,12 @@ pub trait UPCEANReader: OneDReader {
|
||||
}
|
||||
|
||||
let resultString = result;
|
||||
|
||||
// UPC/EAN should never be less than 8 chars anyway
|
||||
if resultString.chars().count() < 8 {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
|
||||
if !self.checkChecksum(&resultString)? {
|
||||
return Err(Exceptions::ChecksumException(None));
|
||||
}
|
||||
@@ -234,7 +217,9 @@ pub trait UPCEANReader: OneDReader {
|
||||
|
||||
decodeRXingResult.putMetadata(
|
||||
RXingResultMetadataType::UPC_EAN_EXTENSION,
|
||||
RXingResultMetadataValue::UpcEanExtension(extensionRXingResult.getText().clone()),
|
||||
RXingResultMetadataValue::UpcEanExtension(
|
||||
extensionRXingResult.getText().to_owned(),
|
||||
),
|
||||
);
|
||||
decodeRXingResult.putAllMetadata(extensionRXingResult.getRXingResultMetadata().clone());
|
||||
decodeRXingResult
|
||||
@@ -244,27 +229,12 @@ pub trait UPCEANReader: OneDReader {
|
||||
};
|
||||
|
||||
let _try_result = attempt();
|
||||
// if let Err(Exceptions::ReaderException(_)) = try_result {
|
||||
// } else if try_result.is_err() {
|
||||
// return Err(try_result.err().unwrap());
|
||||
// }
|
||||
|
||||
// try {
|
||||
// RXingResult extensionRXingResult = extensionReader.decodeRow(rowNumber, row, endRange[1]);
|
||||
// decodeRXingResult.putMetadata(RXingResultMetadataType.UPC_EAN_EXTENSION, extensionRXingResult.getText());
|
||||
// decodeRXingResult.putAllMetadata(extensionRXingResult.getRXingResultMetadata());
|
||||
// decodeRXingResult.addRXingResultPoints(extensionRXingResult.getRXingResultPoints());
|
||||
// extensionLength = extensionRXingResult.getText().length();
|
||||
// } catch (ReaderException re) {
|
||||
// // continue
|
||||
// }
|
||||
|
||||
if let Some(DecodeHintValue::AllowedEanExtensions(allowedExtensions)) =
|
||||
hints.get(&DecodeHintType::ALLOWED_EAN_EXTENSIONS)
|
||||
{
|
||||
let mut valid = false;
|
||||
for length in allowedExtensions {
|
||||
// for (int length : allowedExtensions) {
|
||||
if extensionLength == *length as usize {
|
||||
valid = true;
|
||||
break;
|
||||
@@ -274,20 +244,6 @@ pub trait UPCEANReader: OneDReader {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
}
|
||||
// let allowedExtensions =
|
||||
// hints == null ? null : (int[]) hints.get(DecodeHintType.ALLOWED_EAN_EXTENSIONS);
|
||||
// if (allowedExtensions != null) {
|
||||
// let valid = false;
|
||||
// for (int length : allowedExtensions) {
|
||||
// if (extensionLength == length) {
|
||||
// valid = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!valid) {
|
||||
// return Err(Exceptions::NotFoundException(None));
|
||||
// }
|
||||
// }
|
||||
|
||||
if format == BarcodeFormat::EAN_13 || format == BarcodeFormat::UPC_A {
|
||||
let countryID = EAN_MANUFACTURER_SUPPORT.lookupCountryIdentifier(&resultString);
|
||||
@@ -298,6 +254,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if format == BarcodeFormat::EAN_8 {
|
||||
symbologyIdentifier = 4;
|
||||
}
|
||||
@@ -332,16 +289,20 @@ pub trait UPCEANReader: OneDReader {
|
||||
if length == 0 {
|
||||
return Ok(false);
|
||||
}
|
||||
let char_in_question = s.chars().nth(length - 1).unwrap();
|
||||
let char_in_question = s
|
||||
.chars()
|
||||
.nth(length - 1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
let check = char_in_question.is_ascii_digit();
|
||||
// let check = Character.digit(s.charAt(length - 1), 10);
|
||||
|
||||
let check_against = &s[..length - 1]; //s.subSequence(0, length - 1);
|
||||
let calculated_checksum = self.getStandardUPCEANChecksum(check_against)?;
|
||||
|
||||
Ok(calculated_checksum
|
||||
== if check {
|
||||
char_in_question.to_digit(10).unwrap()
|
||||
char_in_question
|
||||
.to_digit(10)
|
||||
.ok_or(Exceptions::ParseException(None))?
|
||||
} else {
|
||||
u32::MAX
|
||||
})
|
||||
@@ -353,7 +314,11 @@ pub trait UPCEANReader: OneDReader {
|
||||
let mut i = length as isize - 1;
|
||||
while i >= 0 {
|
||||
// for (int i = length - 1; i >= 0; i -= 2) {
|
||||
let digit = (s.chars().nth(i as usize).unwrap() as i32) - ('0' as i32);
|
||||
let digit =
|
||||
(s.chars()
|
||||
.nth(i as usize)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as i32)
|
||||
- ('0' as i32);
|
||||
if !(0..=9).contains(&digit) {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
@@ -365,7 +330,11 @@ pub trait UPCEANReader: OneDReader {
|
||||
let mut i = length as isize - 2;
|
||||
while i >= 0 {
|
||||
// for (int i = length - 2; i >= 0; i -= 2) {
|
||||
let digit = (s.chars().nth(i as usize).unwrap() as i32) - ('0' as i32);
|
||||
let digit =
|
||||
(s.chars()
|
||||
.nth(i as usize)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as i32)
|
||||
- ('0' as i32);
|
||||
if !(0..=9).contains(&digit) {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
@@ -442,7 +411,7 @@ pub trait UPCEANReader: OneDReader {
|
||||
patternStart += (counters[0] + counters[1]) as usize;
|
||||
|
||||
counters.copy_within(2..(counterPosition - 1 + 2), 0);
|
||||
// System.arraycopy(counters, 2, counters, 0, counterPosition - 1);
|
||||
|
||||
counters[counterPosition - 1] = 0;
|
||||
counters[counterPosition] = 0;
|
||||
counterPosition -= 1;
|
||||
@@ -481,7 +450,6 @@ pub trait UPCEANReader: OneDReader {
|
||||
let mut bestMatch = -1_isize;
|
||||
let max = patterns.len();
|
||||
for (i, pattern) in patterns.iter().enumerate().take(max) {
|
||||
// for (int i = 0; i < max; i++) {
|
||||
let variance: f32 =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
if variance < bestVariance {
|
||||
|
||||
Reference in New Issue
Block a user