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:
Henry
2023-02-10 20:41:25 -06:00
parent 5222bb25b7
commit 28723be2eb
180 changed files with 3248 additions and 4117 deletions

View File

@@ -32,7 +32,7 @@ use crate::{
RXingResultPoint,
};
use super::{decoder, AztecDetectorResult::AztecDetectorRXingResult};
use super::{aztec_detector_result::AztecDetectorRXingResult, decoder};
/**
* Tests {@link Decoder}.

View File

@@ -185,7 +185,7 @@ fn test_error_in_parameter_locator(data: &str) {
// Zooms a bit matrix so that each bit is factor x factor
fn make_larger(input: &BitMatrix, factor: u32) -> BitMatrix {
let width = input.getWidth();
let mut output = BitMatrix::with_single_dimension(width * factor);
let mut output = BitMatrix::with_single_dimension(width * factor).expect("new");
for inputY in 0..width {
// for (int inputY = 0; inputY < width; inputY++) {
for inputX in 0..width {
@@ -216,7 +216,7 @@ fn get_rotations(matrix0: &BitMatrix) -> Vec<BitMatrix> {
// Rotates a square BitMatrix to the right by 90 degrees
fn rotate_right(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let mut result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width).expect("new");
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {
@@ -233,7 +233,7 @@ fn rotate_right(input: &BitMatrix) -> BitMatrix {
// matrix to the right, and then flipping it left-to-right
fn transpose(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let mut result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width).expect("new");
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {
@@ -248,7 +248,7 @@ fn transpose(input: &BitMatrix) -> BitMatrix {
fn clone(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth();
let mut result = BitMatrix::with_single_dimension(width);
let mut result = BitMatrix::with_single_dimension(width).expect("new");
for x in 0..width {
// for (int x = 0; x < width; x++) {
for y in 0..width {

View File

@@ -20,10 +20,10 @@ use encoding::EncodingRef;
use crate::{
aztec::{
aztec_detector_result::AztecDetectorRXingResult,
decoder,
encoder::HighLevelEncoder,
shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
AztecDetectorResult::AztecDetectorRXingResult,
},
BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint,
};
@@ -810,7 +810,7 @@ fn testModeMessageComplex(compact: bool, layers: u32, words: u32, expected: &str
fn testStuffBits(wordSize: usize, bits: &str, expected: &str) {
let indata = toBitArray(bits);
let stuffed = aztec_encoder::stuffBits(&indata, wordSize);
let stuffed = aztec_encoder::stuffBits(&indata, wordSize).unwrap();
assert_eq!(
stripSpace(expected),
stripSpace(&stuffed.to_string()),

View File

@@ -33,7 +33,7 @@ use crate::{
*/
pub struct AztecDetectorRXingResult {
bits: BitMatrix,
points: Vec<RXingResultPoint>,
points: [RXingResultPoint; 4],
compact: bool,
nbDatablocks: u32,
nbLayers: u32,
@@ -59,7 +59,7 @@ impl AztecDetectorRXingResult {
) -> Self {
Self {
bits,
points: points.to_vec(),
points,
compact,
nbDatablocks,
nbLayers,

View File

@@ -130,8 +130,4 @@ impl Reader for AztecReader {
Ok(result)
}
fn reset(&mut self) {
// do nothing
}
}

View File

@@ -53,36 +53,25 @@ impl Writer for AztecWriter {
let mut charset = None; // Do not add any ECI code by default
let mut ecc_percent = aztec_encoder::DEFAULT_EC_PERCENT;
let mut layers = aztec_encoder::DEFAULT_AZTEC_LAYERS;
if hints.contains_key(&EncodeHintType::CHARACTER_SET) {
if let EncodeHintValue::CharacterSet(cset_name) = hints
.get(&EncodeHintType::CHARACTER_SET)
.expect("already knonw presence")
{
if cset_name != "iso-8859-1" {
charset = Some(encoding::label::encoding_from_whatwg_label(cset_name).unwrap());
}
// dbg!(cset_name);
// dbg!(encoding::label::encoding_from_whatwg_label(cset_name).unwrap().name(), encoding::label::encoding_from_whatwg_label(cset_name).unwrap().whatwg_name());
if let Some(EncodeHintValue::CharacterSet(cset_name)) =
hints.get(&EncodeHintType::CHARACTER_SET)
{
if cset_name.to_lowercase() != "iso-8859-1" {
charset = Some(
encoding::label::encoding_from_whatwg_label(cset_name)
.ok_or(Exceptions::IllegalArgumentException(None))?,
);
}
// charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
}
if hints.contains_key(&EncodeHintType::ERROR_CORRECTION) {
if let EncodeHintValue::ErrorCorrection(ecc_level) = hints
.get(&EncodeHintType::ERROR_CORRECTION)
.expect("key exists")
{
ecc_percent = ecc_level.parse().expect("should convert to int");
}
// eccPercent = Integer.parseInt(hints.get(EncodeHintType::ERROR_CORRECTION).toString());
if let Some(EncodeHintValue::ErrorCorrection(ecc_level)) =
hints.get(&EncodeHintType::ERROR_CORRECTION)
{
ecc_percent = ecc_level.parse().unwrap_or(23);
}
if hints.contains_key(&EncodeHintType::AZTEC_LAYERS) {
if let EncodeHintValue::AztecLayers(az_layers) = hints
.get(&EncodeHintType::AZTEC_LAYERS)
.expect("key exists")
{
layers = *az_layers;
}
// layers = Integer.parseInt(hints.get(EncodeHintType.AZTEC_LAYERS).toString());
if let Some(EncodeHintValue::AztecLayers(az_layers)) =
hints.get(&EncodeHintType::AZTEC_LAYERS)
{
layers = *az_layers;
}
encode(
contents,
@@ -121,9 +110,7 @@ fn encode(
fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMatrix, Exceptions> {
let input = code.getMatrix();
// if input == null {
// throw new IllegalStateException();
// }
let input_width = input.getWidth();
let input_height = input.getHeight();
let output_width = width.max(input_width);
@@ -152,13 +139,5 @@ fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMat
input_y += 1;
output_y += multiple
}
// for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
// // Write the contents of this row of the barcode
// for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
// if (input.get(inputX, inputY)) {
// output.setRegion(outputX, outputY, multiple, multiple);
// }
// }
// }
Ok(output)
}

View File

@@ -24,7 +24,7 @@ use crate::{
exceptions::Exceptions,
};
use super::AztecDetectorResult::AztecDetectorRXingResult;
use super::aztec_detector_result::AztecDetectorRXingResult;
/**
* <p>The main class which implements Aztec Code decoding -- as opposed to locating and extracting
@@ -164,7 +164,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String, Exceptions> {
result.push_str(
&encdr
.decode(&decoded_bytes, encoding::DecoderTrap::Strict)
.unwrap(),
.map_err(|a| Exceptions::IllegalStateException(Some(a.to_string())))?,
);
decoded_bytes.clear();
@@ -210,8 +210,17 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String, Exceptions> {
// That's including when that mode is a shift.
// Our test case dlusbs.png for issue #642 exercises that.
latch_table = shift_table; // Latch the current mode, so as to return to Upper after U/S B/S
shift_table = getTable(str.chars().nth(5).unwrap());
if str.chars().nth(6).unwrap() == 'L' {
shift_table = getTable(
str.chars()
.nth(5)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
);
if str
.chars()
.nth(6)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
== 'L'
{
latch_table = shift_table;
}
} else {

View File

@@ -26,7 +26,7 @@ use crate::{
RXingResultPoint, ResultPoint,
};
use super::AztecDetectorResult::AztecDetectorRXingResult;
use super::aztec_detector_result::AztecDetectorRXingResult;
const EXPECTED_CORNER_BITS: [u32; 4] = [
0xee0, // 07340 XXX .XX X.. ...
@@ -731,11 +731,11 @@ impl<'a> Detector<'_> {
}
fn distance_points(a: &Point, b: &Point) -> f32 {
MathUtils::distance_int(a.get_x(), a.get_y(), b.get_x(), b.get_y())
MathUtils::distance(a.get_x(), a.get_y(), b.get_x(), b.get_y())
}
fn distance(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
MathUtils::distance_float(a.getX(), a.getY(), b.getX(), b.getY())
MathUtils::distance(a.getX(), a.getY(), b.getX(), b.getY())
}
fn get_dimension(&self) -> u32 {

View File

@@ -185,7 +185,7 @@ pub fn encode_bytes_with_charset(
total_bits_in_layer_var = total_bits_in_layer(layers, compact);
word_size = WORD_SIZE[layers as usize];
let usable_bits_in_layers = total_bits_in_layer_var - (total_bits_in_layer_var % word_size);
stuffed_bits = stuffBits(&bits, word_size as usize);
stuffed_bits = stuffBits(&bits, word_size as usize)?;
if stuffed_bits.getSize() as u32 + ecc_bits > usable_bits_in_layers {
return Err(Exceptions::IllegalArgumentException(Some(
"Data to large for user specified layer".to_owned(),
@@ -222,7 +222,7 @@ pub fn encode_bytes_with_charset(
// wordSize has changed
if stuffed_bits.getSize() == 0 || word_size != WORD_SIZE[layers as usize] {
word_size = WORD_SIZE[layers as usize];
stuffed_bits = stuffBits(&bits, word_size as usize);
stuffed_bits = stuffBits(&bits, word_size as usize)?;
}
let usable_bits_in_layers =
total_bits_in_layer_var - (total_bits_in_layer_var % word_size);
@@ -267,7 +267,7 @@ pub fn encode_bytes_with_charset(
alignmentMap[origCenter + i] = center + newOffset + 1;
}
}
let mut matrix = BitMatrix::with_single_dimension(matrixSize);
let mut matrix = BitMatrix::with_single_dimension(matrixSize)?;
// dbg!(matrix.to_string());
@@ -307,13 +307,9 @@ pub fn encode_bytes_with_charset(
rowOffset += rowSize * 8;
}
// dbg!(matrix.to_string());
// draw mode message
drawModeMessage(&mut matrix, compact, matrixSize, modeMessage);
// dbg!(matrix.to_string());
// draw alignment marks
if compact {
drawBullsEye(&mut matrix, matrixSize / 2, 5);
@@ -385,20 +381,12 @@ pub fn generateModeMessage(
) -> Result<BitArray, Exceptions> {
let mut mode_message = BitArray::new();
if compact {
mode_message
.appendBits(layers - 1, 2)
.expect("should append");
mode_message
.appendBits(messageSizeInWords - 1, 6)
.expect("should append");
mode_message.appendBits(layers - 1, 2)?;
mode_message.appendBits(messageSizeInWords - 1, 6)?;
mode_message = generateCheckWords(&mode_message, 28, 4)?;
} else {
mode_message
.appendBits(layers - 1, 5)
.expect("should append");
mode_message
.appendBits(messageSizeInWords - 1, 11)
.expect("should append");
mode_message.appendBits(layers - 1, 5)?;
mode_message.appendBits(messageSizeInWords - 1, 11)?;
mode_message = generateCheckWords(&mode_message, 40, 4)?;
}
Ok(mode_message)
@@ -407,7 +395,7 @@ pub fn generateModeMessage(
fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeMessage: BitArray) {
let center = matrixSize / 2;
if compact {
for i in 0..7usize {
for i in 0..7_usize {
// for (int i = 0; i < 7; i++) {
let offset = (center as usize - 3 + i) as u32;
if modeMessage.get(i) {
@@ -424,7 +412,7 @@ fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeM
}
}
} else {
for i in 0..10usize {
for i in 0..10_usize {
// for (int i = 0; i < 10; i++) {
let offset = (center as usize - 5 + i + i / 5) as u32;
if modeMessage.get(i) {
@@ -450,13 +438,13 @@ fn generateCheckWords(
) -> Result<BitArray, Exceptions> {
// bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
let message_size_in_words = bitArray.getSize() / wordSize;
let mut rs = ReedSolomonEncoder::new(getGF(wordSize)?);
let mut rs = ReedSolomonEncoder::new(getGF(wordSize)?)?;
let total_words = totalBits / wordSize;
let mut message_words = bitsToWords(bitArray, wordSize, total_words);
rs.encode(&mut message_words, total_words - message_size_in_words)?;
let start_pad = totalBits % wordSize;
let mut message_bits = BitArray::new();
message_bits.appendBits(0, start_pad).expect("must append");
message_bits.appendBits(0, start_pad)?;
for message_word in message_words {
// for (int messageWord : messageWords) {
message_bits.appendBits(message_word as u32, wordSize)?
@@ -498,23 +486,9 @@ fn getGF(wordSize: usize) -> Result<GenericGFRef, Exceptions> {
"Unsupported word size {wordSize}"
)))),
}
// switch (wordSize) {
// case 4:
// return GenericGF.AZTEC_PARAM;
// case 6:
// return GenericGF.AZTEC_DATA_6;
// case 8:
// return GenericGF.AZTEC_DATA_8;
// case 10:
// return GenericGF.AZTEC_DATA_10;
// case 12:
// return GenericGF.AZTEC_DATA_12;
// default:
// throw new IllegalArgumentException("Unsupported word size " + wordSize);
// }
}
pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
pub fn stuffBits(bits: &BitArray, word_size: usize) -> Result<BitArray, Exceptions> {
let mut out = BitArray::new();
let n = bits.getSize() as isize;
@@ -530,21 +504,20 @@ pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
}
}
if (word & mask) == mask {
out.appendBits(word & mask, word_size).unwrap();
out.appendBits(word & mask, word_size)?;
i -= 1;
} else if (word & mask) == 0 {
out.appendBits(word | 1, word_size).unwrap();
out.appendBits(word | 1, word_size)?;
i -= 1;
} else {
out.appendBits(word, word_size).unwrap();
out.appendBits(word, word_size)?;
}
i += word_size as isize;
}
out
Ok(out)
}
fn total_bits_in_layer(layers: u32, compact: bool) -> u32 {
((if compact { 88 } else { 112 }) + 16 * layers) * layers
// return ((compact ? 88 : 112) + 16 * layers) * layers;
}

View File

@@ -16,7 +16,7 @@
use std::fmt;
use crate::common::BitArray;
use crate::{common::BitArray, Exceptions};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BinaryShiftToken {
@@ -32,28 +32,27 @@ impl BinaryShiftToken {
}
}
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) -> Result<(), Exceptions> {
let bsbc = self.binary_shift_byte_count as usize;
for i in 0..bsbc {
// for (int i = 0; i < bsbc; i++) {
if i == 0 || (i == 31 && bsbc <= 62) {
// We need a header before the first character, and before
// character 31 when the total byte code is <= 62
bit_array.appendBits(31, 5).unwrap(); // BINARY_SHIFT
bit_array.appendBits(31, 5)?; // BINARY_SHIFT
if bsbc > 62 {
bit_array.appendBits(bsbc as u32 - 31, 16).unwrap();
bit_array.appendBits(bsbc as u32 - 31, 16)?;
} else if i == 0 {
// 1 <= binaryShiftByteCode <= 62
bit_array.appendBits(bsbc.min(31) as u32, 5).unwrap();
bit_array.appendBits(bsbc.min(31) as u32, 5)?;
} else {
// 32 <= binaryShiftCount <= 62 and i == 31
bit_array.appendBits(bsbc as u32 - 31, 5).unwrap();
bit_array.appendBits(bsbc as u32 - 31, 5)?;
}
}
bit_array
.appendBits(text[self.binary_shift_start as usize + i].into(), 8)
.expect("should never fail to append");
bit_array.appendBits(text[self.binary_shift_start as usize + i].into(), 8)?;
}
Ok(())
}
// @Override

View File

@@ -324,7 +324,7 @@ impl HighLevelEncoder {
// Convert it to a bit array, and return.
// dbg!(min_state.clone().toBitArray(&self.text).to_string());
Ok(min_state.toBitArray(&self.text))
min_state.toBitArray(&self.text)
}
// We update a set of states for a new character by updating each state

View File

@@ -16,7 +16,7 @@
use std::fmt;
use crate::common::BitArray;
use crate::{common::BitArray, Exceptions};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SimpleToken {
@@ -33,10 +33,8 @@ impl SimpleToken {
}
}
pub fn appendTo(&self, bit_array: &mut BitArray, _text: &[u8]) {
bit_array
.appendBits(self.value as u32, self.bit_count as usize)
.expect("append should never fail");
pub fn appendTo(&self, bit_array: &mut BitArray, _text: &[u8]) -> Result<(), Exceptions> {
bit_array.appendBits(self.value as u32, self.bit_count as usize)
}
// @Override

View File

@@ -85,9 +85,11 @@ impl State {
)));
// throw new IllegalArgumentException("ECI code must be between 0 and 999999");
} else {
let eci_digits = encoding::all::ISO_8859_1
let Ok(eci_digits) = encoding::all::ISO_8859_1
.encode(&format!("{eci}"), encoding::EncoderTrap::Strict)
.unwrap();
else {
return Err(Exceptions::IllegalArgumentException(None))
};
// let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1);
token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits
for eci_digit in &eci_digits {
@@ -205,7 +207,7 @@ impl State {
new_mode_bit_count <= other.bit_count
}
pub fn toBitArray(self, text: &[u8]) -> BitArray {
pub fn toBitArray(self, text: &[u8]) -> Result<BitArray, Exceptions> {
let mut symbols = Vec::new();
let tok = self.endBinaryShift(text.len() as u32).token;
for tkn in tok.into_iter() {
@@ -223,22 +225,22 @@ impl State {
for symbol in symbols.into_iter().rev() {
// for i in (0..symbols.len()).rev() {
// for (int i = symbols.size() - 1; i >= 0; i--) {
symbol.appendTo(&mut bit_array, text);
symbol.appendTo(&mut bit_array, text)?;
}
bit_array
Ok(bit_array)
}
#[inline(always)]
fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
if binary_shift_byte_count > 62 {
return 21; // B/S with extended length
21 // B/S with extended length
} else if binary_shift_byte_count > 31 {
20 // two B/S
} else if binary_shift_byte_count > 0 {
10 // one B/S
} else {
0
}
if binary_shift_byte_count > 31 {
return 20; // two B/S
}
if binary_shift_byte_count > 0 {
return 10; // one B/S
}
0
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
use crate::common::BitArray;
use crate::{common::BitArray, Exceptions};
use super::{BinaryShiftToken, SimpleToken};
@@ -26,12 +26,14 @@ pub enum TokenType {
}
impl TokenType {
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) -> Result<(), Exceptions> {
// let token = &self.tokens[self.current_pointer];
match self {
TokenType::Simple(a) => a.appendTo(bit_array, text),
TokenType::BinaryShift(a) => a.appendTo(bit_array, text),
TokenType::Empty => panic!("cannot appendTo on Empty final item"),
TokenType::Empty => Err(Exceptions::IllegalStateException(Some(String::from(
"cannot appendTo on Empty final item",
)))),
}
}
}
@@ -95,27 +97,6 @@ impl IntoIterator for Token {
}
}
// pub enum Token{
// Simple(Rc<SimpleToken>),
// BinaryShift(),
// Empty,
// }
// pub trait TokenTrait {
// fn getPrevious(&self)->&Token;
// fn add(&self, value: i32, bitCount: u32) -> Token{
// Token::Simple(Rc::new(SimpleToken::new(self, value, bitCount)))
// }
// fn addBinaryShift(&self, start: i32, byteCount: u32) -> &Token; //{
// // //int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);
// // return new BinaryShiftToken(this, start, byteCount);
// // }
// fn appendTo(&self, bitArray: BitArray, text: &[u8]);
// }
impl Default for Token {
fn default() -> Self {
Self::new()

View File

@@ -1,4 +1,4 @@
mod AztecDetectorResult;
mod aztec_detector_result;
mod aztec_reader;
mod aztec_writer;
pub mod decoder;

View File

@@ -78,6 +78,8 @@ impl BinaryBitmap {
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
* fetched using getBlackRow(), so don't mix and match between them.
*
* Panics if the binarizer cannot be created.
*
* @return The 2D array of bits for the image (true means black).
* @throws NotFoundException if image can't be binarized to make a matrix
*/
@@ -99,6 +101,8 @@ impl BinaryBitmap {
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
* fetched using getBlackRow(), so don't mix and match between them.
*
* Panics if the binarizer cannot be created.
*
* @return The 2D array of bits for the image (true means black).
* @throws NotFoundException if image can't be binarized to make a matrix
*/
@@ -125,6 +129,8 @@ impl BinaryBitmap {
* Returns a new object with cropped image data. Implementations may keep a reference to the
* original data rather than a copy. Only callable if isCropSupported() is true.
*
* Panics if the binarizer cannot be created.
*
* @param left The left coordinate, which must be in [0,getWidth())
* @param top The top coordinate, which must be in [0,getHeight())
* @param width The width of the rectangle to crop.
@@ -140,10 +146,6 @@ impl BinaryBitmap {
self.binarizer
.createBinarizer(newSource.expect("new lum source expected")),
);
// Self {
// binarizer: self.binarizer.clone(),
// matrix: Some(self.getBlackMatrix().crop(top, left, height, width)),
// }
}
/**
@@ -157,6 +159,8 @@ impl BinaryBitmap {
* Returns a new object with rotated image data by 90 degrees counterclockwise.
* Only callable if {@link #isRotateSupported()} is true.
*
* Panics if the binarizer cannot be created.
*
* @return A rotated version of this object.
*/
pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap {
@@ -165,19 +169,14 @@ impl BinaryBitmap {
self.binarizer
.createBinarizer(newSource.expect("new lum source expected")),
);
// let mut new_matrix = self.getBlackMatrix().clone();
// new_matrix.rotate90();
// Self {
// binarizer: self.binarizer.clone(),
// matrix: Some(new_matrix),
// }
}
/**
* Returns a new object with rotated image data by 45 degrees counterclockwise.
* Only callable if {@link #isRotateSupported()} is true.
*
* Panics if the binarizer cannot be created.
*
* @return A rotated version of this object.
*/
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {

View File

@@ -54,46 +54,6 @@ impl BufferedImageLuminanceSource {
width: usize,
height: usize,
) -> Self {
// if image.getType() == BufferedImage.TYPE_BYTE_GRAY {
// this.image = image;
// } else {
// int sourceWidth = image.getWidth();
// int sourceHeight = image.getHeight();
// if (left + width > sourceWidth || top + height > sourceHeight) {
// throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
// }
// this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
// WritableRaster raster = this.image.getRaster();
// int[] buffer = new int[width];
// for (int y = top; y < top + height; y++) {
// image.getRGB(left, y, width, 1, buffer, 0, sourceWidth);
// for (int x = 0; x < width; x++) {
// int pixel = buffer[x];
// // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent
// // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a
// // barcode image. Force any such pixel to be white:
// if ((pixel & 0xFF000000) == 0) {
// // white, so we know its luminance is 255
// buffer[x] = 0xFF;
// } else {
// // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
// // (306*R) >> 10 is approximately equal to R*0.299, and so on.
// // 0x200 >> 10 is 0.5, it implements rounding.
// buffer[x] =
// (306 * ((pixel >> 16) & 0xFF) +
// 601 * ((pixel >> 8) & 0xFF) +
// 117 * (pixel & 0xFF) +
// 0x200) >> 10;
// }
// }
// raster.setPixels(left, y, width, 1, buffer);
// }
// }
let img = image.to_rgba8();
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(image.width(), image.height());
@@ -116,29 +76,6 @@ impl BufferedImageLuminanceSource {
}
}
// for pixel in img.pixels() {
// // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent
// // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a
// // barcode image. Force any such pixel to be white:
// let [red,green,blue,alpha] = pixel.0;
// if (alpha & 0xFF) == 0 {
// // white, so we know its luminance is 255
// raster.push(0xFF);
// // buffer[x] = 0xFF;
// } else {
// // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
// // (306*R) >> 10 is approximately equal to R*0.299, and so on.
// // 0x200 >> 10 is 0.5, it implements rounding.
// raster.push((
// (306 * ((red as u32 >> 16) & 0xFF) +
// 601 * ((green as u32 >> 8) & 0xFF) +
// 117 * (blue as u32 & 0xFF) +
// 0x200) >> 10) as u8);
// }
// }
// let ib:ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::from_raw(image.width() , image.height(), raster).unwrap();
Self {
image: Rc::new(DynamicImage::from(raster)),
width,
@@ -146,14 +83,6 @@ impl BufferedImageLuminanceSource {
left,
top,
}
// Self {
// image: DynamicImage::from(image.to_luma8()),
// width: width,
// height: height,
// left: left,
// top: top,
// }
}
}
@@ -161,20 +90,19 @@ impl LuminanceSource for BufferedImageLuminanceSource {
fn getRow(&self, y: usize) -> Vec<u8> {
let width = self.getWidth(); // - self.left as usize;
let pixels: Vec<u8> = self
.image
.as_luma8()
.unwrap()
.rows()
.nth(y + self.top as usize)
.unwrap()
.skip(self.left as usize)
.take(width)
.map(|&p| p.0[0])
.collect();
// The underlying raster of image consists of bytes with the luminance values
// row[..width].clone_from_slice(&pixels[..]);
let pixels: Vec<u8> = || -> Option<Vec<u8>> {
Some(
self.image
.as_luma8()?
.rows()
.nth(y + self.top as usize)?
.skip(self.left as usize)
.take(width)
.map(|&p| p.0[0])
.collect(),
)
}()
.unwrap_or_default();
pixels
}
@@ -221,7 +149,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
}
fn invert(&mut self) {
// self.image.borrow_mut().invert();
let mut img = (*self.image).clone();
img.invert();
self.image = Rc::new(img);
@@ -238,18 +165,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
width: usize,
height: usize,
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> {
// Ok(Box::new(BufferedImageLuminanceSource::with_details(
// self.image
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
// self.left + left as u32,
// self.top + top as u32,
// width,
// height,
// )))
Ok(Box::new(Self {
// image: self
// .image
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
image: self.image.clone(),
width,
height,
@@ -265,9 +181,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
fn rotateCounterClockwise(
&self,
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> {
// Ok(Box::new(BufferedImageLuminanceSource::new(
// self.image.rotate270(),
// )))
let img = self.image.rotate270();
Ok(Box::new(Self {
width: img.width() as usize,
@@ -290,7 +203,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
let new_img = DynamicImage::from(img);
// Ok(Box::new(BufferedImageLuminanceSource::new(new_img)))
Ok(Box::new(Self {
width: new_img.width() as usize,
height: new_img.height() as usize,

View File

@@ -50,17 +50,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
let note = ResultParser::matchSinglePrefixedField("MEMORY:", &rawText, '\r', false)
.unwrap_or_default();
let address = ResultParser::matchSinglePrefixedField("ADD:", &rawText, '\r', true);
let addresses = if address.is_none() {
Vec::new()
} else {
vec![address?]
};
let addresses = address.map_or_else(Vec::new, |add| vec![add]);
if let Ok(new_data) = AddressBookParsedRXingResult::with_details(
if let Some(nm) = ResultParser::maybeWrap(name) {
nm
} else {
Vec::new()
},
ResultParser::maybeWrap(name).unwrap_or_default(),
Vec::new(),
pronunciation.unwrap_or_default(),
phoneNumbers,
@@ -90,10 +83,12 @@ fn matchMultipleValuePrefix(prefix: &str, rawText: &str) -> Vec<String> {
// for (int i = 1; i <= 3; i++) {
let value =
ResultParser::matchSinglePrefixedField(&format!("{prefix}{i}:"), rawText, '\r', true);
if value.is_none() {
if let Some(value) = value {
values.push(value)
} else {
break;
}
values.push(value.unwrap());
}
values

View File

@@ -43,35 +43,32 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
if !rawText.starts_with("MECARD:") {
return None;
}
let rawName = ResultParser::match_do_co_mo_prefixed_field("N:", &rawText)?;
let rawName = ResultParser::match_docomo_prefixed_field("N:", &rawText)?;
let name = parseName(&rawName[0]);
let pronunciation =
ResultParser::match_single_do_co_mo_prefixed_field("SOUND:", &rawText, true)
.unwrap_or_default();
let phoneNumbers =
ResultParser::match_do_co_mo_prefixed_field("TEL:", &rawText).unwrap_or_default();
let emails =
ResultParser::match_do_co_mo_prefixed_field("EMAIL:", &rawText).unwrap_or_default();
let note = ResultParser::match_single_do_co_mo_prefixed_field("NOTE:", &rawText, false)
let pronunciation = ResultParser::match_single_docomo_prefixed_field("SOUND:", &rawText, true)
.unwrap_or_default();
let addresses =
ResultParser::match_do_co_mo_prefixed_field("ADR:", &rawText).unwrap_or_default();
let mut birthday = ResultParser::match_single_do_co_mo_prefixed_field("BDAY:", &rawText, true)
let phoneNumbers =
ResultParser::match_docomo_prefixed_field("TEL:", &rawText).unwrap_or_default();
let emails = ResultParser::match_docomo_prefixed_field("EMAIL:", &rawText).unwrap_or_default();
let note = ResultParser::match_single_docomo_prefixed_field("NOTE:", &rawText, false)
.unwrap_or_default();
let addresses = ResultParser::match_docomo_prefixed_field("ADR:", &rawText).unwrap_or_default();
let mut birthday = ResultParser::match_single_docomo_prefixed_field("BDAY:", &rawText, true)
.unwrap_or_default();
if !ResultParser::isStringOfDigits(&birthday, 8) {
// No reason to throw out the whole card because the birthday is formatted wrong.
birthday = String::default();
}
let urls = ResultParser::match_do_co_mo_prefixed_field("URL:", &rawText).unwrap_or_default();
let urls = ResultParser::match_docomo_prefixed_field("URL:", &rawText).unwrap_or_default();
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
// honor it when found in the wild.
let org = ResultParser::match_single_do_co_mo_prefixed_field("ORG:", &rawText, true)
let org = ResultParser::match_single_docomo_prefixed_field("ORG:", &rawText, true)
.unwrap_or_default();
if let Ok(new_adb) = AddressBookParsedRXingResult::with_details(
ResultParser::maybeWrap(Some(name))?,
ResultParser::maybeWrap(Some(name)).unwrap_or_default(),
Vec::new(),
pronunciation,
phoneNumbers,
@@ -100,12 +97,4 @@ fn parseName(name: &str) -> String {
} else {
name.to_owned()
}
// let comma = name.indexOf(',');
// if (comma >= 0) {
// // Format may be last,first; switch it around
// return name.substring(comma + 1) + ' ' + name.substring(0, comma);
// }
// return name;
}
// }

View File

@@ -41,36 +41,36 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
return None;
}
let firstName = ResultParser::match_single_do_co_mo_prefixed_field("N:", &rawText, true)
.unwrap_or_default();
let lastName = ResultParser::match_single_do_co_mo_prefixed_field("X:", &rawText, true)
.unwrap_or_default();
let firstName =
ResultParser::match_single_docomo_prefixed_field("N:", &rawText, true).unwrap_or_default();
let lastName =
ResultParser::match_single_docomo_prefixed_field("X:", &rawText, true).unwrap_or_default();
let fullName = buildName(&firstName, &lastName);
let title = ResultParser::match_single_do_co_mo_prefixed_field("T:", &rawText, true)
.unwrap_or_default();
let org = ResultParser::match_single_do_co_mo_prefixed_field("C:", &rawText, true)
.unwrap_or_default();
let addresses = ResultParser::match_do_co_mo_prefixed_field("A:", &rawText);
let phoneNumber1 = ResultParser::match_single_do_co_mo_prefixed_field("B:", &rawText, true)
.unwrap_or_default();
let phoneNumber2 = ResultParser::match_single_do_co_mo_prefixed_field("M:", &rawText, true)
.unwrap_or_default();
let phoneNumber3 = ResultParser::match_single_do_co_mo_prefixed_field("F:", &rawText, true)
.unwrap_or_default();
let email = ResultParser::match_single_do_co_mo_prefixed_field("E:", &rawText, true)
.unwrap_or_default();
let title =
ResultParser::match_single_docomo_prefixed_field("T:", &rawText, true).unwrap_or_default();
let org =
ResultParser::match_single_docomo_prefixed_field("C:", &rawText, true).unwrap_or_default();
let addresses = ResultParser::match_docomo_prefixed_field("A:", &rawText);
let phoneNumber1 =
ResultParser::match_single_docomo_prefixed_field("B:", &rawText, true).unwrap_or_default();
let phoneNumber2 =
ResultParser::match_single_docomo_prefixed_field("M:", &rawText, true).unwrap_or_default();
let phoneNumber3 =
ResultParser::match_single_docomo_prefixed_field("F:", &rawText, true).unwrap_or_default();
let email =
ResultParser::match_single_docomo_prefixed_field("E:", &rawText, true).unwrap_or_default();
if let Ok(adb) = AddressBookParsedRXingResult::with_details(
ResultParser::maybeWrap(Some(fullName))?,
ResultParser::maybeWrap(Some(fullName)).unwrap_or_default(),
Vec::new(),
String::default(),
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
Vec::new(),
ResultParser::maybeWrap(Some(email))?,
ResultParser::maybeWrap(Some(email)).unwrap_or_default(),
Vec::new(),
String::default(),
String::default(),
addresses?,
addresses.unwrap_or_default(),
Vec::new(),
org,
String::default(),
@@ -82,23 +82,6 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
} else {
None
}
// return new AddressBookParsedRXingResult(maybeWrap(fullName),
// null,
// null,
// buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
// null,
// maybeWrap(email),
// null,
// null,
// null,
// addresses,
// null,
// org,
// null,
// title,
// null,
// null);
}
fn buildPhoneNumbers(number1: String, number2: String, number3: String) -> Vec<String> {

View File

@@ -30,20 +30,16 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
if !rawText.starts_with("MEBKM:") {
return None;
}
let title = ResultParser::match_single_do_co_mo_prefixed_field("TITLE:", rawText, true);
let rawUri = ResultParser::match_do_co_mo_prefixed_field("URL:", rawText);
rawUri.as_ref()?;
let uri = rawUri?[0].clone();
if URIResultParser::is_basically_valid_uri(&uri) {
let title = ResultParser::match_single_docomo_prefixed_field("TITLE:", rawText, true);
let rawUri = ResultParser::match_docomo_prefixed_field("URL:", rawText)?;
let uri = &rawUri[0];
if URIResultParser::is_basically_valid_uri(uri) {
Some(ParsedClientResult::URIResult(URIParsedRXingResult::new(
uri,
uri.to_string(),
title.unwrap_or_default(),
)))
} else {
None
}
// return URIRXingResultParser.isBasicallyValidURI(uri) ? new URIParsedRXingResult(uri, title) : null;
}
// }

View File

@@ -112,7 +112,7 @@ impl CalendarParsedRXingResult {
) -> Result<Self, Exceptions> {
let start = Self::parseDate(startString.clone())?;
let end = if endString.is_empty() {
let durationMS = Self::parseDurationMS(&durationString);
let durationMS = Self::parseDurationMS(&durationString)?;
if durationMS < 0i64 {
-1i64
} else {
@@ -165,7 +165,6 @@ impl CalendarParsedRXingResult {
* @throws ParseException if not able to parse as a date
*/
fn parseDate(when: String) -> Result<i64, Exceptions> {
// let date_time_regex = Regex::new(DATE_TIME).unwrap();
if !DATE_TIME.is_match(&when) {
return Err(Exceptions::ParseException(Some(when)));
}
@@ -178,37 +177,23 @@ impl CalendarParsedRXingResult {
// http://code.google.com/p/android/issues/detail?id=8330
return match Utc.datetime_from_str(&format!("{}T000000Z", &when,), date_format_string) {
Ok(dtm) => Ok(dtm.timestamp()),
Err(e) => panic!("{}", e),
// Err(e) => Err(Exceptions::ParseException(format!(
// "couldn't parse string: {}",
// e
// ))),
Err(e) => Err(Exceptions::ParseException(Some(e.to_string()))),
};
// let dtm = DateTime::parse_from_str(&when, date_format_string).unwrap();
// let dtm = dtm.with_timezone(&Utc);
// // format.setTimeZone(TimeZone.getTimeZone("GMT"));
// // return format.parse(when).getTime();
// return Ok(dtm.timestamp());
}
// The when string can be local time, or UTC if it ends with a Z
if when.len() == 16 && when.chars().nth(15).unwrap() == 'Z' {
if when.len() == 16
&& when
.chars()
.nth(15)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
== 'Z'
{
return match Utc.datetime_from_str(&when, "%Y%m%dT%H%M%SZ") {
Ok(dtm) => Ok(dtm.with_timezone(&Utc).timestamp()),
Err(e) => Err(Exceptions::ParseException(Some(format!(
"couldn't parse string: {e}"
)))),
};
// let dtm = DateTime::parse_from_str(&when, "%Y%m%dT%H%M%S").unwrap().with_timezone(&Utc);
// //let milliseconds = Self::parseDateTimeString(&when[0..15]);
// // Calendar calendar = new GregorianCalendar();
// // // Account for time zone difference
// // milliseconds += calendar.get(Calendar.ZONE_OFFSET);
// // // Might need to correct for daylight savings time, but use target time since
// // // now might be in DST but not then, or vice versa
// // calendar.setTime(new Date(milliseconds));
// // return milliseconds + calendar.get(Calendar.DST_OFFSET);
// return Ok(dtm.timestamp());
}
// Try once more, with weird tz formatting
if when.len() > 16 {
@@ -258,9 +243,9 @@ impl CalendarParsedRXingResult {
}
}
fn parseDurationMS(durationString: &str) -> i64 {
fn parseDurationMS(durationString: &str) -> Result<i64, Exceptions> {
if durationString.is_empty() {
return -1;
return Ok(-1);
}
// let regex = Regex::new(RFC2445_DURATION).unwrap();
if let Some(m) = RFC2445_DURATION.captures(durationString) {
@@ -270,13 +255,16 @@ impl CalendarParsedRXingResult {
// for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {
let fieldValue = m.get(i + 1);
if let Some(parseable) = fieldValue {
let z = parseable.as_str().parse::<i64>().unwrap();
let z = parseable
.as_str()
.parse::<i64>()
.map_err(|e| Exceptions::ParseException(Some(e.to_string())))?;
durationMS += unit * z;
}
}
durationMS
Ok(durationMS)
} else {
-1
Ok(-1)
}
// if (!m.matches()) {
// return -1L;

View File

@@ -41,8 +41,6 @@ use super::{
* @author Sean Owen
*/
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
// let comma_regex = Regex::new(",").unwrap();
// private static final Pattern COMMA = Pattern.compile(",");
let rawText = ResultParser::getMassagedText(result);
if rawText.starts_with("mailto:") || rawText.starts_with("MAILTO:") {
// If it starts with mailto:, assume it is definitely trying to be an email address
@@ -55,11 +53,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
// hostEmail = hostEmail.substring(0, queryStart);
// }
// try {
let tmp = if let Ok(res) = ResultParser::urlDecode(hostEmail) {
res
} else {
return None;
};
let tmp = ResultParser::urlDecode(hostEmail).ok()?;
hostEmail = tmp.as_str();
// } catch (IllegalArgumentException iae) {
// return null;

View File

@@ -43,16 +43,16 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
if !rawText.starts_with("MATMSG:") {
return None;
}
let tos = ResultParser::match_do_co_mo_prefixed_field("TO:", &rawText)?;
let tos = ResultParser::match_docomo_prefixed_field("TO:", &rawText)?;
for to in &tos {
if !isBasicallyValidEmailAddress(to, &ATEXT_ALPHANUMERIC) {
return None;
}
}
let subject = ResultParser::match_single_do_co_mo_prefixed_field("SUB:", &rawText, false)
let subject = ResultParser::match_single_docomo_prefixed_field("SUB:", &rawText, false)
.unwrap_or_default();
let body = ResultParser::match_single_do_co_mo_prefixed_field("BODY:", &rawText, false)
let body = ResultParser::match_single_docomo_prefixed_field("BODY:", &rawText, false)
.unwrap_or_default();
Some(ParsedClientResult::EmailResult(
EmailAddressParsedRXingResult::with_details(tos, Vec::new(), Vec::new(), subject, body),

View File

@@ -110,47 +110,6 @@ impl ExpandedProductParsedRXingResult {
}
}
// @Override
// public boolean equals(Object o) {
// if (!(o instanceof ExpandedProductParsedRXingResult)) {
// return false;
// }
// ExpandedProductParsedRXingResult other = (ExpandedProductParsedRXingResult) o;
// return Objects.equals(productID, other.productID)
// && Objects.equals(sscc, other.sscc)
// && Objects.equals(lotNumber, other.lotNumber)
// && Objects.equals(productionDate, other.productionDate)
// && Objects.equals(bestBeforeDate, other.bestBeforeDate)
// && Objects.equals(expirationDate, other.expirationDate)
// && Objects.equals(weight, other.weight)
// && Objects.equals(weightType, other.weightType)
// && Objects.equals(weightIncrement, other.weightIncrement)
// && Objects.equals(price, other.price)
// && Objects.equals(priceIncrement, other.priceIncrement)
// && Objects.equals(priceCurrency, other.priceCurrency)
// && Objects.equals(uncommonAIs, other.uncommonAIs);
// }
// @Override
// public int hashCode() {
// int hash = Objects.hashCode(productID);
// hash ^= Objects.hashCode(sscc);
// hash ^= Objects.hashCode(lotNumber);
// hash ^= Objects.hashCode(productionDate);
// hash ^= Objects.hashCode(bestBeforeDate);
// hash ^= Objects.hashCode(expirationDate);
// hash ^= Objects.hashCode(weight);
// hash ^= Objects.hashCode(weightType);
// hash ^= Objects.hashCode(weightIncrement);
// hash ^= Objects.hashCode(price);
// hash ^= Objects.hashCode(priceIncrement);
// hash ^= Objects.hashCode(priceCurrency);
// hash ^= Objects.hashCode(uncommonAIs);
// return hash;
// }
pub fn getRawText(&self) -> &str {
&self.rawText
}

View File

@@ -24,16 +24,6 @@
* http://www.piramidepse.com/
*/
// package com.google.zxing.client.result;
// import com.google.zxing.BarcodeFormat;
// import com.google.zxing.RXingResult;
// import org.junit.Assert;
// import org.junit.Test;
// import java.util.HashMap;
// import java.util.Map;
// /**
// * @author Antonio Manuel Benjumea Conde, Servinform, S.A.
// * @author Agustín Delgado, Servinform, S.A.

View File

@@ -77,7 +77,7 @@ pub fn parse(result: &crate::RXingResult) -> Option<super::ParsedClientResult> {
// return None;
// }
i += ai.len() + 2;
let value = findValue(i, &rawText);
let value = findValue(i, &rawText)?;
i += value.len();
match ai.as_str() {
"00" => sscc = value,
@@ -260,13 +260,13 @@ fn findAIvalue(i: usize, rawText: &str) -> Option<String> {
Some(buf)
}
fn findValue(i: usize, rawText: &str) -> String {
fn findValue(i: usize, rawText: &str) -> Option<String> {
let mut buf = String::new();
let rawTextAux = &rawText[i..];
for index in 0..rawTextAux.len() {
// for (int index = 0; index < rawTextAux.length(); index++) {
let c = rawTextAux.chars().nth(index).unwrap();
let c = rawTextAux.chars().nth(index)?;
if c == '(' {
// We look for a new AI. If it doesn't exist (ERROR), we continue
// with the iteration
@@ -281,5 +281,5 @@ fn findValue(i: usize, rawText: &str) -> String {
buf.push(c);
}
}
buf
Some(buf)
}

View File

@@ -50,31 +50,41 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
""
};
let latitude = if let Some(la) = captures.get(1) {
if let Ok(laf64) = la.as_str().parse::<f64>() {
if !(-90.0..=90.0).contains(&laf64) {
return None;
}
laf64
} else {
return None;
}
} else {
let latitude = captures.get(1)?.as_str().parse::<f64>().ok()?;
if !(-90.0..=90.0).contains(&latitude) {
return None;
};
}
let longitude = if let Some(lo) = captures.get(2) {
if let Ok(lof64) = lo.as_str().parse::<f64>() {
if !(-180.0..=180.0).contains(&lof64) {
return None;
}
lof64
} else {
return None;
}
} else {
// let latitude = if let Some(la) = captures.get(1) {
// if let Ok(laf64) = la.as_str().parse::<f64>() {
// if !(-90.0..=90.0).contains(&laf64) {
// return None;
// }
// laf64
// } else {
// return None;
// }
// } else {
// return None;
// };
let longitude = captures.get(2)?.as_str().parse::<f64>().ok()?;
if !(-180.0..=180.0).contains(&longitude) {
return None;
};
}
// let longitude = if let Some(lo) = captures.get(2) {
// if let Ok(lof64) = lo.as_str().parse::<f64>() {
// if !(-180.0..=180.0).contains(&lof64) {
// return None;
// }
// lof64
// } else {
// return None;
// }
// } else {
// return None;
// };
let altitude = if let Some(al) = captures.get(3) {
if let Ok(alf64) = al.as_str().parse::<f64>() {
@@ -88,28 +98,6 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
} else {
0.0
};
// let longitude;
// let altitude;
// try {
// // latitude = Double.parseDouble(matcher.group(1));
// // if (latitude > 90.0 || latitude < -90.0) {
// // return null;
// // }
// // longitude = Double.parseDouble(matcher.group(2));
// // if (longitude > 180.0 || longitude < -180.0) {
// // return null;
// // }
// // if (matcher.group(3) == null) {
// // altitude = 0.0;
// // } else {
// // altitude = Double.parseDouble(matcher.group(3));
// // if (altitude < 0.0) {
// // return null;
// // }
// // }
// } catch (NumberFormatException ignored) {
// return null;
// }
Some(ParsedClientResult::GeoResult(GeoParsedRXingResult::new(
latitude,
longitude,
@@ -119,10 +107,4 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
} else {
None
}
// Matcher matcher = GEO_URL_PATTERN.matcher(rawText);
// if (!matcher.matches()) {
// return null;
// }
}
// }

View File

@@ -36,4 +36,5 @@ pub enum ParsedRXingResultType {
WIFI,
ISBN,
VIN,
OTHER,
}

View File

@@ -40,6 +40,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
{
return None;
}
let rawText = ResultParser::getMassagedText(result);
if !ResultParser::isStringOfDigits(&rawText, rawText.len()) {
return None;
@@ -50,7 +51,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
// Expand UPC-E for purposes of searching
if format == &BarcodeFormat::UPC_E && rawText.len() == 8 {
// unimplemented!("UPCEReader is required to parse this");
crate::oned::convertUPCEtoUPCA(&rawText)
crate::oned::convertUPCEtoUPCA(&rawText)?
} else {
rawText.clone()
};

View File

@@ -102,11 +102,14 @@ const BYTE_ORDER_MARK: &str = "\u{feff}"; //private static final String BYTE_ORD
// const EMPTY_STR_ARRAY: &'static str = "";
pub fn getMassagedText(result: &RXingResult) -> String {
let mut text = result.getText().clone();
if text.starts_with(BYTE_ORDER_MARK) {
text = text[1..].to_owned();
}
text
result
.getText()
.trim_start_matches(BYTE_ORDER_MARK)
.to_owned()
// if text.starts_with(BYTE_ORDER_MARK) {
// text = &text[1..];
// }
// text.to_owned()
}
pub fn parse_result_with_parsers(
@@ -181,19 +184,18 @@ pub fn maybe_append_string(value: &str, result: &mut String) {
}
pub fn maybe_append_multiple(value: &[String], result: &mut String) {
if !value.is_empty() {
for s in value {
// for (String s : value) {
if !s.is_empty() {
if !result.is_empty() {
result.push('\n');
}
result.push_str(s);
for s in value {
// for (String s : value) {
if !s.is_empty() {
if !result.is_empty() {
result.push('\n');
}
result.push_str(s);
}
}
}
#[inline(always)]
pub fn maybeWrap(value: Option<String>) -> Option<Vec<String>> {
if value.is_none() {
None
@@ -207,14 +209,12 @@ pub fn unescapeBackslash(escaped: &str) -> String {
if backslash.is_none() {
return escaped.to_owned();
}
let max = escaped.len();
let mut unescaped = String::with_capacity(max - 1);
let max = escaped.chars().count();
let backslash = backslash.unwrap_or(0);
unescaped.push_str(&escaped[0..backslash]);
let mut unescaped = escaped.chars().take(backslash).collect::<String>();
unescaped.reserve(max - 1);
let mut nextIsEscaped = false;
for i in backslash..max {
// for (int i = backslash; i < max; i++) {
let c = escaped.chars().nth(i).unwrap();
for c in escaped.chars().skip(backslash) {
if nextIsEscaped || c != '\\' {
unescaped.push(c);
nextIsEscaped = false;
@@ -239,6 +239,7 @@ pub fn parseHexDigit(c: char) -> i32 {
-1
}
#[inline(always)]
pub fn isStringOfDigits(value: &str, length: usize) -> bool {
!value.is_empty() && length > 0 && length == value.len() && DIGITS.is_match(value)
}
@@ -249,10 +250,10 @@ pub fn isSubstringOfDigits(value: &str, offset: usize, length: usize) -> bool {
}
let max = offset + length;
let sub_seq = &value[offset..max];
let sub_seq: String = value.chars().skip(offset).take(length).collect(); //&value[offset..max];
let is_a_match = if let Some(mtch) = DIGITS.find(sub_seq) {
mtch.start() == 0 && mtch.end() == sub_seq.len()
let is_a_match = if let Some(mtch) = DIGITS.find(&sub_seq) {
mtch.start() == 0 && mtch.end() == sub_seq.chars().count()
} else {
false
};
@@ -266,16 +267,11 @@ pub fn parseNameValuePairs(uri: &str) -> Option<HashMap<String, String>> {
let mut result = HashMap::with_capacity(3);
let paramStart = paramStart.unwrap_or(0);
let sub_str = &uri[paramStart + 1..];
let sub_str = &uri[paramStart + 1..]; // This is likely ok because we're looking for a specific single byte charaacter
let list = sub_str.split(AMPERSAND);
for keyValue in list {
appendKeyValue(keyValue, &mut result);
}
// for keyValue in Self::AMPERSAND.split(uri[paramStart + 1..]) {
// // for (String keyValue : AMPERSAND.split(uri.substring(paramStart + 1))) {
// Self::appendKeyValue(keyValue, &mut result);
// }
Some(result)
}
@@ -304,9 +300,9 @@ pub fn urlDecode(encoded: &str) -> Result<String, Exceptions> {
if let Ok(decoded) = decode(encoded) {
Ok(decoded.to_string())
} else {
Err(Exceptions::IllegalStateException(Some(
"UnsupportedEncodingException".to_owned(),
)))
Err(Exceptions::IllegalStateException(Some(String::from(
"UnsupportedEncodingException",
))))
}
}
@@ -329,7 +325,7 @@ pub fn matchPrefixedField(
// if (i < 0) {
// break;
// }
i += prefix.len(); // Skip past this prefix we found to start
i += prefix.chars().count(); // Skip past this prefix we found to start
let start = i; // Found the start of a match here
let mut more = true;
while more {
@@ -337,7 +333,7 @@ pub fn matchPrefixedField(
i += next_index;
} else {
// No terminating end character? uh, done. Set i such that loop terminates and break
i = rawText.len();
i = rawText.chars().count();
more = false;
continue;
}
@@ -411,11 +407,11 @@ pub fn matchSinglePrefixedField(
// return matches == null ? null : matches[0];
}
pub fn match_do_co_mo_prefixed_field(prefix: &str, raw_text: &str) -> Option<Vec<String>> {
pub fn match_docomo_prefixed_field(prefix: &str, raw_text: &str) -> Option<Vec<String>> {
matchPrefixedField(prefix, raw_text, ';', true)
}
pub fn match_single_do_co_mo_prefixed_field(
pub fn match_single_docomo_prefixed_field(
prefix: &str,
raw_text: &str,
trim: bool,
@@ -426,7 +422,9 @@ pub fn match_single_do_co_mo_prefixed_field(
#[cfg(test)]
mod tests {
use crate::{
client::result::{ParsedClientResult, TextParsedRXingResult},
client::result::{
OtherParsedResult, ParsedClientResult, ParsedRXingResult, TextParsedRXingResult,
},
RXingResult,
};
@@ -449,4 +447,32 @@ mod tests {
.unwrap();
assert_eq!(p_res.to_string(), "parsed with parser");
}
#[test]
fn test_other_parser() {
let result: RXingResult = RXingResult::new(
"text",
vec![12, 23, 54, 23],
Vec::new(),
crate::BarcodeFormat::EAN_13,
);
let p_res = parse_result_with_parser(&result, |v| {
Some(ParsedClientResult::Other(OtherParsedResult::new(Box::new(
v.getRawBytes().clone(),
))))
})
.unwrap();
assert_eq!(p_res.getDisplayRXingResult(), "Any { .. }");
if let ParsedClientResult::Other(opr) = p_res {
if let Some(d) = opr.get_data().downcast_ref::<Vec<u8>>() {
assert_eq!(d, result.getRawBytes());
} else {
panic!("did not get vec<u8>");
}
} else {
panic!("did not get ParsedClientResult::Other");
}
}
}

View File

@@ -14,15 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import com.google.zxing.RXingResult;
// import java.util.ArrayList;
// import java.util.Collection;
// import java.util.List;
// import java.util.Map;
/**
* <p>Parses an "sms:" URI result, which specifies a number to SMS.
* See <a href="http://tools.ietf.org/html/rfc5724"> RFC 5724</a> on this.</p>
@@ -38,7 +29,6 @@
*
* @author Sean Owen
*/
// public final class SMSMMSRXingResultParser extends RXingResultParser {
use crate::RXingResult;
use super::{ParsedClientResult, ResultParser, SMSParsedRXingResult};
@@ -121,21 +111,13 @@ fn add_number_via(numbers: &mut Vec<String>, vias: &mut Vec<String>, number_part
return;
}
if let Some(number_end) = number_part.find(';') {
// if numberEnd < 0 {
numbers.push(number_part[..number_end].to_string());
let maybe_via = &number_part[number_end + 1..];
let via = if let Some(stripped) = maybe_via.strip_prefix("via=") {
stripped
} else {
""
};
let via = maybe_via.strip_prefix("via=").unwrap_or_default();
if !via.is_empty() {
vias.push(via.to_owned());
}
} else {
numbers.push(number_part.to_owned());
//vias.push(String::default());
}
}
// }

View File

@@ -49,11 +49,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
body = &number[body_start + 1..];
number = &number[..body_start];
}
// let bodyStart = number.indexOf(':');
// if (bodyStart >= 0) {
// body = number.substring(bodyStart + 1);
// number = number.substring(0, bodyStart);
// }
Some(ParsedClientResult::SMSResult(
SMSParsedRXingResult::with_singles(
number.to_owned(),
@@ -62,5 +58,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
body.to_owned(),
),
))
// return new SMSParsedRXingResult(number, null, null, body);
}

View File

@@ -44,16 +44,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
subject = &subject[..new_colon];
}
}
// let colon = emailAddress.indexOf(':');
// if (colon >= 0) {
// subject = emailAddress.substring(colon + 1);
// emailAddress = emailAddress.substring(0, colon);
// colon = subject.indexOf(':');
// if (colon >= 0) {
// body = subject.substring(colon + 1);
// subject = subject.substring(0, colon);
// }
// }
Some(ParsedClientResult::EmailResult(
EmailAddressParsedRXingResult::with_details(
vec![emailAddress.to_owned()],
@@ -63,9 +54,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
body.to_owned(),
),
))
// return new EmailAddressParsedRXingResult(new String[] {emailAddress},
// null,
// null,
// subject,
// body);
}

View File

@@ -92,7 +92,7 @@ impl URIParsedRXingResult {
let nextSlash = if let Some(pos) = uri[start..].find('/') {
pos + start
} else {
uri.len()
uri.chars().count()
};
// let nextSlash = uri.indexOf('/', start);
// if (nextSlash < 0) {

View File

@@ -39,18 +39,16 @@ static ALLOWED_URI_CHARS: Lazy<Regex> = Lazy::new(|| {
});
static USER_IN_HOST: Lazy<Regex> =
Lazy::new(|| Regex::new(":/*([^/@]+)@[^/]+").expect("Regex patterns should always copile"));
/// See http://www.ietf.org/rfc/rfc2396.txt
static URL_WITH_PROTOCOL_PATTERN: Lazy<Regex> =
Lazy::new(|| Regex::new("[a-zA-Z][a-zA-Z0-9+-.]+:").unwrap());
/// (host name elements; allow up to say 6 domain elements), (maybe port), (query, path or nothing)
static URL_WITHOUT_PROTOCOL_PATTERN: Lazy<Regex> =
Lazy::new(|| Regex::new("([a-zA-Z0-9\\-]+\\.){1,6}[a-zA-Z]{2,}(:\\d{1,5})?(/|\\?|$)").unwrap());
const ALLOWED_URI_CHARS_PATTERN: &str = "[-._~:/?#\\[\\]@!$&'()*+,;=%A-Za-z0-9]+";
// const USER_IN_HOST: &'static str = ":/*([^/@]+)@[^/]+";
/// See http://www.ietf.org/rfc/rfc2396.txt
// const URL_WITH_PROTOCOL_PATTERN: &'static str = "[a-zA-Z][a-zA-Z0-9+-.]+:";
/// (host name elements; allow up to say 6 domain elements), (maybe port), (query, path or nothing)
// const URL_WITHOUT_PROTOCOL_PATTERN: &'static str =
// "([a-zA-Z0-9\\-]+\\.){1,6}[a-zA-Z]{2,}(:\\d{1,5})?(/|\\?|$)";
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
let raw_text = ResultParser::getMassagedText(result);

View File

@@ -14,20 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import com.google.zxing.RXingResult;
// import java.io.ByteArrayOutputStream;
// import java.io.UnsupportedEncodingException;
// import java.net.URI;
// import java.nio.charset.StandardCharsets;
// import java.util.ArrayList;
// import java.util.Collection;
// import java.util.List;
// import java.util.regex.Matcher;
// import java.util.regex.Pattern;
use std::convert::TryFrom;
use regex::Regex;

View File

@@ -14,13 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import com.google.zxing.BarcodeFormat;
// import com.google.zxing.RXingResult;
// import org.junit.Assert;
// import org.junit.Test;
/**
* Tests {@link VINParsedRXingResult}.
*/

View File

@@ -14,13 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import com.google.zxing.BarcodeFormat;
// import com.google.zxing.RXingResult;
// import java.util.regex.Pattern;
use regex::Regex;
use crate::{
@@ -46,26 +39,18 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
let raw_text_res = result.getText().trim();
let raw_text = IOQ_MATCHER.replace_all(raw_text_res, "").to_string();
// rawText = IOQ.matcher(rawText).replaceAll("").trim();
AZ09_MATCHER.find(&raw_text)?;
// if !AZ09.matcher(rawText).matches() {
// return null;
// }
let check_cs = check_checksum(&raw_text).unwrap_or(false);
if !check_cs {
return None;
}
let wmi = &raw_text[..3];
// try {
// if (!checkChecksum(rawText)) {
// return null;
// }
// String wmi = rawText.substring(0, 3);
let country_code = country_code(wmi).unwrap_or("");
let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_'));
if model_year.is_err() {
return None;
}
let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_')).ok();
Some(ParsedClientResult::VINResult(VINParsedRXingResult::new(
raw_text.to_owned(),
wmi.to_owned(),
@@ -73,22 +58,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
raw_text[9..17].to_owned(),
country_code.to_owned(),
raw_text[3..8].to_owned(),
model_year.unwrap(),
raw_text.chars().nth(10).unwrap(),
model_year?,
raw_text.chars().nth(10)?,
raw_text[11..].to_owned(),
)))
// return new VINParsedRXingResult(rawText,
// wmi,
// rawText.substring(3, 9),
// rawText.substring(9, 17),
// countryCode(wmi),
// rawText.substring(3, 8),
// modelYear(rawText.charAt(9)),
// rawText.charAt(10),
// rawText.substring(11));
// } catch (IllegalArgumentException iae) {
// return null;
// }
}
const IOQ: &str = "[IOQ]";
@@ -97,10 +70,17 @@ const AZ09: &str = "[A-Z0-9]{17}";
fn check_checksum(vin: &str) -> Result<bool, Exceptions> {
let mut sum = 0;
for i in 0..vin.len() {
// for (int i = 0; i < vin.length(); i++) {
sum += vin_position_weight(i + 1)? as u32 * vin_char_value(vin.chars().nth(i).unwrap())?;
sum += vin_position_weight(i + 1)? as u32
* vin_char_value(
vin.chars()
.nth(i)
.ok_or(Exceptions::IllegalArgumentException(None))?,
)?;
}
let check_to_char = vin.chars().nth(8).unwrap();
let check_to_char = vin
.chars()
.nth(8)
.ok_or(Exceptions::IllegalArgumentException(None))?;
let expected_check_char = check_char((sum % 11) as u8)?;
Ok(check_to_char == expected_check_char)
}
@@ -115,21 +95,6 @@ fn vin_char_value(c: char) -> Result<u32, Exceptions> {
"vin char out of range".to_owned(),
))),
}
// if c >= 'A' && c <= 'I' {
// return Ok((c as u8 as u32 - 'A' as u8 as u32) + 1);
// }
// if c >= 'J' && c <= 'R' {
// return Ok((c as u8 as u32 - 'J' as u8 as u32) + 1);
// }
// if c >= 'S' && c <= 'Z' {
// return Ok((c as u8 as u32 - 'S' as u8 as u32) + 2);
// }
// if c >= '0' && c <= '9' {
// return Ok(c as u8 as u32 - '0' as u8 as u32);
// }
// Err(Exceptions::IllegalArgumentException(
// "vin char out of range".to_owned(),
// ))
}
fn vin_position_weight(position: usize) -> Result<usize, Exceptions> {
@@ -142,19 +107,6 @@ fn vin_position_weight(position: usize) -> Result<usize, Exceptions> {
"vin position weight out of bounds".to_owned(),
))),
}
// if position >= 1 && position <= 7 {
// return 9 - position;
// }
// if position == 8 {
// return 10;
// }
// if position == 9 {
// return 0;
// }
// if position >= 10 && position <= 17 {
// return 19 - position;
// }
// throw new IllegalArgumentException();
}
fn check_char(remainder: u8) -> Result<char, Exceptions> {
@@ -165,15 +117,6 @@ fn check_char(remainder: u8) -> Result<char, Exceptions> {
"remainder too high".to_owned(),
))),
}
// if remainder < 10 {
// return Ok(('0' as u8 + remainder) as char);
// }
// if remainder == 10 {
// return Ok('X');
// }
// Err(Exceptions::IllegalArgumentException(
// "remainder too high".to_owned(),
// ))
}
fn model_year(c: char) -> Result<u32, Exceptions> {
@@ -189,33 +132,11 @@ fn model_year(c: char) -> Result<u32, Exceptions> {
"model year argument out of range",
)))),
}
// if c >= 'E' && c <= 'H' {
// return (c - 'E') + 1984;
// }
// if c >= 'J' && c <= 'N' {
// return (c - 'J') + 1988;
// }
// if c == 'P' {
// return 1993;
// }
// if c >= 'R' && c <= 'T' {
// return (c - 'R') + 1994;
// }
// if c >= 'V' && c <= 'Y' {
// return (c - 'V') + 1997;
// }
// if c >= '1' && c <= '9' {
// return (c - '1') + 2001;
// }
// if c >= 'A' && c <= 'D' {
// return (c - 'A') + 2010;
// }
// throw new IllegalArgumentException();
}
fn country_code(wmi: &str) -> Option<&'static str> {
let c1 = wmi.chars().next().unwrap();
let c2 = wmi.chars().nth(1).unwrap();
let c1 = wmi.chars().next()?;
let c2 = wmi.chars().nth(1)?;
match c1 {
'1' | '4' | '5' => Some("US"),
'2' => Some("CA"),

View File

@@ -14,15 +14,10 @@
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import com.google.zxing.RXingResult;
use crate::client::result::{ParsedClientResult, WifiParsedRXingResult};
use super::ResultParser;
// @SuppressWarnings("checkstyle:lineLength")
/**
* <p>Parses a WIFI configuration string. Strings will be of the form:</p>
*
@@ -40,9 +35,6 @@ use super::ResultParser;
* @author Sean Owen
* @author Steffen Kieß
*/
// pub struct WifiRXingResultParser {}
// impl RXingResultParser for WifiRXingResultParser {
pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientResult> {
const WIFI_TEST: &str = "WIFI:";
@@ -53,35 +45,29 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
let rawText = rawText_unstripped[WIFI_TEST.len()..].to_owned();
let ssid =
ResultParser::matchSinglePrefixedField("S:", &rawText, ';', false).unwrap_or_default();
if ssid.is_empty() {
return None;
}
let pass =
ResultParser::matchSinglePrefixedField("P:", &rawText, ';', false).unwrap_or_default();
let n_type =
if let Some(nt) = ResultParser::matchSinglePrefixedField("T:", &rawText, ';', false) {
nt
} else {
String::from("nopass")
};
let n_type = ResultParser::matchSinglePrefixedField("T:", &rawText, ';', false)
.unwrap_or(String::from("nopass"));
// Unfortunately, in the past, H: was not just used for boolean 'hidden', but 'phase 2 method'.
// To try to retain backwards compatibility, we set one or the other based on whether the string
// is 'true' or 'false':
let mut hidden = false;
let mut phase2Method = ResultParser::matchSinglePrefixedField("PH2:", &rawText, ';', false);
let _hValue = if let Some(hv) =
ResultParser::matchSinglePrefixedField("H:", &rawText, ';', false)
{
if let Some(hv) = ResultParser::matchSinglePrefixedField("H:", &rawText, ';', false) {
// If PH2 was specified separately, or if the value is clearly boolean, interpret it as 'hidden'
if phase2Method.is_some() || "true" == hv.to_lowercase() || "false" == hv.to_lowercase() {
hidden = hv.parse().unwrap(); //Boolean.parseBoolean(hValue);
hidden = hv.parse().ok()?;
} else {
phase2Method = Some(hv.clone());
phase2Method = Some(hv);
}
hv
} else {
String::default()
};
let identity =

View File

@@ -60,6 +60,9 @@ pub use SMSParsedResult::*;
pub use URIParsedResult::*;
pub use VINParsedResult::*;
mod other_parsed_result;
pub use other_parsed_result::*;
#[cfg(test)]
mod AddressBookParsedResultTestCase;
#[cfg(test)]
@@ -102,6 +105,7 @@ pub enum ParsedClientResult {
AddressBookResult(AddressBookParsedRXingResult),
CalendarEventResult(CalendarParsedRXingResult),
ExpandedProductResult(ExpandedProductParsedRXingResult),
Other(OtherParsedResult),
}
impl ParsedRXingResult for ParsedClientResult {
@@ -120,6 +124,7 @@ impl ParsedRXingResult for ParsedClientResult {
ParsedClientResult::AddressBookResult(a) => a.getType(),
ParsedClientResult::CalendarEventResult(a) => a.getType(),
ParsedClientResult::ExpandedProductResult(a) => a.getType(),
ParsedClientResult::Other(a) => a.getType(),
}
}
@@ -138,6 +143,7 @@ impl ParsedRXingResult for ParsedClientResult {
ParsedClientResult::AddressBookResult(a) => a.getDisplayRXingResult(),
ParsedClientResult::CalendarEventResult(a) => a.getDisplayRXingResult(),
ParsedClientResult::ExpandedProductResult(a) => a.getDisplayRXingResult(),
ParsedClientResult::Other(a) => a.getDisplayRXingResult(),
}
}
}

View File

@@ -0,0 +1,37 @@
use std::any::Any;
use super::ParsedRXingResult;
#[derive(Debug)]
pub struct OtherParsedResult {
data: Box<dyn Any>,
}
impl ParsedRXingResult for OtherParsedResult {
fn getType(&self) -> super::ParsedRXingResultType {
super::ParsedRXingResultType::OTHER
}
fn getDisplayRXingResult(&self) -> String {
format!("{:?}", self.data)
}
}
impl OtherParsedResult {
pub fn new(data: Box<dyn Any>) -> Self {
Self { data }
}
pub fn get_data(&self) -> &Box<dyn Any> {
&self.data
}
}
/// This always returns false, any cannot be equal
impl PartialEq for OtherParsedResult {
fn eq(&self, _other: &Self) -> bool {
false
}
}
impl Eq for OtherParsedResult {}

View File

@@ -39,7 +39,9 @@ fn test_random() {
// }
assert_eq!(
encoding::all::UTF_8.name(),
StringUtils::guessCharset(&bytes, &HashMap::new()).name()
StringUtils::guessCharset(&bytes, &HashMap::new())
.unwrap()
.name()
);
}
@@ -100,8 +102,8 @@ fn test_utf16_le() {
}
fn do_test(bytes: &[u8], charset: EncodingRef, encoding: &str) {
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new());
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new());
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()).unwrap();
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()).unwrap();
assert_eq!(charset.name(), guessedCharset.name());
assert_eq!(encoding, guessedEncoding);
}

View File

@@ -50,7 +50,7 @@ impl BitArray {
}
}
// For testing only
/// For testing only
#[cfg(test)]
pub fn with_initial_values(bits: Vec<u32>, size: usize) -> Self {
Self { bits, size }

View File

@@ -53,8 +53,8 @@ impl BitMatrix {
*
* @param dimension height and width
*/
pub fn with_single_dimension(dimension: u32) -> Self {
Self::new(dimension, dimension).unwrap()
pub fn with_single_dimension(dimension: u32) -> Result<Self, Exceptions> {
Self::new(dimension, dimension)
}
/**
@@ -134,8 +134,16 @@ impl BitMatrix {
let mut nRows = 0;
let mut pos = 0;
while pos < string_representation.chars().count() {
if string_representation.chars().nth(pos).unwrap() == '\n'
|| string_representation.chars().nth(pos).unwrap() == '\r'
if string_representation
.chars()
.nth(pos)
.ok_or(Exceptions::IllegalStateException(None))?
== '\n'
|| string_representation
.chars()
.nth(pos)
.ok_or(Exceptions::IllegalStateException(None))?
== '\r'
{
if bitsPos > rowStartPos {
//if rowLength == -1 {
@@ -181,15 +189,12 @@ impl BitMatrix {
nRows += 1;
}
let mut matrix = BitMatrix::new(rowLength.try_into().unwrap(), nRows)?;
let mut matrix = BitMatrix::new(rowLength as u32, nRows)?;
for (i, bit) in bits.iter().enumerate().take(bitsPos) {
// for i in 0..bitsPos {
//for (int i = 0; i < bitsPos; i++) {
if *bit {
matrix.set(
(i % rowLength).try_into().unwrap(),
(i / rowLength).try_into().unwrap(),
);
matrix.set((i % rowLength) as u32, (i / rowLength) as u32);
}
}
Ok(matrix)

View File

@@ -33,7 +33,7 @@ static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
#[test]
fn test_get_set() {
let mut matrix = BitMatrix::with_single_dimension(33);
let mut matrix = BitMatrix::with_single_dimension(33).expect("new");
assert_eq!(33, matrix.getHeight());
for y in 0..33 {
// for (int y = 0; y < 33; y++) {
@@ -55,7 +55,7 @@ fn test_get_set() {
#[test]
fn test_set_region() {
let mut matrix = BitMatrix::with_single_dimension(5);
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
matrix.setRegion(1, 1, 3, 3).expect("must set");
for y in 0..5 {
// for (int y = 0; y < 5; y++) {
@@ -71,7 +71,7 @@ fn test_set_region() {
#[test]
fn test_enclosing() {
let mut matrix = BitMatrix::with_single_dimension(5);
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
assert!(matrix.getEnclosingRectangle().is_none());
matrix.setRegion(1, 1, 1, 1).expect("must set");
assert_eq!(vec![1, 1, 1, 1], matrix.getEnclosingRectangle().unwrap());
@@ -83,7 +83,7 @@ fn test_enclosing() {
#[test]
fn test_on_bit() {
let mut matrix = BitMatrix::with_single_dimension(5);
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
assert!(matrix.getTopLeftOnBit().is_none());
assert!(matrix.getBottomRightOnBit().is_none());
matrix.setRegion(1, 1, 1, 1).expect("must set");

View File

@@ -90,13 +90,18 @@ impl GridSampler for DefaultGridSampler {
let mut x = 0;
while x < max {
// for (int x = 0; x < max; x += 2) {
if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight()
{
return Err(Exceptions::NotFoundException(Some(
// if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight()
// {
// return Err(Exceptions::NotFoundException(Some(
// "index out of bounds, see documentation in file for explanation".to_owned(),
// )));
// }
if image
.try_get(points[x] as u32, points[x + 1] as u32)
.ok_or(Exceptions::NotFoundException(Some(
"index out of bounds, see documentation in file for explanation".to_owned(),
)));
}
if image.get(points[x] as u32, points[x + 1] as u32) {
)))?
{
// Black(-ish) pixel
bits.set(x as u32 / 2, y);
}

View File

@@ -14,8 +14,10 @@
* limitations under the License.
*/
//package com.google.zxing.common.detector;
use std::{f32, i32};
use std::{
f32, i32,
ops::{Add, Sub},
};
/**
* General math-related and numeric utility functions.
@@ -32,32 +34,43 @@ use std::{f32, i32};
*/
#[inline(always)]
pub fn round(d: f32) -> i32 {
(d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32
// (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32
d.round() as i32
}
/**
* @param aX point A x coordinate
* @param aY point A y coordinate
* @param bX point B x coordinate
* @param bY point B y coordinate
* @return Euclidean distance between points A and B
*/
#[inline(always)]
pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
let xDiff: f64 = (aX - bX).into();
let yDiff: f64 = (aY - bY).into();
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32
}
// /**
// * @param aX point A x coordinate
// * @param aY point A y coordinate
// * @param bX point B x coordinate
// * @param bY point B y coordinate
// * @return Euclidean distance between points A and B
// */
// #[inline(always)]
// pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
// let xDiff: f64 = (aX - bX).into();
// let yDiff: f64 = (aY - bY).into();
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
// }
// /**
// * @param aX point A x coordinate
// * @param aY point A y coordinate
// * @param bX point B x coordinate
// * @param bY point B y coordinate
// * @return Euclidean distance between points A and B
// */
// #[inline(always)]
// pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
// let xDiff: f64 = (aX - bX).into();
// let yDiff: f64 = (aY - bY).into();
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
// }
/**
* @param aX point A x coordinate
* @param aY point A y coordinate
* @param bX point B x coordinate
* @param bY point B y coordinate
* @return Euclidean distance between points A and B
*/
#[inline(always)]
pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
pub fn distance<T>(aX: T, aY: T, bX: T, bY: T) -> f32
where
T: Sub<T, Output = T> + Into<f64>,
{
let xDiff: f64 = (aX - bX).into();
let yDiff: f64 = (aY - bY).into();
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32
@@ -68,13 +81,11 @@ pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
* @return sum of values in array
*/
#[inline(always)]
pub fn sum(array: &[i32]) -> i32 {
pub fn sum<'a, T>(array: &'a [T]) -> T
where
T: Add + std::iter::Sum<&'a T>,
{
array.iter().sum()
// let mut count = 0;
// for a in array {
// count += a;
// }
// count
}
#[cfg(test)]
@@ -112,15 +123,12 @@ mod tests {
fn testDistance() {
assert_eq!(
(8.0f32).sqrt(),
MathUtils::distance_float(1.0f32, 2.0f32, 3.0f32, 4.0f32)
);
assert_eq!(
0.0f32,
MathUtils::distance_float(1.0f32, 2.0f32, 1.0f32, 2.0f32)
MathUtils::distance(1.0f32, 2.0f32, 3.0f32, 4.0f32)
);
assert_eq!(0.0f32, MathUtils::distance(1.0f32, 2.0f32, 1.0f32, 2.0f32));
assert_eq!((8.0f32).sqrt(), MathUtils::distance_int(1, 2, 3, 4));
assert_eq!(0.0f32, MathUtils::distance_int(1, 2, 1, 2));
assert_eq!((8.0f32).sqrt(), MathUtils::distance(1, 2, 3, 4));
assert_eq!(0.0f32, MathUtils::distance(1, 2, 1, 2));
}
#[test]
@@ -129,5 +137,7 @@ mod tests {
assert_eq!(1, MathUtils::sum(&[1]));
assert_eq!(4, MathUtils::sum(&[1, 3]));
assert_eq!(0, MathUtils::sum(&[-1, 1]));
assert_eq!(0.0, MathUtils::sum(&[-1.0, 1.0]));
assert_eq!(4.0, MathUtils::sum(&[1.0, 3.0]));
}
}

View File

@@ -293,7 +293,7 @@ impl<'a> WhiteRectangleDetector<'_> {
b_x: f32,
b_y: f32,
) -> Option<RXingResultPoint> {
let dist = MathUtils::round(MathUtils::distance_float(a_x, a_y, b_x, b_y));
let dist = MathUtils::round(MathUtils::distance(a_x, a_y, b_x, b_y));
let x_step: f32 = (b_x - a_x) / dist as f32;
let y_step: f32 = (b_y - a_y) / dist as f32;

View File

@@ -210,14 +210,20 @@ impl ECIEncoderSet {
self.encoders.is_empty()
}
pub fn getCharsetName(&self, index: usize) -> &'static str {
assert!(index < self.len());
return self.encoders[index].name();
pub fn getCharsetName(&self, index: usize) -> Option<&'static str> {
if index < self.len() {
Some(self.encoders[index].name())
} else {
None
}
}
pub fn getCharset(&self, index: usize) -> EncodingRef {
assert!(index < self.len());
self.encoders[index]
pub fn getCharset(&self, index: usize) -> Option<EncodingRef> {
if index < self.len() {
Some(self.encoders[index])
} else {
None
}
}
pub fn getECIValue(&self, encoderIndex: usize) -> u32 {
@@ -233,25 +239,35 @@ impl ECIEncoderSet {
self.priorityEncoderIndex
}
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> bool {
assert!(encoderIndex < self.len());
let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> Option<bool> {
if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
enc_data.is_ok()
Some(enc_data.is_ok())
} else {
None
}
}
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Vec<u8> {
assert!(encoderIndex < self.len());
let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
assert!(enc_data.is_ok());
enc_data.unwrap()
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Option<Vec<u8>> {
if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
enc_data.ok()
// assert!(enc_data.is_ok());
// enc_data.unwrap()
} else {
None
}
}
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Vec<u8> {
assert!(encoderIndex < self.len());
let encoder = self.encoders[encoderIndex];
encoder.encode(s, encoding::EncoderTrap::Replace).unwrap()
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Option<Vec<u8>> {
if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex];
encoder.encode(s, encoding::EncoderTrap::Strict).ok()
} else {
None
}
}
}

View File

@@ -106,5 +106,5 @@ pub trait ECIInput: Display {
* if the value at the {@code index} argument is not an ECI (@see #isECI)
*/
fn getECIValue(&self, index: usize) -> Result<i32, Exceptions>;
fn haveNCharacters(&self, index: usize, n: usize) -> bool;
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions>;
}

View File

@@ -51,7 +51,7 @@ impl ECIStringBuilder {
pub fn with_capacity(initial_capacity: usize) -> Self {
Self {
current_bytes: Vec::with_capacity(initial_capacity),
result: String::new(),
result: String::with_capacity(initial_capacity),
current_charset: Some(encoding::all::ISO_8859_1),
}
}
@@ -121,31 +121,25 @@ impl ECIStringBuilder {
Ok(())
}
/// Finishes encoding anything in the buffer using the current ECI and resets.
///
/// This function can panic
pub fn encodeCurrentBytesIfAny(&mut self) {
if let Some(encoder) = self.current_charset {
if encoder.name() == encoding::all::UTF_8.name() {
if !self.current_bytes.is_empty() {
// if result == null {
// result = currentBytes;
// currentBytes = new StringBuilder();
// } else {
self.result.push_str(
&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(),
);
self.current_bytes.clear();
// }
}
} else if !self.current_bytes.is_empty() {
let bytes = std::mem::take(&mut self.current_bytes);
self.current_bytes.clear();
// if (result == null) {
// result = new StringBuilder(new String(bytes, currentCharset));
// } else {
let encoded_value = encoder
.decode(&bytes, encoding::DecoderTrap::Strict)
.unwrap();
self.result.push_str(&encoded_value);
// }
}
} else {
for byte in &self.current_bytes {
@@ -172,7 +166,7 @@ impl ECIStringBuilder {
*/
pub fn len(&mut self) -> usize {
self.encodeCurrentBytesIfAny(); //return toString().length();
self.result.len()
self.result.chars().count()
}
/**

View File

@@ -102,11 +102,6 @@ impl Binarizer for GlobalHistogramBinarizer {
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> {
// if self.black_matrix.is_none() {
// self.black_matrix =
// Some(Self::build_black_matrix(&self.source).expect("matrix must generate"))
// }
// Ok(self.black_matrix.as_ref().unwrap())
let matrix = self
.black_matrix
.get_or_try_init(|| Self::build_black_matrix(&self.source))?;

View File

@@ -144,22 +144,22 @@ pub trait GridSampler {
// for (int offset = 0; offset < maxOffset && nudged; offset += 2) {
let x = points[offset] as i32;
let y = points[offset + 1] as i32;
if x < -1 || x > width.try_into().unwrap() || y < -1 || y > height.try_into().unwrap() {
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
return Err(Exceptions::NotFoundException(None));
}
nudged = false;
if x == -1 {
points[offset] = 0.0f32;
points[offset] = 0.0;
nudged = true;
} else if x == width.try_into().unwrap() {
points[offset] = width as f32 - 1f32;
} else if x == width as i32 {
points[offset] = width as f32 - 1.0;
nudged = true;
}
if y == -1 {
points[offset + 1] = 0.0f32;
points[offset + 1] = 0.0;
nudged = true;
} else if y == height.try_into().unwrap() {
points[offset + 1] = height as f32 - 1f32;
} else if y == height as i32 {
points[offset + 1] = height as f32 - 1.0;
nudged = true;
}
offset += 2;
@@ -171,22 +171,22 @@ pub trait GridSampler {
// for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
let x = points[offset as usize] as i32;
let y = points[offset as usize + 1] as i32;
if x < -1 || x > width.try_into().unwrap() || y < -1 || y > height.try_into().unwrap() {
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
return Err(Exceptions::NotFoundException(None));
}
nudged = false;
if x == -1 {
points[offset as usize] = 0.0f32;
points[offset as usize] = 0.0;
nudged = true;
} else if x == width.try_into().unwrap() {
points[offset as usize] = width as f32 - 1f32;
} else if x == width as i32 {
points[offset as usize] = width as f32 - 1.0;
nudged = true;
}
if y == -1 {
points[offset as usize + 1] = 0.0f32;
points[offset as usize + 1] = 0.0;
nudged = true;
} else if y == height.try_into().unwrap() {
points[offset as usize + 1] = height as f32 - 1f32;
} else if y == height as i32 {
points[offset as usize + 1] = height as f32 - 1.0;
nudged = true;
}
offset += -2;

View File

@@ -67,13 +67,6 @@ impl Binarizer for HybridBinarizer {
* profiling easier, and not doing heavy lifting when callers don't expect it.
*/
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> {
// if self.black_matrix.is_none() {
// self.black_matrix = Some(
// Self::calculateBlackMatrix(&mut self.ghb)
// .expect("generate black matrix must complete"),
// )
// }
// Ok(self.black_matrix.as_ref().unwrap())
let matrix = self
.black_matrix
.get_or_try_init(|| Self::calculateBlackMatrix(&self.ghb))?;
@@ -200,6 +193,7 @@ impl HybridBinarizer {
}
}
#[inline(always)]
fn cap(value: u32, max: u32) -> u32 {
if value < 2 {
2

View File

@@ -14,12 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.common;
// import java.nio.charset.Charset;
// import java.util.ArrayList;
// import java.util.List;
use std::{fmt, rc::Rc};
use encoding::EncodingRef;
@@ -174,17 +168,17 @@ impl ECIInput for MinimalECIInput {
Ok((self.bytes[index] as u32 - 256) as i32)
}
fn haveNCharacters(&self, index: usize, n: usize) -> bool {
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions> {
if index + n > self.bytes.len() {
return false;
return Ok(false);
}
for i in 0..n {
// for (int i = 0; i < n; i++) {
if self.isECI(index as u32 + i as u32).unwrap() {
return false;
if self.isECI(index as u32 + i as u32)? {
return Ok(false);
}
}
true
Ok(true)
}
}
impl MinimalECIInput {
@@ -209,10 +203,14 @@ impl MinimalECIInput {
let bytes = if encoderSet.len() == 1 {
//optimization for the case when all can be encoded without ECI in ISO-8859-1
let mut bytes_hld = vec![0; stringToEncode.len()];
for (i, byt) in bytes_hld.iter_mut().enumerate().take(stringToEncode.len()) {
for (byt, c) in bytes_hld
.iter_mut()
.zip(&stringToEncode)
.take(stringToEncode.len())
{
// for i in 0..stringToEncode.len() {
// for (int i = 0; i < bytes.length; i++) {
let c = stringToEncode.get(i).unwrap();
// let c = stringToEncode.get(i).unwrap();
*byt = if fnc1.is_some() && c == fnc1.as_ref().unwrap() {
1000
} else {
@@ -287,7 +285,9 @@ impl MinimalECIInput {
if encoderSet.getPriorityEncoderIndex().is_some()
&& ((fnc1.is_some()
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap())
|| encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex().unwrap()))
|| encoderSet
.canEncode(ch, encoderSet.getPriorityEncoderIndex().unwrap())
.unwrap())
{
start = encoderSet.getPriorityEncoderIndex().unwrap();
end = start + 1;
@@ -298,7 +298,7 @@ impl MinimalECIInput {
// for (int i = start; i < end; i++) {
if (fnc1.is_some()
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap())
|| encoderSet.canEncode(ch, i)
|| encoderSet.canEncode(ch, i).unwrap()
{
Self::addEdge(
edges,
@@ -309,6 +309,9 @@ impl MinimalECIInput {
}
}
/// Minimially encode a string with the given characterset.
///
/// Function can panic if the string cannot be encoded.
pub fn encodeMinimally(
stringToEncode: &str,
encoderSet: &ECIEncoderSet,
@@ -360,6 +363,7 @@ impl MinimalECIInput {
} else {
let bytes: Vec<u16> = encoderSet
.encode_char(&c.c, c.encoderIndex)
.unwrap()
.iter()
.map(|x| *x as u16)
.collect();
@@ -414,7 +418,7 @@ impl InputEdge {
let mut size = if c == Self::FNC1_UNICODE {
1
} else {
encoderSet.encode_char(c, encoderIndex).len()
encoderSet.encode_char(c, encoderIndex).unwrap().len()
};
//let fnc1Str = String::from_utf16(&[fnc1]).unwrap();

View File

@@ -404,7 +404,7 @@ fn test_encode_decode_random(field: GenericGFRef, dataSize: usize, ecSize: usize
ecSize > 0 && ecSize + dataSize <= field.getSize(),
"Invalid ECC size for {field}"
);
let mut encoder = ReedSolomonEncoder::new(field);
let mut encoder = ReedSolomonEncoder::new(field).expect("new");
let mut message = vec![0; dataSize + ecSize];
let mut dataWords: Vec<i32> = vec![0; dataSize];
let mut ecWords = vec![0; ecSize];
@@ -440,7 +440,7 @@ fn test_encode_decode(field: GenericGFRef, dataWords: &Vec<i32>, ecWords: &Vec<i
}
fn test_encoder(field: GenericGFRef, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
let mut encoder = ReedSolomonEncoder::new(field);
let mut encoder = ReedSolomonEncoder::new(field).expect("new");
let mut messageExpected = vec![0; dataWords.len() + ecWords.len()];
let mut message = vec![0; dataWords.len() + ecWords.len()];
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);

View File

@@ -49,9 +49,9 @@ impl GenericGFPoly {
*/
pub fn new(field: GenericGFRef, coefficients: &[i32]) -> Result<Self, Exceptions> {
if coefficients.is_empty() {
return Err(Exceptions::IllegalArgumentException(Some(
"coefficients.len()".to_owned(),
)));
return Err(Exceptions::IllegalArgumentException(Some(String::from(
"coefficients cannot be empty",
))));
}
Ok(Self {
field,

View File

@@ -61,7 +61,7 @@ impl ReedSolomonDecoder {
* @throws ReedSolomonException if decoding fails for any reason
*/
pub fn decode(&self, received: &mut Vec<i32>, twoS: i32) -> Result<usize, Exceptions> {
let poly = GenericGFPoly::new(self.field, received).unwrap();
let poly = GenericGFPoly::new(self.field, received)?;
let mut syndromeCoefficients = vec![0; twoS as usize];
let mut noError = true;
for i in 0..twoS {
@@ -87,7 +87,7 @@ impl ReedSolomonDecoder {
let sigma = &sigmaOmega[0];
let omega = &sigmaOmega[1];
let errorLocations = self.findErrorLocations(sigma)?;
let errorMagnitudes = self.findErrorMagnitudes(omega, &errorLocations);
let errorMagnitudes = self.findErrorMagnitudes(omega, &errorLocations)?;
for i in 0..errorLocations.len() {
//for (int i = 0; i < errorLocations.length; i++) {
let log_value = self.field.log(errorLocations[i] as i32)?;
@@ -145,62 +145,17 @@ impl ReedSolomonDecoder {
r = rLastLast;
let mut q = r.getZero();
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
Ok(inv) => inv,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"ArithmetricException".to_owned(),
)))
}
};
let dltInverse = self.field.inverse(denominatorLeadingTerm)?;
while r.getDegree() >= rLast.getDegree() && !r.isZero() {
let degreeDiff = r.getDegree() - rLast.getDegree();
let scale = self
.field
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale))
{
Ok(res) => res,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"IllegalArgumentException".to_owned(),
)))
}
};
r = match r.addOrSubtract(&match rLast.multiply_by_monomial(degreeDiff, scale) {
Ok(res) => res,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"IllegalArgumentException".to_owned(),
)))
}
}) {
Ok(res) => res,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"IllegalArgumentException".to_owned(),
)))
}
};
q = q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale))?;
r = r.addOrSubtract(&rLast.multiply_by_monomial(degreeDiff, scale)?)?;
}
t = match (match q.multiply(&tLast) {
Ok(res) => res,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"IllegalArgumentException".to_owned(),
)))
}
})
.addOrSubtract(&tLastLast)
{
Ok(res) => res,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"IllegalArgumentException".to_owned(),
)))
}
};
t = (q.multiply(&tLast)?).addOrSubtract(&tLastLast)?;
if r.getDegree() >= rLast.getDegree() {
return Err(Exceptions::ReedSolomonException(Some(format!(
@@ -245,14 +200,7 @@ impl ReedSolomonDecoder {
break;
}
if errorLocator.evaluateAt(i) == 0 {
result[e] = match self.field.inverse(i as i32) {
Ok(res) => res as usize,
Err(_err) => {
return Err(Exceptions::ReedSolomonException(Some(
"ArithmetricException".to_owned(),
)))
}
};
result[e] = self.field.inverse(i as i32)? as usize;
e += 1;
}
}
@@ -268,13 +216,13 @@ impl ReedSolomonDecoder {
&self,
errorEvaluator: &GenericGFPoly,
errorLocations: &Vec<usize>,
) -> Vec<i32> {
) -> Result<Vec<i32>, Exceptions> {
// This is directly applying Forney's Formula
let s = errorLocations.len();
let mut result = vec![0; s];
for i in 0..s {
//for (int i = 0; i < s; i++) {
let xiInverse = self.field.inverse(errorLocations[i] as i32).unwrap();
let xiInverse = self.field.inverse(errorLocations[i] as i32)?;
let mut denominator = 1;
for (j, loc) in errorLocations.iter().enumerate().take(s) {
// for j in 0..s {
@@ -295,12 +243,12 @@ impl ReedSolomonDecoder {
}
result[i] = self.field.multiply(
errorEvaluator.evaluateAt(xiInverse as usize),
self.field.inverse(denominator).unwrap(),
self.field.inverse(denominator)?,
);
if self.field.getGeneratorBase() != 0 {
result[i] = self.field.multiply(result[i], xiInverse);
}
}
result
Ok(result)
}
}

View File

@@ -35,17 +35,17 @@ pub struct ReedSolomonEncoder {
}
impl ReedSolomonEncoder {
pub fn new(field: GenericGFRef) -> Self {
pub fn new(field: GenericGFRef) -> Result<Self, Exceptions> {
let n = field;
Self {
cachedGenerators: vec![GenericGFPoly::new(n, &[1]).unwrap()],
Ok(Self {
cachedGenerators: vec![GenericGFPoly::new(n, &[1])?],
field: n,
}
})
}
fn buildGenerator(&mut self, degree: usize) -> &GenericGFPoly {
fn buildGenerator(&mut self, degree: usize) -> Option<&GenericGFPoly> {
if degree >= self.cachedGenerators.len() {
let mut lastGenerator = self.cachedGenerators.last().unwrap();
let mut lastGenerator = self.cachedGenerators.last()?;
let cg_len = self.cachedGenerators.len();
let mut nextGenerator;
for d in cg_len..=degree {
@@ -59,16 +59,16 @@ impl ReedSolomonEncoder {
self.field.exp(d as i32 - 1 + self.field.getGeneratorBase()),
],
)
.unwrap(),
.ok()?,
)
.unwrap();
.ok()?;
self.cachedGenerators.push(nextGenerator);
lastGenerator = self.cachedGenerators.get(d).unwrap();
lastGenerator = self.cachedGenerators.get(d)?;
//lastGenerator = &nextGenerator;
}
}
let rv = self.cachedGenerators.get(degree).unwrap();
rv
let rv = self.cachedGenerators.get(degree)?;
Some(rv)
}
pub fn encode(&mut self, to_encode: &mut Vec<i32>, ec_bytes: usize) -> Result<(), Exceptions> {
@@ -90,7 +90,9 @@ impl ReedSolomonEncoder {
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
let mut info = GenericGFPoly::new(fld, &info_coefficients)?;
info = info.multiply_by_monomial(ec_bytes, 1)?;
let remainder = &info.divide(generator)?.1;
let remainder = &info
.divide(generator.ok_or(Exceptions::ReedSolomonException(None))?)?
.1;
let coefficients = remainder.getCoefficients();
let num_zero_coefficients = ec_bytes - coefficients.len();
for i in 0..num_zero_coefficients {

View File

@@ -14,12 +14,6 @@
* limitations under the License.
*/
// package com.google.zxing.common;
// import java.nio.charset.Charset;
// import java.nio.charset.StandardCharsets;
// import java.util.Map;
use encoding::{Encoding, EncodingRef};
use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary};
@@ -71,20 +65,16 @@ impl StringUtils {
* "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none
* of these can possibly be correct
*/
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> &'static str {
let c = StringUtils::guessCharset(bytes, hints);
if c.name()
== encoding::label::encoding_from_whatwg_label("SJIS")
.unwrap()
.name()
{
"SJIS"
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<&'static str> {
let c = StringUtils::guessCharset(bytes, hints)?;
if c.name() == encoding::label::encoding_from_whatwg_label("SJIS")?.name() {
Some("SJIS")
} else if c.name() == encoding::all::UTF_8.name() {
"UTF8"
Some("UTF8")
} else if c.name() == encoding::all::ISO_8859_1.name() {
"ISO8859_1"
Some("ISO8859_1")
} else {
c.name()
Some(c.name())
}
}
@@ -97,12 +87,12 @@ impl StringUtils {
* or the platform default encoding if
* none of these can possibly be correct
*/
pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> EncodingRef {
pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<EncodingRef> {
if let Some(DecodeHintValue::CharacterSet(cs_name)) =
hints.get(&DecodeHintType::CHARACTER_SET)
{
// if let DecodeHintValue::CharacterSet(cs_name) = hint {
return encoding::label::encoding_from_whatwg_label(cs_name).unwrap();
return encoding::label::encoding_from_whatwg_label(cs_name);
// }
}
// if hints.contains_key(&DecodeHintType::CHARACTER_SET) {
@@ -114,9 +104,9 @@ impl StringUtils {
&& ((bytes[0] == 0xFE && bytes[1] == 0xFF) || (bytes[0] == 0xFF && bytes[1] == 0xFE))
{
if bytes[0] == 0xFE && bytes[1] == 0xFF {
return encoding::all::UTF_16BE;
return Some(encoding::all::UTF_16BE);
} else {
return encoding::all::UTF_16LE;
return Some(encoding::all::UTF_16LE);
}
}
@@ -234,7 +224,7 @@ impl StringUtils {
// Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
if can_be_utf8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) {
return encoding::all::UTF_8;
return Some(encoding::all::UTF_8);
}
// Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done
if can_be_shift_jis
@@ -242,7 +232,7 @@ impl StringUtils {
|| sjis_max_katakana_word_length >= 3
|| sjis_max_double_bytes_word_length >= 3)
{
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
return encoding::label::encoding_from_whatwg_label("SJIS");
}
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
// - If we saw
@@ -253,23 +243,23 @@ impl StringUtils {
return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2)
|| iso_high_other * 10 >= length
{
encoding::label::encoding_from_whatwg_label("SJIS").unwrap()
encoding::label::encoding_from_whatwg_label("SJIS")
} else {
encoding::all::ISO_8859_1
Some(encoding::all::ISO_8859_1)
};
}
// Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
if can_be_iso88591 {
return encoding::all::ISO_8859_1;
return Some(encoding::all::ISO_8859_1);
}
if can_be_shift_jis {
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
return Some(encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
}
if can_be_utf8 {
return encoding::all::UTF_8;
return Some(encoding::all::UTF_8);
}
// Otherwise, we take a wild guess with platform encoding
encoding::all::UTF_8
Some(encoding::all::UTF_8)
}
}

View File

@@ -169,15 +169,10 @@ impl Writer for DataMatrixWriter {
symbolInfo.getSymbolDataWidth()? as usize,
symbolInfo.getSymbolDataHeight()? as usize,
);
placement.place();
placement.place()?;
//4. step: low-level encoding
Self::encodeLowLevel(
&placement,
symbolInfo,
width.try_into().unwrap(),
height.try_into().unwrap(),
)
Self::encodeLowLevel(&placement, symbolInfo, width as u32, height as u32)
}
}

View File

@@ -85,8 +85,8 @@ impl BitMatrixParser {
let mut row = 4;
let mut column = 0;
let numRows = self.mappingBitMatrix.getHeight().try_into().unwrap();
let numColumns = self.mappingBitMatrix.getWidth().try_into().unwrap();
let numRows = self.mappingBitMatrix.getHeight() as isize;
let numColumns = self.mappingBitMatrix.getWidth() as isize;
let mut corner1Read = false;
let mut corner2Read = false;
@@ -497,11 +497,3 @@ impl BitMatrixParser {
Ok(bitMatrixWithoutAlignment)
}
}
// const IS_MOSTLY_BLACK_RATIO : f32= 0.5;
// fn is_mostly_black(array: &[bool]) -> bool {
// let array_len = array.len() as f32;
// let true_count = array.iter().fold(0, |acc,b| acc + i32::from(*b)) as f32;
// (array_len / true_count ) > IS_MOSTLY_BLACK_RATIO
// }

View File

@@ -206,12 +206,6 @@ pub fn decode(bytes: &[u8], is_flipped: bool) -> Result<DecoderRXingResult, Exce
}
Ok(result)
// return new DecoderRXingResult(bytes,
// result.toString(),
// byteSegments.isEmpty() ? null : byteSegments,
// null,
// symbologyModifier);
}
/**
@@ -238,7 +232,9 @@ fn decodeAsciiSegment(
oneByte += 128;
//upperShift = false;
}
result.append_char(char::from_u32(oneByte - 1).unwrap());
result.append_char(
char::from_u32(oneByte - 1).ok_or(Exceptions::ParseException(None))?,
);
return Ok(Mode::ASCII_ENCODE);
}
129 => return Ok(Mode::PAD_ENCODE), // Pad
@@ -249,7 +245,6 @@ fn decodeAsciiSegment(
// pad with '0' for single digit values
result.append_char('0');
}
//result.append_char(char::from_u32(value).unwrap());
result.append_string(&format!("{value}"));
}
230 =>
@@ -391,7 +386,10 @@ fn decodeC40Segment(
} else if cValue < C40_BASIC_SET_CHARS.len() as u32 {
let c40char = C40_BASIC_SET_CHARS[cValue as usize];
if upperShift {
result.append_char(char::from_u32(c40char as u32 + 128).unwrap());
result.append_char(
char::from_u32(c40char as u32 + 128)
.ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(c40char);
@@ -402,10 +400,14 @@ fn decodeC40Segment(
}
1 => {
if upperShift {
result.append_char(char::from_u32(cValue + 128).unwrap());
result.append_char(
char::from_u32(cValue + 128).ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(char::from_u32(cValue).unwrap());
result.append_char(
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
);
}
shift = 0;
}
@@ -413,7 +415,10 @@ fn decodeC40Segment(
if cValue < C40_SHIFT2_SET_CHARS.len() as u32 {
let c40char = C40_SHIFT2_SET_CHARS[cValue as usize];
if upperShift {
result.append_char(char::from_u32(c40char as u32 + 128).unwrap());
result.append_char(
char::from_u32(c40char as u32 + 128)
.ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(c40char);
@@ -438,10 +443,14 @@ fn decodeC40Segment(
}
3 => {
if upperShift {
result.append_char(char::from_u32(cValue + 224).unwrap());
result.append_char(
char::from_u32(cValue + 224).ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(char::from_u32(cValue + 96).unwrap());
result.append_char(
char::from_u32(cValue + 96).ok_or(Exceptions::ParseException(None))?,
);
}
shift = 0;
}
@@ -494,7 +503,10 @@ fn decodeTextSegment(
} else if cValue < TEXT_BASIC_SET_CHARS.len() as u32 {
let textChar = TEXT_BASIC_SET_CHARS[cValue as usize];
if upperShift {
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
result.append_char(
char::from_u32(textChar as u32 + 128)
.ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(textChar);
@@ -505,10 +517,14 @@ fn decodeTextSegment(
}
1 => {
if upperShift {
result.append_char(char::from_u32(cValue + 128).unwrap());
result.append_char(
char::from_u32(cValue + 128).ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(char::from_u32(cValue).unwrap());
result.append_char(
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
);
}
shift = 0;
}
@@ -518,7 +534,10 @@ fn decodeTextSegment(
if cValue < TEXT_SHIFT2_SET_CHARS.len() as u32 {
let textChar = TEXT_SHIFT2_SET_CHARS[cValue as usize];
if upperShift {
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
result.append_char(
char::from_u32(textChar as u32 + 128)
.ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(textChar);
@@ -545,7 +564,10 @@ fn decodeTextSegment(
if cValue < TEXT_SHIFT3_SET_CHARS.len() as u32 {
let textChar = TEXT_SHIFT3_SET_CHARS[cValue as usize];
if upperShift {
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
result.append_char(
char::from_u32(textChar as u32 + 128)
.ok_or(Exceptions::ParseException(None))?,
);
upperShift = false;
} else {
result.append_char(textChar);
@@ -622,10 +644,14 @@ fn decodeAnsiX12Segment(
_ => {
if cValue < 14 {
// 0 - 9
result.append_char(char::from_u32(cValue + 44).unwrap());
result.append_char(
char::from_u32(cValue + 44).ok_or(Exceptions::ParseException(None))?,
);
} else if cValue < 40 {
// A - Z
result.append_char(char::from_u32(cValue + 51).unwrap());
result.append_char(
char::from_u32(cValue + 51).ok_or(Exceptions::ParseException(None))?,
);
} else {
return Err(Exceptions::FormatException(None));
}
@@ -682,7 +708,8 @@ fn decodeEdifactSegment(
// no 1 in the leading (6th) bit
edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value
}
result.append_char(char::from_u32(edifactValue).unwrap());
result
.append_char(char::from_u32(edifactValue).ok_or(Exceptions::ParseException(None))?);
}
if bits.available() == 0 {
@@ -724,8 +751,6 @@ fn decodeBase256Segment(
let mut bytes = vec![0u8; count as usize];
for byte in bytes.iter_mut().take(count as usize) {
// for i in 0..count as usize {
// for (int i = 0; i < count; i++) {
// Have seen this particular error in the wild, such as at
// http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
if bits.available() < 8 {
@@ -737,10 +762,9 @@ fn decodeBase256Segment(
result.append_string(
&encoding::all::ISO_8859_1
.decode(&bytes, encoding::DecoderTrap::Strict)
.expect("decode"),
.map_err(|e| Exceptions::ParseException(Some(e.to_string())))?,
);
byteSegments.push(bytes);
// result.append_string(&encoding::all::ISO_8859_1.decode(&bytes, encoding::DecoderTrap::Strict).expect("decode"));
Ok(())
}
@@ -768,30 +792,6 @@ fn decodeECISegment(
result.appendECI((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1)?;
Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900)
// if bits.available() < 8 {
// return Err(Exceptions::FormatException(None));
// }
// let c1 = bits.readBits(8)?;
// if c1 <= 127 {
// result.appendECI(c1 - 1)?;
// }
// Ok(())
//currently we only support character set ECIs
/*} else {
if (bits.available() < 8) {
throw FormatException.getFormatInstance();
}
int c2 = bits.readBits(8);
if (c1 >= 128 && c1 <= 191) {
} else {
if (bits.available() < 8) {
throw FormatException.getFormatInstance();
}
int c3 = bits.readBits(8);
}
}*/
}
/**

View File

@@ -60,17 +60,6 @@ impl Version {
acc + ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords)
})
},
// totalCodewords: {
// // Calculate the total number of codewords
// let mut total = 0;
// let ecCodewords = &ecBlocks.getECCodewords();
// let ecbArray = ecBlocks.getECBlocks();
// for ecBlock in ecbArray {
// total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
// }
// total
// },
ecBlocks,
}
}

View File

@@ -212,7 +212,7 @@ impl<'a> Detector<'_> {
/**
* Calculates the corner position of the white top right module.
*/
fn correctTopRight(&self, points: &[RXingResultPoint]) -> Option<RXingResultPoint> {
fn correctTopRight(&self, points: &[RXingResultPoint; 4]) -> Option<RXingResultPoint> {
// A..D
// | :
// B--C

View File

@@ -249,7 +249,7 @@ fn Scan(
CHECK!(res.is_ok());
return Ok(DatamatrixDetectorResult::new(
res.unwrap(),
res?,
sourcePoints.points().to_vec(),
));
}

View File

@@ -30,14 +30,6 @@ impl Default for DMRegressionLine {
}
impl RegressionLine for DMRegressionLine {
// fn intersect<T: RegressionLine, T2: RegressionLine>(
// &self,
// l1: &T,
// l2: &T2,
// ) -> RXingResultPoint {
// int
// }
fn points(&self) -> &[RXingResultPoint] {
&self.points
}
@@ -272,7 +264,14 @@ impl DMRegressionLine {
// calculate the (expected average) distance of two adjacent pixels
let unitPixelDist = RXingResultPoint::length(RXingResultPoint::bresenhamDirection(
&(*self.points.last().unwrap() - *self.points.first().unwrap()),
&(*self
.points
.last()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
- *self
.points
.first()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
)) as f64;
// calculate the width of 2 modules (first black pixel to first black pixel)
@@ -291,8 +290,17 @@ impl DMRegressionLine {
}
}
modSizes
.push(sumFront + self.distance(end, &self.project(self.points.last().unwrap())) as f64);
modSizes.push(
sumFront
+ self.distance(
end,
&self.project(
self.points
.last()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
),
) as f64,
);
modSizes[0] = 0.0; // the first element is an invalid sumBack value, would be pop_front() if vector supported this
let lineLength = self.distance(beg, end) as f64 - unitPixelDist;
let mut meanModSize = Self::average(&modSizes, |_: f64| true);

View File

@@ -272,7 +272,12 @@ impl<'a> EdgeTracer<'_> {
return Ok(false);
}
if !self.updateDirectionFromOrigin(
&(self.p - line.project(&self.p) + **line.points().first().as_ref().unwrap()),
&(self.p - line.project(&self.p)
+ **line
.points()
.first()
.as_ref()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
) {
return Ok(false);
}
@@ -296,10 +301,24 @@ impl<'a> EdgeTracer<'_> {
let mut gaps = 0;
loop {
// detect an endless loop (lack of progress). if encountered, please report.
if !(line.points().is_empty() || &&self.p != line.points().last().as_ref().unwrap()) {
if !(line.points().is_empty()
|| &&self.p
!= line
.points()
.last()
.as_ref()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?)
{
return Err(Exceptions::IllegalStateException(None));
}
if !line.points().is_empty() && &&self.p == line.points().last().as_ref().unwrap() {
if !line.points().is_empty()
&& &&self.p
== line
.points()
.last()
.as_ref()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
{
return Ok(false);
}
// log(p);
@@ -340,7 +359,12 @@ impl<'a> EdgeTracer<'_> {
// to prevent a dead lock. see #245.png
while RXingResultPoint::distance(
np,
line.project(line.points().last().as_ref().unwrap()),
line.project(
line.points()
.last()
.as_ref()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
),
) < 1.0
{
np += self.d;
@@ -352,7 +376,11 @@ impl<'a> EdgeTracer<'_> {
} else {
RXingResultPoint::dot(
RXingResultPoint::mainDirection(self.d),
self.p - line.points().last().unwrap(),
self.p
- line
.points()
.last()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
)
};
line.add(&self.p)?;
@@ -364,7 +392,11 @@ impl<'a> EdgeTracer<'_> {
return Ok(false);
}
if !self.updateDirectionFromOrigin(
&(self.p - line.project(&self.p) + *line.points().first().unwrap()),
&(self.p - line.project(&self.p)
+ *line
.points()
.first()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
) {
return Ok(false);
}

View File

@@ -31,12 +31,12 @@ impl Encoder for ASCIIEncoder {
.getMessage()
.chars()
.nth(context.pos as usize)
.unwrap(),
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
context
.getMessage()
.chars()
.nth(context.pos as usize + 1)
.unwrap(),
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
)? as u8);
context.pos += 2;
} else {

View File

@@ -51,19 +51,36 @@ impl Encoder for Base256Encoder {
let lengthFieldSize = 1;
let currentSize = context.getCodewordCount() + dataCount + lengthFieldSize;
context.updateSymbolInfoWithLength(currentSize);
let mustPad = (context.getSymbolInfo().unwrap().getDataCapacity() - currentSize as u32) > 0;
let mustPad = (context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity()
- currentSize as u32)
> 0;
if context.hasMoreCharacters() || mustPad {
if dataCount <= 249 {
buffer.replace_range(0..1, &char::from_u32(dataCount as u32).unwrap().to_string());
buffer.replace_range(
0..1,
&char::from_u32(dataCount as u32)
.ok_or(Exceptions::ParseException(None))?
.to_string(),
);
} else if dataCount <= 1555 {
buffer.replace_range(
0..1,
&char::from_u32((dataCount as u32 / 250) + 249)
.unwrap()
.ok_or(Exceptions::ParseException(None))?
.to_string(),
);
let (ci_pos, _) = buffer.char_indices().nth(1).unwrap();
buffer.insert(ci_pos, char::from_u32(dataCount as u32 % 250).unwrap());
let (ci_pos, _) = buffer
.char_indices()
.nth(1)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
buffer.insert(
ci_pos,
char::from_u32(dataCount as u32 % 250)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
);
} else {
return Err(Exceptions::IllegalStateException(Some(format!(
"Message length not in valid ranges: {dataCount}"
@@ -73,10 +90,16 @@ impl Encoder for Base256Encoder {
let c = buffer.chars().count();
for i in 0..c {
// for (int i = 0, c = buffer.length(); i < c; i++) {
context.writeCodeword(Self::randomize255State(
buffer.chars().nth(i).unwrap(),
context.getCodewordCount() as u32 + 1,
) as u8);
context.writeCodeword(
Self::randomize255State(
buffer
.chars()
.nth(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
context.getCodewordCount() as u32 + 1,
)
.ok_or(Exceptions::ParseException(None))? as u8,
);
}
Ok(())
}
@@ -85,13 +108,13 @@ impl Base256Encoder {
pub fn new() -> Self {
Self
}
fn randomize255State(ch: char, codewordPosition: u32) -> char {
fn randomize255State(ch: char, codewordPosition: u32) -> Option<char> {
let pseudoRandom = ((149 * codewordPosition) % 255) + 1;
let tempVariable = ch as u32 + pseudoRandom;
if tempVariable <= 255 {
char::from_u32(tempVariable).unwrap()
char::from_u32(tempVariable)
} else {
char::from_u32(tempVariable - 256).unwrap()
char::from_u32(tempVariable - 256)
}
}
}

View File

@@ -63,8 +63,11 @@ impl C40Encoder {
let curCodewordCount = context.getCodewordCount() + unwritten;
context.updateSymbolInfoWithLength(curCodewordCount);
let available =
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
let available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
if !context.hasMoreCharacters() {
//Avoid having a single C40 value in the last triplet
@@ -107,7 +110,7 @@ impl C40Encoder {
handleEOD(context, &mut buffer)
}
pub fn encodeMaximalC40(&self, context: &mut EncoderContext) {
pub fn encodeMaximalC40(&self, context: &mut EncoderContext) -> Result<(), Exceptions> {
self.encodeMaximal(context, &Self::encodeChar_c40, &Self::handleEOD_c40)
}
@@ -116,7 +119,7 @@ impl C40Encoder {
context: &mut EncoderContext,
encodeChar: &dyn Fn(char, &mut String) -> u32,
handleEOD: &dyn Fn(&mut EncoderContext, &mut String) -> Result<(), Exceptions>,
) {
) -> Result<(), Exceptions> {
let mut buffer = String::new();
let mut lastCharSize = 0;
let mut backtrackStartPosition = context.pos;
@@ -135,8 +138,11 @@ impl C40Encoder {
let curCodewordCount = context.getCodewordCount() + unwritten + 1; // +1 for the latch to C40
context.updateSymbolInfoWithLength(curCodewordCount);
let available =
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
let available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
let rest = buffer.chars().count() % 3;
if (rest == 2 && available != 2) || (rest == 1 && (lastCharSize > 3 || available != 1))
{
@@ -149,7 +155,9 @@ impl C40Encoder {
context.writeCodeword(LATCH_TO_C40);
}
handleEOD(context, &mut buffer).expect("eod");
handleEOD(context, &mut buffer)?;
Ok(())
}
fn backtrackOneCharacter(
@@ -170,10 +178,16 @@ impl C40Encoder {
lastCharSize
}
pub(super) fn writeNextTriplet(context: &mut EncoderContext, buffer: &mut String) {
context.writeCodewords(&Self::encodeToCodewords(buffer));
pub(super) fn writeNextTriplet(
context: &mut EncoderContext,
buffer: &mut String,
) -> Result<(), Exceptions> {
context.writeCodewords(
&Self::encodeToCodewords(buffer).ok_or(Exceptions::FormatException(None))?,
);
buffer.replace_range(0..3, "");
// buffer.delete(0, 3);
Ok(())
}
/**
@@ -191,20 +205,23 @@ impl C40Encoder {
let curCodewordCount = context.getCodewordCount() + unwritten;
context.updateSymbolInfoWithLength(curCodewordCount);
let available =
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
let available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
if rest == 2 {
buffer.push('\0'); //Shift 1
while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer);
C40Encoder::writeNextTriplet(context, buffer)?;
}
if context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH);
}
} else if available == 1 && rest == 1 {
while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer);
C40Encoder::writeNextTriplet(context, buffer)?;
}
if context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH);
@@ -213,7 +230,7 @@ impl C40Encoder {
context.pos -= 1;
} else if rest == 0 {
while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer);
C40Encoder::writeNextTriplet(context, buffer)?;
}
if available > 0 || context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH);
@@ -273,16 +290,18 @@ impl C40Encoder {
len
}
fn encodeToCodewords(sb: &str) -> String {
let v = (1600 * sb.chars().next().unwrap() as u32)
+ (40 * sb.chars().nth(1).unwrap() as u32)
+ sb.chars().nth(2).unwrap() as u32
fn encodeToCodewords(sb: &str) -> Option<String> {
let v = (1600 * sb.chars().next()? as u32)
+ (40 * sb.chars().nth(1)? as u32)
+ sb.chars().nth(2)? as u32
+ 1;
let cw1 = v / 256;
let cw2 = v % 256;
[char::from_u32(cw1).unwrap(), char::from_u32(cw2).unwrap()]
.into_iter()
.collect()
Some(
[char::from_u32(cw1)?, char::from_u32(cw2)?]
.into_iter()
.collect(),
)
// return new String(new char[] {cw1, cw2});
}
}

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
use crate::Exceptions;
const EMPTY_BIT_VAL: u8 = 13;
/**
@@ -71,7 +73,7 @@ impl DefaultPlacement {
self.bits[row * self.numcols + col] == EMPTY_BIT_VAL
}
pub fn place(&mut self) {
pub fn place(&mut self) -> Result<(), Exceptions> {
let mut pos = 0;
let mut row = 4_isize;
let mut col = 0_isize;
@@ -79,19 +81,19 @@ impl DefaultPlacement {
loop {
// repeatedly first check for one of the special corner cases, then...
if (row == self.numrows as isize) && (col == 0) {
self.corner1(pos);
self.corner1(pos)?;
pos += 1;
}
if (row == self.numrows as isize - 2) && (col == 0) && ((self.numcols % 4) != 0) {
self.corner2(pos);
self.corner2(pos)?;
pos += 1;
}
if (row == self.numrows as isize - 2) && (col == 0) && (self.numcols % 8 == 4) {
self.corner3(pos);
self.corner3(pos)?;
pos += 1;
}
if (row == self.numrows as isize + 4) && (col == 2) && ((self.numcols % 8) == 0) {
self.corner4(pos);
self.corner4(pos)?;
pos += 1;
}
// sweep upward diagonally, inserting successive characters...
@@ -100,7 +102,7 @@ impl DefaultPlacement {
&& (col >= 0)
&& self.noBit(col as usize, row as usize)
{
self.utah(row, col, pos);
self.utah(row, col, pos)?;
pos += 1;
}
row -= 2;
@@ -118,7 +120,7 @@ impl DefaultPlacement {
&& (col < self.numcols as isize)
&& self.noBit(col as usize, row as usize)
{
self.utah(row, col, pos);
self.utah(row, col, pos)?;
pos += 1;
}
row += 2;
@@ -142,9 +144,10 @@ impl DefaultPlacement {
self.setBit(self.numcols - 1, self.numrows - 1, true);
self.setBit(self.numcols - 2, self.numrows - 2, true);
}
Ok(())
}
fn module(&mut self, row: isize, col: isize, pos: usize, bit: u32) {
fn module(&mut self, row: isize, col: isize, pos: usize, bit: u32) -> Result<(), Exceptions> {
let mut row = row;
let mut col = col;
@@ -157,9 +160,15 @@ impl DefaultPlacement {
row += 4 - ((self.numcols + 4) % 8) as isize;
}
// Note the conversion:
let mut v = self.codewords.chars().nth(pos).unwrap() as u32;
let mut v = self
.codewords
.chars()
.nth(pos)
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as u32;
v &= 1 << (8 - bit);
self.setBit(col as usize, row as usize, v != 0);
Ok(())
}
/**
@@ -169,59 +178,64 @@ impl DefaultPlacement {
* @param col the column
* @param pos character position
*/
fn utah(&mut self, row: isize, col: isize, pos: usize) {
self.module(row - 2, col - 2, pos, 1);
self.module(row - 2, col - 1, pos, 2);
self.module(row - 1, col - 2, pos, 3);
self.module(row - 1, col - 1, pos, 4);
self.module(row - 1, col, pos, 5);
self.module(row, col - 2, pos, 6);
self.module(row, col - 1, pos, 7);
self.module(row, col, pos, 8);
fn utah(&mut self, row: isize, col: isize, pos: usize) -> Result<(), Exceptions> {
self.module(row - 2, col - 2, pos, 1)?;
self.module(row - 2, col - 1, pos, 2)?;
self.module(row - 1, col - 2, pos, 3)?;
self.module(row - 1, col - 1, pos, 4)?;
self.module(row - 1, col, pos, 5)?;
self.module(row, col - 2, pos, 6)?;
self.module(row, col - 1, pos, 7)?;
self.module(row, col, pos, 8)?;
Ok(())
}
fn corner1(&mut self, pos: usize) {
self.module(self.numrows as isize - 1, 0, pos, 1);
self.module(self.numrows as isize - 1, 1, pos, 2);
self.module(self.numrows as isize - 1, 2, pos, 3);
self.module(0, self.numcols as isize - 2, pos, 4);
self.module(0, self.numcols as isize - 1, pos, 5);
self.module(1, self.numcols as isize - 1, pos, 6);
self.module(2, self.numcols as isize - 1, pos, 7);
self.module(3, self.numcols as isize - 1, pos, 8);
fn corner1(&mut self, pos: usize) -> Result<(), Exceptions> {
self.module(self.numrows as isize - 1, 0, pos, 1)?;
self.module(self.numrows as isize - 1, 1, pos, 2)?;
self.module(self.numrows as isize - 1, 2, pos, 3)?;
self.module(0, self.numcols as isize - 2, pos, 4)?;
self.module(0, self.numcols as isize - 1, pos, 5)?;
self.module(1, self.numcols as isize - 1, pos, 6)?;
self.module(2, self.numcols as isize - 1, pos, 7)?;
self.module(3, self.numcols as isize - 1, pos, 8)?;
Ok(())
}
fn corner2(&mut self, pos: usize) {
self.module(self.numrows as isize - 3, 0, pos, 1);
self.module(self.numrows as isize - 2, 0, pos, 2);
self.module(self.numrows as isize - 1, 0, pos, 3);
self.module(0, self.numcols as isize - 4, pos, 4);
self.module(0, self.numcols as isize - 3, pos, 5);
self.module(0, self.numcols as isize - 2, pos, 6);
self.module(0, self.numcols as isize - 1, pos, 7);
self.module(1, self.numcols as isize - 1, pos, 8);
fn corner2(&mut self, pos: usize) -> Result<(), Exceptions> {
self.module(self.numrows as isize - 3, 0, pos, 1)?;
self.module(self.numrows as isize - 2, 0, pos, 2)?;
self.module(self.numrows as isize - 1, 0, pos, 3)?;
self.module(0, self.numcols as isize - 4, pos, 4)?;
self.module(0, self.numcols as isize - 3, pos, 5)?;
self.module(0, self.numcols as isize - 2, pos, 6)?;
self.module(0, self.numcols as isize - 1, pos, 7)?;
self.module(1, self.numcols as isize - 1, pos, 8)?;
Ok(())
}
fn corner3(&mut self, pos: usize) {
self.module(self.numrows as isize - 3, 0, pos, 1);
self.module(self.numrows as isize - 2, 0, pos, 2);
self.module(self.numrows as isize - 1, 0, pos, 3);
self.module(0, self.numcols as isize - 2, pos, 4);
self.module(0, self.numcols as isize - 1, pos, 5);
self.module(1, self.numcols as isize - 1, pos, 6);
self.module(2, self.numcols as isize - 1, pos, 7);
self.module(3, self.numcols as isize - 1, pos, 8);
fn corner3(&mut self, pos: usize) -> Result<(), Exceptions> {
self.module(self.numrows as isize - 3, 0, pos, 1)?;
self.module(self.numrows as isize - 2, 0, pos, 2)?;
self.module(self.numrows as isize - 1, 0, pos, 3)?;
self.module(0, self.numcols as isize - 2, pos, 4)?;
self.module(0, self.numcols as isize - 1, pos, 5)?;
self.module(1, self.numcols as isize - 1, pos, 6)?;
self.module(2, self.numcols as isize - 1, pos, 7)?;
self.module(3, self.numcols as isize - 1, pos, 8)?;
Ok(())
}
fn corner4(&mut self, pos: usize) {
self.module(self.numrows as isize - 1, 0, pos, 1);
self.module(self.numrows as isize - 1, self.numcols as isize - 1, pos, 2);
self.module(0, self.numcols as isize - 3, pos, 3);
self.module(0, self.numcols as isize - 2, pos, 4);
self.module(0, self.numcols as isize - 1, pos, 5);
self.module(1, self.numcols as isize - 3, pos, 6);
self.module(1, self.numcols as isize - 2, pos, 7);
self.module(1, self.numcols as isize - 1, pos, 8);
fn corner4(&mut self, pos: usize) -> Result<(), Exceptions> {
self.module(self.numrows as isize - 1, 0, pos, 1)?;
self.module(self.numrows as isize - 1, self.numcols as isize - 1, pos, 2)?;
self.module(0, self.numcols as isize - 3, pos, 3)?;
self.module(0, self.numcols as isize - 2, pos, 4)?;
self.module(0, self.numcols as isize - 1, pos, 5)?;
self.module(1, self.numcols as isize - 3, pos, 6)?;
self.module(1, self.numcols as isize - 2, pos, 7)?;
self.module(1, self.numcols as isize - 1, pos, 8)?;
Ok(())
}
#[allow(dead_code)]
@@ -257,7 +271,7 @@ mod test_placement {
fn testPlacement() {
let codewords = unvisualize("66 74 78 66 74 78 129 56 35 102 192 96 226 100 156 1 107 221"); //"AIMAIM" encoded
let mut placement = DefaultPlacement::new(codewords, 12, 12);
placement.place();
placement.place().expect("msg");
let expected = [
"011100001111",
"001010101000",

View File

@@ -29,7 +29,7 @@ impl Encoder for EdifactEncoder {
let mut buffer = String::new();
while context.hasMoreCharacters() {
let c = context.getCurrentChar();
Self::encodeChar(c, &mut buffer);
Self::encodeChar(c, &mut buffer)?;
context.pos += 1;
let count = buffer.chars().count();
@@ -74,13 +74,19 @@ impl EdifactEncoder {
if count == 1 {
//Only an unlatch at the end
context.updateSymbolInfo();
let mut available = context.getSymbolInfo().unwrap().getDataCapacity()
let mut available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity()
- context.getCodewordCount() as u32;
let remaining = context.getRemainingCharacters();
// The following two lines are a hack inspired by the 'fix' from https://sourceforge.net/p/barcode4j/svn/221/
if remaining > available {
context.updateSymbolInfoWithLength(context.getCodewordCount() + 1);
available = context.getSymbolInfo().unwrap().getDataCapacity()
available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity()
- context.getCodewordCount() as u32;
}
if remaining <= available && available <= 2 {
@@ -100,7 +106,10 @@ impl EdifactEncoder {
if restChars <= 2 {
context.updateSymbolInfoWithLength(context.getCodewordCount() + restChars);
let available = context.getSymbolInfo().unwrap().getDataCapacity()
let available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity()
- context.getCodewordCount() as u32;
if available >= 3 {
restInAscii = false;
@@ -126,14 +135,15 @@ impl EdifactEncoder {
res
}
fn encodeChar(c: char, sb: &mut String) {
fn encodeChar(c: char, sb: &mut String) -> Result<(), Exceptions> {
if (' '..='?').contains(&c) {
sb.push(c);
} else if ('@'..='^').contains(&c) {
sb.push((c as u8 - 64) as char);
} else {
high_level_encoder::illegalCharacter(c).expect("");
high_level_encoder::illegalCharacter(c)?
}
Ok(())
}
fn encodeToCodewords(sb: &str) -> Result<String, Exceptions> {
@@ -143,19 +153,28 @@ impl EdifactEncoder {
"StringBuilder must not be empty".to_owned(),
)));
}
let c1 = sb.chars().next().unwrap();
let c1 = sb
.chars()
.next()
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
let c2 = if len >= 2 {
sb.chars().nth(1).unwrap()
sb.chars()
.nth(1)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
} else {
0 as char
};
let c3 = if len >= 3 {
sb.chars().nth(2).unwrap()
sb.chars()
.nth(2)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
} else {
0 as char
};
let c4 = if len >= 4 {
sb.chars().nth(3).unwrap()
sb.chars()
.nth(3)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
} else {
0 as char
};
@@ -165,12 +184,12 @@ impl EdifactEncoder {
let cw2 = (v >> 8) & 255;
let cw3 = v & 255;
let mut res = String::with_capacity(3);
res.push(char::from_u32(cw1).unwrap());
res.push(char::from_u32(cw1).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
if len >= 2 {
res.push(char::from_u32(cw2).unwrap());
res.push(char::from_u32(cw2).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
}
if len >= 3 {
res.push(char::from_u32(cw3).unwrap());
res.push(char::from_u32(cw3).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
}
Ok(res)

View File

@@ -62,7 +62,11 @@ impl<'a> EncoderContext<'_> {
{
ISO_8859_1_ENCODER
.decode(&encoded_bytes, encoding::DecoderTrap::Strict)
.expect("round trip decode should always work")
.map_err(|e| {
Exceptions::ParseException(Some(format!(
"round trip decode should always work: {e}"
)))
})?
} else {
return Err(Exceptions::IllegalArgumentException(Some(
"Message contains characters outside ISO-8859-1 encoding.".to_owned(),
@@ -99,13 +103,13 @@ impl<'a> EncoderContext<'_> {
self.skipAtEnd = count;
}
/// panics if current position is out of bounds
pub fn getCurrentChar(&self) -> char {
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
self.msg.chars().nth(self.pos as usize).unwrap()
}
/// panics if current position is out of bounds
pub fn getCurrent(&self) -> char {
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
self.msg.chars().nth(self.pos as usize).unwrap()
}
@@ -157,6 +161,9 @@ impl<'a> EncoderContext<'_> {
self.updateSymbolInfoWithLength(self.getCodewordCount());
}
/// Update symbol info with the length
///
/// This function can panic
pub fn updateSymbolInfoWithLength(&mut self, len: usize) {
if self.symbolInfo.is_none()
|| len > self.symbolInfo.as_ref().unwrap().getDataCapacity() as usize

View File

@@ -35,61 +35,61 @@ const FACTOR_SETS: [u32; 16] = [5, 7, 10, 11, 12, 14, 18, 20, 24, 28, 36, 42, 48
*/
static FACTORS: Lazy<[Vec<u32>; 16]> = Lazy::new(|| {
[
Vec::from([228, 48, 15, 111, 62]),
Vec::from([23, 68, 144, 134, 240, 92, 254]),
Vec::from([28, 24, 185, 166, 223, 248, 116, 255, 110, 61]),
Vec::from([175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120]),
Vec::from([41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242]),
Vec::from([
vec![228, 48, 15, 111, 62],
vec![23, 68, 144, 134, 240, 92, 254],
vec![28, 24, 185, 166, 223, 248, 116, 255, 110, 61],
vec![175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120],
vec![41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242],
vec![
156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185,
]),
Vec::from([
],
vec![
83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48, 90, 188,
]),
Vec::from([
],
vec![
15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186,
172,
]),
Vec::from([
],
vec![
52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12,
181, 184, 96, 50, 193,
]),
Vec::from([
],
vec![
211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121, 17, 138, 110,
213, 141, 136, 120, 151, 233, 168, 93, 255,
]),
Vec::from([
],
vec![
245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182, 229, 18,
2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25, 225, 98, 81, 112,
]),
Vec::from([
],
vec![
77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8, 175, 95, 100, 9,
167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, 248, 202, 69, 50, 150, 177, 226,
5, 9, 5,
]),
Vec::from([
],
vec![
245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, 191, 106,
16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138, 186, 240, 82, 44, 176,
87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19,
]),
Vec::from([
],
vec![
175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235, 150, 159,
36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232, 144, 238, 22, 150,
201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, 155, 43, 203, 107, 233, 53,
143, 46,
]),
Vec::from([
],
vec![
242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, 185, 112,
134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71, 161, 44, 147, 6, 27,
218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31, 176, 170, 4, 107, 232, 7, 94, 166, 224,
124, 86, 47, 11, 204,
]),
Vec::from([
],
vec![
220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127, 213, 136,
248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236, 66, 139, 153, 185,
202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239, 181, 241, 59, 52, 172, 25,
49, 232, 211, 189, 64, 54, 108, 153, 132, 63, 96, 103, 82, 186,
]),
],
]
});
@@ -181,7 +181,12 @@ pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String,
let mut d = block;
while d < symbolInfo.getDataCapacity() as usize {
// for (int d = block; d < symbolInfo.getDataCapacity(); d += blockCount) {
temp.push(codewords.chars().nth(d).unwrap());
temp.push(
codewords
.chars()
.nth(d)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
);
d += blockCount;
}
@@ -193,10 +198,13 @@ pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String,
let (char_index, replace_char) = sb
.char_indices()
.nth(symbolInfo.getDataCapacity() as usize + e)
.unwrap();
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
sb.replace_range(
char_index..(replace_char.len_utf8()),
&ecc.chars().nth(pos).unwrap().to_string(),
&ecc.chars()
.nth(pos)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
.to_string(),
);
// sb.setCharAt(symbolInfo.getDataCapacity() + e, ecc.charAt(pos));
pos += 1;
@@ -232,20 +240,25 @@ fn createECCBlock(codewords: &str, numECWords: usize) -> Result<String, Exceptio
// }
for i in 0..codewords.chars().count() {
// for (int i = 0; i < codewords.length(); i++) {
let m = ecc[numECWords - 1] as usize ^ codewords.chars().nth(i).unwrap() as usize;
let m = ecc[numECWords - 1] as usize
^ codewords
.chars()
.nth(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as usize;
for k in (1..numECWords).rev() {
// for (int k = numECWords - 1; k > 0; k--) {
if m != 0 && poly[k] != 0 {
ecc[k] = char::from_u32(
ecc[k - 1] as u32 ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255],
)
.unwrap();
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
} else {
ecc[k] = ecc[k - 1];
}
}
if m != 0 && poly[0] != 0 {
ecc[0] = char::from_u32(ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255]).unwrap();
ecc[0] = char::from_u32(ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255])
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
} else {
ecc[0] = 0 as char;
}

View File

@@ -121,7 +121,8 @@ fn randomize253State(codewordPosition: u32) -> String {
} else {
char::from_u32(tempVariable - 254)
}
.expect("must become a char")
// .expect("must become a char")
.unwrap_or(char::default())
.to_string()
// return (char) (tempVariable <= 254 ? tempVariable : tempVariable - 254);
}
@@ -219,21 +220,28 @@ pub fn encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup(
let mut encodingMode = ASCII_ENCODATION; //Default mode
if forceC40 {
c40Encoder.encodeMaximalC40(&mut context);
encodingMode = context.getNewEncoding().unwrap();
c40Encoder.encodeMaximalC40(&mut context)?;
encodingMode = context
.getNewEncoding()
.ok_or(Exceptions::IllegalStateException(None))?;
context.resetEncoderSignal();
}
while context.hasMoreCharacters() {
encoders[encodingMode].encode(&mut context)?;
if context.getNewEncoding().is_some() {
encodingMode = context.getNewEncoding().unwrap();
encodingMode = context
.getNewEncoding()
.ok_or(Exceptions::IllegalStateException(None))?;
context.resetEncoderSignal();
}
}
let len = context.getCodewordCount();
context.updateSymbolInfo();
let capacity = context.getSymbolInfo().unwrap().getDataCapacity();
let capacity = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity();
if len < capacity as usize
&& encodingMode != ASCII_ENCODATION
&& encodingMode != BASE256_ENCODATION
@@ -289,8 +297,10 @@ pub fn lookAheadTest(msg: &str, startpos: u32, currentMode: u32) -> usize {
let endpos = (startpos + 3).min(msg.chars().count() as u32);
for i in startpos..endpos {
// for (int i = startpos; i < endpos; i++) {
if !isNativeX12(msg.chars().nth(i as usize).unwrap()) {
return ASCII_ENCODATION;
if let Some(c) = msg.chars().nth(i as usize) {
if !isNativeX12(c) {
return ASCII_ENCODATION;
}
}
}
} else if currentMode as usize == EDIFACT_ENCODATION && newMode == EDIFACT_ENCODATION {
@@ -298,8 +308,10 @@ pub fn lookAheadTest(msg: &str, startpos: u32, currentMode: u32) -> usize {
let endpos = (startpos + 4).min(msg.chars().count() as u32);
for i in startpos..endpos {
// for (int i = startpos; i < endpos; i++) {
if !isNativeEDIFACT(msg.chars().nth(i as usize).unwrap()) {
return ASCII_ENCODATION;
if let Some(c) = msg.chars().nth(i as usize) {
if !isNativeEDIFACT(c) {
return ASCII_ENCODATION;
}
}
}
}
@@ -352,15 +364,11 @@ fn lookAheadTestIntern(msg: &str, startpos: u32, currentMode: u32) -> usize {
return C40_ENCODATION;
}
// let c = msg
// .graphemes(true)
// .nth((startpos + charsProcessed) as usize)
// .unwrap();
// let c = msg.charAt(startpos + charsProcessed);
let c = msg
.chars()
.nth((startpos + charsProcessed) as usize)
.unwrap();
let Some(c) = msg
.chars()
.nth((startpos + charsProcessed) as usize) else {
break 0;
};
charsProcessed += 1;
//step L
@@ -593,7 +601,8 @@ pub fn determineConsecutiveDigitCount(msg: &str, startpos: u32) -> u32 {
let len = msg.chars().count(); //len();
let mut idx = startpos;
// let graphemes = msg.graphemes(true);
while (idx as usize) < len && isDigit(msg.chars().nth(idx as usize).unwrap()) {
while (idx as usize) < len && isDigit(msg.chars().nth(idx as usize).unwrap_or(char::default()))
{
idx += 1;
}
idx - startpos

View File

@@ -218,7 +218,7 @@ fn addEdge(edges: &mut [Vec<Option<Rc<Edge>>>], edge: Rc<Edge>) -> Result<(), Ex
if edges[vertexIndex][edge.getEndMode()?.ordinal()].is_none()
|| edges[vertexIndex][edge.getEndMode()?.ordinal()]
.as_ref()
.unwrap()
.ok_or(Exceptions::IllegalStateException(None))?
.cachedTotalSize
> edge.cachedTotalSize
{
@@ -296,7 +296,7 @@ fn addEdges(
//not possible to unlatch a full EDF edge to something
//else
if high_level_encoder::isDigit(ch)
&& input.haveNCharacters(from as usize, 2)
&& input.haveNCharacters(from as usize, 2)?
&& high_level_encoder::isDigit(input.charAt(from as usize + 1)?)
{
// two digits ASCII encoded
@@ -344,7 +344,7 @@ fn addEdges(
}
}
if input.haveNCharacters(from as usize, 3)
if input.haveNCharacters(from as usize, 3)?
&& high_level_encoder::isNativeX12(input.charAt(from as usize)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?)
@@ -379,7 +379,7 @@ fn addEdges(
while i < 3 {
// for (i = 0; i < 3; i++) {
let pos = from + i;
if input.haveNCharacters(pos as usize, 1)
if input.haveNCharacters(pos as usize, 1)?
&& high_level_encoder::isNativeEDIFACT(input.charAt(pos as usize)?)
{
addEdge(
@@ -398,7 +398,7 @@ fn addEdges(
i += 1;
}
if i == 3
&& input.haveNCharacters(from as usize, 4)
&& input.haveNCharacters(from as usize, 4)?
&& high_level_encoder::isNativeEDIFACT(input.charAt(from as usize + 3)?)
{
addEdge(
@@ -604,9 +604,7 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
addEdges(input.clone(), &mut edges, 0, None)?;
for i in 1..=inputLength {
// for (int i = 1; i <= inputLength; i++) {
for j in 0..6 {
// for (int j = 0; j < 6; j++) {
if edges[i][j].is_some() && i < inputLength {
let edge = edges[i][j].clone();
addEdges(input.clone(), &mut edges, i as u32, edge)?;
@@ -614,7 +612,6 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
}
//optimize memory by removing edges that have been passed.
for j in 0..6 {
// for (int j = 0; j < 6; j++) {
edges[i - 1][j] = None;
}
}
@@ -622,7 +619,6 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
let mut minimalJ: i32 = -1;
let mut minimalSize = i32::MAX;
for j in 0..6 {
// for (int j = 0; j < 6; j++) {
if edges[inputLength][j].is_some() {
let edge = edges[inputLength][j].as_ref().unwrap();
let size = if (1..=3).contains(&j) {
@@ -672,12 +668,9 @@ impl Edge {
characterLength: u32,
previous: Option<Rc<Edge>>,
) -> Result<Self, Exceptions> {
// this.input = input;
// this.mode = mode;
// this.fromPosition = fromPosition;
// this.characterLength = characterLength;
// this.previous = previous;
assert!(fromPosition + characterLength <= input.length() as u32);
if fromPosition + characterLength > input.length() as u32 {
return Err(Exceptions::FormatException(None));
}
let mut size = if let Some(previous) = previous.clone() {
previous.cachedTotalSize
@@ -704,11 +697,9 @@ impl Edge {
match mode {
Mode::Ascii => {
size += 1;
if input.isECI(fromPosition).expect("bool")
if input.isECI(fromPosition)?
|| isExtendedASCII(
input
.charAt(fromPosition as usize)
.expect("char must exist)"),
input.charAt(fromPosition as usize)?,
input.getFNC1Character(),
)
{
@@ -748,9 +739,7 @@ impl Edge {
fromPosition,
mode == Mode::C40,
&mut charLen,
)
.expect("works")
* 2;
)? * 2;
}
if previousMode == Mode::Ascii || previousMode == Mode::B256 {
@@ -1382,10 +1371,9 @@ impl RXingResult {
pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) {
for i in 0..length as usize {
// for (int i = 0; i < length; i++) {
//See "B.1 253-state algorithm
let Pad_codeword_position = startPosition as usize + i;
let Pad_codeword_value = bytesAL.get(Pad_codeword_position).expect("known to exist");
let Pad_codeword_value = bytesAL.get(Pad_codeword_position).unwrap_or(&0);
let pseudo_random_number = ((149 * (Pad_codeword_position + 1)) % 255) + 1;
let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16;
bytesAL[Pad_codeword_position] = if temp_variable <= 255 {
@@ -1452,7 +1440,7 @@ impl Input {
Some(self.internal.getFNC1Character() as u8 as char)
}
}
fn haveNCharacters(&self, index: usize, n: usize) -> bool {
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions> {
self.internal.haveNCharacters(index, n)
}
fn isFNC1(&self, index: usize) -> Result<bool, Exceptions> {

View File

@@ -132,19 +132,6 @@ impl SymbolInfo {
"Cannot handle this number of data regions".to_owned(),
))),
}
// switch (dataRegions) {
// case 1:
// return 1;
// case 2:
// case 4:
// return 2;
// case 16:
// return 4;
// case 36:
// return 6;
// default:
// throw new IllegalStateException("Cannot handle this number of data regions");
// }
}
fn getVerticalDataRegions(&self) -> Result<u32, Exceptions> {
@@ -157,19 +144,6 @@ impl SymbolInfo {
"Cannot handle this number of data regions".to_owned(),
))),
}
// switch (dataRegions) {
// case 1:
// case 2:
// return 1;
// case 4:
// return 2;
// case 16:
// return 4;
// case 36:
// return 6;
// default:
// throw new IllegalStateException("Cannot handle this number of data regions");
// }
}
pub fn getSymbolDataWidth(&self) -> Result<u32, Exceptions> {
@@ -223,15 +197,6 @@ impl SymbolInfo {
pub fn getErrorLengthForInterleavedBlock(&self, _index: u32) -> u32 {
self.rsBlockError
}
// @Override
// public final String toString() {
// return (rectangular ? "Rectangular Symbol:" : "Square Symbol:") +
// " data region " + matrixWidth + 'x' + matrixHeight +
// ", symbol size " + getSymbolWidth() + 'x' + getSymbolHeight() +
// ", symbol data size " + getSymbolDataWidth() + 'x' + getSymbolDataHeight() +
// ", codewords " + dataCapacity + '+' + errorCodewords;
// }
}
impl fmt::Display for SymbolInfo {
@@ -424,7 +389,7 @@ mod tests {
assert_eq!(24, info.getSymbolWidth().expect("return"));
assert_eq!(24, info.getSymbolHeight().expect("return"));
let fixedSize = Dimension::new(26, 26).expect("new dimension");
let fixedSize = Dimension::new(26, 26);
let info = LOOKUP
.lookup_with_codewords_shape_size_fail(
35,
@@ -451,7 +416,7 @@ mod tests {
assert!(info.is_none());
let minSize = fixedSize;
let maxSize = Dimension::new(32, 32).expect("new dimension");
let maxSize = Dimension::new(32, 32);
let info = LOOKUP
.lookup_with_codewords_shape_size_fail(

View File

@@ -31,11 +31,11 @@ impl Encoder for X12Encoder {
let c = context.getCurrentChar();
context.pos += 1;
Self::encodeChar(c, &mut buffer);
Self::encodeChar(c, &mut buffer)?;
let count = buffer.chars().count();
if (count % 3) == 0 {
C40Encoder::writeNextTriplet(context, &mut buffer);
C40Encoder::writeNextTriplet(context, &mut buffer)?;
let newMode = high_level_encoder::lookAheadTest(
context.getMessage(),
@@ -58,7 +58,7 @@ impl X12Encoder {
Self(C40Encoder::new())
}
fn encodeChar(c: char, sb: &mut String) -> u32 {
fn encodeChar(c: char, sb: &mut String) -> Result<u32, Exceptions> {
match c {
'\r' => sb.push('\0'),
'*' => sb.push('\u{1}'),
@@ -70,17 +70,20 @@ impl X12Encoder {
} else if ('A'..='Z').contains(&c) {
sb.push((c as u8 - 65 + 14) as char);
} else {
high_level_encoder::illegalCharacter(c).expect("detect_illegal_character");
high_level_encoder::illegalCharacter(c)?;
}
}
}
1
Ok(1)
}
fn handleEOD(context: &mut EncoderContext, buffer: &mut str) -> Result<(), Exceptions> {
context.updateSymbolInfo();
let available =
context.getSymbolInfo().unwrap().getDataCapacity() - context.getCodewordCount() as u32;
let available = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity()
- context.getCodewordCount() as u32;
let count = buffer.chars().count();
context.pos -= count as u32;
if context.getRemainingCharacters() > 1

View File

@@ -18,8 +18,6 @@
use std::fmt;
use crate::Exceptions;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -31,8 +29,8 @@ use serde::{Deserialize, Serialize};
pub struct Dimension(usize, usize);
impl Dimension {
pub fn new(width: usize, height: usize) -> Result<Self, Exceptions> {
Ok(Self(width, height))
pub fn new(width: usize, height: usize) -> Self {
Self(width, height)
}
pub fn getWidth(&self) -> usize {

View File

@@ -68,7 +68,7 @@ impl fmt::Display for Exceptions {
Exceptions::RuntimeException(None) => write!(f, "RuntimeException"),
Exceptions::ParseException(None) => write!(f, "ParseException"),
Exceptions::ReaderDecodeException() => write!(f, "ReaderDecodeException - -"),
Exceptions::ReaderDecodeException() => write!(f, "ReaderDecodeException"),
}
}
}

View File

@@ -167,7 +167,9 @@ pub fn detect_multiple_in_file_with_hints(
file_name: &str,
hints: &mut DecodingHintDictionary,
) -> Result<Vec<RXingResult>, Exceptions> {
let img = image::open(file_name).unwrap();
let img = image::open(file_name).map_err(|e| {
Exceptions::RuntimeException(Some(format!("couldn't read {file_name}: {e}")))
})?;
let multi_format_reader = MultiFormatReader::default();
let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader);

View File

@@ -34,12 +34,8 @@ pub use barcode_format::*;
mod encode_hints;
pub use encode_hints::*;
/**
* Callback which is invoked when a possible result point (significant
* point in the barcode image such as a corner) is found.
*
* @see DecodeHintType#NEED_RESULT_POINT_CALLBACK
*/
/// Callback which is invoked when a possible result point (significant
/// point in the barcode image such as a corner) is found.
pub type RXingResultPointCallback = Rc<dyn Fn(&dyn ResultPoint)>;
mod decode_hints;

View File

@@ -104,15 +104,12 @@ impl LuminanceSource for Luma8LuminanceSource {
impl Luma8LuminanceSource {
fn reverseColumns(&mut self) {
for i in 0..self.getWidth() {
// for (int i = 0; i < C; i++)
let mut j = 0;
let mut k = self.getWidth() - 1;
while j < k {
// for (int j = 0, k = C - 1; j < k; j++, k--)
let offset_a = (self.getWidth() * i) + j;
let offset_b = (self.getWidth() * i) + k;
self.data.swap(offset_a, offset_b);
// swap(arr[j][i], arr[k][i]);
j += 1;
k -= 1;
}
@@ -121,13 +118,10 @@ impl Luma8LuminanceSource {
fn transpose(&mut self) {
for i in 0..self.getHeight() {
// for (int i = 0; i < R; i++)
for j in i..self.getWidth() {
// for (int j = i; j < C; j++)
let offset_a = (self.getWidth() * i) + j;
let offset_b = (self.getWidth() * j) + i;
self.data.swap(offset_a, offset_b);
// swap(arr[i][j], arr[j][i]);
}
}
}

View File

@@ -162,7 +162,9 @@ fn getPostCode3(bytes: &[u8]) -> String {
let mut graphemes = SETS[0].graphemes(true);
for p3bytes in &POSTCODE_3_BYTES {
// for (byte[] p3bytes : POSTCODE_3_BYTES) {
sb.push_str(graphemes.nth(getInt(bytes, p3bytes) as usize).unwrap());
if let Some(c) = graphemes.nth(getInt(bytes, p3bytes) as usize) {
sb.push_str(c);
}
}
sb
}
@@ -178,7 +180,7 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
// for i in start..(start+len) {
// for (int i = start; i < start + len; i++) {
let mut set_graphemes = SETS[set].graphemes(true);
let c = set_graphemes.nth(bytes[i as usize] as usize).unwrap();
let Some(c) = set_graphemes.nth(bytes[i as usize] as usize) else { break; };
match c {
LATCHA => {
set = 0;
@@ -234,11 +236,6 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
}
String::from(sb.trim_end_matches(PAD))
// while sb.len() > 0 && sb.chars().nth(sb.len() - 1).unwrap() == PAD {
// sb.setLength(sb.length() - 1);
// }
// sb
}
fn subtract_two_single_char_strings(str1: &str, str2: &str) -> usize {

View File

@@ -97,16 +97,13 @@ fn correctErrors(
// First read into an array of ints
let mut codewordsInts = vec![0i32; (codewords / divisor) as usize];
for i in 0..codewords {
// for (int i = 0; i < codewords; i++) {
if (mode == ALL) || (i % 2 == (mode - 1)) {
codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32;
}
}
// try {
RS_DECODER.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?;
// } catch (ReedSolomonException ignored) {
// throw ChecksumException.getChecksumInstance();
// }
// Copy back into array of bytes -- only need to worry about the bytes that were data
// We don't care about errors in the error-correction codewords
for i in 0..dataCodewords {

View File

@@ -155,8 +155,8 @@ impl Circle<'_> {
*length_set = (length, rotation, points);
}
lengths.sort_by_key(|e| e.0);
let major_axis = lengths.last().unwrap();
let minor_axis = lengths.first().unwrap();
let Some(major_axis) = lengths.last() else {return (false, (0,0),0,0,0)};
let Some(minor_axis) = lengths.first() else {return (false, (0,0),0,0,0)};
// // find foci
let linear_eccentricity = ((major_axis.0 / 2).pow(2) - (minor_axis.0 / 2).pow(2)).sqrt();
@@ -348,8 +348,8 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
let [tl, bl, tr, br] = &symbol_box.0;
let target_width = MathUtils::distance_float(tl.0, tl.1, tr.0, tr.1);
let target_height = MathUtils::distance_float(br.0, br.1, tr.0, tr.1);
let target_width = MathUtils::distance(tl.0, tl.1, tr.0, tr.1);
let target_height = MathUtils::distance(br.0, br.1, tr.0, tr.1);
// let target_width = (tr.0 - tl.0).round().abs() as u32;
// let target_height = (br.1 - tr.1).round().abs() as u32;
@@ -1045,12 +1045,16 @@ fn compare_circle(a: &Circle, b: &Circle) -> std::cmp::Ordering {
let a_var = a.calculate_circle_variance();
let b_var = b.calculate_circle_variance();
a_var.partial_cmp(&b_var).unwrap()
a_var
.partial_cmp(&b_var)
.unwrap_or(std::cmp::Ordering::Equal)
}
/// Read appropriate bits from a bitmatrix for the maxicode decoder
pub fn read_bits(image: &BitMatrix) -> Result<BitMatrix, Exceptions> {
let enclosingRectangle = image.getEnclosingRectangle().unwrap();
let enclosingRectangle = image
.getEnclosingRectangle()
.ok_or(Exceptions::NotFoundException(None))?;
let left = enclosingRectangle[0];
let top = enclosingRectangle[1];

View File

@@ -129,7 +129,8 @@ impl MaxiCodeReader {
return Err(Exceptions::NotFoundException(None));
}
let enclosingRectangle = enclosingRectangleOption.unwrap();
let enclosingRectangle =
enclosingRectangleOption.ok_or(Exceptions::NotFoundException(None))?;
let left = enclosingRectangle[0];
let top = enclosingRectangle[1];

View File

@@ -46,24 +46,21 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
let halfWidth = width / 2;
let halfHeight = height / 2;
// try {
let attempt = self
.0
.decode_with_hints(&mut image.crop(0, 0, halfWidth, halfHeight), hints);
// No need to call makeAbsolute as results will be relative to original top left here
// This is a match because only NotFoundExceptions should be ignored
match attempt {
// Ok() => return attempt,
Err(Exceptions::NotFoundException(_)) => {}
_ => return attempt,
}
// } catch (NotFoundException re) {
// continue
// }
// try {
let result = self
.0
.decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
// This is a match because only NotFoundExceptions should be ignored
match result {
Ok(res) => {
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0);
@@ -72,15 +69,11 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
Err(Exceptions::NotFoundException(_)) => {}
_ => return result,
}
// makeAbsolute(result.getRXingResultPoints(), halfWidth, 0);
// return result;
// } catch (NotFoundException re) {
// continue
// }
let result = self
.0
.decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints);
// This is a match because only NotFoundExceptions should be ignored
match result {
Ok(res) => {
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32);
@@ -89,18 +82,12 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
Err(Exceptions::NotFoundException(_)) => {}
_ => return result,
}
// try {
// RXingResult result = delegate.decode(image.crop(0, halfHeight, halfWidth, halfHeight), hints);
// makeAbsolute(result.getRXingResultPoints(), 0, halfHeight);
// return result;
// } catch (NotFoundException re) {
// // continue
// }
let result = self.0.decode_with_hints(
&mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
hints,
);
// This is a match because only NotFoundExceptions should be ignored
match result {
Ok(res) => {
let points = Self::makeAbsolute(
@@ -114,14 +101,6 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
_ => return result,
}
// try {
// RXingResult result = delegate.decode(image.crop(halfWidth, halfHeight, halfWidth, halfHeight), hints);
// makeAbsolute(result.getRXingResultPoints(), halfWidth, halfHeight);
// return result;
// } catch (NotFoundException re) {
// // continue
// }
let quarterWidth = halfWidth / 2;
let quarterHeight = halfHeight / 2;
let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
@@ -150,19 +129,22 @@ impl<T: Reader> ByQuadrantReader<T> {
leftOffset: f32,
topOffset: f32,
) -> Vec<RXingResultPoint> {
let mut result = Vec::new();
if !points.is_empty() {
for relative in points {
// for (int i = 0; i < points.length; i++) {
// let relative = points[i];
// if relative != null {
result.push(RXingResultPoint::new(
relative.getX() + leftOffset,
relative.getY() + topOffset,
));
// }
}
}
result
// let mut result = Vec::new();
// if !points.is_empty() {
// // for relative in points {
// // result.push(RXingResultPoint::new(
// // relative.getX() + leftOffset,
// // relative.getY() + topOffset,
// // ));
// // }
// }
// result
points
.iter()
.map(|relative| {
RXingResultPoint::new(relative.getX() + leftOffset, relative.getY() + topOffset)
})
.collect()
}
}

View File

@@ -182,17 +182,24 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
if oldRXingResultPoints.is_empty() {
return result;
}
let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len()); //new RXingResultPoint[oldRXingResultPoints.length];
for oldPoint in oldRXingResultPoints {
// for (int i = 0; i < oldRXingResultPoints.length; i++) {
// RXingResultPoint oldPoint = oldRXingResultPoints[i];
// if (oldPoint != null) {
newRXingResultPoints.push(RXingResultPoint::new(
oldPoint.getX() + xOffset as f32,
oldPoint.getY() + yOffset as f32,
));
// }
}
let newRXingResultPoints: Vec<RXingResultPoint> = oldRXingResultPoints
.iter()
.map(|oldPoint| {
RXingResultPoint::new(
oldPoint.getX() + xOffset as f32,
oldPoint.getY() + yOffset as f32,
)
})
.collect();
// let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len());
// for oldPoint in oldRXingResultPoints {
// newRXingResultPoints.push(RXingResultPoint::new(
// oldPoint.getX() + xOffset as f32,
// oldPoint.getY() + yOffset as f32,
// ));
// }
let mut newRXingResult = RXingResult::new_complex(
result.getText(),
result.getRawBytes().clone(),

View File

@@ -61,11 +61,6 @@ impl<'a> MultiDetector<'_> {
if let Ok(potential) = self.0.processFinderPatternInfo(info) {
result.push(potential);
}
// try {
// result.add(processFinderPatternInfo(info));
// } catch (ReaderException e) {
// // ignore
// }
}
Ok(result)

View File

@@ -56,9 +56,9 @@ const DIFF_MODSIZE_CUTOFF: f32 = 0.5_f32;
* @author Sean Owen
* @author Hannes Erven
*/
pub struct MultiFinderPatternFinder(FinderPatternFinder);
pub struct MultiFinderPatternFinder<'a>(FinderPatternFinder<'a>);
impl MultiFinderPatternFinder {
impl<'a> MultiFinderPatternFinder<'_> {
// private static final FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0];
// private static final FinderPattern[] EMPTY_FP_ARRAY = new FinderPattern[0];
// private static final FinderPattern[][] EMPTY_FP_2D_ARRAY = new FinderPattern[0][];
@@ -66,9 +66,12 @@ impl MultiFinderPatternFinder {
// TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for
// since it limits the number of regions to decode
pub fn new(image: &BitMatrix, resultPointCallback: Option<RXingResultPointCallback>) -> Self {
Self(FinderPatternFinder::with_callback(
image.clone(),
pub fn new(
image: &'a BitMatrix,
resultPointCallback: Option<RXingResultPointCallback>,
) -> MultiFinderPatternFinder<'a> {
MultiFinderPatternFinder(FinderPatternFinder::with_callback(
image,
resultPointCallback,
))
}
@@ -80,7 +83,7 @@ impl MultiFinderPatternFinder {
* @throws NotFoundException if 3 such finder patterns do not exist
*/
fn selectMultipleBestPatterns(&self) -> Result<Vec<[FinderPattern; 3]>, Exceptions> {
let mut possibleCenters = Vec::new(); //new ArrayList<>();
let mut possibleCenters = Vec::new();
for fp in self.0.getPossibleCenters() {
if fp.getCount() >= 2 {
possibleCenters.push(*fp);
@@ -125,19 +128,18 @@ impl MultiFinderPatternFinder {
* So, if the layout seems right, lets have the decoder try to decode.
*/
let mut results = Vec::new(); //new ArrayList<>(); // holder for the results
let mut results = Vec::new(); // holder for the results
for i1 in 0..(size - 2) {
// for (int i1 = 0; i1 < (size - 2); i1++) {
let Some(p1) = possibleCenters.get(i1)else {
continue;
};
let Some(p1) = possibleCenters.get(i1) else {
continue;
};
for i2 in (i1 + 1)..(size - 1) {
// for (int i2 = i1 + 1; i2 < (size - 1); i2++) {
let Some(p2) = possibleCenters.get(i2) else {
continue;
};
continue;
};
// Compare the expected module sizes; if they are really off, skip
let vModSize12 = (p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize())
@@ -151,9 +153,9 @@ impl MultiFinderPatternFinder {
for i3 in (i2 + 1)..size {
// for (int i3 = i2 + 1; i3 < size; i3++) {
let Some( p3) = possibleCenters.get(i3)else {
continue;
};
let Some( p3) = possibleCenters.get(i3) else {
continue;
};
// Compare the expected module sizes; if they are really off, skip
let vModSize23 = (p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize())

View File

@@ -58,18 +58,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
hints,
)?;
let mut points = detectorRXingResult.getPoints().to_vec();
// If the code was mirrored: swap the bottom-left and the top-right points.
if let Some(other) = decoderRXingResult.getOther() {
if other.is::<QRCodeDecoderMetaData>() {
(other
.downcast::<QRCodeDecoderMetaData>()
.expect("must downcast to QRCodeDecoderMetaData"))
.applyMirroredCorrection(&mut points);
if let Some(oth) = other.downcast_ref::<QRCodeDecoderMetaData>() {
oth.applyMirroredCorrection(&mut points);
}
}
// if (decoderRXingResult.getOther() instanceof QRCodeDecoderMetaData) {
// ((QRCodeDecoderMetaData) decoderRXingResult.getOther()).applyMirroredCorrection(points);
// }
let mut result = RXingResult::new(
decoderRXingResult.getText(),
decoderRXingResult.getRawBytes().clone(),
@@ -77,14 +73,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
BarcodeFormat::QR_CODE,
);
let byteSegments = decoderRXingResult.getByteSegments();
// if (byteSegments != null) {
result.putMetadata(
RXingResultMetadataType::BYTE_SEGMENTS,
RXingResultMetadataValue::ByteSegments(byteSegments.clone()),
);
// }
let ecLevel = decoderRXingResult.getECLevel();
// if (ecLevel != null) {
result.putMetadata(
RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
RXingResultMetadataValue::ErrorCorrectionLevel(ecLevel.to_owned()),
@@ -115,7 +111,7 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
// ignore and continue
continue;
} else {
return Err(output.err().unwrap());
return Err(output.err().unwrap_or(Exceptions::NotFoundException(None)));
}
}

View File

@@ -73,11 +73,9 @@ impl Reader for MultiFormatReader {
}
fn reset(&mut self) {
// if (readers != null) {
for reader in self.readers.iter_mut() {
reader.reset();
}
// }
}
}
@@ -109,10 +107,13 @@ impl MultiFormatReader {
* @param hints The set of hints to use for subsequent calls to decode(image)
*/
pub fn set_ints(&mut self, hints: &DecodingHintDictionary) {
self.hints = hints.clone(); // {hint} else {HashMap::new()};
self.hints = hints.clone();
let tryHarder = matches!(
self.hints.get(&DecodeHintType::TRY_HARDER),
Some(DecodeHintValue::TryHarder(true))
);
let tryHarder = self.hints.contains_key(&DecodeHintType::TRY_HARDER);
//@SuppressWarnings("unchecked")
let formats = hints.get(&DecodeHintType::POSSIBLE_FORMATS);
let mut readers: Vec<Box<dyn Reader>> = Vec::new();
if let Some(DecodeHintValue::PossibleFormats(formats)) = formats {
@@ -161,48 +162,33 @@ impl MultiFormatReader {
readers.push(Box::<AztecReader>::default());
readers.push(Box::<PDF417Reader>::default());
readers.push(Box::<MaxiCodeReader>::default());
// unimplemented!("");
if tryHarder {
readers.push(Box::new(MultiFormatOneDReader::new(hints)));
}
}
self.readers = readers; //Vec::new(); //readers.toArray(EMPTY_READER_ARRAY);
self.readers = readers;
}
pub fn decode_internal(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions> {
if !self.readers.is_empty() {
for reader in self.readers.iter_mut() {
// I'm not sure how to model this in rust
// if (Thread.currentThread().isInterrupted()) {
// throw NotFoundException.getNotFoundInstance();
// }
//try {
let res = reader.decode_with_hints(image, &self.hints);
if res.is_ok() {
return res;
}
//} catch (ReaderException re) {
// continue
//}
}
if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) {
if matches!(
self.hints.get(&DecodeHintType::ALSO_INVERTED),
Some(DecodeHintValue::AlsoInverted(true))
) {
// Calling all readers again with inverted image
// let mut image = image.clone();
image.getBlackMatrixMut().flip_self();
for reader in self.readers.iter_mut() {
// if (Thread.currentThread().isInterrupted()) {
// throw NotFoundException.getNotFoundInstance();
// }
let res = reader.decode_with_hints(image, &self.hints);
if res.is_ok() {
return res;
}
// try {
// return reader.decode(image, hints);
// } catch (ReaderException re) {
// // continue
// }
}
}
}

View File

@@ -80,66 +80,3 @@ impl Writer for MultiFormatWriter {
writer.encode_with_hints(contents, format, width, height, hints)
}
}
// @Override
// public BitMatrix encode(String contents,
// BarcodeFormat format,
// int width,
// int height) throws WriterException {
// return encode(contents, format, width, height, null);
// }
// @Override
// public BitMatrix encode(String contents,
// BarcodeFormat format,
// int width, int height,
// Map<EncodeHintType,?> hints) throws WriterException {
// Writer writer;
// switch (format) {
// case EAN_8:
// writer = new EAN8Writer();
// break;
// case UPC_E:
// writer = new UPCEWriter();
// break;
// case EAN_13:
// writer = new EAN13Writer();
// break;
// case UPC_A:
// writer = new UPCAWriter();
// break;
// case QR_CODE:
// writer = new QRCodeWriter();
// break;
// case CODE_39:
// writer = new Code39Writer();
// break;
// case CODE_93:
// writer = new Code93Writer();
// break;
// case CODE_128:
// writer = new Code128Writer();
// break;
// case ITF:
// writer = new ITFWriter();
// break;
// case PDF_417:
// writer = new PDF417Writer();
// break;
// case CODABAR:
// writer = new CodaBarWriter();
// break;
// case DATA_MATRIX:
// writer = new DataMatrixWriter();
// break;
// case AZTEC:
// writer = new AztecWriter();
// break;
// default:
// throw new IllegalArgumentException("No encoder available for format " + format);
// }
// return writer.encode(contents, format, width, height, hints);
// }
// }

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More