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, RXingResultPoint,
}; };
use super::{decoder, AztecDetectorResult::AztecDetectorRXingResult}; use super::{aztec_detector_result::AztecDetectorRXingResult, decoder};
/** /**
* Tests {@link 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 // Zooms a bit matrix so that each bit is factor x factor
fn make_larger(input: &BitMatrix, factor: u32) -> BitMatrix { fn make_larger(input: &BitMatrix, factor: u32) -> BitMatrix {
let width = input.getWidth(); 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 inputY in 0..width {
// for (int inputY = 0; inputY < width; inputY++) { // for (int inputY = 0; inputY < width; inputY++) {
for inputX in 0..width { 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 // Rotates a square BitMatrix to the right by 90 degrees
fn rotate_right(input: &BitMatrix) -> BitMatrix { fn rotate_right(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); 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 x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { 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 // matrix to the right, and then flipping it left-to-right
fn transpose(input: &BitMatrix) -> BitMatrix { fn transpose(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); 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 x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { for y in 0..width {
@@ -248,7 +248,7 @@ fn transpose(input: &BitMatrix) -> BitMatrix {
fn clone(input: &BitMatrix) -> BitMatrix { fn clone(input: &BitMatrix) -> BitMatrix {
let width = input.getWidth(); 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 x in 0..width {
// for (int x = 0; x < width; x++) { // for (int x = 0; x < width; x++) {
for y in 0..width { for y in 0..width {

View File

@@ -20,10 +20,10 @@ use encoding::EncodingRef;
use crate::{ use crate::{
aztec::{ aztec::{
aztec_detector_result::AztecDetectorRXingResult,
decoder, decoder,
encoder::HighLevelEncoder, encoder::HighLevelEncoder,
shared_test_methods::{stripSpace, toBitArray, toBooleanArray}, shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
AztecDetectorResult::AztecDetectorRXingResult,
}, },
BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint, 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) { fn testStuffBits(wordSize: usize, bits: &str, expected: &str) {
let indata = toBitArray(bits); let indata = toBitArray(bits);
let stuffed = aztec_encoder::stuffBits(&indata, wordSize); let stuffed = aztec_encoder::stuffBits(&indata, wordSize).unwrap();
assert_eq!( assert_eq!(
stripSpace(expected), stripSpace(expected),
stripSpace(&stuffed.to_string()), stripSpace(&stuffed.to_string()),

View File

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

View File

@@ -130,8 +130,4 @@ impl Reader for AztecReader {
Ok(result) 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 charset = None; // Do not add any ECI code by default
let mut ecc_percent = aztec_encoder::DEFAULT_EC_PERCENT; let mut ecc_percent = aztec_encoder::DEFAULT_EC_PERCENT;
let mut layers = aztec_encoder::DEFAULT_AZTEC_LAYERS; let mut layers = aztec_encoder::DEFAULT_AZTEC_LAYERS;
if hints.contains_key(&EncodeHintType::CHARACTER_SET) { if let Some(EncodeHintValue::CharacterSet(cset_name)) =
if let EncodeHintValue::CharacterSet(cset_name) = hints hints.get(&EncodeHintType::CHARACTER_SET)
.get(&EncodeHintType::CHARACTER_SET) {
.expect("already knonw presence") if cset_name.to_lowercase() != "iso-8859-1" {
{ charset = Some(
if cset_name != "iso-8859-1" { encoding::label::encoding_from_whatwg_label(cset_name)
charset = Some(encoding::label::encoding_from_whatwg_label(cset_name).unwrap()); .ok_or(Exceptions::IllegalArgumentException(None))?,
} );
// 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());
} }
// charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
} }
if hints.contains_key(&EncodeHintType::ERROR_CORRECTION) { if let Some(EncodeHintValue::ErrorCorrection(ecc_level)) =
if let EncodeHintValue::ErrorCorrection(ecc_level) = hints hints.get(&EncodeHintType::ERROR_CORRECTION)
.get(&EncodeHintType::ERROR_CORRECTION) {
.expect("key exists") ecc_percent = ecc_level.parse().unwrap_or(23);
{
ecc_percent = ecc_level.parse().expect("should convert to int");
}
// eccPercent = Integer.parseInt(hints.get(EncodeHintType::ERROR_CORRECTION).toString());
} }
if hints.contains_key(&EncodeHintType::AZTEC_LAYERS) { if let Some(EncodeHintValue::AztecLayers(az_layers)) =
if let EncodeHintValue::AztecLayers(az_layers) = hints hints.get(&EncodeHintType::AZTEC_LAYERS)
.get(&EncodeHintType::AZTEC_LAYERS) {
.expect("key exists") layers = *az_layers;
{
layers = *az_layers;
}
// layers = Integer.parseInt(hints.get(EncodeHintType.AZTEC_LAYERS).toString());
} }
encode( encode(
contents, contents,
@@ -121,9 +110,7 @@ fn encode(
fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMatrix, Exceptions> { fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMatrix, Exceptions> {
let input = code.getMatrix(); let input = code.getMatrix();
// if input == null {
// throw new IllegalStateException();
// }
let input_width = input.getWidth(); let input_width = input.getWidth();
let input_height = input.getHeight(); let input_height = input.getHeight();
let output_width = width.max(input_width); let output_width = width.max(input_width);
@@ -152,13 +139,5 @@ fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMat
input_y += 1; input_y += 1;
output_y += multiple 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) Ok(output)
} }

View File

@@ -24,7 +24,7 @@ use crate::{
exceptions::Exceptions, 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 * <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( result.push_str(
&encdr &encdr
.decode(&decoded_bytes, encoding::DecoderTrap::Strict) .decode(&decoded_bytes, encoding::DecoderTrap::Strict)
.unwrap(), .map_err(|a| Exceptions::IllegalStateException(Some(a.to_string())))?,
); );
decoded_bytes.clear(); 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. // That's including when that mode is a shift.
// Our test case dlusbs.png for issue #642 exercises that. // 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 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()); shift_table = getTable(
if str.chars().nth(6).unwrap() == 'L' { str.chars()
.nth(5)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
);
if str
.chars()
.nth(6)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
== 'L'
{
latch_table = shift_table; latch_table = shift_table;
} }
} else { } else {

View File

@@ -26,7 +26,7 @@ use crate::{
RXingResultPoint, ResultPoint, RXingResultPoint, ResultPoint,
}; };
use super::AztecDetectorResult::AztecDetectorRXingResult; use super::aztec_detector_result::AztecDetectorRXingResult;
const EXPECTED_CORNER_BITS: [u32; 4] = [ const EXPECTED_CORNER_BITS: [u32; 4] = [
0xee0, // 07340 XXX .XX X.. ... 0xee0, // 07340 XXX .XX X.. ...
@@ -731,11 +731,11 @@ impl<'a> Detector<'_> {
} }
fn distance_points(a: &Point, b: &Point) -> f32 { 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 { 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 { 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); total_bits_in_layer_var = total_bits_in_layer(layers, compact);
word_size = WORD_SIZE[layers as usize]; word_size = WORD_SIZE[layers as usize];
let usable_bits_in_layers = total_bits_in_layer_var - (total_bits_in_layer_var % word_size); 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 { if stuffed_bits.getSize() as u32 + ecc_bits > usable_bits_in_layers {
return Err(Exceptions::IllegalArgumentException(Some( return Err(Exceptions::IllegalArgumentException(Some(
"Data to large for user specified layer".to_owned(), "Data to large for user specified layer".to_owned(),
@@ -222,7 +222,7 @@ pub fn encode_bytes_with_charset(
// wordSize has changed // wordSize has changed
if stuffed_bits.getSize() == 0 || word_size != WORD_SIZE[layers as usize] { if stuffed_bits.getSize() == 0 || word_size != WORD_SIZE[layers as usize] {
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 = let usable_bits_in_layers =
total_bits_in_layer_var - (total_bits_in_layer_var % word_size); 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; 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()); // dbg!(matrix.to_string());
@@ -307,13 +307,9 @@ pub fn encode_bytes_with_charset(
rowOffset += rowSize * 8; rowOffset += rowSize * 8;
} }
// dbg!(matrix.to_string());
// draw mode message // draw mode message
drawModeMessage(&mut matrix, compact, matrixSize, modeMessage); drawModeMessage(&mut matrix, compact, matrixSize, modeMessage);
// dbg!(matrix.to_string());
// draw alignment marks // draw alignment marks
if compact { if compact {
drawBullsEye(&mut matrix, matrixSize / 2, 5); drawBullsEye(&mut matrix, matrixSize / 2, 5);
@@ -385,20 +381,12 @@ pub fn generateModeMessage(
) -> Result<BitArray, Exceptions> { ) -> Result<BitArray, Exceptions> {
let mut mode_message = BitArray::new(); let mut mode_message = BitArray::new();
if compact { if compact {
mode_message mode_message.appendBits(layers - 1, 2)?;
.appendBits(layers - 1, 2) mode_message.appendBits(messageSizeInWords - 1, 6)?;
.expect("should append");
mode_message
.appendBits(messageSizeInWords - 1, 6)
.expect("should append");
mode_message = generateCheckWords(&mode_message, 28, 4)?; mode_message = generateCheckWords(&mode_message, 28, 4)?;
} else { } else {
mode_message mode_message.appendBits(layers - 1, 5)?;
.appendBits(layers - 1, 5) mode_message.appendBits(messageSizeInWords - 1, 11)?;
.expect("should append");
mode_message
.appendBits(messageSizeInWords - 1, 11)
.expect("should append");
mode_message = generateCheckWords(&mode_message, 40, 4)?; mode_message = generateCheckWords(&mode_message, 40, 4)?;
} }
Ok(mode_message) Ok(mode_message)
@@ -407,7 +395,7 @@ pub fn generateModeMessage(
fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeMessage: BitArray) { fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeMessage: BitArray) {
let center = matrixSize / 2; let center = matrixSize / 2;
if compact { if compact {
for i in 0..7usize { for i in 0..7_usize {
// for (int i = 0; i < 7; i++) { // for (int i = 0; i < 7; i++) {
let offset = (center as usize - 3 + i) as u32; let offset = (center as usize - 3 + i) as u32;
if modeMessage.get(i) { if modeMessage.get(i) {
@@ -424,7 +412,7 @@ fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeM
} }
} }
} else { } else {
for i in 0..10usize { for i in 0..10_usize {
// for (int i = 0; i < 10; i++) { // for (int i = 0; i < 10; i++) {
let offset = (center as usize - 5 + i + i / 5) as u32; let offset = (center as usize - 5 + i + i / 5) as u32;
if modeMessage.get(i) { if modeMessage.get(i) {
@@ -450,13 +438,13 @@ fn generateCheckWords(
) -> Result<BitArray, Exceptions> { ) -> Result<BitArray, Exceptions> {
// bitArray is guaranteed to be a multiple of the wordSize, so no padding needed // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
let message_size_in_words = bitArray.getSize() / wordSize; 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 total_words = totalBits / wordSize;
let mut message_words = bitsToWords(bitArray, wordSize, total_words); let mut message_words = bitsToWords(bitArray, wordSize, total_words);
rs.encode(&mut message_words, total_words - message_size_in_words)?; rs.encode(&mut message_words, total_words - message_size_in_words)?;
let start_pad = totalBits % wordSize; let start_pad = totalBits % wordSize;
let mut message_bits = BitArray::new(); 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 message_word in message_words {
// for (int messageWord : messageWords) { // for (int messageWord : messageWords) {
message_bits.appendBits(message_word as u32, wordSize)? message_bits.appendBits(message_word as u32, wordSize)?
@@ -498,23 +486,9 @@ fn getGF(wordSize: usize) -> Result<GenericGFRef, Exceptions> {
"Unsupported word size {wordSize}" "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 mut out = BitArray::new();
let n = bits.getSize() as isize; let n = bits.getSize() as isize;
@@ -530,21 +504,20 @@ pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
} }
} }
if (word & mask) == mask { if (word & mask) == mask {
out.appendBits(word & mask, word_size).unwrap(); out.appendBits(word & mask, word_size)?;
i -= 1; i -= 1;
} else if (word & mask) == 0 { } else if (word & mask) == 0 {
out.appendBits(word | 1, word_size).unwrap(); out.appendBits(word | 1, word_size)?;
i -= 1; i -= 1;
} else { } else {
out.appendBits(word, word_size).unwrap(); out.appendBits(word, word_size)?;
} }
i += word_size as isize; i += word_size as isize;
} }
out Ok(out)
} }
fn total_bits_in_layer(layers: u32, compact: bool) -> u32 { fn total_bits_in_layer(layers: u32, compact: bool) -> u32 {
((if compact { 88 } else { 112 }) + 16 * layers) * layers ((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 std::fmt;
use crate::common::BitArray; use crate::{common::BitArray, Exceptions};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct BinaryShiftToken { 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; let bsbc = self.binary_shift_byte_count as usize;
for i in 0..bsbc { for i in 0..bsbc {
// for (int i = 0; i < bsbc; i++) { // for (int i = 0; i < bsbc; i++) {
if i == 0 || (i == 31 && bsbc <= 62) { if i == 0 || (i == 31 && bsbc <= 62) {
// We need a header before the first character, and before // We need a header before the first character, and before
// character 31 when the total byte code is <= 62 // 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 { if bsbc > 62 {
bit_array.appendBits(bsbc as u32 - 31, 16).unwrap(); bit_array.appendBits(bsbc as u32 - 31, 16)?;
} else if i == 0 { } else if i == 0 {
// 1 <= binaryShiftByteCode <= 62 // 1 <= binaryShiftByteCode <= 62
bit_array.appendBits(bsbc.min(31) as u32, 5).unwrap(); bit_array.appendBits(bsbc.min(31) as u32, 5)?;
} else { } else {
// 32 <= binaryShiftCount <= 62 and i == 31 // 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 bit_array.appendBits(text[self.binary_shift_start as usize + i].into(), 8)?;
.appendBits(text[self.binary_shift_start as usize + i].into(), 8)
.expect("should never fail to append");
} }
Ok(())
} }
// @Override // @Override

View File

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

View File

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

View File

@@ -85,9 +85,11 @@ impl State {
))); )));
// throw new IllegalArgumentException("ECI code must be between 0 and 999999"); // throw new IllegalArgumentException("ECI code must be between 0 and 999999");
} else { } else {
let eci_digits = encoding::all::ISO_8859_1 let Ok(eci_digits) = encoding::all::ISO_8859_1
.encode(&format!("{eci}"), encoding::EncoderTrap::Strict) .encode(&format!("{eci}"), encoding::EncoderTrap::Strict)
.unwrap(); else {
return Err(Exceptions::IllegalArgumentException(None))
};
// let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1); // let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1);
token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits
for eci_digit in &eci_digits { for eci_digit in &eci_digits {
@@ -205,7 +207,7 @@ impl State {
new_mode_bit_count <= other.bit_count 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 mut symbols = Vec::new();
let tok = self.endBinaryShift(text.len() as u32).token; let tok = self.endBinaryShift(text.len() as u32).token;
for tkn in tok.into_iter() { for tkn in tok.into_iter() {
@@ -223,22 +225,22 @@ impl State {
for symbol in symbols.into_iter().rev() { for symbol in symbols.into_iter().rev() {
// for i in (0..symbols.len()).rev() { // for i in (0..symbols.len()).rev() {
// for (int i = symbols.size() - 1; i >= 0; i--) { // 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 { fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
if binary_shift_byte_count > 62 { 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. * limitations under the License.
*/ */
use crate::common::BitArray; use crate::{common::BitArray, Exceptions};
use super::{BinaryShiftToken, SimpleToken}; use super::{BinaryShiftToken, SimpleToken};
@@ -26,12 +26,14 @@ pub enum TokenType {
} }
impl 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]; // let token = &self.tokens[self.current_pointer];
match self { match self {
TokenType::Simple(a) => a.appendTo(bit_array, text), TokenType::Simple(a) => a.appendTo(bit_array, text),
TokenType::BinaryShift(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 { impl Default for Token {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()

View File

@@ -1,4 +1,4 @@
mod AztecDetectorResult; mod aztec_detector_result;
mod aztec_reader; mod aztec_reader;
mod aztec_writer; mod aztec_writer;
pub mod decoder; 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 * 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. * 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). * @return The 2D array of bits for the image (true means black).
* @throws NotFoundException if image can't be binarized to make a matrix * @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 * 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. * 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). * @return The 2D array of bits for the image (true means black).
* @throws NotFoundException if image can't be binarized to make a matrix * @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 * 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. * 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 left The left coordinate, which must be in [0,getWidth())
* @param top The top coordinate, which must be in [0,getHeight()) * @param top The top coordinate, which must be in [0,getHeight())
* @param width The width of the rectangle to crop. * @param width The width of the rectangle to crop.
@@ -140,10 +146,6 @@ impl BinaryBitmap {
self.binarizer self.binarizer
.createBinarizer(newSource.expect("new lum source expected")), .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. * Returns a new object with rotated image data by 90 degrees counterclockwise.
* Only callable if {@link #isRotateSupported()} is true. * Only callable if {@link #isRotateSupported()} is true.
* *
* Panics if the binarizer cannot be created.
*
* @return A rotated version of this object. * @return A rotated version of this object.
*/ */
pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap { pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap {
@@ -165,19 +169,14 @@ impl BinaryBitmap {
self.binarizer self.binarizer
.createBinarizer(newSource.expect("new lum source expected")), .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. * Returns a new object with rotated image data by 45 degrees counterclockwise.
* Only callable if {@link #isRotateSupported()} is true. * Only callable if {@link #isRotateSupported()} is true.
* *
* Panics if the binarizer cannot be created.
*
* @return A rotated version of this object. * @return A rotated version of this object.
*/ */
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap { pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {

View File

@@ -54,46 +54,6 @@ impl BufferedImageLuminanceSource {
width: usize, width: usize,
height: usize, height: usize,
) -> Self { ) -> 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 img = image.to_rgba8();
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(image.width(), image.height()); 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 { Self {
image: Rc::new(DynamicImage::from(raster)), image: Rc::new(DynamicImage::from(raster)),
width, width,
@@ -146,14 +83,6 @@ impl BufferedImageLuminanceSource {
left, left,
top, 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> { fn getRow(&self, y: usize) -> Vec<u8> {
let width = self.getWidth(); // - self.left as usize; let width = self.getWidth(); // - self.left as usize;
let pixels: Vec<u8> = self let pixels: Vec<u8> = || -> Option<Vec<u8>> {
.image Some(
.as_luma8() self.image
.unwrap() .as_luma8()?
.rows() .rows()
.nth(y + self.top as usize) .nth(y + self.top as usize)?
.unwrap() .skip(self.left as usize)
.skip(self.left as usize) .take(width)
.take(width) .map(|&p| p.0[0])
.map(|&p| p.0[0]) .collect(),
.collect(); )
}()
// The underlying raster of image consists of bytes with the luminance values .unwrap_or_default();
// row[..width].clone_from_slice(&pixels[..]);
pixels pixels
} }
@@ -221,7 +149,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
} }
fn invert(&mut self) { fn invert(&mut self) {
// self.image.borrow_mut().invert();
let mut img = (*self.image).clone(); let mut img = (*self.image).clone();
img.invert(); img.invert();
self.image = Rc::new(img); self.image = Rc::new(img);
@@ -238,18 +165,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
width: usize, width: usize,
height: usize, height: usize,
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> { ) -> 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 { 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(), image: self.image.clone(),
width, width,
height, height,
@@ -265,9 +181,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
fn rotateCounterClockwise( fn rotateCounterClockwise(
&self, &self,
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> { ) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> {
// Ok(Box::new(BufferedImageLuminanceSource::new(
// self.image.rotate270(),
// )))
let img = self.image.rotate270(); let img = self.image.rotate270();
Ok(Box::new(Self { Ok(Box::new(Self {
width: img.width() as usize, width: img.width() as usize,
@@ -290,7 +203,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
let new_img = DynamicImage::from(img); let new_img = DynamicImage::from(img);
// Ok(Box::new(BufferedImageLuminanceSource::new(new_img)))
Ok(Box::new(Self { Ok(Box::new(Self {
width: new_img.width() as usize, width: new_img.width() as usize,
height: new_img.height() 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) let note = ResultParser::matchSinglePrefixedField("MEMORY:", &rawText, '\r', false)
.unwrap_or_default(); .unwrap_or_default();
let address = ResultParser::matchSinglePrefixedField("ADD:", &rawText, '\r', true); let address = ResultParser::matchSinglePrefixedField("ADD:", &rawText, '\r', true);
let addresses = if address.is_none() { let addresses = address.map_or_else(Vec::new, |add| vec![add]);
Vec::new()
} else {
vec![address?]
};
if let Ok(new_data) = AddressBookParsedRXingResult::with_details( if let Ok(new_data) = AddressBookParsedRXingResult::with_details(
if let Some(nm) = ResultParser::maybeWrap(name) { ResultParser::maybeWrap(name).unwrap_or_default(),
nm
} else {
Vec::new()
},
Vec::new(), Vec::new(),
pronunciation.unwrap_or_default(), pronunciation.unwrap_or_default(),
phoneNumbers, phoneNumbers,
@@ -90,10 +83,12 @@ fn matchMultipleValuePrefix(prefix: &str, rawText: &str) -> Vec<String> {
// for (int i = 1; i <= 3; i++) { // for (int i = 1; i <= 3; i++) {
let value = let value =
ResultParser::matchSinglePrefixedField(&format!("{prefix}{i}:"), rawText, '\r', true); ResultParser::matchSinglePrefixedField(&format!("{prefix}{i}:"), rawText, '\r', true);
if value.is_none() {
if let Some(value) = value {
values.push(value)
} else {
break; break;
} }
values.push(value.unwrap());
} }
values values

View File

@@ -43,35 +43,32 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
if !rawText.starts_with("MECARD:") { if !rawText.starts_with("MECARD:") {
return None; 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 name = parseName(&rawName[0]);
let pronunciation = let pronunciation = ResultParser::match_single_docomo_prefixed_field("SOUND:", &rawText, true)
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)
.unwrap_or_default(); .unwrap_or_default();
let addresses = let phoneNumbers =
ResultParser::match_do_co_mo_prefixed_field("ADR:", &rawText).unwrap_or_default(); ResultParser::match_docomo_prefixed_field("TEL:", &rawText).unwrap_or_default();
let mut birthday = ResultParser::match_single_do_co_mo_prefixed_field("BDAY:", &rawText, true) 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(); .unwrap_or_default();
if !ResultParser::isStringOfDigits(&birthday, 8) { if !ResultParser::isStringOfDigits(&birthday, 8) {
// No reason to throw out the whole card because the birthday is formatted wrong. // No reason to throw out the whole card because the birthday is formatted wrong.
birthday = String::default(); 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 // 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. // 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(); .unwrap_or_default();
if let Ok(new_adb) = AddressBookParsedRXingResult::with_details( if let Ok(new_adb) = AddressBookParsedRXingResult::with_details(
ResultParser::maybeWrap(Some(name))?, ResultParser::maybeWrap(Some(name)).unwrap_or_default(),
Vec::new(), Vec::new(),
pronunciation, pronunciation,
phoneNumbers, phoneNumbers,
@@ -100,12 +97,4 @@ fn parseName(name: &str) -> String {
} else { } else {
name.to_owned() 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; return None;
} }
let firstName = ResultParser::match_single_do_co_mo_prefixed_field("N:", &rawText, true) let firstName =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("N:", &rawText, true).unwrap_or_default();
let lastName = ResultParser::match_single_do_co_mo_prefixed_field("X:", &rawText, true) let lastName =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("X:", &rawText, true).unwrap_or_default();
let fullName = buildName(&firstName, &lastName); let fullName = buildName(&firstName, &lastName);
let title = ResultParser::match_single_do_co_mo_prefixed_field("T:", &rawText, true) let title =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("T:", &rawText, true).unwrap_or_default();
let org = ResultParser::match_single_do_co_mo_prefixed_field("C:", &rawText, true) let org =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("C:", &rawText, true).unwrap_or_default();
let addresses = ResultParser::match_do_co_mo_prefixed_field("A:", &rawText); let addresses = ResultParser::match_docomo_prefixed_field("A:", &rawText);
let phoneNumber1 = ResultParser::match_single_do_co_mo_prefixed_field("B:", &rawText, true) let phoneNumber1 =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("B:", &rawText, true).unwrap_or_default();
let phoneNumber2 = ResultParser::match_single_do_co_mo_prefixed_field("M:", &rawText, true) let phoneNumber2 =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("M:", &rawText, true).unwrap_or_default();
let phoneNumber3 = ResultParser::match_single_do_co_mo_prefixed_field("F:", &rawText, true) let phoneNumber3 =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("F:", &rawText, true).unwrap_or_default();
let email = ResultParser::match_single_do_co_mo_prefixed_field("E:", &rawText, true) let email =
.unwrap_or_default(); ResultParser::match_single_docomo_prefixed_field("E:", &rawText, true).unwrap_or_default();
if let Ok(adb) = AddressBookParsedRXingResult::with_details( if let Ok(adb) = AddressBookParsedRXingResult::with_details(
ResultParser::maybeWrap(Some(fullName))?, ResultParser::maybeWrap(Some(fullName)).unwrap_or_default(),
Vec::new(), Vec::new(),
String::default(), String::default(),
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3), buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
Vec::new(), Vec::new(),
ResultParser::maybeWrap(Some(email))?, ResultParser::maybeWrap(Some(email)).unwrap_or_default(),
Vec::new(), Vec::new(),
String::default(), String::default(),
String::default(), String::default(),
addresses?, addresses.unwrap_or_default(),
Vec::new(), Vec::new(),
org, org,
String::default(), String::default(),
@@ -82,23 +82,6 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
} else { } else {
None 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> { 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:") { if !rawText.starts_with("MEBKM:") {
return None; return None;
} }
let title = ResultParser::match_single_do_co_mo_prefixed_field("TITLE:", rawText, true); let title = ResultParser::match_single_docomo_prefixed_field("TITLE:", rawText, true);
let rawUri = ResultParser::match_do_co_mo_prefixed_field("URL:", rawText); let rawUri = ResultParser::match_docomo_prefixed_field("URL:", rawText)?;
rawUri.as_ref()?;
let uri = rawUri?[0].clone(); let uri = &rawUri[0];
if URIResultParser::is_basically_valid_uri(&uri) { if URIResultParser::is_basically_valid_uri(uri) {
Some(ParsedClientResult::URIResult(URIParsedRXingResult::new( Some(ParsedClientResult::URIResult(URIParsedRXingResult::new(
uri, uri.to_string(),
title.unwrap_or_default(), title.unwrap_or_default(),
))) )))
} else { } else {
None None
} }
// return URIRXingResultParser.isBasicallyValidURI(uri) ? new URIParsedRXingResult(uri, title) : null;
} }
// }

View File

@@ -112,7 +112,7 @@ impl CalendarParsedRXingResult {
) -> Result<Self, Exceptions> { ) -> Result<Self, Exceptions> {
let start = Self::parseDate(startString.clone())?; let start = Self::parseDate(startString.clone())?;
let end = if endString.is_empty() { let end = if endString.is_empty() {
let durationMS = Self::parseDurationMS(&durationString); let durationMS = Self::parseDurationMS(&durationString)?;
if durationMS < 0i64 { if durationMS < 0i64 {
-1i64 -1i64
} else { } else {
@@ -165,7 +165,6 @@ impl CalendarParsedRXingResult {
* @throws ParseException if not able to parse as a date * @throws ParseException if not able to parse as a date
*/ */
fn parseDate(when: String) -> Result<i64, Exceptions> { fn parseDate(when: String) -> Result<i64, Exceptions> {
// let date_time_regex = Regex::new(DATE_TIME).unwrap();
if !DATE_TIME.is_match(&when) { if !DATE_TIME.is_match(&when) {
return Err(Exceptions::ParseException(Some(when))); return Err(Exceptions::ParseException(Some(when)));
} }
@@ -178,37 +177,23 @@ impl CalendarParsedRXingResult {
// http://code.google.com/p/android/issues/detail?id=8330 // http://code.google.com/p/android/issues/detail?id=8330
return match Utc.datetime_from_str(&format!("{}T000000Z", &when,), date_format_string) { return match Utc.datetime_from_str(&format!("{}T000000Z", &when,), date_format_string) {
Ok(dtm) => Ok(dtm.timestamp()), Ok(dtm) => Ok(dtm.timestamp()),
Err(e) => panic!("{}", e), Err(e) => Err(Exceptions::ParseException(Some(e.to_string()))),
// Err(e) => Err(Exceptions::ParseException(format!(
// "couldn't parse string: {}",
// e
// ))),
}; };
// 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 // 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") { return match Utc.datetime_from_str(&when, "%Y%m%dT%H%M%SZ") {
Ok(dtm) => Ok(dtm.with_timezone(&Utc).timestamp()), Ok(dtm) => Ok(dtm.with_timezone(&Utc).timestamp()),
Err(e) => Err(Exceptions::ParseException(Some(format!( Err(e) => Err(Exceptions::ParseException(Some(format!(
"couldn't parse string: {e}" "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 // Try once more, with weird tz formatting
if when.len() > 16 { 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() { if durationString.is_empty() {
return -1; return Ok(-1);
} }
// let regex = Regex::new(RFC2445_DURATION).unwrap(); // let regex = Regex::new(RFC2445_DURATION).unwrap();
if let Some(m) = RFC2445_DURATION.captures(durationString) { 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++) { // for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {
let fieldValue = m.get(i + 1); let fieldValue = m.get(i + 1);
if let Some(parseable) = fieldValue { 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 += unit * z;
} }
} }
durationMS Ok(durationMS)
} else { } else {
-1 Ok(-1)
} }
// if (!m.matches()) { // if (!m.matches()) {
// return -1L; // return -1L;

View File

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

View File

@@ -43,16 +43,16 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
if !rawText.starts_with("MATMSG:") { if !rawText.starts_with("MATMSG:") {
return None; 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 { for to in &tos {
if !isBasicallyValidEmailAddress(to, &ATEXT_ALPHANUMERIC) { if !isBasicallyValidEmailAddress(to, &ATEXT_ALPHANUMERIC) {
return None; 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(); .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(); .unwrap_or_default();
Some(ParsedClientResult::EmailResult( Some(ParsedClientResult::EmailResult(
EmailAddressParsedRXingResult::with_details(tos, Vec::new(), Vec::new(), subject, body), 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 { pub fn getRawText(&self) -> &str {
&self.rawText &self.rawText
} }

View File

@@ -24,16 +24,6 @@
* http://www.piramidepse.com/ * 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 Antonio Manuel Benjumea Conde, Servinform, S.A.
// * @author Agustín Delgado, 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; // return None;
// } // }
i += ai.len() + 2; i += ai.len() + 2;
let value = findValue(i, &rawText); let value = findValue(i, &rawText)?;
i += value.len(); i += value.len();
match ai.as_str() { match ai.as_str() {
"00" => sscc = value, "00" => sscc = value,
@@ -260,13 +260,13 @@ fn findAIvalue(i: usize, rawText: &str) -> Option<String> {
Some(buf) Some(buf)
} }
fn findValue(i: usize, rawText: &str) -> String { fn findValue(i: usize, rawText: &str) -> Option<String> {
let mut buf = String::new(); let mut buf = String::new();
let rawTextAux = &rawText[i..]; let rawTextAux = &rawText[i..];
for index in 0..rawTextAux.len() { for index in 0..rawTextAux.len() {
// for (int index = 0; index < rawTextAux.length(); index++) { // for (int index = 0; index < rawTextAux.length(); index++) {
let c = rawTextAux.chars().nth(index).unwrap(); let c = rawTextAux.chars().nth(index)?;
if c == '(' { if c == '(' {
// We look for a new AI. If it doesn't exist (ERROR), we continue // We look for a new AI. If it doesn't exist (ERROR), we continue
// with the iteration // with the iteration
@@ -281,5 +281,5 @@ fn findValue(i: usize, rawText: &str) -> String {
buf.push(c); 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) { let latitude = captures.get(1)?.as_str().parse::<f64>().ok()?;
if let Ok(laf64) = la.as_str().parse::<f64>() { if !(-90.0..=90.0).contains(&latitude) {
if !(-90.0..=90.0).contains(&laf64) {
return None;
}
laf64
} else {
return None;
}
} else {
return None; return None;
}; }
let longitude = if let Some(lo) = captures.get(2) { // let latitude = if let Some(la) = captures.get(1) {
if let Ok(lof64) = lo.as_str().parse::<f64>() { // if let Ok(laf64) = la.as_str().parse::<f64>() {
if !(-180.0..=180.0).contains(&lof64) { // if !(-90.0..=90.0).contains(&laf64) {
return None; // return None;
} // }
lof64 // laf64
} else { // } else {
return None; // return None;
} // }
} else { // } else {
// return None;
// };
let longitude = captures.get(2)?.as_str().parse::<f64>().ok()?;
if !(-180.0..=180.0).contains(&longitude) {
return None; 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) { let altitude = if let Some(al) = captures.get(3) {
if let Ok(alf64) = al.as_str().parse::<f64>() { if let Ok(alf64) = al.as_str().parse::<f64>() {
@@ -88,28 +98,6 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
} else { } else {
0.0 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( Some(ParsedClientResult::GeoResult(GeoParsedRXingResult::new(
latitude, latitude,
longitude, longitude,
@@ -119,10 +107,4 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
} else { } else {
None None
} }
// Matcher matcher = GEO_URL_PATTERN.matcher(rawText);
// if (!matcher.matches()) {
// return null;
// }
} }
// }

View File

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

View File

@@ -40,6 +40,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
{ {
return None; return None;
} }
let rawText = ResultParser::getMassagedText(result); let rawText = ResultParser::getMassagedText(result);
if !ResultParser::isStringOfDigits(&rawText, rawText.len()) { if !ResultParser::isStringOfDigits(&rawText, rawText.len()) {
return None; return None;
@@ -50,7 +51,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
// Expand UPC-E for purposes of searching // Expand UPC-E for purposes of searching
if format == &BarcodeFormat::UPC_E && rawText.len() == 8 { if format == &BarcodeFormat::UPC_E && rawText.len() == 8 {
// unimplemented!("UPCEReader is required to parse this"); // unimplemented!("UPCEReader is required to parse this");
crate::oned::convertUPCEtoUPCA(&rawText) crate::oned::convertUPCEtoUPCA(&rawText)?
} else { } else {
rawText.clone() 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 = ""; // const EMPTY_STR_ARRAY: &'static str = "";
pub fn getMassagedText(result: &RXingResult) -> String { pub fn getMassagedText(result: &RXingResult) -> String {
let mut text = result.getText().clone(); result
if text.starts_with(BYTE_ORDER_MARK) { .getText()
text = text[1..].to_owned(); .trim_start_matches(BYTE_ORDER_MARK)
} .to_owned()
text // if text.starts_with(BYTE_ORDER_MARK) {
// text = &text[1..];
// }
// text.to_owned()
} }
pub fn parse_result_with_parsers( 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) { pub fn maybe_append_multiple(value: &[String], result: &mut String) {
if !value.is_empty() { for s in value {
for s in value { // for (String s : value) {
// for (String s : value) { if !s.is_empty() {
if !s.is_empty() { if !result.is_empty() {
if !result.is_empty() { result.push('\n');
result.push('\n');
}
result.push_str(s);
} }
result.push_str(s);
} }
} }
} }
#[inline(always)]
pub fn maybeWrap(value: Option<String>) -> Option<Vec<String>> { pub fn maybeWrap(value: Option<String>) -> Option<Vec<String>> {
if value.is_none() { if value.is_none() {
None None
@@ -207,14 +209,12 @@ pub fn unescapeBackslash(escaped: &str) -> String {
if backslash.is_none() { if backslash.is_none() {
return escaped.to_owned(); return escaped.to_owned();
} }
let max = escaped.len(); let max = escaped.chars().count();
let mut unescaped = String::with_capacity(max - 1);
let backslash = backslash.unwrap_or(0); 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; let mut nextIsEscaped = false;
for i in backslash..max { for c in escaped.chars().skip(backslash) {
// for (int i = backslash; i < max; i++) {
let c = escaped.chars().nth(i).unwrap();
if nextIsEscaped || c != '\\' { if nextIsEscaped || c != '\\' {
unescaped.push(c); unescaped.push(c);
nextIsEscaped = false; nextIsEscaped = false;
@@ -239,6 +239,7 @@ pub fn parseHexDigit(c: char) -> i32 {
-1 -1
} }
#[inline(always)]
pub fn isStringOfDigits(value: &str, length: usize) -> bool { pub fn isStringOfDigits(value: &str, length: usize) -> bool {
!value.is_empty() && length > 0 && length == value.len() && DIGITS.is_match(value) !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 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) { let is_a_match = if let Some(mtch) = DIGITS.find(&sub_seq) {
mtch.start() == 0 && mtch.end() == sub_seq.len() mtch.start() == 0 && mtch.end() == sub_seq.chars().count()
} else { } else {
false false
}; };
@@ -266,16 +267,11 @@ pub fn parseNameValuePairs(uri: &str) -> Option<HashMap<String, String>> {
let mut result = HashMap::with_capacity(3); let mut result = HashMap::with_capacity(3);
let paramStart = paramStart.unwrap_or(0); 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); let list = sub_str.split(AMPERSAND);
for keyValue in list { for keyValue in list {
appendKeyValue(keyValue, &mut result); 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) Some(result)
} }
@@ -304,9 +300,9 @@ pub fn urlDecode(encoded: &str) -> Result<String, Exceptions> {
if let Ok(decoded) = decode(encoded) { if let Ok(decoded) = decode(encoded) {
Ok(decoded.to_string()) Ok(decoded.to_string())
} else { } else {
Err(Exceptions::IllegalStateException(Some( Err(Exceptions::IllegalStateException(Some(String::from(
"UnsupportedEncodingException".to_owned(), "UnsupportedEncodingException",
))) ))))
} }
} }
@@ -329,7 +325,7 @@ pub fn matchPrefixedField(
// if (i < 0) { // if (i < 0) {
// break; // 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 start = i; // Found the start of a match here
let mut more = true; let mut more = true;
while more { while more {
@@ -337,7 +333,7 @@ pub fn matchPrefixedField(
i += next_index; i += next_index;
} else { } else {
// No terminating end character? uh, done. Set i such that loop terminates and break // No terminating end character? uh, done. Set i such that loop terminates and break
i = rawText.len(); i = rawText.chars().count();
more = false; more = false;
continue; continue;
} }
@@ -411,11 +407,11 @@ pub fn matchSinglePrefixedField(
// return matches == null ? null : matches[0]; // 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) matchPrefixedField(prefix, raw_text, ';', true)
} }
pub fn match_single_do_co_mo_prefixed_field( pub fn match_single_docomo_prefixed_field(
prefix: &str, prefix: &str,
raw_text: &str, raw_text: &str,
trim: bool, trim: bool,
@@ -426,7 +422,9 @@ pub fn match_single_do_co_mo_prefixed_field(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
client::result::{ParsedClientResult, TextParsedRXingResult}, client::result::{
OtherParsedResult, ParsedClientResult, ParsedRXingResult, TextParsedRXingResult,
},
RXingResult, RXingResult,
}; };
@@ -449,4 +447,32 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(p_res.to_string(), "parsed with parser"); 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. * 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. * <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> * See <a href="http://tools.ietf.org/html/rfc5724"> RFC 5724</a> on this.</p>
@@ -38,7 +29,6 @@
* *
* @author Sean Owen * @author Sean Owen
*/ */
// public final class SMSMMSRXingResultParser extends RXingResultParser {
use crate::RXingResult; use crate::RXingResult;
use super::{ParsedClientResult, ResultParser, SMSParsedRXingResult}; use super::{ParsedClientResult, ResultParser, SMSParsedRXingResult};
@@ -121,21 +111,13 @@ fn add_number_via(numbers: &mut Vec<String>, vias: &mut Vec<String>, number_part
return; return;
} }
if let Some(number_end) = number_part.find(';') { if let Some(number_end) = number_part.find(';') {
// if numberEnd < 0 {
numbers.push(number_part[..number_end].to_string()); numbers.push(number_part[..number_end].to_string());
let maybe_via = &number_part[number_end + 1..]; let maybe_via = &number_part[number_end + 1..];
let via = if let Some(stripped) = maybe_via.strip_prefix("via=") { let via = maybe_via.strip_prefix("via=").unwrap_or_default();
stripped
} else {
""
};
if !via.is_empty() { if !via.is_empty() {
vias.push(via.to_owned()); vias.push(via.to_owned());
} }
} else { } else {
numbers.push(number_part.to_owned()); 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..]; body = &number[body_start + 1..];
number = &number[..body_start]; number = &number[..body_start];
} }
// let bodyStart = number.indexOf(':');
// if (bodyStart >= 0) {
// body = number.substring(bodyStart + 1);
// number = number.substring(0, bodyStart);
// }
Some(ParsedClientResult::SMSResult( Some(ParsedClientResult::SMSResult(
SMSParsedRXingResult::with_singles( SMSParsedRXingResult::with_singles(
number.to_owned(), number.to_owned(),
@@ -62,5 +58,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
body.to_owned(), 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]; 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( Some(ParsedClientResult::EmailResult(
EmailAddressParsedRXingResult::with_details( EmailAddressParsedRXingResult::with_details(
vec![emailAddress.to_owned()], vec![emailAddress.to_owned()],
@@ -63,9 +54,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
body.to_owned(), 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('/') { let nextSlash = if let Some(pos) = uri[start..].find('/') {
pos + start pos + start
} else { } else {
uri.len() uri.chars().count()
}; };
// let nextSlash = uri.indexOf('/', start); // let nextSlash = uri.indexOf('/', start);
// if (nextSlash < 0) { // if (nextSlash < 0) {

View File

@@ -39,18 +39,16 @@ static ALLOWED_URI_CHARS: Lazy<Regex> = Lazy::new(|| {
}); });
static USER_IN_HOST: Lazy<Regex> = static USER_IN_HOST: Lazy<Regex> =
Lazy::new(|| Regex::new(":/*([^/@]+)@[^/]+").expect("Regex patterns should always copile")); 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> = static URL_WITH_PROTOCOL_PATTERN: Lazy<Regex> =
Lazy::new(|| Regex::new("[a-zA-Z][a-zA-Z0-9+-.]+:").unwrap()); 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> = 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()); 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 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> { pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
let raw_text = ResultParser::getMassagedText(result); let raw_text = ResultParser::getMassagedText(result);

View File

@@ -14,20 +14,6 @@
* limitations under the License. * 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 std::convert::TryFrom;
use regex::Regex; use regex::Regex;

View File

@@ -14,13 +14,6 @@
* limitations under the License. * 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}. * Tests {@link VINParsedRXingResult}.
*/ */

View File

@@ -14,13 +14,6 @@
* limitations under the License. * 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 regex::Regex;
use crate::{ use crate::{
@@ -46,26 +39,18 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
let raw_text_res = result.getText().trim(); let raw_text_res = result.getText().trim();
let raw_text = IOQ_MATCHER.replace_all(raw_text_res, "").to_string(); let raw_text = IOQ_MATCHER.replace_all(raw_text_res, "").to_string();
// rawText = IOQ.matcher(rawText).replaceAll("").trim();
AZ09_MATCHER.find(&raw_text)?; AZ09_MATCHER.find(&raw_text)?;
// if !AZ09.matcher(rawText).matches() {
// return null;
// }
let check_cs = check_checksum(&raw_text).unwrap_or(false); let check_cs = check_checksum(&raw_text).unwrap_or(false);
if !check_cs { if !check_cs {
return None; return None;
} }
let wmi = &raw_text[..3]; 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 country_code = country_code(wmi).unwrap_or("");
let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_')); let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_')).ok();
if model_year.is_err() {
return None;
}
Some(ParsedClientResult::VINResult(VINParsedRXingResult::new( Some(ParsedClientResult::VINResult(VINParsedRXingResult::new(
raw_text.to_owned(), raw_text.to_owned(),
wmi.to_owned(), wmi.to_owned(),
@@ -73,22 +58,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
raw_text[9..17].to_owned(), raw_text[9..17].to_owned(),
country_code.to_owned(), country_code.to_owned(),
raw_text[3..8].to_owned(), raw_text[3..8].to_owned(),
model_year.unwrap(), model_year?,
raw_text.chars().nth(10).unwrap(), raw_text.chars().nth(10)?,
raw_text[11..].to_owned(), 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]"; const IOQ: &str = "[IOQ]";
@@ -97,10 +70,17 @@ const AZ09: &str = "[A-Z0-9]{17}";
fn check_checksum(vin: &str) -> Result<bool, Exceptions> { fn check_checksum(vin: &str) -> Result<bool, Exceptions> {
let mut sum = 0; let mut sum = 0;
for i in 0..vin.len() { for i in 0..vin.len() {
// for (int i = 0; i < vin.length(); i++) { sum += vin_position_weight(i + 1)? as u32
sum += vin_position_weight(i + 1)? as u32 * vin_char_value(vin.chars().nth(i).unwrap())?; * 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)?; let expected_check_char = check_char((sum % 11) as u8)?;
Ok(check_to_char == expected_check_char) 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(), "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> { 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(), "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> { 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(), "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> { 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", "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> { fn country_code(wmi: &str) -> Option<&'static str> {
let c1 = wmi.chars().next().unwrap(); let c1 = wmi.chars().next()?;
let c2 = wmi.chars().nth(1).unwrap(); let c2 = wmi.chars().nth(1)?;
match c1 { match c1 {
'1' | '4' | '5' => Some("US"), '1' | '4' | '5' => Some("US"),
'2' => Some("CA"), '2' => Some("CA"),

View File

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

View File

@@ -60,6 +60,9 @@ pub use SMSParsedResult::*;
pub use URIParsedResult::*; pub use URIParsedResult::*;
pub use VINParsedResult::*; pub use VINParsedResult::*;
mod other_parsed_result;
pub use other_parsed_result::*;
#[cfg(test)] #[cfg(test)]
mod AddressBookParsedResultTestCase; mod AddressBookParsedResultTestCase;
#[cfg(test)] #[cfg(test)]
@@ -102,6 +105,7 @@ pub enum ParsedClientResult {
AddressBookResult(AddressBookParsedRXingResult), AddressBookResult(AddressBookParsedRXingResult),
CalendarEventResult(CalendarParsedRXingResult), CalendarEventResult(CalendarParsedRXingResult),
ExpandedProductResult(ExpandedProductParsedRXingResult), ExpandedProductResult(ExpandedProductParsedRXingResult),
Other(OtherParsedResult),
} }
impl ParsedRXingResult for ParsedClientResult { impl ParsedRXingResult for ParsedClientResult {
@@ -120,6 +124,7 @@ impl ParsedRXingResult for ParsedClientResult {
ParsedClientResult::AddressBookResult(a) => a.getType(), ParsedClientResult::AddressBookResult(a) => a.getType(),
ParsedClientResult::CalendarEventResult(a) => a.getType(), ParsedClientResult::CalendarEventResult(a) => a.getType(),
ParsedClientResult::ExpandedProductResult(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::AddressBookResult(a) => a.getDisplayRXingResult(),
ParsedClientResult::CalendarEventResult(a) => a.getDisplayRXingResult(), ParsedClientResult::CalendarEventResult(a) => a.getDisplayRXingResult(),
ParsedClientResult::ExpandedProductResult(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!( assert_eq!(
encoding::all::UTF_8.name(), 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) { fn do_test(bytes: &[u8], charset: EncodingRef, encoding: &str) {
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()); let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()).unwrap();
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()); let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()).unwrap();
assert_eq!(charset.name(), guessedCharset.name()); assert_eq!(charset.name(), guessedCharset.name());
assert_eq!(encoding, guessedEncoding); assert_eq!(encoding, guessedEncoding);
} }

View File

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

View File

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

View File

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

View File

@@ -90,13 +90,18 @@ impl GridSampler for DefaultGridSampler {
let mut x = 0; let mut x = 0;
while x < max { while x < max {
// for (int x = 0; x < max; x += 2) { // for (int x = 0; x < max; x += 2) {
if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight() // if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight()
{ // {
return Err(Exceptions::NotFoundException(Some( // 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(), "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 // Black(-ish) pixel
bits.set(x as u32 / 2, y); bits.set(x as u32 / 2, y);
} }

View File

@@ -14,8 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
//package com.google.zxing.common.detector; use std::{
use std::{f32, i32}; f32, i32,
ops::{Add, Sub},
};
/** /**
* General math-related and numeric utility functions. * General math-related and numeric utility functions.
@@ -32,32 +34,43 @@ use std::{f32, i32};
*/ */
#[inline(always)] #[inline(always)]
pub fn round(d: f32) -> i32 { 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 aX point A x coordinate
* @param aY point A y coordinate // * @param aY point A y coordinate
* @param bX point B x coordinate // * @param bX point B x coordinate
* @param bY point B y coordinate // * @param bY point B y coordinate
* @return Euclidean distance between points A and B // * @return Euclidean distance between points A and B
*/ // */
#[inline(always)] // #[inline(always)]
pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 { // pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
let xDiff: f64 = (aX - bX).into(); // let xDiff: f64 = (aX - bX).into();
let yDiff: f64 = (aY - bY).into(); // let yDiff: f64 = (aY - bY).into();
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32 // (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)] #[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 xDiff: f64 = (aX - bX).into();
let yDiff: f64 = (aY - bY).into(); let yDiff: f64 = (aY - bY).into();
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32 (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 * @return sum of values in array
*/ */
#[inline(always)] #[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() array.iter().sum()
// let mut count = 0;
// for a in array {
// count += a;
// }
// count
} }
#[cfg(test)] #[cfg(test)]
@@ -112,15 +123,12 @@ mod tests {
fn testDistance() { fn testDistance() {
assert_eq!( assert_eq!(
(8.0f32).sqrt(), (8.0f32).sqrt(),
MathUtils::distance_float(1.0f32, 2.0f32, 3.0f32, 4.0f32) MathUtils::distance(1.0f32, 2.0f32, 3.0f32, 4.0f32)
);
assert_eq!(
0.0f32,
MathUtils::distance_float(1.0f32, 2.0f32, 1.0f32, 2.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!((8.0f32).sqrt(), MathUtils::distance(1, 2, 3, 4));
assert_eq!(0.0f32, MathUtils::distance_int(1, 2, 1, 2)); assert_eq!(0.0f32, MathUtils::distance(1, 2, 1, 2));
} }
#[test] #[test]
@@ -129,5 +137,7 @@ mod tests {
assert_eq!(1, MathUtils::sum(&[1])); assert_eq!(1, MathUtils::sum(&[1]));
assert_eq!(4, MathUtils::sum(&[1, 3])); assert_eq!(4, MathUtils::sum(&[1, 3]));
assert_eq!(0, MathUtils::sum(&[-1, 1])); 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_x: f32,
b_y: f32, b_y: f32,
) -> Option<RXingResultPoint> { ) -> 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 x_step: f32 = (b_x - a_x) / dist as f32;
let y_step: f32 = (b_y - a_y) / 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() self.encoders.is_empty()
} }
pub fn getCharsetName(&self, index: usize) -> &'static str { pub fn getCharsetName(&self, index: usize) -> Option<&'static str> {
assert!(index < self.len()); if index < self.len() {
return self.encoders[index].name(); Some(self.encoders[index].name())
} else {
None
}
} }
pub fn getCharset(&self, index: usize) -> EncodingRef { pub fn getCharset(&self, index: usize) -> Option<EncodingRef> {
assert!(index < self.len()); if index < self.len() {
self.encoders[index] Some(self.encoders[index])
} else {
None
}
} }
pub fn getECIValue(&self, encoderIndex: usize) -> u32 { pub fn getECIValue(&self, encoderIndex: usize) -> u32 {
@@ -233,25 +239,35 @@ impl ECIEncoderSet {
self.priorityEncoderIndex self.priorityEncoderIndex
} }
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> bool { pub fn canEncode(&self, c: &str, encoderIndex: usize) -> Option<bool> {
assert!(encoderIndex < self.len()); if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict); 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> { pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Option<Vec<u8>> {
assert!(encoderIndex < self.len()); if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict); let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
assert!(enc_data.is_ok()); enc_data.ok()
enc_data.unwrap() // assert!(enc_data.is_ok());
// enc_data.unwrap()
} else {
None
}
} }
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Vec<u8> { pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Option<Vec<u8>> {
assert!(encoderIndex < self.len()); if encoderIndex < self.len() {
let encoder = self.encoders[encoderIndex]; let encoder = self.encoders[encoderIndex];
encoder.encode(s, encoding::EncoderTrap::Replace).unwrap() 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) * if the value at the {@code index} argument is not an ECI (@see #isECI)
*/ */
fn getECIValue(&self, index: usize) -> Result<i32, Exceptions>; 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 { pub fn with_capacity(initial_capacity: usize) -> Self {
Self { Self {
current_bytes: Vec::with_capacity(initial_capacity), current_bytes: Vec::with_capacity(initial_capacity),
result: String::new(), result: String::with_capacity(initial_capacity),
current_charset: Some(encoding::all::ISO_8859_1), current_charset: Some(encoding::all::ISO_8859_1),
} }
} }
@@ -121,31 +121,25 @@ impl ECIStringBuilder {
Ok(()) Ok(())
} }
/// Finishes encoding anything in the buffer using the current ECI and resets.
///
/// This function can panic
pub fn encodeCurrentBytesIfAny(&mut self) { pub fn encodeCurrentBytesIfAny(&mut self) {
if let Some(encoder) = self.current_charset { if let Some(encoder) = self.current_charset {
if encoder.name() == encoding::all::UTF_8.name() { if encoder.name() == encoding::all::UTF_8.name() {
if !self.current_bytes.is_empty() { if !self.current_bytes.is_empty() {
// if result == null {
// result = currentBytes;
// currentBytes = new StringBuilder();
// } else {
self.result.push_str( self.result.push_str(
&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(), &String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(),
); );
self.current_bytes.clear(); self.current_bytes.clear();
// }
} }
} else if !self.current_bytes.is_empty() { } else if !self.current_bytes.is_empty() {
let bytes = std::mem::take(&mut self.current_bytes); let bytes = std::mem::take(&mut self.current_bytes);
self.current_bytes.clear(); self.current_bytes.clear();
// if (result == null) {
// result = new StringBuilder(new String(bytes, currentCharset));
// } else {
let encoded_value = encoder let encoded_value = encoder
.decode(&bytes, encoding::DecoderTrap::Strict) .decode(&bytes, encoding::DecoderTrap::Strict)
.unwrap(); .unwrap();
self.result.push_str(&encoded_value); self.result.push_str(&encoded_value);
// }
} }
} else { } else {
for byte in &self.current_bytes { for byte in &self.current_bytes {
@@ -172,7 +166,7 @@ impl ECIStringBuilder {
*/ */
pub fn len(&mut self) -> usize { pub fn len(&mut self) -> usize {
self.encodeCurrentBytesIfAny(); //return toString().length(); 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. // Does not sharpen the data, as this call is intended to only be used by 2D Readers.
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> { 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 let matrix = self
.black_matrix .black_matrix
.get_or_try_init(|| Self::build_black_matrix(&self.source))?; .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) { // for (int offset = 0; offset < maxOffset && nudged; offset += 2) {
let x = points[offset] as i32; let x = points[offset] as i32;
let y = points[offset + 1] 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)); return Err(Exceptions::NotFoundException(None));
} }
nudged = false; nudged = false;
if x == -1 { if x == -1 {
points[offset] = 0.0f32; points[offset] = 0.0;
nudged = true; nudged = true;
} else if x == width.try_into().unwrap() { } else if x == width as i32 {
points[offset] = width as f32 - 1f32; points[offset] = width as f32 - 1.0;
nudged = true; nudged = true;
} }
if y == -1 { if y == -1 {
points[offset + 1] = 0.0f32; points[offset + 1] = 0.0;
nudged = true; nudged = true;
} else if y == height.try_into().unwrap() { } else if y == height as i32 {
points[offset + 1] = height as f32 - 1f32; points[offset + 1] = height as f32 - 1.0;
nudged = true; nudged = true;
} }
offset += 2; offset += 2;
@@ -171,22 +171,22 @@ pub trait GridSampler {
// for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { // for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
let x = points[offset as usize] as i32; let x = points[offset as usize] as i32;
let y = points[offset as usize + 1] 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)); return Err(Exceptions::NotFoundException(None));
} }
nudged = false; nudged = false;
if x == -1 { if x == -1 {
points[offset as usize] = 0.0f32; points[offset as usize] = 0.0;
nudged = true; nudged = true;
} else if x == width.try_into().unwrap() { } else if x == width as i32 {
points[offset as usize] = width as f32 - 1f32; points[offset as usize] = width as f32 - 1.0;
nudged = true; nudged = true;
} }
if y == -1 { if y == -1 {
points[offset as usize + 1] = 0.0f32; points[offset as usize + 1] = 0.0;
nudged = true; nudged = true;
} else if y == height.try_into().unwrap() { } else if y == height as i32 {
points[offset as usize + 1] = height as f32 - 1f32; points[offset as usize + 1] = height as f32 - 1.0;
nudged = true; nudged = true;
} }
offset += -2; 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. * profiling easier, and not doing heavy lifting when callers don't expect it.
*/ */
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> { 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 let matrix = self
.black_matrix .black_matrix
.get_or_try_init(|| Self::calculateBlackMatrix(&self.ghb))?; .get_or_try_init(|| Self::calculateBlackMatrix(&self.ghb))?;
@@ -200,6 +193,7 @@ impl HybridBinarizer {
} }
} }
#[inline(always)]
fn cap(value: u32, max: u32) -> u32 { fn cap(value: u32, max: u32) -> u32 {
if value < 2 { if value < 2 {
2 2

View File

@@ -14,12 +14,6 @@
* limitations under the License. * 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 std::{fmt, rc::Rc};
use encoding::EncodingRef; use encoding::EncodingRef;
@@ -174,17 +168,17 @@ impl ECIInput for MinimalECIInput {
Ok((self.bytes[index] as u32 - 256) as i32) 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() { if index + n > self.bytes.len() {
return false; return Ok(false);
} }
for i in 0..n { for i in 0..n {
// for (int i = 0; i < n; i++) { // for (int i = 0; i < n; i++) {
if self.isECI(index as u32 + i as u32).unwrap() { if self.isECI(index as u32 + i as u32)? {
return false; return Ok(false);
} }
} }
true Ok(true)
} }
} }
impl MinimalECIInput { impl MinimalECIInput {
@@ -209,10 +203,14 @@ impl MinimalECIInput {
let bytes = if encoderSet.len() == 1 { let bytes = if encoderSet.len() == 1 {
//optimization for the case when all can be encoded without ECI in ISO-8859-1 //optimization for the case when all can be encoded without ECI in ISO-8859-1
let mut bytes_hld = vec![0; stringToEncode.len()]; let mut bytes_hld = vec![0; stringToEncode.len()];
for (i, 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 i in 0..stringToEncode.len() {
// for (int i = 0; i < bytes.length; i++) { // 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() { *byt = if fnc1.is_some() && c == fnc1.as_ref().unwrap() {
1000 1000
} else { } else {
@@ -287,7 +285,9 @@ impl MinimalECIInput {
if encoderSet.getPriorityEncoderIndex().is_some() if encoderSet.getPriorityEncoderIndex().is_some()
&& ((fnc1.is_some() && ((fnc1.is_some()
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap()) && 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(); start = encoderSet.getPriorityEncoderIndex().unwrap();
end = start + 1; end = start + 1;
@@ -298,7 +298,7 @@ impl MinimalECIInput {
// for (int i = start; i < end; i++) { // for (int i = start; i < end; i++) {
if (fnc1.is_some() if (fnc1.is_some()
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap()) && ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap())
|| encoderSet.canEncode(ch, i) || encoderSet.canEncode(ch, i).unwrap()
{ {
Self::addEdge( Self::addEdge(
edges, 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( pub fn encodeMinimally(
stringToEncode: &str, stringToEncode: &str,
encoderSet: &ECIEncoderSet, encoderSet: &ECIEncoderSet,
@@ -360,6 +363,7 @@ impl MinimalECIInput {
} else { } else {
let bytes: Vec<u16> = encoderSet let bytes: Vec<u16> = encoderSet
.encode_char(&c.c, c.encoderIndex) .encode_char(&c.c, c.encoderIndex)
.unwrap()
.iter() .iter()
.map(|x| *x as u16) .map(|x| *x as u16)
.collect(); .collect();
@@ -414,7 +418,7 @@ impl InputEdge {
let mut size = if c == Self::FNC1_UNICODE { let mut size = if c == Self::FNC1_UNICODE {
1 1
} else { } else {
encoderSet.encode_char(c, encoderIndex).len() encoderSet.encode_char(c, encoderIndex).unwrap().len()
}; };
//let fnc1Str = String::from_utf16(&[fnc1]).unwrap(); //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(), ecSize > 0 && ecSize + dataSize <= field.getSize(),
"Invalid ECC size for {field}" "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 message = vec![0; dataSize + ecSize];
let mut dataWords: Vec<i32> = vec![0; dataSize]; let mut dataWords: Vec<i32> = vec![0; dataSize];
let mut ecWords = vec![0; ecSize]; 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>) { 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 messageExpected = vec![0; dataWords.len() + ecWords.len()];
let mut message = 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()]); 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> { pub fn new(field: GenericGFRef, coefficients: &[i32]) -> Result<Self, Exceptions> {
if coefficients.is_empty() { if coefficients.is_empty() {
return Err(Exceptions::IllegalArgumentException(Some( return Err(Exceptions::IllegalArgumentException(Some(String::from(
"coefficients.len()".to_owned(), "coefficients cannot be empty",
))); ))));
} }
Ok(Self { Ok(Self {
field, field,

View File

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

View File

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

View File

@@ -14,12 +14,6 @@
* limitations under the License. * 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 encoding::{Encoding, EncodingRef};
use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary}; use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary};
@@ -71,20 +65,16 @@ impl StringUtils {
* "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none * "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none
* of these can possibly be correct * of these can possibly be correct
*/ */
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> &'static str { pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<&'static str> {
let c = StringUtils::guessCharset(bytes, hints); let c = StringUtils::guessCharset(bytes, hints)?;
if c.name() if c.name() == encoding::label::encoding_from_whatwg_label("SJIS")?.name() {
== encoding::label::encoding_from_whatwg_label("SJIS") Some("SJIS")
.unwrap()
.name()
{
"SJIS"
} else if c.name() == encoding::all::UTF_8.name() { } else if c.name() == encoding::all::UTF_8.name() {
"UTF8" Some("UTF8")
} else if c.name() == encoding::all::ISO_8859_1.name() { } else if c.name() == encoding::all::ISO_8859_1.name() {
"ISO8859_1" Some("ISO8859_1")
} else { } else {
c.name() Some(c.name())
} }
} }
@@ -97,12 +87,12 @@ impl StringUtils {
* or the platform default encoding if * or the platform default encoding if
* none of these can possibly be correct * 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)) = if let Some(DecodeHintValue::CharacterSet(cs_name)) =
hints.get(&DecodeHintType::CHARACTER_SET) hints.get(&DecodeHintType::CHARACTER_SET)
{ {
// if let DecodeHintValue::CharacterSet(cs_name) = hint { // 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) { // 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)) && ((bytes[0] == 0xFE && bytes[1] == 0xFF) || (bytes[0] == 0xFF && bytes[1] == 0xFE))
{ {
if bytes[0] == 0xFE && bytes[1] == 0xFF { if bytes[0] == 0xFE && bytes[1] == 0xFF {
return encoding::all::UTF_16BE; return Some(encoding::all::UTF_16BE);
} else { } 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 // 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) { 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 // 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 if can_be_shift_jis
@@ -242,7 +232,7 @@ impl StringUtils {
|| sjis_max_katakana_word_length >= 3 || sjis_max_katakana_word_length >= 3
|| sjis_max_double_bytes_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: // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
// - If we saw // - If we saw
@@ -253,23 +243,23 @@ impl StringUtils {
return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2)
|| iso_high_other * 10 >= length || iso_high_other * 10 >= length
{ {
encoding::label::encoding_from_whatwg_label("SJIS").unwrap() encoding::label::encoding_from_whatwg_label("SJIS")
} else { } 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 // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
if can_be_iso88591 { if can_be_iso88591 {
return encoding::all::ISO_8859_1; return Some(encoding::all::ISO_8859_1);
} }
if can_be_shift_jis { 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 { if can_be_utf8 {
return encoding::all::UTF_8; return Some(encoding::all::UTF_8);
} }
// Otherwise, we take a wild guess with platform encoding // 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.getSymbolDataWidth()? as usize,
symbolInfo.getSymbolDataHeight()? as usize, symbolInfo.getSymbolDataHeight()? as usize,
); );
placement.place(); placement.place()?;
//4. step: low-level encoding //4. step: low-level encoding
Self::encodeLowLevel( Self::encodeLowLevel(&placement, symbolInfo, width as u32, height as u32)
&placement,
symbolInfo,
width.try_into().unwrap(),
height.try_into().unwrap(),
)
} }
} }

View File

@@ -85,8 +85,8 @@ impl BitMatrixParser {
let mut row = 4; let mut row = 4;
let mut column = 0; let mut column = 0;
let numRows = self.mappingBitMatrix.getHeight().try_into().unwrap(); let numRows = self.mappingBitMatrix.getHeight() as isize;
let numColumns = self.mappingBitMatrix.getWidth().try_into().unwrap(); let numColumns = self.mappingBitMatrix.getWidth() as isize;
let mut corner1Read = false; let mut corner1Read = false;
let mut corner2Read = false; let mut corner2Read = false;
@@ -497,11 +497,3 @@ impl BitMatrixParser {
Ok(bitMatrixWithoutAlignment) 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) Ok(result)
// return new DecoderRXingResult(bytes,
// result.toString(),
// byteSegments.isEmpty() ? null : byteSegments,
// null,
// symbologyModifier);
} }
/** /**
@@ -238,7 +232,9 @@ fn decodeAsciiSegment(
oneByte += 128; oneByte += 128;
//upperShift = false; //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); return Ok(Mode::ASCII_ENCODE);
} }
129 => return Ok(Mode::PAD_ENCODE), // Pad 129 => return Ok(Mode::PAD_ENCODE), // Pad
@@ -249,7 +245,6 @@ fn decodeAsciiSegment(
// pad with '0' for single digit values // pad with '0' for single digit values
result.append_char('0'); result.append_char('0');
} }
//result.append_char(char::from_u32(value).unwrap());
result.append_string(&format!("{value}")); result.append_string(&format!("{value}"));
} }
230 => 230 =>
@@ -391,7 +386,10 @@ fn decodeC40Segment(
} else if cValue < C40_BASIC_SET_CHARS.len() as u32 { } else if cValue < C40_BASIC_SET_CHARS.len() as u32 {
let c40char = C40_BASIC_SET_CHARS[cValue as usize]; let c40char = C40_BASIC_SET_CHARS[cValue as usize];
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(c40char); result.append_char(c40char);
@@ -402,10 +400,14 @@ fn decodeC40Segment(
} }
1 => { 1 => {
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(char::from_u32(cValue).unwrap()); result.append_char(
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
);
} }
shift = 0; shift = 0;
} }
@@ -413,7 +415,10 @@ fn decodeC40Segment(
if cValue < C40_SHIFT2_SET_CHARS.len() as u32 { if cValue < C40_SHIFT2_SET_CHARS.len() as u32 {
let c40char = C40_SHIFT2_SET_CHARS[cValue as usize]; let c40char = C40_SHIFT2_SET_CHARS[cValue as usize];
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(c40char); result.append_char(c40char);
@@ -438,10 +443,14 @@ fn decodeC40Segment(
} }
3 => { 3 => {
if upperShift { 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; upperShift = false;
} else { } 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; shift = 0;
} }
@@ -494,7 +503,10 @@ fn decodeTextSegment(
} else if cValue < TEXT_BASIC_SET_CHARS.len() as u32 { } else if cValue < TEXT_BASIC_SET_CHARS.len() as u32 {
let textChar = TEXT_BASIC_SET_CHARS[cValue as usize]; let textChar = TEXT_BASIC_SET_CHARS[cValue as usize];
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(textChar); result.append_char(textChar);
@@ -505,10 +517,14 @@ fn decodeTextSegment(
} }
1 => { 1 => {
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(char::from_u32(cValue).unwrap()); result.append_char(
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
);
} }
shift = 0; shift = 0;
} }
@@ -518,7 +534,10 @@ fn decodeTextSegment(
if cValue < TEXT_SHIFT2_SET_CHARS.len() as u32 { if cValue < TEXT_SHIFT2_SET_CHARS.len() as u32 {
let textChar = TEXT_SHIFT2_SET_CHARS[cValue as usize]; let textChar = TEXT_SHIFT2_SET_CHARS[cValue as usize];
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(textChar); result.append_char(textChar);
@@ -545,7 +564,10 @@ fn decodeTextSegment(
if cValue < TEXT_SHIFT3_SET_CHARS.len() as u32 { if cValue < TEXT_SHIFT3_SET_CHARS.len() as u32 {
let textChar = TEXT_SHIFT3_SET_CHARS[cValue as usize]; let textChar = TEXT_SHIFT3_SET_CHARS[cValue as usize];
if upperShift { 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; upperShift = false;
} else { } else {
result.append_char(textChar); result.append_char(textChar);
@@ -622,10 +644,14 @@ fn decodeAnsiX12Segment(
_ => { _ => {
if cValue < 14 { if cValue < 14 {
// 0 - 9 // 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 { } else if cValue < 40 {
// A - Z // 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 { } else {
return Err(Exceptions::FormatException(None)); return Err(Exceptions::FormatException(None));
} }
@@ -682,7 +708,8 @@ fn decodeEdifactSegment(
// no 1 in the leading (6th) bit // no 1 in the leading (6th) bit
edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value 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 { if bits.available() == 0 {
@@ -724,8 +751,6 @@ fn decodeBase256Segment(
let mut bytes = vec![0u8; count as usize]; let mut bytes = vec![0u8; count as usize];
for byte in bytes.iter_mut().take(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 // 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 // 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 { if bits.available() < 8 {
@@ -737,10 +762,9 @@ fn decodeBase256Segment(
result.append_string( result.append_string(
&encoding::all::ISO_8859_1 &encoding::all::ISO_8859_1
.decode(&bytes, encoding::DecoderTrap::Strict) .decode(&bytes, encoding::DecoderTrap::Strict)
.expect("decode"), .map_err(|e| Exceptions::ParseException(Some(e.to_string())))?,
); );
byteSegments.push(bytes); byteSegments.push(bytes);
// result.append_string(&encoding::all::ISO_8859_1.decode(&bytes, encoding::DecoderTrap::Strict).expect("decode"));
Ok(()) Ok(())
} }
@@ -768,30 +792,6 @@ fn decodeECISegment(
result.appendECI((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1)?; result.appendECI((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1)?;
Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900) 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) 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, ecBlocks,
} }
} }

View File

@@ -212,7 +212,7 @@ impl<'a> Detector<'_> {
/** /**
* Calculates the corner position of the white top right module. * 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 // A..D
// | : // | :
// B--C // B--C

View File

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

View File

@@ -30,14 +30,6 @@ impl Default for DMRegressionLine {
} }
impl RegressionLine for DMRegressionLine { impl RegressionLine for DMRegressionLine {
// fn intersect<T: RegressionLine, T2: RegressionLine>(
// &self,
// l1: &T,
// l2: &T2,
// ) -> RXingResultPoint {
// int
// }
fn points(&self) -> &[RXingResultPoint] { fn points(&self) -> &[RXingResultPoint] {
&self.points &self.points
} }
@@ -272,7 +264,14 @@ impl DMRegressionLine {
// calculate the (expected average) distance of two adjacent pixels // calculate the (expected average) distance of two adjacent pixels
let unitPixelDist = RXingResultPoint::length(RXingResultPoint::bresenhamDirection( 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; )) as f64;
// calculate the width of 2 modules (first black pixel to first black pixel) // calculate the width of 2 modules (first black pixel to first black pixel)
@@ -291,8 +290,17 @@ impl DMRegressionLine {
} }
} }
modSizes modSizes.push(
.push(sumFront + self.distance(end, &self.project(self.points.last().unwrap())) as f64); 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 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 lineLength = self.distance(beg, end) as f64 - unitPixelDist;
let mut meanModSize = Self::average(&modSizes, |_: f64| true); let mut meanModSize = Self::average(&modSizes, |_: f64| true);

View File

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

View File

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

View File

@@ -51,19 +51,36 @@ impl Encoder for Base256Encoder {
let lengthFieldSize = 1; let lengthFieldSize = 1;
let currentSize = context.getCodewordCount() + dataCount + lengthFieldSize; let currentSize = context.getCodewordCount() + dataCount + lengthFieldSize;
context.updateSymbolInfoWithLength(currentSize); 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 context.hasMoreCharacters() || mustPad {
if dataCount <= 249 { 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 { } else if dataCount <= 1555 {
buffer.replace_range( buffer.replace_range(
0..1, 0..1,
&char::from_u32((dataCount as u32 / 250) + 249) &char::from_u32((dataCount as u32 / 250) + 249)
.unwrap() .ok_or(Exceptions::ParseException(None))?
.to_string(), .to_string(),
); );
let (ci_pos, _) = buffer.char_indices().nth(1).unwrap(); let (ci_pos, _) = buffer
buffer.insert(ci_pos, char::from_u32(dataCount as u32 % 250).unwrap()); .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 { } else {
return Err(Exceptions::IllegalStateException(Some(format!( return Err(Exceptions::IllegalStateException(Some(format!(
"Message length not in valid ranges: {dataCount}" "Message length not in valid ranges: {dataCount}"
@@ -73,10 +90,16 @@ impl Encoder for Base256Encoder {
let c = buffer.chars().count(); let c = buffer.chars().count();
for i in 0..c { for i in 0..c {
// for (int i = 0, c = buffer.length(); i < c; i++) { // for (int i = 0, c = buffer.length(); i < c; i++) {
context.writeCodeword(Self::randomize255State( context.writeCodeword(
buffer.chars().nth(i).unwrap(), Self::randomize255State(
context.getCodewordCount() as u32 + 1, buffer
) as u8); .chars()
.nth(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
context.getCodewordCount() as u32 + 1,
)
.ok_or(Exceptions::ParseException(None))? as u8,
);
} }
Ok(()) Ok(())
} }
@@ -85,13 +108,13 @@ impl Base256Encoder {
pub fn new() -> Self { pub fn new() -> Self {
Self Self
} }
fn randomize255State(ch: char, codewordPosition: u32) -> char { fn randomize255State(ch: char, codewordPosition: u32) -> Option<char> {
let pseudoRandom = ((149 * codewordPosition) % 255) + 1; let pseudoRandom = ((149 * codewordPosition) % 255) + 1;
let tempVariable = ch as u32 + pseudoRandom; let tempVariable = ch as u32 + pseudoRandom;
if tempVariable <= 255 { if tempVariable <= 255 {
char::from_u32(tempVariable).unwrap() char::from_u32(tempVariable)
} else { } 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; let curCodewordCount = context.getCodewordCount() + unwritten;
context.updateSymbolInfoWithLength(curCodewordCount); context.updateSymbolInfoWithLength(curCodewordCount);
let available = let available = context
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount; .getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
if !context.hasMoreCharacters() { if !context.hasMoreCharacters() {
//Avoid having a single C40 value in the last triplet //Avoid having a single C40 value in the last triplet
@@ -107,7 +110,7 @@ impl C40Encoder {
handleEOD(context, &mut buffer) 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) self.encodeMaximal(context, &Self::encodeChar_c40, &Self::handleEOD_c40)
} }
@@ -116,7 +119,7 @@ impl C40Encoder {
context: &mut EncoderContext, context: &mut EncoderContext,
encodeChar: &dyn Fn(char, &mut String) -> u32, encodeChar: &dyn Fn(char, &mut String) -> u32,
handleEOD: &dyn Fn(&mut EncoderContext, &mut String) -> Result<(), Exceptions>, handleEOD: &dyn Fn(&mut EncoderContext, &mut String) -> Result<(), Exceptions>,
) { ) -> Result<(), Exceptions> {
let mut buffer = String::new(); let mut buffer = String::new();
let mut lastCharSize = 0; let mut lastCharSize = 0;
let mut backtrackStartPosition = context.pos; let mut backtrackStartPosition = context.pos;
@@ -135,8 +138,11 @@ impl C40Encoder {
let curCodewordCount = context.getCodewordCount() + unwritten + 1; // +1 for the latch to C40 let curCodewordCount = context.getCodewordCount() + unwritten + 1; // +1 for the latch to C40
context.updateSymbolInfoWithLength(curCodewordCount); context.updateSymbolInfoWithLength(curCodewordCount);
let available = let available = context
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount; .getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
let rest = buffer.chars().count() % 3; let rest = buffer.chars().count() % 3;
if (rest == 2 && available != 2) || (rest == 1 && (lastCharSize > 3 || available != 1)) if (rest == 2 && available != 2) || (rest == 1 && (lastCharSize > 3 || available != 1))
{ {
@@ -149,7 +155,9 @@ impl C40Encoder {
context.writeCodeword(LATCH_TO_C40); context.writeCodeword(LATCH_TO_C40);
} }
handleEOD(context, &mut buffer).expect("eod"); handleEOD(context, &mut buffer)?;
Ok(())
} }
fn backtrackOneCharacter( fn backtrackOneCharacter(
@@ -170,10 +178,16 @@ impl C40Encoder {
lastCharSize lastCharSize
} }
pub(super) fn writeNextTriplet(context: &mut EncoderContext, buffer: &mut String) { pub(super) fn writeNextTriplet(
context.writeCodewords(&Self::encodeToCodewords(buffer)); context: &mut EncoderContext,
buffer: &mut String,
) -> Result<(), Exceptions> {
context.writeCodewords(
&Self::encodeToCodewords(buffer).ok_or(Exceptions::FormatException(None))?,
);
buffer.replace_range(0..3, ""); buffer.replace_range(0..3, "");
// buffer.delete(0, 3); // buffer.delete(0, 3);
Ok(())
} }
/** /**
@@ -191,20 +205,23 @@ impl C40Encoder {
let curCodewordCount = context.getCodewordCount() + unwritten; let curCodewordCount = context.getCodewordCount() + unwritten;
context.updateSymbolInfoWithLength(curCodewordCount); context.updateSymbolInfoWithLength(curCodewordCount);
let available = let available = context
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount; .getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity() as usize
- curCodewordCount;
if rest == 2 { if rest == 2 {
buffer.push('\0'); //Shift 1 buffer.push('\0'); //Shift 1
while buffer.chars().count() >= 3 { while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer); C40Encoder::writeNextTriplet(context, buffer)?;
} }
if context.hasMoreCharacters() { if context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH); context.writeCodeword(C40_UNLATCH);
} }
} else if available == 1 && rest == 1 { } else if available == 1 && rest == 1 {
while buffer.chars().count() >= 3 { while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer); C40Encoder::writeNextTriplet(context, buffer)?;
} }
if context.hasMoreCharacters() { if context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH); context.writeCodeword(C40_UNLATCH);
@@ -213,7 +230,7 @@ impl C40Encoder {
context.pos -= 1; context.pos -= 1;
} else if rest == 0 { } else if rest == 0 {
while buffer.chars().count() >= 3 { while buffer.chars().count() >= 3 {
C40Encoder::writeNextTriplet(context, buffer); C40Encoder::writeNextTriplet(context, buffer)?;
} }
if available > 0 || context.hasMoreCharacters() { if available > 0 || context.hasMoreCharacters() {
context.writeCodeword(C40_UNLATCH); context.writeCodeword(C40_UNLATCH);
@@ -273,16 +290,18 @@ impl C40Encoder {
len len
} }
fn encodeToCodewords(sb: &str) -> String { fn encodeToCodewords(sb: &str) -> Option<String> {
let v = (1600 * sb.chars().next().unwrap() as u32) let v = (1600 * sb.chars().next()? as u32)
+ (40 * sb.chars().nth(1).unwrap() as u32) + (40 * sb.chars().nth(1)? as u32)
+ sb.chars().nth(2).unwrap() as u32 + sb.chars().nth(2)? as u32
+ 1; + 1;
let cw1 = v / 256; let cw1 = v / 256;
let cw2 = v % 256; let cw2 = v % 256;
[char::from_u32(cw1).unwrap(), char::from_u32(cw2).unwrap()] Some(
.into_iter() [char::from_u32(cw1)?, char::from_u32(cw2)?]
.collect() .into_iter()
.collect(),
)
// return new String(new char[] {cw1, cw2}); // return new String(new char[] {cw1, cw2});
} }
} }

View File

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

View File

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

View File

@@ -62,7 +62,11 @@ impl<'a> EncoderContext<'_> {
{ {
ISO_8859_1_ENCODER ISO_8859_1_ENCODER
.decode(&encoded_bytes, encoding::DecoderTrap::Strict) .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 { } else {
return Err(Exceptions::IllegalArgumentException(Some( return Err(Exceptions::IllegalArgumentException(Some(
"Message contains characters outside ISO-8859-1 encoding.".to_owned(), "Message contains characters outside ISO-8859-1 encoding.".to_owned(),
@@ -99,13 +103,13 @@ impl<'a> EncoderContext<'_> {
self.skipAtEnd = count; self.skipAtEnd = count;
} }
/// panics if current position is out of bounds
pub fn getCurrentChar(&self) -> char { pub fn getCurrentChar(&self) -> char {
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
self.msg.chars().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 { pub fn getCurrent(&self) -> char {
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
self.msg.chars().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()); self.updateSymbolInfoWithLength(self.getCodewordCount());
} }
/// Update symbol info with the length
///
/// This function can panic
pub fn updateSymbolInfoWithLength(&mut self, len: usize) { pub fn updateSymbolInfoWithLength(&mut self, len: usize) {
if self.symbolInfo.is_none() if self.symbolInfo.is_none()
|| len > self.symbolInfo.as_ref().unwrap().getDataCapacity() as usize || 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(|| { static FACTORS: Lazy<[Vec<u32>; 16]> = Lazy::new(|| {
[ [
Vec::from([228, 48, 15, 111, 62]), vec![228, 48, 15, 111, 62],
Vec::from([23, 68, 144, 134, 240, 92, 254]), vec![23, 68, 144, 134, 240, 92, 254],
Vec::from([28, 24, 185, 166, 223, 248, 116, 255, 110, 61]), vec![28, 24, 185, 166, 223, 248, 116, 255, 110, 61],
Vec::from([175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120]), vec![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![41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242],
Vec::from([ vec![
156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185, 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, 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, 15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186,
172, 172,
]), ],
Vec::from([ vec![
52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12, 52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12,
181, 184, 96, 50, 193, 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, 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, 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, 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, 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, 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, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, 248, 202, 69, 50, 150, 177, 226,
5, 9, 5, 5, 9, 5,
]), ],
Vec::from([ vec![
245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, 191, 106, 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, 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, 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, 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, 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, 201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, 155, 43, 203, 107, 233, 53,
143, 46, 143, 46,
]), ],
Vec::from([ vec![
242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, 185, 112, 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, 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, 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, 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, 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, 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, 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, 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; let mut d = block;
while d < symbolInfo.getDataCapacity() as usize { while d < symbolInfo.getDataCapacity() as usize {
// for (int d = block; d < symbolInfo.getDataCapacity(); d += blockCount) { // 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; d += blockCount;
} }
@@ -193,10 +198,13 @@ pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String,
let (char_index, replace_char) = sb let (char_index, replace_char) = sb
.char_indices() .char_indices()
.nth(symbolInfo.getDataCapacity() as usize + e) .nth(symbolInfo.getDataCapacity() as usize + e)
.unwrap(); .ok_or(Exceptions::IndexOutOfBoundsException(None))?;
sb.replace_range( sb.replace_range(
char_index..(replace_char.len_utf8()), 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)); // sb.setCharAt(symbolInfo.getDataCapacity() + e, ecc.charAt(pos));
pos += 1; pos += 1;
@@ -232,20 +240,25 @@ fn createECCBlock(codewords: &str, numECWords: usize) -> Result<String, Exceptio
// } // }
for i in 0..codewords.chars().count() { for i in 0..codewords.chars().count() {
// for (int i = 0; i < codewords.length(); i++) { // 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 k in (1..numECWords).rev() {
// for (int k = numECWords - 1; k > 0; k--) { // for (int k = numECWords - 1; k > 0; k--) {
if m != 0 && poly[k] != 0 { if m != 0 && poly[k] != 0 {
ecc[k] = char::from_u32( ecc[k] = char::from_u32(
ecc[k - 1] as u32 ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255], ecc[k - 1] as u32 ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255],
) )
.unwrap(); .ok_or(Exceptions::IndexOutOfBoundsException(None))?;
} else { } else {
ecc[k] = ecc[k - 1]; ecc[k] = ecc[k - 1];
} }
} }
if m != 0 && poly[0] != 0 { 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 { } else {
ecc[0] = 0 as char; ecc[0] = 0 as char;
} }

View File

@@ -121,7 +121,8 @@ fn randomize253State(codewordPosition: u32) -> String {
} else { } else {
char::from_u32(tempVariable - 254) char::from_u32(tempVariable - 254)
} }
.expect("must become a char") // .expect("must become a char")
.unwrap_or(char::default())
.to_string() .to_string()
// return (char) (tempVariable <= 254 ? tempVariable : tempVariable - 254); // return (char) (tempVariable <= 254 ? tempVariable : tempVariable - 254);
} }
@@ -219,21 +220,28 @@ pub fn encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup(
let mut encodingMode = ASCII_ENCODATION; //Default mode let mut encodingMode = ASCII_ENCODATION; //Default mode
if forceC40 { if forceC40 {
c40Encoder.encodeMaximalC40(&mut context); c40Encoder.encodeMaximalC40(&mut context)?;
encodingMode = context.getNewEncoding().unwrap(); encodingMode = context
.getNewEncoding()
.ok_or(Exceptions::IllegalStateException(None))?;
context.resetEncoderSignal(); context.resetEncoderSignal();
} }
while context.hasMoreCharacters() { while context.hasMoreCharacters() {
encoders[encodingMode].encode(&mut context)?; encoders[encodingMode].encode(&mut context)?;
if context.getNewEncoding().is_some() { if context.getNewEncoding().is_some() {
encodingMode = context.getNewEncoding().unwrap(); encodingMode = context
.getNewEncoding()
.ok_or(Exceptions::IllegalStateException(None))?;
context.resetEncoderSignal(); context.resetEncoderSignal();
} }
} }
let len = context.getCodewordCount(); let len = context.getCodewordCount();
context.updateSymbolInfo(); context.updateSymbolInfo();
let capacity = context.getSymbolInfo().unwrap().getDataCapacity(); let capacity = context
.getSymbolInfo()
.ok_or(Exceptions::IllegalStateException(None))?
.getDataCapacity();
if len < capacity as usize if len < capacity as usize
&& encodingMode != ASCII_ENCODATION && encodingMode != ASCII_ENCODATION
&& encodingMode != BASE256_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); let endpos = (startpos + 3).min(msg.chars().count() as u32);
for i in startpos..endpos { for i in startpos..endpos {
// for (int i = startpos; i < endpos; i++) { // for (int i = startpos; i < endpos; i++) {
if !isNativeX12(msg.chars().nth(i as usize).unwrap()) { if let Some(c) = msg.chars().nth(i as usize) {
return ASCII_ENCODATION; if !isNativeX12(c) {
return ASCII_ENCODATION;
}
} }
} }
} else if currentMode as usize == EDIFACT_ENCODATION && newMode == EDIFACT_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); let endpos = (startpos + 4).min(msg.chars().count() as u32);
for i in startpos..endpos { for i in startpos..endpos {
// for (int i = startpos; i < endpos; i++) { // for (int i = startpos; i < endpos; i++) {
if !isNativeEDIFACT(msg.chars().nth(i as usize).unwrap()) { if let Some(c) = msg.chars().nth(i as usize) {
return ASCII_ENCODATION; if !isNativeEDIFACT(c) {
return ASCII_ENCODATION;
}
} }
} }
} }
@@ -352,15 +364,11 @@ fn lookAheadTestIntern(msg: &str, startpos: u32, currentMode: u32) -> usize {
return C40_ENCODATION; return C40_ENCODATION;
} }
// let c = msg let Some(c) = msg
// .graphemes(true) .chars()
// .nth((startpos + charsProcessed) as usize) .nth((startpos + charsProcessed) as usize) else {
// .unwrap(); break 0;
// let c = msg.charAt(startpos + charsProcessed); };
let c = msg
.chars()
.nth((startpos + charsProcessed) as usize)
.unwrap();
charsProcessed += 1; charsProcessed += 1;
//step L //step L
@@ -593,7 +601,8 @@ pub fn determineConsecutiveDigitCount(msg: &str, startpos: u32) -> u32 {
let len = msg.chars().count(); //len(); let len = msg.chars().count(); //len();
let mut idx = startpos; let mut idx = startpos;
// let graphemes = msg.graphemes(true); // 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 += 1;
} }
idx - startpos 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() if edges[vertexIndex][edge.getEndMode()?.ordinal()].is_none()
|| edges[vertexIndex][edge.getEndMode()?.ordinal()] || edges[vertexIndex][edge.getEndMode()?.ordinal()]
.as_ref() .as_ref()
.unwrap() .ok_or(Exceptions::IllegalStateException(None))?
.cachedTotalSize .cachedTotalSize
> edge.cachedTotalSize > edge.cachedTotalSize
{ {
@@ -296,7 +296,7 @@ fn addEdges(
//not possible to unlatch a full EDF edge to something //not possible to unlatch a full EDF edge to something
//else //else
if high_level_encoder::isDigit(ch) 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)?) && high_level_encoder::isDigit(input.charAt(from as usize + 1)?)
{ {
// two digits ASCII encoded // 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)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?) && high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?)
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?) && high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?)
@@ -379,7 +379,7 @@ fn addEdges(
while i < 3 { while i < 3 {
// for (i = 0; i < 3; i++) { // for (i = 0; i < 3; i++) {
let pos = from + 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)?) && high_level_encoder::isNativeEDIFACT(input.charAt(pos as usize)?)
{ {
addEdge( addEdge(
@@ -398,7 +398,7 @@ fn addEdges(
i += 1; i += 1;
} }
if i == 3 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)?) && high_level_encoder::isNativeEDIFACT(input.charAt(from as usize + 3)?)
{ {
addEdge( addEdge(
@@ -604,9 +604,7 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
addEdges(input.clone(), &mut edges, 0, None)?; addEdges(input.clone(), &mut edges, 0, None)?;
for i in 1..=inputLength { for i in 1..=inputLength {
// for (int i = 1; i <= inputLength; i++) {
for j in 0..6 { for j in 0..6 {
// for (int j = 0; j < 6; j++) {
if edges[i][j].is_some() && i < inputLength { if edges[i][j].is_some() && i < inputLength {
let edge = edges[i][j].clone(); let edge = edges[i][j].clone();
addEdges(input.clone(), &mut edges, i as u32, edge)?; 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. //optimize memory by removing edges that have been passed.
for j in 0..6 { for j in 0..6 {
// for (int j = 0; j < 6; j++) {
edges[i - 1][j] = None; edges[i - 1][j] = None;
} }
} }
@@ -622,7 +619,6 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
let mut minimalJ: i32 = -1; let mut minimalJ: i32 = -1;
let mut minimalSize = i32::MAX; let mut minimalSize = i32::MAX;
for j in 0..6 { for j in 0..6 {
// for (int j = 0; j < 6; j++) {
if edges[inputLength][j].is_some() { if edges[inputLength][j].is_some() {
let edge = edges[inputLength][j].as_ref().unwrap(); let edge = edges[inputLength][j].as_ref().unwrap();
let size = if (1..=3).contains(&j) { let size = if (1..=3).contains(&j) {
@@ -672,12 +668,9 @@ impl Edge {
characterLength: u32, characterLength: u32,
previous: Option<Rc<Edge>>, previous: Option<Rc<Edge>>,
) -> Result<Self, Exceptions> { ) -> Result<Self, Exceptions> {
// this.input = input; if fromPosition + characterLength > input.length() as u32 {
// this.mode = mode; return Err(Exceptions::FormatException(None));
// this.fromPosition = fromPosition; }
// this.characterLength = characterLength;
// this.previous = previous;
assert!(fromPosition + characterLength <= input.length() as u32);
let mut size = if let Some(previous) = previous.clone() { let mut size = if let Some(previous) = previous.clone() {
previous.cachedTotalSize previous.cachedTotalSize
@@ -704,11 +697,9 @@ impl Edge {
match mode { match mode {
Mode::Ascii => { Mode::Ascii => {
size += 1; size += 1;
if input.isECI(fromPosition).expect("bool") if input.isECI(fromPosition)?
|| isExtendedASCII( || isExtendedASCII(
input input.charAt(fromPosition as usize)?,
.charAt(fromPosition as usize)
.expect("char must exist)"),
input.getFNC1Character(), input.getFNC1Character(),
) )
{ {
@@ -748,9 +739,7 @@ impl Edge {
fromPosition, fromPosition,
mode == Mode::C40, mode == Mode::C40,
&mut charLen, &mut charLen,
) )? * 2;
.expect("works")
* 2;
} }
if previousMode == Mode::Ascii || previousMode == Mode::B256 { if previousMode == Mode::Ascii || previousMode == Mode::B256 {
@@ -1382,10 +1371,9 @@ impl RXingResult {
pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) { pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) {
for i in 0..length as usize { for i in 0..length as usize {
// for (int i = 0; i < length; i++) {
//See "B.1 253-state algorithm //See "B.1 253-state algorithm
let Pad_codeword_position = startPosition as usize + i; 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 pseudo_random_number = ((149 * (Pad_codeword_position + 1)) % 255) + 1;
let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16; let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16;
bytesAL[Pad_codeword_position] = if temp_variable <= 255 { bytesAL[Pad_codeword_position] = if temp_variable <= 255 {
@@ -1452,7 +1440,7 @@ impl Input {
Some(self.internal.getFNC1Character() as u8 as char) 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) self.internal.haveNCharacters(index, n)
} }
fn isFNC1(&self, index: usize) -> Result<bool, Exceptions> { 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(), "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> { fn getVerticalDataRegions(&self) -> Result<u32, Exceptions> {
@@ -157,19 +144,6 @@ impl SymbolInfo {
"Cannot handle this number of data regions".to_owned(), "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> { pub fn getSymbolDataWidth(&self) -> Result<u32, Exceptions> {
@@ -223,15 +197,6 @@ impl SymbolInfo {
pub fn getErrorLengthForInterleavedBlock(&self, _index: u32) -> u32 { pub fn getErrorLengthForInterleavedBlock(&self, _index: u32) -> u32 {
self.rsBlockError 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 { impl fmt::Display for SymbolInfo {
@@ -424,7 +389,7 @@ mod tests {
assert_eq!(24, info.getSymbolWidth().expect("return")); assert_eq!(24, info.getSymbolWidth().expect("return"));
assert_eq!(24, info.getSymbolHeight().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 let info = LOOKUP
.lookup_with_codewords_shape_size_fail( .lookup_with_codewords_shape_size_fail(
35, 35,
@@ -451,7 +416,7 @@ mod tests {
assert!(info.is_none()); assert!(info.is_none());
let minSize = fixedSize; let minSize = fixedSize;
let maxSize = Dimension::new(32, 32).expect("new dimension"); let maxSize = Dimension::new(32, 32);
let info = LOOKUP let info = LOOKUP
.lookup_with_codewords_shape_size_fail( .lookup_with_codewords_shape_size_fail(

View File

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

View File

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

View File

@@ -68,7 +68,7 @@ impl fmt::Display for Exceptions {
Exceptions::RuntimeException(None) => write!(f, "RuntimeException"), Exceptions::RuntimeException(None) => write!(f, "RuntimeException"),
Exceptions::ParseException(None) => write!(f, "ParseException"), 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, file_name: &str,
hints: &mut DecodingHintDictionary, hints: &mut DecodingHintDictionary,
) -> Result<Vec<RXingResult>, Exceptions> { ) -> 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 multi_format_reader = MultiFormatReader::default();
let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader); let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader);

View File

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

View File

@@ -104,15 +104,12 @@ impl LuminanceSource for Luma8LuminanceSource {
impl Luma8LuminanceSource { impl Luma8LuminanceSource {
fn reverseColumns(&mut self) { fn reverseColumns(&mut self) {
for i in 0..self.getWidth() { for i in 0..self.getWidth() {
// for (int i = 0; i < C; i++)
let mut j = 0; let mut j = 0;
let mut k = self.getWidth() - 1; let mut k = self.getWidth() - 1;
while j < k { while j < k {
// for (int j = 0, k = C - 1; j < k; j++, k--)
let offset_a = (self.getWidth() * i) + j; let offset_a = (self.getWidth() * i) + j;
let offset_b = (self.getWidth() * i) + k; let offset_b = (self.getWidth() * i) + k;
self.data.swap(offset_a, offset_b); self.data.swap(offset_a, offset_b);
// swap(arr[j][i], arr[k][i]);
j += 1; j += 1;
k -= 1; k -= 1;
} }
@@ -121,13 +118,10 @@ impl Luma8LuminanceSource {
fn transpose(&mut self) { fn transpose(&mut self) {
for i in 0..self.getHeight() { for i in 0..self.getHeight() {
// for (int i = 0; i < R; i++)
for j in i..self.getWidth() { for j in i..self.getWidth() {
// for (int j = i; j < C; j++)
let offset_a = (self.getWidth() * i) + j; let offset_a = (self.getWidth() * i) + j;
let offset_b = (self.getWidth() * j) + i; let offset_b = (self.getWidth() * j) + i;
self.data.swap(offset_a, offset_b); 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); let mut graphemes = SETS[0].graphemes(true);
for p3bytes in &POSTCODE_3_BYTES { for p3bytes in &POSTCODE_3_BYTES {
// for (byte[] p3bytes : 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 sb
} }
@@ -178,7 +180,7 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
// for i in start..(start+len) { // for i in start..(start+len) {
// for (int i = start; i < start + len; i++) { // for (int i = start; i < start + len; i++) {
let mut set_graphemes = SETS[set].graphemes(true); 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 { match c {
LATCHA => { LATCHA => {
set = 0; set = 0;
@@ -234,11 +236,6 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
} }
String::from(sb.trim_end_matches(PAD)) 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 { 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 // First read into an array of ints
let mut codewordsInts = vec![0i32; (codewords / divisor) as usize]; let mut codewordsInts = vec![0i32; (codewords / divisor) as usize];
for i in 0..codewords { for i in 0..codewords {
// for (int i = 0; i < codewords; i++) {
if (mode == ALL) || (i % 2 == (mode - 1)) { if (mode == ALL) || (i % 2 == (mode - 1)) {
codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32; codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32;
} }
} }
// try {
RS_DECODER.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?; 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 // 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 // We don't care about errors in the error-correction codewords
for i in 0..dataCodewords { for i in 0..dataCodewords {

View File

@@ -155,8 +155,8 @@ impl Circle<'_> {
*length_set = (length, rotation, points); *length_set = (length, rotation, points);
} }
lengths.sort_by_key(|e| e.0); lengths.sort_by_key(|e| e.0);
let major_axis = lengths.last().unwrap(); let Some(major_axis) = lengths.last() else {return (false, (0,0),0,0,0)};
let minor_axis = lengths.first().unwrap(); let Some(minor_axis) = lengths.first() else {return (false, (0,0),0,0,0)};
// // find foci // // find foci
let linear_eccentricity = ((major_axis.0 / 2).pow(2) - (minor_axis.0 / 2).pow(2)).sqrt(); 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 [tl, bl, tr, br] = &symbol_box.0;
let target_width = MathUtils::distance_float(tl.0, tl.1, tr.0, tr.1); let target_width = MathUtils::distance(tl.0, tl.1, tr.0, tr.1);
let target_height = MathUtils::distance_float(br.0, br.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_width = (tr.0 - tl.0).round().abs() as u32;
// let target_height = (br.1 - tr.1).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 a_var = a.calculate_circle_variance();
let b_var = b.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 /// Read appropriate bits from a bitmatrix for the maxicode decoder
pub fn read_bits(image: &BitMatrix) -> Result<BitMatrix, Exceptions> { 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 left = enclosingRectangle[0];
let top = enclosingRectangle[1]; let top = enclosingRectangle[1];

View File

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

View File

@@ -46,24 +46,21 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
let halfWidth = width / 2; let halfWidth = width / 2;
let halfHeight = height / 2; let halfHeight = height / 2;
// try {
let attempt = self let attempt = self
.0 .0
.decode_with_hints(&mut image.crop(0, 0, halfWidth, halfHeight), hints); .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 // 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 { match attempt {
// Ok() => return attempt,
Err(Exceptions::NotFoundException(_)) => {} Err(Exceptions::NotFoundException(_)) => {}
_ => return attempt, _ => return attempt,
} }
// } catch (NotFoundException re) {
// continue
// }
// try { // try {
let result = self let result = self
.0 .0
.decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints); .decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
// This is a match because only NotFoundExceptions should be ignored
match result { match result {
Ok(res) => { Ok(res) => {
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0); 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(_)) => {} Err(Exceptions::NotFoundException(_)) => {}
_ => return result, _ => return result,
} }
// makeAbsolute(result.getRXingResultPoints(), halfWidth, 0);
// return result;
// } catch (NotFoundException re) {
// continue
// }
let result = self let result = self
.0 .0
.decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints); .decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints);
// This is a match because only NotFoundExceptions should be ignored
match result { match result {
Ok(res) => { Ok(res) => {
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32); 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(_)) => {} Err(Exceptions::NotFoundException(_)) => {}
_ => return result, _ => 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( let result = self.0.decode_with_hints(
&mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight), &mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
hints, hints,
); );
// This is a match because only NotFoundExceptions should be ignored
match result { match result {
Ok(res) => { Ok(res) => {
let points = Self::makeAbsolute( let points = Self::makeAbsolute(
@@ -114,14 +101,6 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
_ => return result, _ => 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 quarterWidth = halfWidth / 2;
let quarterHeight = halfHeight / 2; let quarterHeight = halfHeight / 2;
let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight); let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
@@ -150,19 +129,22 @@ impl<T: Reader> ByQuadrantReader<T> {
leftOffset: f32, leftOffset: f32,
topOffset: f32, topOffset: f32,
) -> Vec<RXingResultPoint> { ) -> Vec<RXingResultPoint> {
let mut result = Vec::new(); // let mut result = Vec::new();
if !points.is_empty() { // if !points.is_empty() {
for relative in points {
// for (int i = 0; i < points.length; i++) { // // for relative in points {
// let relative = points[i]; // // result.push(RXingResultPoint::new(
// if relative != null { // // relative.getX() + leftOffset,
result.push(RXingResultPoint::new( // // relative.getY() + topOffset,
relative.getX() + leftOffset, // // ));
relative.getY() + topOffset, // // }
)); // }
// } // result
} points
} .iter()
result .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() { if oldRXingResultPoints.is_empty() {
return result; return result;
} }
let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len()); //new RXingResultPoint[oldRXingResultPoints.length];
for oldPoint in oldRXingResultPoints { let newRXingResultPoints: Vec<RXingResultPoint> = oldRXingResultPoints
// for (int i = 0; i < oldRXingResultPoints.length; i++) { .iter()
// RXingResultPoint oldPoint = oldRXingResultPoints[i]; .map(|oldPoint| {
// if (oldPoint != null) { RXingResultPoint::new(
newRXingResultPoints.push(RXingResultPoint::new( oldPoint.getX() + xOffset as f32,
oldPoint.getX() + xOffset as f32, oldPoint.getY() + yOffset 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( let mut newRXingResult = RXingResult::new_complex(
result.getText(), result.getText(),
result.getRawBytes().clone(), result.getRawBytes().clone(),

View File

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

View File

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

View File

@@ -58,18 +58,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
hints, hints,
)?; )?;
let mut points = detectorRXingResult.getPoints().to_vec(); let mut points = detectorRXingResult.getPoints().to_vec();
// If the code was mirrored: swap the bottom-left and the top-right points. // If the code was mirrored: swap the bottom-left and the top-right points.
if let Some(other) = decoderRXingResult.getOther() { if let Some(other) = decoderRXingResult.getOther() {
if other.is::<QRCodeDecoderMetaData>() { if let Some(oth) = other.downcast_ref::<QRCodeDecoderMetaData>() {
(other oth.applyMirroredCorrection(&mut points);
.downcast::<QRCodeDecoderMetaData>()
.expect("must downcast to QRCodeDecoderMetaData"))
.applyMirroredCorrection(&mut points);
} }
} }
// if (decoderRXingResult.getOther() instanceof QRCodeDecoderMetaData) {
// ((QRCodeDecoderMetaData) decoderRXingResult.getOther()).applyMirroredCorrection(points);
// }
let mut result = RXingResult::new( let mut result = RXingResult::new(
decoderRXingResult.getText(), decoderRXingResult.getText(),
decoderRXingResult.getRawBytes().clone(), decoderRXingResult.getRawBytes().clone(),
@@ -77,14 +73,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
BarcodeFormat::QR_CODE, BarcodeFormat::QR_CODE,
); );
let byteSegments = decoderRXingResult.getByteSegments(); let byteSegments = decoderRXingResult.getByteSegments();
// if (byteSegments != null) {
result.putMetadata( result.putMetadata(
RXingResultMetadataType::BYTE_SEGMENTS, RXingResultMetadataType::BYTE_SEGMENTS,
RXingResultMetadataValue::ByteSegments(byteSegments.clone()), RXingResultMetadataValue::ByteSegments(byteSegments.clone()),
); );
// }
let ecLevel = decoderRXingResult.getECLevel(); let ecLevel = decoderRXingResult.getECLevel();
// if (ecLevel != null) {
result.putMetadata( result.putMetadata(
RXingResultMetadataType::ERROR_CORRECTION_LEVEL, RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
RXingResultMetadataValue::ErrorCorrectionLevel(ecLevel.to_owned()), RXingResultMetadataValue::ErrorCorrectionLevel(ecLevel.to_owned()),
@@ -115,7 +111,7 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
// ignore and continue // ignore and continue
continue; continue;
} else { } 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) { fn reset(&mut self) {
// if (readers != null) {
for reader in self.readers.iter_mut() { for reader in self.readers.iter_mut() {
reader.reset(); reader.reset();
} }
// }
} }
} }
@@ -109,10 +107,13 @@ impl MultiFormatReader {
* @param hints The set of hints to use for subsequent calls to decode(image) * @param hints The set of hints to use for subsequent calls to decode(image)
*/ */
pub fn set_ints(&mut self, hints: &DecodingHintDictionary) { 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 formats = hints.get(&DecodeHintType::POSSIBLE_FORMATS);
let mut readers: Vec<Box<dyn Reader>> = Vec::new(); let mut readers: Vec<Box<dyn Reader>> = Vec::new();
if let Some(DecodeHintValue::PossibleFormats(formats)) = formats { if let Some(DecodeHintValue::PossibleFormats(formats)) = formats {
@@ -161,48 +162,33 @@ impl MultiFormatReader {
readers.push(Box::<AztecReader>::default()); readers.push(Box::<AztecReader>::default());
readers.push(Box::<PDF417Reader>::default()); readers.push(Box::<PDF417Reader>::default());
readers.push(Box::<MaxiCodeReader>::default()); readers.push(Box::<MaxiCodeReader>::default());
// unimplemented!("");
if tryHarder { if tryHarder {
readers.push(Box::new(MultiFormatOneDReader::new(hints))); 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> { pub fn decode_internal(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions> {
if !self.readers.is_empty() { if !self.readers.is_empty() {
for reader in self.readers.iter_mut() { 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); let res = reader.decode_with_hints(image, &self.hints);
if res.is_ok() { if res.is_ok() {
return res; 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 // Calling all readers again with inverted image
// let mut image = image.clone();
image.getBlackMatrixMut().flip_self(); image.getBlackMatrixMut().flip_self();
for reader in self.readers.iter_mut() { for reader in self.readers.iter_mut() {
// if (Thread.currentThread().isInterrupted()) {
// throw NotFoundException.getNotFoundInstance();
// }
let res = reader.decode_with_hints(image, &self.hints); let res = reader.decode_with_hints(image, &self.hints);
if res.is_ok() { if res.is_ok() {
return res; 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) 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::common::BitArray;
use crate::BarcodeFormat; use crate::BarcodeFormat;
use crate::DecodeHintValue;
use crate::Exceptions; use crate::Exceptions;
use crate::RXingResult; use crate::RXingResult;
@@ -70,7 +71,7 @@ impl OneDReader for CodaBarReader {
// StringBuilder, so that we can access the decoded patterns in // StringBuilder, so that we can access the decoded patterns in
// validatePattern. We'll translate to the actual characters later. // validatePattern. We'll translate to the actual characters later.
self.decodeRowRXingResult self.decodeRowRXingResult
.push(char::from_u32(charOffset as u32).unwrap()); .push(char::from_u32(charOffset as u32).ok_or(Exceptions::ParseException(None))?);
nextStart += 8; nextStart += 8;
// Stop as soon as we see the end character. // Stop as soon as we see the end character.
if self.decodeRowRXingResult.chars().count() > 1 if self.decodeRowRXingResult.chars().count() > 1
@@ -81,16 +82,16 @@ impl OneDReader for CodaBarReader {
{ {
break; break;
} }
// no fixed end pattern so keep on reading while data is available
if nextStart >= self.counterLength { if nextStart >= self.counterLength {
break; 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: // Look for whitespace after pattern:
let trailingWhitespace = self.counters[nextStart - 1]; let trailingWhitespace = self.counters[nextStart - 1];
let mut lastPatternSize = 0; let mut lastPatternSize = 0;
for i in -8isize..-1isize { for i in -8isize..-1 {
// for (int i = -8; i < -1; i++) {
lastPatternSize += self.counters[(nextStart as isize + i) as usize]; 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++) { // for (int i = 0; i < decodeRowRXingResult.length(); i++) {
self.decodeRowRXingResult.replace_range( self.decodeRowRXingResult.replace_range(
i..=i, 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(), .to_string(),
); );
// self.decodeRowRXingResult.setCharAt(i, Self::ALPHABET[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]);
} }
// Ensure a valid start and end character // 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) { if !Self::arrayContains(&Self::STARTEND_ENCODING, startchar) {
return Err(Exceptions::NotFoundException(None)); return Err(Exceptions::NotFoundException(None));
} }
@@ -122,7 +131,7 @@ impl OneDReader for CodaBarReader {
.decodeRowRXingResult .decodeRowRXingResult
.chars() .chars()
.nth(self.decodeRowRXingResult.chars().count() - 1) .nth(self.decodeRowRXingResult.chars().count() - 1)
.unwrap(); .ok_or(Exceptions::IndexOutOfBoundsException(None))?;
if !Self::arrayContains(&Self::STARTEND_ENCODING, endchar) { if !Self::arrayContains(&Self::STARTEND_ENCODING, endchar) {
return Err(Exceptions::NotFoundException(None)); return Err(Exceptions::NotFoundException(None));
} }
@@ -133,23 +142,29 @@ impl OneDReader for CodaBarReader {
return Err(Exceptions::NotFoundException(None)); return Err(Exceptions::NotFoundException(None));
} }
if !hints.contains_key(&DecodeHintType::RETURN_CODABAR_START_END) { if !matches!(
// self.decodeRowRXingResult.deleteCharAt(self.decodeRowRXingResult.chars().count() - 1); hints.get(&DecodeHintType::RETURN_CODABAR_START_END),
// self.decodeRowRXingResult.deleteCharAt(0); Some(DecodeHintValue::ReturnCodabarStartEnd(true))
) {
self.decodeRowRXingResult = self.decodeRowRXingResult =
self.decodeRowRXingResult[1..self.decodeRowRXingResult.len() - 1].to_owned(); self.decodeRowRXingResult[1..self.decodeRowRXingResult.len() - 1].to_owned();
} }
let mut runningCount = 0; let mut runningCount = 0;
for i in 0..startOffset { runningCount += self.counters.iter().take(startOffset).sum::<u32>();
// for (int i = 0; i < startOffset; i++) { // for i in 0..startOffset {
runningCount += self.counters[i]; // runningCount += self.counters[i];
} // }
let left: f32 = runningCount as f32; let left: f32 = runningCount as f32;
for i in startOffset..(nextStart - 1) { runningCount += self
// for (int i = startOffset; i < nextStart - 1; i++) { .counters
runningCount += self.counters[i]; .iter()
} .skip(startOffset)
.take(nextStart)
.sum::<u32>();
// for i in startOffset..(nextStart - 1) {
// runningCount += self.counters[i];
// }
let right: f32 = runningCount as f32; let right: f32 = runningCount as f32;
let mut result = RXingResult::new( let mut result = RXingResult::new(
@@ -224,10 +239,13 @@ impl CodaBarReader {
let mut pos = start; let mut pos = start;
for i in 0..=end { for i in 0..=end {
// for (int i = 0; i <= end; i++) { // for (int i = 0; i <= end; i++) {
let mut pattern = Self::CHARACTER_ENCODINGS let mut pattern = Self::CHARACTER_ENCODINGS[self
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]; .decodeRowRXingResult
.chars()
.nth(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
as usize];
for j in (0_usize..=6).rev() { 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 // Even j = bars, while odd j = spaces. Categories 2 and 3 are for
// long stripes, while 0 and 1 are for short stripes. // long stripes, while 0 and 1 are for short stripes.
let category = (j & 1) + ((pattern as usize) & 1) * 2; let category = (j & 1) + ((pattern as usize) & 1) * 2;
@@ -260,10 +278,13 @@ impl CodaBarReader {
pos = start; pos = start;
for i in 0..=end { for i in 0..=end {
// for (int i = 0; i <= end; i++) { // for (int i = 0; i <= end; i++) {
let mut pattern = Self::CHARACTER_ENCODINGS let mut pattern = Self::CHARACTER_ENCODINGS[self
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]; .decodeRowRXingResult
.chars()
.nth(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
as usize];
for j in (0usize..=6).rev() { 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 // Even j = bars, while odd j = spaces. Categories 2 and 3 are for
// long stripes, while 0 and 1 are for short stripes. // long stripes, while 0 and 1 are for short stripes.
let category = (j & 1) + ((pattern as usize) & 1) * 2; let category = (j & 1) + ((pattern as usize) & 1) * 2;
@@ -312,9 +333,8 @@ impl CodaBarReader {
self.counters[self.counterLength] = e; self.counters[self.counterLength] = e;
self.counterLength += 1; self.counterLength += 1;
if self.counterLength >= self.counters.len() { 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[..]); temp[0..self.counterLength].clone_from_slice(&self.counters[..]);
// System.arraycopy(counters, 0, temp, 0, counterLength);
self.counters = temp; self.counters = temp;
} }
} }
@@ -334,7 +354,6 @@ impl CodaBarReader {
// We make an exception if the whitespace is the first element. // We make an exception if the whitespace is the first element.
let mut patternSize = 0; let mut patternSize = 0;
for j in i..(i + 7) { for j in i..(i + 7) {
// for (int j = i; j < i + 7; j++) {
patternSize += self.counters[j]; patternSize += self.counters[j];
} }
if i == 1 || self.counters[i - 1] >= patternSize / 2 { if i == 1 || self.counters[i - 1] >= patternSize / 2 {
@@ -348,14 +367,7 @@ impl CodaBarReader {
} }
pub fn arrayContains(array: &[char], key: char) -> bool { pub fn arrayContains(array: &[char], key: char) -> bool {
// if (array != null) { array.contains(&key)
for c in array {
if c == &key {
return true;
}
}
// }
false
} }
// Assumes that counters[position] is a bar. // Assumes that counters[position] is a bar.
@@ -371,7 +383,6 @@ impl CodaBarReader {
let mut minBar = u32::MAX; let mut minBar = u32::MAX;
let mut j = position; let mut j = position;
while j < end { while j < end {
// for (int j = position; j < end; j += 2) {
let currentCounter = theCounters[j]; let currentCounter = theCounters[j];
if currentCounter < minBar { if currentCounter < minBar {
minBar = currentCounter; minBar = currentCounter;
@@ -388,14 +399,9 @@ impl CodaBarReader {
let mut minSpace = u32::MAX; let mut minSpace = u32::MAX;
let mut j = position + 1; let mut j = position + 1;
while j < end { while j < end {
// for (int j = position + 1; j < end; j += 2) {
let currentCounter = theCounters[j]; let currentCounter = theCounters[j];
if currentCounter < minSpace { minSpace = std::cmp::min(currentCounter, minSpace);
minSpace = currentCounter; maxSpace = std::cmp::max(currentCounter, maxSpace);
}
if currentCounter > maxSpace {
maxSpace = currentCounter;
}
j += 2; j += 2;
} }
@@ -404,7 +410,6 @@ impl CodaBarReader {
let mut bitmask = 1 << 7; let mut bitmask = 1 << 7;
let mut pattern = 0; let mut pattern = 0;
for i in 0..7 { for i in 0..7 {
// for (int i = 0; i < 7; i++) {
let threshold = if (i & 1) == 0 { let threshold = if (i & 1) == 0 {
thresholdBar thresholdBar
} else { } else {
@@ -417,7 +422,6 @@ impl CodaBarReader {
} }
for i in 0..Self::CHARACTER_ENCODINGS.len() { for i in 0..Self::CHARACTER_ENCODINGS.len() {
// for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) {
if Self::CHARACTER_ENCODINGS[i] == pattern { if Self::CHARACTER_ENCODINGS[i] == pattern {
return i as i32; return i as i32;
} }

View File

@@ -40,11 +40,15 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
format!("{DEFAULT_GUARD}{contents}{DEFAULT_GUARD}") format!("{DEFAULT_GUARD}{contents}{DEFAULT_GUARD}")
} else { } else {
// Verify input and calculate decoded length. // 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 let lastChar = contents
.chars() .chars()
.nth(contents.chars().count() - 1) .nth(contents.chars().count() - 1)
.unwrap() .ok_or(Exceptions::IndexOutOfBoundsException(None))?
.to_ascii_uppercase(); .to_ascii_uppercase();
let startsNormal = CodaBarReader::arrayContains(&START_END_CHARS, firstChar); let startsNormal = CodaBarReader::arrayContains(&START_END_CHARS, firstChar);
let endsNormal = CodaBarReader::arrayContains(&START_END_CHARS, lastChar); 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. // The start character and the end character are decoded to 10 length each.
let mut resultLength = 20; let mut resultLength = 20;
//for i in 1..contents.chars().count() {
for ch in contents[1..contents.chars().count() - 1].chars() { 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 == '$' { if ch.is_ascii_digit() || ch == '-' || ch == '$' {
resultLength += 9; resultLength += 9;
} else if CodaBarReader::arrayContains( } else if CodaBarReader::arrayContains(
@@ -103,7 +105,11 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
let mut position = 0; let mut position = 0;
for index in 0..contents.chars().count() { for index in 0..contents.chars().count() {
// for (int index = 0; index < contents.length(); index++) { // 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 { if index == 0 || index == contents.chars().count() - 1 {
// The start/end chars are not in the CodaBarReader.ALPHABET. // The start/end chars are not in the CodaBarReader.ALPHABET.
c = match c { c = match c {
@@ -116,7 +122,6 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
} }
let mut code = 0; let mut code = 0;
for i in 0..CodaBarReader::ALPHABET.len() { for i in 0..CodaBarReader::ALPHABET.len() {
// for (int i = 0; i < CodaBarReader::ALPHABET.length; i++) {
// Found any, because I checked above. // Found any, because I checked above.
if c == CodaBarReader::ALPHABET[i] { if c == CodaBarReader::ALPHABET[i] {
code = CodaBarReader::CHARACTER_ENCODINGS[i]; code = CodaBarReader::CHARACTER_ENCODINGS[i];

View File

@@ -98,11 +98,6 @@ impl OneDReader for Code128Reader {
nextStart += counters.iter().sum::<u32>() as usize; nextStart += counters.iter().sum::<u32>() as usize;
// for counter in counters {
// // for (int counter : counters) {
// nextStart += counter;
// }
// Take care of illegal start codes // Take care of illegal start codes
match code { match code {
CODE_START_A | CODE_START_B | CODE_START_C => { 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(); let new_str = result.chars().take(len_trim).collect();
result = new_str; 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; let left: f32 = (startPatternInfo[1] + startPatternInfo[0]) as f32 / 2.0;
@@ -341,8 +331,9 @@ impl OneDReader for Code128Reader {
let rawCodesSize = rawCodes.len(); let rawCodesSize = rawCodes.len();
let mut rawBytes = vec![0u8; rawCodesSize]; let mut rawBytes = vec![0u8; rawCodesSize];
for (i, rawByte) in rawBytes.iter_mut().enumerate().take(rawCodesSize) { for (i, rawByte) in rawBytes.iter_mut().enumerate().take(rawCodesSize) {
// for (int i = 0; i < rawCodesSize; i++) { *rawByte = *rawCodes
*rawByte = *rawCodes.get(i).unwrap(); .get(i)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
} }
let mut resultObject = RXingResult::new( let mut resultObject = RXingResult::new(
&result, &result,
@@ -374,7 +365,6 @@ impl Code128Reader {
let patternLength = counters.len(); let patternLength = counters.len();
for i in rowOffset..width { for i in rowOffset..width {
// for (int i = rowOffset; i < width; i++) {
if row.get(i) != isWhite { if row.get(i) != isWhite {
counters[counterPosition] += 1; counters[counterPosition] += 1;
} else { } else {
@@ -382,7 +372,6 @@ impl Code128Reader {
let mut bestVariance = MAX_AVG_VARIANCE; let mut bestVariance = MAX_AVG_VARIANCE;
let mut bestMatch = -1_isize; let mut bestMatch = -1_isize;
for startCode in CODE_START_A..=CODE_START_C { 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( let variance = one_d_reader::patternMatchVariance(
&counters, &counters,
&CODE_PATTERNS[startCode as usize], &CODE_PATTERNS[startCode as usize],
@@ -407,7 +396,6 @@ impl Code128Reader {
patternStart += (counters[0] + counters[1]) as usize; patternStart += (counters[0] + counters[1]) as usize;
counters.copy_within(2..(counterPosition - 1 + 2), 0); counters.copy_within(2..(counterPosition - 1 + 2), 0);
// System.arraycopy(counters, 2, counters, 0, counterPosition - 1);
counters[counterPosition - 1] = 0; counters[counterPosition - 1] = 0;
counters[counterPosition] = 0; counters[counterPosition] = 0;
counterPosition -= 1; counterPosition -= 1;
@@ -432,7 +420,6 @@ impl Code128Reader {
let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
let mut bestMatch = -1_isize; let mut bestMatch = -1_isize;
for d in 0..CODE_PATTERNS.len() { for d in 0..CODE_PATTERNS.len() {
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
let pattern = &CODE_PATTERNS[d]; let pattern = &CODE_PATTERNS[d];
let variance = let variance =
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);

View File

@@ -73,13 +73,17 @@ impl OneDimensionalCodeWriter for Code128Writer {
) -> Result<Vec<bool>, Exceptions> { ) -> Result<Vec<bool>, Exceptions> {
let forcedCodeSet = check(contents, hints)?; let forcedCodeSet = check(contents, hints)?;
let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) = let hasCompactionHint = matches!(
hints.get(&EncodeHintType::CODE128_COMPACT) hints.get(&EncodeHintType::CODE128_COMPACT),
{ Some(EncodeHintValue::Code128Compact(true))
*compat );
} else { // let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) =
false // hints.get(&EncodeHintType::CODE128_COMPACT)
}; // {
// *compat
// } else {
// false
// };
// let hasCompactionHint = hints != null && hints.containsKey(EncodeHintType::CODE128_COMPACT) && // let hasCompactionHint = hints != null && hints.containsKey(EncodeHintType::CODE128_COMPACT) &&
// Boolean.parseBoolean(hints.get(EncodeHintType::CODE128_COMPACT).toString()); // 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. // Check for forced code set hint.
let mut forcedCodeSet = -1_i32; let mut forcedCodeSet = -1_i32;
if hints.contains_key(&EncodeHintType::FORCE_CODE_SET) { 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() { match codeSetHint.as_str() {
"A" => forcedCodeSet = CODE_CODE_A as i32, "A" => forcedCodeSet = CODE_CODE_A as i32,
"B" => forcedCodeSet = CODE_CODE_B 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 //Select code to use
let newCodeSet = if forcedCodeSet == -1 { let newCodeSet = if forcedCodeSet == -1 {
chooseCode(contents, position, codeSet) chooseCode(contents, position, codeSet)
.ok_or(Exceptions::IllegalStateException(None))?
} else { } else {
forcedCodeSet as usize // THIS IS RISKY forcedCodeSet as usize // THIS IS RISKY
}; };
@@ -201,7 +206,11 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
if newCodeSet == codeSet { if newCodeSet == codeSet {
// Encode the current character // Encode the current character
// First handle escapes // 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_1 => patternIndex = CODE_FNC_1 as isize,
ESCAPE_FNC_2 => patternIndex = CODE_FNC_2 as isize, ESCAPE_FNC_2 => patternIndex = CODE_FNC_2 as isize,
ESCAPE_FNC_3 => patternIndex = CODE_FNC_3 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 { match codeSet {
CODE_CODE_A => { CODE_CODE_A => {
patternIndex = patternIndex = contents
contents.chars().nth(position).unwrap() as isize - ' ' as isize; .chars()
.nth(position)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
as isize
- ' ' as isize;
if patternIndex < 0 { if patternIndex < 0 {
// everything below a space character comes behind the underscore in the code patterns table // everything below a space character comes behind the underscore in the code patterns table
patternIndex += '`' as isize; patternIndex += '`' as isize;
} }
} }
CODE_CODE_B => { CODE_CODE_B => {
patternIndex = patternIndex = contents
contents.chars().nth(position).unwrap() as isize - ' ' as isize .chars()
.nth(position)
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
as isize
- ' ' as isize
} }
_ => { _ => {
// CODE_CODE_C // CODE_CODE_C
@@ -242,9 +259,9 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
.take(2) .take(2)
.map(|(_u, c)| c) .map(|(_u, c)| c)
.collect(); .collect();
patternIndex = s.parse::<isize>().unwrap(); patternIndex = s.parse::<isize>().map_err(|e| {
// contents[position..position + 2].parse::<isize>().unwrap(); Exceptions::ParseException(Some(format!("issue parsing {s}: {e}")))
// patternIndex = Integer.parseInt(contents.substring(position, position + 2)); })?;
position += 1; position += 1;
} // Also incremented below } // Also incremented below
} }
@@ -308,11 +325,7 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
// Compute code width // Compute code width
let mut codeWidth = 0_usize; let mut codeWidth = 0_usize;
for pattern in &mut *patterns { for pattern in &mut *patterns {
// for (int[] pattern : patterns) { codeWidth += pattern.iter().sum::<usize>();
for width in pattern {
// for (int width : pattern) {
codeWidth += *width;
}
} }
// Compute result // Compute result
@@ -326,99 +339,99 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
result result
} }
fn findCType(value: &str, start: usize) -> CType { fn findCType(value: &str, start: usize) -> Option<CType> {
let last = value.chars().count(); let last = value.chars().count();
if start >= last { 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 { if c == ESCAPE_FNC_1 {
return CType::Fnc1; return Some(CType::Fnc1);
} }
if !('0'..='9').contains(&c) { if !('0'..='9').contains(&c) {
return CType::Uncodable; return Some(CType::Uncodable);
} }
if start + 1 >= last { 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) { 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 { fn chooseCode(value: &str, start: usize, oldCode: usize) -> Option<usize> {
let mut lookahead = findCType(value, start); let mut lookahead = findCType(value, start)?;
if lookahead == CType::OneDigit { if lookahead == CType::OneDigit {
if oldCode == CODE_CODE_A { 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 lookahead == CType::Uncodable {
if start < value.chars().count() { if start < value.chars().count() {
let c = value.chars().nth(start).unwrap(); let c = value.chars().nth(start)?;
if c < ' ' if c < ' '
|| (oldCode == CODE_CODE_A && (c < '`' || (c >= ESCAPE_FNC_1 && c <= ESCAPE_FNC_4))) || (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 // 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 { if oldCode == CODE_CODE_A && lookahead == CType::Fnc1 {
return CODE_CODE_A; return Some(CODE_CODE_A);
} }
if oldCode == CODE_CODE_C { if oldCode == CODE_CODE_C {
// can continue in code C // can continue in code C
return CODE_CODE_C; return Some(CODE_CODE_C);
} }
if oldCode == CODE_CODE_B { if oldCode == CODE_CODE_B {
if lookahead == CType::Fnc1 { 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 // Seen two consecutive digits, see what follows
lookahead = findCType(value, start + 2); lookahead = findCType(value, start + 2)?;
if lookahead == CType::Uncodable || lookahead == CType::OneDigit { 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 { if lookahead == CType::Fnc1 {
// two digits, then FNC_1... // two digits, then FNC_1...
lookahead = findCType(value, start + 3); lookahead = findCType(value, start + 3)?;
if lookahead == CType::TwoDigits { if lookahead == CType::TwoDigits {
// then two more digits, switch // then two more digits, switch
return CODE_CODE_C; return Some(CODE_CODE_C);
} else { } 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. // At this point, there are at least 4 consecutive digits.
// Look ahead to choose whether to switch now or on the next round. // Look ahead to choose whether to switch now or on the next round.
let mut index = start + 4; let mut index = start + 4;
let mut lookahead = findCType(value, index); let mut lookahead = findCType(value, index)?;
while lookahead == CType::TwoDigits { while lookahead == CType::TwoDigits {
// while (lookahead = findCType(value, index)) == CType::TWO_DIGITS { // while (lookahead = findCType(value, index)) == CType::TWO_DIGITS {
index += 2; index += 2;
lookahead = findCType(value, index); lookahead = findCType(value, index)?;
} }
if lookahead == CType::OneDigit { if lookahead == CType::OneDigit {
// odd number of digits, switch later // 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 // Here oldCode == 0, which means we are choosing the initial code
if lookahead == CType::Fnc1 { if lookahead == CType::Fnc1 {
// ignore FNC_1 // ignore FNC_1
lookahead = findCType(value, start + 1); lookahead = findCType(value, start + 1)?;
} }
if lookahead == CType::TwoDigits { if lookahead == CType::TwoDigits {
// at least two digits, start in code C // 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 */ } Latch::None => { /* skip */ }
} }
if charset == Charset::C { 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( addPattern(
&mut patterns, &mut patterns,
CODE_FNC_1, CODE_FNC_1,
@@ -537,7 +555,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
.collect(); .collect();
addPattern( addPattern(
&mut patterns, &mut patterns,
s.parse::<usize>().unwrap(), s.parse::<usize>().map_err(|e| {
Exceptions::ParseException(Some(format!("unable to parse {s} {e}")))
})?,
&mut checkSum, &mut checkSum,
&mut checkWeight, &mut checkWeight,
i, i,
@@ -549,7 +569,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
} }
} else { } else {
// charset A or B // 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_1 => CODE_FNC_1 as isize,
ESCAPE_FNC_2 => CODE_FNC_2 as isize, ESCAPE_FNC_2 => CODE_FNC_2 as isize,
ESCAPE_FNC_3 => CODE_FNC_3 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 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) if ((charset == Charset::A && latch != Latch::Shift)
|| (charset == Charset::B && 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 { 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 { match charset {
Charset::A => { Charset::A => {
c == ESCAPE_FNC_1 c == ESCAPE_FNC_1
@@ -628,10 +661,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|| B.find(c).is_some() || B.find(c).is_some()
} }
Charset::C => { Charset::C => {
let Some(c_p_1) = contents.chars().nth(position + 1) else {
return false;
};
c == ESCAPE_FNC_1 c == ESCAPE_FNC_1
|| (position + 1 < contents.chars().count() || (position + 1 < contents.chars().count() && isDigit(c) && isDigit(c_p_1))
&& isDigit(c)
&& isDigit(contents.chars().nth(position + 1).unwrap()))
} }
_ => false, _ => false,
} }
@@ -647,7 +681,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
memoizedCost: &mut Vec<Vec<u32>>, memoizedCost: &mut Vec<Vec<u32>>,
minPath: &mut Vec<Vec<Latch>>, minPath: &mut Vec<Vec<Latch>>,
) -> Result<u32, Exceptions> { ) -> Result<u32, Exceptions> {
assert!(position < contents.chars().count()); if position >= contents.chars().count() {
return Err(Exceptions::IllegalStateException(None));
}
let mCost = memoizedCost[charset.ordinal()][position]; let mCost = memoizedCost[charset.ordinal()][position];
if mCost > 0 { if mCost > 0 {
return Ok(mCost); return Ok(mCost);
@@ -665,7 +701,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
let mut latch = Latch::None; let mut latch = Latch::None;
if charset != sets[i] { if charset != sets[i] {
cost += 1; cost += 1;
latch = sets[i].into(); //Latch::valueOf(sets[i].toString()); latch = sets[i].into();
} }
if !atEnd { if !atEnd {
cost += encode_with_start_position( cost += encode_with_start_position(
@@ -707,7 +743,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
cost += 1; cost += 1;
latch = Latch::C; 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 1
} else { } else {
2 2

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