mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
Cleanup of many components of the code.
Many unwraps, expects, and panics removed or handled. More rustification of the codebase. Squashed commit of the following: commit 80c6483cf8c819496a7b781f9e3a149d1f18d5fe Author: Henry <henry@azule.info> Date: Fri Feb 10 20:36:57 2023 -0600 add other parsed result option commit 412d92ae585e7bf194697f5282dbc045e448bace Author: Henry <henry@azule.info> Date: Fri Feb 10 19:06:34 2023 -0600 fix some panics commit 9108d3e931aadec00fc0bf346ebc52d24e5d8146 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:56:30 2023 -0600 clippy --fix commit 8cd89d314323f54f342f15fc73297b62d418ac79 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:55:45 2023 -0600 some more cleanup in aztec commit fb7f9242e273b85a4bb212f22a185a0dcbfafc36 Author: Henry <henry@azule.info> Date: Fri Feb 10 18:19:54 2023 -0600 cleanup root commit 4fb7c0639830869149332b29be789e891eade3e7 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:50:15 2023 -0600 format commit 3ac271af657b25fbe5ee39cbdf8859e5aa38ea41 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:43:14 2023 -0600 clippy --fix commit 0c5b4c1477159db93a9da9645039f51cd1a7c574 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 16:04:31 2023 -0600 qrcode cleanup complete commit 70c1d107cc672e45d46567c650c46fece7e7da9c Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:28:25 2023 -0600 clippy --fix commit e13263d0f1f2a13dbb59b6e60d8b871a32babc92 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 13:27:44 2023 -0600 qrcode detector cleanup commit f7f2855099e469fe1091868c6099196705d0ae83 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:48:13 2023 -0600 qrcode decoder commit bdbaaba597b3479639c2ed3726465a69e3004471 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:13:18 2023 -0600 clippy --fix commit fd6dbcaeb1f45dc91ae98f0e7c58aad48d67df78 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 11:12:28 2023 -0600 pdf417 cleanup complete commit 7bbd47604c2639a5eb61bdb5533e71be3bce95a1 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:28 2023 -0600 clippy --fix commit 8f4962b7bb5f133524fe4d3d4948e5672a88c545 Author: Henry Schimke <henry@azule.info> Date: Fri Feb 10 10:39:00 2023 -0600 cleanup on pdf417 hie commit 254c8243953776d3c8704dd81529aadd05d5a94e Author: Henry <henry@azule.info> Date: Fri Feb 10 02:51:21 2023 +0000 partway through pdf417 hle commit d4a5b00fde8c0282b0c6e4175a21c1e111b11533 Author: Henry <henry@azule.info> Date: Wed Feb 8 21:35:25 2023 +0000 clippy --fix commit 2bd4a8e218aa963a88997b50bc5a198f9a88205e Author: Henry <henry@azule.info> Date: Wed Feb 8 21:31:55 2023 +0000 pdf417 decode and detect cleanup commit 05130ac54a72c2303045d64507bf6185aa74e531 Author: Henry Schimke <henry@azule.info> Date: Tue Feb 7 08:06:25 2023 -0600 at decodeTextCompaction in decoded_bit_straem_parser commit 924c023a7d2339dfffa6ef0c4a805fb192576796 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:22:02 2023 -0600 clippy --fix commit 5cfb81a885c22b4b5ec937a79be31d0815def211 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 18:20:22 2023 -0600 oned cleanup commit 0649b64854baf56a8e3314728d4f6cf4063db8b2 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 11:47:28 2023 -0600 rss cleanup commit 2d3127898fc11f7e65d590e983cda799b798b646 Author: Henry Schimke <henry@azule.info> Date: Mon Feb 6 10:19:56 2023 -0600 multi cleanup commit 7e8b43a159083a2096123e6204d4d1d359c59981 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:59 2023 -0600 cargo fmt commit df8285e8da07b4bffd48ca6e596de3f010eb8d9e Author: Henry <henry@azule.info> Date: Sun Feb 5 21:41:29 2023 -0600 maxicode cleanup commit a51f923a14016eb416ca202b2194258808dde3e7 Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:57 2023 -0600 cargo fmt commit 332d7eef4a25318611025a3fcb0b70c604d917be Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:48 2023 -0600 cleanup datamatrix commit eb2311c476a9c9993f271ab6cf9fd359aedca26f Author: Henry <henry@azule.info> Date: Sun Feb 5 21:27:26 2023 -0600 cargo clippy --fix commit 2abaa4c51d287f619d4c7a438f85ba2a30f159cf Author: Henry <henry@azule.info> Date: Sun Feb 5 19:13:02 2023 -0600 finish cleanup in parsers commit 716aa2fbf728716cff36657a5fd80e7bca5276b7 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 17:44:56 2023 -0600 cleanup continues commit 7d843788a49fa9cc82c4616d226c0f882e73612b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 15:15:09 2023 -0600 common cleanup commit fd251866c68f22d450dd428c93d7a3620bf1be27 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 10:24:54 2023 -0600 cleanup reedsolomon commit 132e27ed1468f5c1ce998516ff5a00687217c3e6 Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:52:04 2023 -0600 make MathUtils more generic commit d8352b7fff4cb4f9ecc8e8a969710d26ef410e8b Author: Henry Schimke <henry@azule.info> Date: Sun Feb 5 09:29:33 2023 -0600 cleanup some string handling in ResultParser There may still be some edge cases where multi-byte characters break the parser
This commit is contained in:
@@ -32,7 +32,7 @@ use crate::{
|
||||
RXingResultPoint,
|
||||
};
|
||||
|
||||
use super::{decoder, AztecDetectorResult::AztecDetectorRXingResult};
|
||||
use super::{aztec_detector_result::AztecDetectorRXingResult, decoder};
|
||||
|
||||
/**
|
||||
* Tests {@link Decoder}.
|
||||
|
||||
@@ -185,7 +185,7 @@ fn test_error_in_parameter_locator(data: &str) {
|
||||
// Zooms a bit matrix so that each bit is factor x factor
|
||||
fn make_larger(input: &BitMatrix, factor: u32) -> BitMatrix {
|
||||
let width = input.getWidth();
|
||||
let mut output = BitMatrix::with_single_dimension(width * factor);
|
||||
let mut output = BitMatrix::with_single_dimension(width * factor).expect("new");
|
||||
for inputY in 0..width {
|
||||
// for (int inputY = 0; inputY < width; inputY++) {
|
||||
for inputX in 0..width {
|
||||
@@ -216,7 +216,7 @@ fn get_rotations(matrix0: &BitMatrix) -> Vec<BitMatrix> {
|
||||
// Rotates a square BitMatrix to the right by 90 degrees
|
||||
fn rotate_right(input: &BitMatrix) -> BitMatrix {
|
||||
let width = input.getWidth();
|
||||
let mut result = BitMatrix::with_single_dimension(width);
|
||||
let mut result = BitMatrix::with_single_dimension(width).expect("new");
|
||||
for x in 0..width {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
for y in 0..width {
|
||||
@@ -233,7 +233,7 @@ fn rotate_right(input: &BitMatrix) -> BitMatrix {
|
||||
// matrix to the right, and then flipping it left-to-right
|
||||
fn transpose(input: &BitMatrix) -> BitMatrix {
|
||||
let width = input.getWidth();
|
||||
let mut result = BitMatrix::with_single_dimension(width);
|
||||
let mut result = BitMatrix::with_single_dimension(width).expect("new");
|
||||
for x in 0..width {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
for y in 0..width {
|
||||
@@ -248,7 +248,7 @@ fn transpose(input: &BitMatrix) -> BitMatrix {
|
||||
|
||||
fn clone(input: &BitMatrix) -> BitMatrix {
|
||||
let width = input.getWidth();
|
||||
let mut result = BitMatrix::with_single_dimension(width);
|
||||
let mut result = BitMatrix::with_single_dimension(width).expect("new");
|
||||
for x in 0..width {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
for y in 0..width {
|
||||
|
||||
@@ -20,10 +20,10 @@ use encoding::EncodingRef;
|
||||
|
||||
use crate::{
|
||||
aztec::{
|
||||
aztec_detector_result::AztecDetectorRXingResult,
|
||||
decoder,
|
||||
encoder::HighLevelEncoder,
|
||||
shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
|
||||
AztecDetectorResult::AztecDetectorRXingResult,
|
||||
},
|
||||
BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint,
|
||||
};
|
||||
@@ -810,7 +810,7 @@ fn testModeMessageComplex(compact: bool, layers: u32, words: u32, expected: &str
|
||||
|
||||
fn testStuffBits(wordSize: usize, bits: &str, expected: &str) {
|
||||
let indata = toBitArray(bits);
|
||||
let stuffed = aztec_encoder::stuffBits(&indata, wordSize);
|
||||
let stuffed = aztec_encoder::stuffBits(&indata, wordSize).unwrap();
|
||||
assert_eq!(
|
||||
stripSpace(expected),
|
||||
stripSpace(&stuffed.to_string()),
|
||||
|
||||
@@ -33,7 +33,7 @@ use crate::{
|
||||
*/
|
||||
pub struct AztecDetectorRXingResult {
|
||||
bits: BitMatrix,
|
||||
points: Vec<RXingResultPoint>,
|
||||
points: [RXingResultPoint; 4],
|
||||
compact: bool,
|
||||
nbDatablocks: u32,
|
||||
nbLayers: u32,
|
||||
@@ -59,7 +59,7 @@ impl AztecDetectorRXingResult {
|
||||
) -> Self {
|
||||
Self {
|
||||
bits,
|
||||
points: points.to_vec(),
|
||||
points,
|
||||
compact,
|
||||
nbDatablocks,
|
||||
nbLayers,
|
||||
@@ -130,8 +130,4 @@ impl Reader for AztecReader {
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,36 +53,25 @@ impl Writer for AztecWriter {
|
||||
let mut charset = None; // Do not add any ECI code by default
|
||||
let mut ecc_percent = aztec_encoder::DEFAULT_EC_PERCENT;
|
||||
let mut layers = aztec_encoder::DEFAULT_AZTEC_LAYERS;
|
||||
if hints.contains_key(&EncodeHintType::CHARACTER_SET) {
|
||||
if let EncodeHintValue::CharacterSet(cset_name) = hints
|
||||
.get(&EncodeHintType::CHARACTER_SET)
|
||||
.expect("already knonw presence")
|
||||
{
|
||||
if cset_name != "iso-8859-1" {
|
||||
charset = Some(encoding::label::encoding_from_whatwg_label(cset_name).unwrap());
|
||||
}
|
||||
// dbg!(cset_name);
|
||||
// dbg!(encoding::label::encoding_from_whatwg_label(cset_name).unwrap().name(), encoding::label::encoding_from_whatwg_label(cset_name).unwrap().whatwg_name());
|
||||
if let Some(EncodeHintValue::CharacterSet(cset_name)) =
|
||||
hints.get(&EncodeHintType::CHARACTER_SET)
|
||||
{
|
||||
if cset_name.to_lowercase() != "iso-8859-1" {
|
||||
charset = Some(
|
||||
encoding::label::encoding_from_whatwg_label(cset_name)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?,
|
||||
);
|
||||
}
|
||||
// charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
|
||||
}
|
||||
if hints.contains_key(&EncodeHintType::ERROR_CORRECTION) {
|
||||
if let EncodeHintValue::ErrorCorrection(ecc_level) = hints
|
||||
.get(&EncodeHintType::ERROR_CORRECTION)
|
||||
.expect("key exists")
|
||||
{
|
||||
ecc_percent = ecc_level.parse().expect("should convert to int");
|
||||
}
|
||||
// eccPercent = Integer.parseInt(hints.get(EncodeHintType::ERROR_CORRECTION).toString());
|
||||
if let Some(EncodeHintValue::ErrorCorrection(ecc_level)) =
|
||||
hints.get(&EncodeHintType::ERROR_CORRECTION)
|
||||
{
|
||||
ecc_percent = ecc_level.parse().unwrap_or(23);
|
||||
}
|
||||
if hints.contains_key(&EncodeHintType::AZTEC_LAYERS) {
|
||||
if let EncodeHintValue::AztecLayers(az_layers) = hints
|
||||
.get(&EncodeHintType::AZTEC_LAYERS)
|
||||
.expect("key exists")
|
||||
{
|
||||
layers = *az_layers;
|
||||
}
|
||||
// layers = Integer.parseInt(hints.get(EncodeHintType.AZTEC_LAYERS).toString());
|
||||
if let Some(EncodeHintValue::AztecLayers(az_layers)) =
|
||||
hints.get(&EncodeHintType::AZTEC_LAYERS)
|
||||
{
|
||||
layers = *az_layers;
|
||||
}
|
||||
encode(
|
||||
contents,
|
||||
@@ -121,9 +110,7 @@ fn encode(
|
||||
|
||||
fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMatrix, Exceptions> {
|
||||
let input = code.getMatrix();
|
||||
// if input == null {
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
|
||||
let input_width = input.getWidth();
|
||||
let input_height = input.getHeight();
|
||||
let output_width = width.max(input_width);
|
||||
@@ -152,13 +139,5 @@ fn renderRXingResult(code: &AztecCode, width: u32, height: u32) -> Result<BitMat
|
||||
input_y += 1;
|
||||
output_y += multiple
|
||||
}
|
||||
// for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
|
||||
// // Write the contents of this row of the barcode
|
||||
// for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
|
||||
// if (input.get(inputX, inputY)) {
|
||||
// output.setRegion(outputX, outputY, multiple, multiple);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::{
|
||||
exceptions::Exceptions,
|
||||
};
|
||||
|
||||
use super::AztecDetectorResult::AztecDetectorRXingResult;
|
||||
use super::aztec_detector_result::AztecDetectorRXingResult;
|
||||
|
||||
/**
|
||||
* <p>The main class which implements Aztec Code decoding -- as opposed to locating and extracting
|
||||
@@ -164,7 +164,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String, Exceptions> {
|
||||
result.push_str(
|
||||
&encdr
|
||||
.decode(&decoded_bytes, encoding::DecoderTrap::Strict)
|
||||
.unwrap(),
|
||||
.map_err(|a| Exceptions::IllegalStateException(Some(a.to_string())))?,
|
||||
);
|
||||
|
||||
decoded_bytes.clear();
|
||||
@@ -210,8 +210,17 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String, Exceptions> {
|
||||
// That's including when that mode is a shift.
|
||||
// Our test case dlusbs.png for issue #642 exercises that.
|
||||
latch_table = shift_table; // Latch the current mode, so as to return to Upper after U/S B/S
|
||||
shift_table = getTable(str.chars().nth(5).unwrap());
|
||||
if str.chars().nth(6).unwrap() == 'L' {
|
||||
shift_table = getTable(
|
||||
str.chars()
|
||||
.nth(5)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
);
|
||||
if str
|
||||
.chars()
|
||||
.nth(6)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
== 'L'
|
||||
{
|
||||
latch_table = shift_table;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::{
|
||||
RXingResultPoint, ResultPoint,
|
||||
};
|
||||
|
||||
use super::AztecDetectorResult::AztecDetectorRXingResult;
|
||||
use super::aztec_detector_result::AztecDetectorRXingResult;
|
||||
|
||||
const EXPECTED_CORNER_BITS: [u32; 4] = [
|
||||
0xee0, // 07340 XXX .XX X.. ...
|
||||
@@ -731,11 +731,11 @@ impl<'a> Detector<'_> {
|
||||
}
|
||||
|
||||
fn distance_points(a: &Point, b: &Point) -> f32 {
|
||||
MathUtils::distance_int(a.get_x(), a.get_y(), b.get_x(), b.get_y())
|
||||
MathUtils::distance(a.get_x(), a.get_y(), b.get_x(), b.get_y())
|
||||
}
|
||||
|
||||
fn distance(a: &RXingResultPoint, b: &RXingResultPoint) -> f32 {
|
||||
MathUtils::distance_float(a.getX(), a.getY(), b.getX(), b.getY())
|
||||
MathUtils::distance(a.getX(), a.getY(), b.getX(), b.getY())
|
||||
}
|
||||
|
||||
fn get_dimension(&self) -> u32 {
|
||||
|
||||
@@ -185,7 +185,7 @@ pub fn encode_bytes_with_charset(
|
||||
total_bits_in_layer_var = total_bits_in_layer(layers, compact);
|
||||
word_size = WORD_SIZE[layers as usize];
|
||||
let usable_bits_in_layers = total_bits_in_layer_var - (total_bits_in_layer_var % word_size);
|
||||
stuffed_bits = stuffBits(&bits, word_size as usize);
|
||||
stuffed_bits = stuffBits(&bits, word_size as usize)?;
|
||||
if stuffed_bits.getSize() as u32 + ecc_bits > usable_bits_in_layers {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Data to large for user specified layer".to_owned(),
|
||||
@@ -222,7 +222,7 @@ pub fn encode_bytes_with_charset(
|
||||
// wordSize has changed
|
||||
if stuffed_bits.getSize() == 0 || word_size != WORD_SIZE[layers as usize] {
|
||||
word_size = WORD_SIZE[layers as usize];
|
||||
stuffed_bits = stuffBits(&bits, word_size as usize);
|
||||
stuffed_bits = stuffBits(&bits, word_size as usize)?;
|
||||
}
|
||||
let usable_bits_in_layers =
|
||||
total_bits_in_layer_var - (total_bits_in_layer_var % word_size);
|
||||
@@ -267,7 +267,7 @@ pub fn encode_bytes_with_charset(
|
||||
alignmentMap[origCenter + i] = center + newOffset + 1;
|
||||
}
|
||||
}
|
||||
let mut matrix = BitMatrix::with_single_dimension(matrixSize);
|
||||
let mut matrix = BitMatrix::with_single_dimension(matrixSize)?;
|
||||
|
||||
// dbg!(matrix.to_string());
|
||||
|
||||
@@ -307,13 +307,9 @@ pub fn encode_bytes_with_charset(
|
||||
rowOffset += rowSize * 8;
|
||||
}
|
||||
|
||||
// dbg!(matrix.to_string());
|
||||
|
||||
// draw mode message
|
||||
drawModeMessage(&mut matrix, compact, matrixSize, modeMessage);
|
||||
|
||||
// dbg!(matrix.to_string());
|
||||
|
||||
// draw alignment marks
|
||||
if compact {
|
||||
drawBullsEye(&mut matrix, matrixSize / 2, 5);
|
||||
@@ -385,20 +381,12 @@ pub fn generateModeMessage(
|
||||
) -> Result<BitArray, Exceptions> {
|
||||
let mut mode_message = BitArray::new();
|
||||
if compact {
|
||||
mode_message
|
||||
.appendBits(layers - 1, 2)
|
||||
.expect("should append");
|
||||
mode_message
|
||||
.appendBits(messageSizeInWords - 1, 6)
|
||||
.expect("should append");
|
||||
mode_message.appendBits(layers - 1, 2)?;
|
||||
mode_message.appendBits(messageSizeInWords - 1, 6)?;
|
||||
mode_message = generateCheckWords(&mode_message, 28, 4)?;
|
||||
} else {
|
||||
mode_message
|
||||
.appendBits(layers - 1, 5)
|
||||
.expect("should append");
|
||||
mode_message
|
||||
.appendBits(messageSizeInWords - 1, 11)
|
||||
.expect("should append");
|
||||
mode_message.appendBits(layers - 1, 5)?;
|
||||
mode_message.appendBits(messageSizeInWords - 1, 11)?;
|
||||
mode_message = generateCheckWords(&mode_message, 40, 4)?;
|
||||
}
|
||||
Ok(mode_message)
|
||||
@@ -407,7 +395,7 @@ pub fn generateModeMessage(
|
||||
fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeMessage: BitArray) {
|
||||
let center = matrixSize / 2;
|
||||
if compact {
|
||||
for i in 0..7usize {
|
||||
for i in 0..7_usize {
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
let offset = (center as usize - 3 + i) as u32;
|
||||
if modeMessage.get(i) {
|
||||
@@ -424,7 +412,7 @@ fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeM
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in 0..10usize {
|
||||
for i in 0..10_usize {
|
||||
// for (int i = 0; i < 10; i++) {
|
||||
let offset = (center as usize - 5 + i + i / 5) as u32;
|
||||
if modeMessage.get(i) {
|
||||
@@ -450,13 +438,13 @@ fn generateCheckWords(
|
||||
) -> Result<BitArray, Exceptions> {
|
||||
// bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
|
||||
let message_size_in_words = bitArray.getSize() / wordSize;
|
||||
let mut rs = ReedSolomonEncoder::new(getGF(wordSize)?);
|
||||
let mut rs = ReedSolomonEncoder::new(getGF(wordSize)?)?;
|
||||
let total_words = totalBits / wordSize;
|
||||
let mut message_words = bitsToWords(bitArray, wordSize, total_words);
|
||||
rs.encode(&mut message_words, total_words - message_size_in_words)?;
|
||||
let start_pad = totalBits % wordSize;
|
||||
let mut message_bits = BitArray::new();
|
||||
message_bits.appendBits(0, start_pad).expect("must append");
|
||||
message_bits.appendBits(0, start_pad)?;
|
||||
for message_word in message_words {
|
||||
// for (int messageWord : messageWords) {
|
||||
message_bits.appendBits(message_word as u32, wordSize)?
|
||||
@@ -498,23 +486,9 @@ fn getGF(wordSize: usize) -> Result<GenericGFRef, Exceptions> {
|
||||
"Unsupported word size {wordSize}"
|
||||
)))),
|
||||
}
|
||||
// switch (wordSize) {
|
||||
// case 4:
|
||||
// return GenericGF.AZTEC_PARAM;
|
||||
// case 6:
|
||||
// return GenericGF.AZTEC_DATA_6;
|
||||
// case 8:
|
||||
// return GenericGF.AZTEC_DATA_8;
|
||||
// case 10:
|
||||
// return GenericGF.AZTEC_DATA_10;
|
||||
// case 12:
|
||||
// return GenericGF.AZTEC_DATA_12;
|
||||
// default:
|
||||
// throw new IllegalArgumentException("Unsupported word size " + wordSize);
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
|
||||
pub fn stuffBits(bits: &BitArray, word_size: usize) -> Result<BitArray, Exceptions> {
|
||||
let mut out = BitArray::new();
|
||||
|
||||
let n = bits.getSize() as isize;
|
||||
@@ -530,21 +504,20 @@ pub fn stuffBits(bits: &BitArray, word_size: usize) -> BitArray {
|
||||
}
|
||||
}
|
||||
if (word & mask) == mask {
|
||||
out.appendBits(word & mask, word_size).unwrap();
|
||||
out.appendBits(word & mask, word_size)?;
|
||||
i -= 1;
|
||||
} else if (word & mask) == 0 {
|
||||
out.appendBits(word | 1, word_size).unwrap();
|
||||
out.appendBits(word | 1, word_size)?;
|
||||
i -= 1;
|
||||
} else {
|
||||
out.appendBits(word, word_size).unwrap();
|
||||
out.appendBits(word, word_size)?;
|
||||
}
|
||||
|
||||
i += word_size as isize;
|
||||
}
|
||||
out
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn total_bits_in_layer(layers: u32, compact: bool) -> u32 {
|
||||
((if compact { 88 } else { 112 }) + 16 * layers) * layers
|
||||
// return ((compact ? 88 : 112) + 16 * layers) * layers;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::common::BitArray;
|
||||
use crate::{common::BitArray, Exceptions};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct BinaryShiftToken {
|
||||
@@ -32,28 +32,27 @@ impl BinaryShiftToken {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) -> Result<(), Exceptions> {
|
||||
let bsbc = self.binary_shift_byte_count as usize;
|
||||
for i in 0..bsbc {
|
||||
// for (int i = 0; i < bsbc; i++) {
|
||||
if i == 0 || (i == 31 && bsbc <= 62) {
|
||||
// We need a header before the first character, and before
|
||||
// character 31 when the total byte code is <= 62
|
||||
bit_array.appendBits(31, 5).unwrap(); // BINARY_SHIFT
|
||||
bit_array.appendBits(31, 5)?; // BINARY_SHIFT
|
||||
if bsbc > 62 {
|
||||
bit_array.appendBits(bsbc as u32 - 31, 16).unwrap();
|
||||
bit_array.appendBits(bsbc as u32 - 31, 16)?;
|
||||
} else if i == 0 {
|
||||
// 1 <= binaryShiftByteCode <= 62
|
||||
bit_array.appendBits(bsbc.min(31) as u32, 5).unwrap();
|
||||
bit_array.appendBits(bsbc.min(31) as u32, 5)?;
|
||||
} else {
|
||||
// 32 <= binaryShiftCount <= 62 and i == 31
|
||||
bit_array.appendBits(bsbc as u32 - 31, 5).unwrap();
|
||||
bit_array.appendBits(bsbc as u32 - 31, 5)?;
|
||||
}
|
||||
}
|
||||
bit_array
|
||||
.appendBits(text[self.binary_shift_start as usize + i].into(), 8)
|
||||
.expect("should never fail to append");
|
||||
bit_array.appendBits(text[self.binary_shift_start as usize + i].into(), 8)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
@@ -324,7 +324,7 @@ impl HighLevelEncoder {
|
||||
// Convert it to a bit array, and return.
|
||||
// dbg!(min_state.clone().toBitArray(&self.text).to_string());
|
||||
|
||||
Ok(min_state.toBitArray(&self.text))
|
||||
min_state.toBitArray(&self.text)
|
||||
}
|
||||
|
||||
// We update a set of states for a new character by updating each state
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::common::BitArray;
|
||||
use crate::{common::BitArray, Exceptions};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct SimpleToken {
|
||||
@@ -33,10 +33,8 @@ impl SimpleToken {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, _text: &[u8]) {
|
||||
bit_array
|
||||
.appendBits(self.value as u32, self.bit_count as usize)
|
||||
.expect("append should never fail");
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, _text: &[u8]) -> Result<(), Exceptions> {
|
||||
bit_array.appendBits(self.value as u32, self.bit_count as usize)
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
@@ -85,9 +85,11 @@ impl State {
|
||||
)));
|
||||
// throw new IllegalArgumentException("ECI code must be between 0 and 999999");
|
||||
} else {
|
||||
let eci_digits = encoding::all::ISO_8859_1
|
||||
let Ok(eci_digits) = encoding::all::ISO_8859_1
|
||||
.encode(&format!("{eci}"), encoding::EncoderTrap::Strict)
|
||||
.unwrap();
|
||||
else {
|
||||
return Err(Exceptions::IllegalArgumentException(None))
|
||||
};
|
||||
// let eciDigits = Integer.toString(eci).getBytes(StandardCharsets.ISO_8859_1);
|
||||
token.add(eci_digits.len() as i32, 3); // 1-6: number of ECI digits
|
||||
for eci_digit in &eci_digits {
|
||||
@@ -205,7 +207,7 @@ impl State {
|
||||
new_mode_bit_count <= other.bit_count
|
||||
}
|
||||
|
||||
pub fn toBitArray(self, text: &[u8]) -> BitArray {
|
||||
pub fn toBitArray(self, text: &[u8]) -> Result<BitArray, Exceptions> {
|
||||
let mut symbols = Vec::new();
|
||||
let tok = self.endBinaryShift(text.len() as u32).token;
|
||||
for tkn in tok.into_iter() {
|
||||
@@ -223,22 +225,22 @@ impl State {
|
||||
for symbol in symbols.into_iter().rev() {
|
||||
// for i in (0..symbols.len()).rev() {
|
||||
// for (int i = symbols.size() - 1; i >= 0; i--) {
|
||||
symbol.appendTo(&mut bit_array, text);
|
||||
symbol.appendTo(&mut bit_array, text)?;
|
||||
}
|
||||
bit_array
|
||||
Ok(bit_array)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn calculate_binary_shift_cost(binary_shift_byte_count: u32) -> u32 {
|
||||
if binary_shift_byte_count > 62 {
|
||||
return 21; // B/S with extended length
|
||||
21 // B/S with extended length
|
||||
} else if binary_shift_byte_count > 31 {
|
||||
20 // two B/S
|
||||
} else if binary_shift_byte_count > 0 {
|
||||
10 // one B/S
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if binary_shift_byte_count > 31 {
|
||||
return 20; // two B/S
|
||||
}
|
||||
if binary_shift_byte_count > 0 {
|
||||
return 10; // one B/S
|
||||
}
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::common::BitArray;
|
||||
use crate::{common::BitArray, Exceptions};
|
||||
|
||||
use super::{BinaryShiftToken, SimpleToken};
|
||||
|
||||
@@ -26,12 +26,14 @@ pub enum TokenType {
|
||||
}
|
||||
|
||||
impl TokenType {
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) {
|
||||
pub fn appendTo(&self, bit_array: &mut BitArray, text: &[u8]) -> Result<(), Exceptions> {
|
||||
// let token = &self.tokens[self.current_pointer];
|
||||
match self {
|
||||
TokenType::Simple(a) => a.appendTo(bit_array, text),
|
||||
TokenType::BinaryShift(a) => a.appendTo(bit_array, text),
|
||||
TokenType::Empty => panic!("cannot appendTo on Empty final item"),
|
||||
TokenType::Empty => Err(Exceptions::IllegalStateException(Some(String::from(
|
||||
"cannot appendTo on Empty final item",
|
||||
)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,27 +97,6 @@ impl IntoIterator for Token {
|
||||
}
|
||||
}
|
||||
|
||||
// pub enum Token{
|
||||
// Simple(Rc<SimpleToken>),
|
||||
// BinaryShift(),
|
||||
// Empty,
|
||||
// }
|
||||
|
||||
// pub trait TokenTrait {
|
||||
// fn getPrevious(&self)->&Token;
|
||||
|
||||
// fn add(&self, value: i32, bitCount: u32) -> Token{
|
||||
// Token::Simple(Rc::new(SimpleToken::new(self, value, bitCount)))
|
||||
// }
|
||||
|
||||
// fn addBinaryShift(&self, start: i32, byteCount: u32) -> &Token; //{
|
||||
// // //int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);
|
||||
// // return new BinaryShiftToken(this, start, byteCount);
|
||||
// // }
|
||||
|
||||
// fn appendTo(&self, bitArray: BitArray, text: &[u8]);
|
||||
// }
|
||||
|
||||
impl Default for Token {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
mod AztecDetectorResult;
|
||||
mod aztec_detector_result;
|
||||
mod aztec_reader;
|
||||
mod aztec_writer;
|
||||
pub mod decoder;
|
||||
|
||||
@@ -78,6 +78,8 @@ impl BinaryBitmap {
|
||||
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
* fetched using getBlackRow(), so don't mix and match between them.
|
||||
*
|
||||
* Panics if the binarizer cannot be created.
|
||||
*
|
||||
* @return The 2D array of bits for the image (true means black).
|
||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||
*/
|
||||
@@ -99,6 +101,8 @@ impl BinaryBitmap {
|
||||
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
* fetched using getBlackRow(), so don't mix and match between them.
|
||||
*
|
||||
* Panics if the binarizer cannot be created.
|
||||
*
|
||||
* @return The 2D array of bits for the image (true means black).
|
||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||
*/
|
||||
@@ -125,6 +129,8 @@ impl BinaryBitmap {
|
||||
* Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
* original data rather than a copy. Only callable if isCropSupported() is true.
|
||||
*
|
||||
* Panics if the binarizer cannot be created.
|
||||
*
|
||||
* @param left The left coordinate, which must be in [0,getWidth())
|
||||
* @param top The top coordinate, which must be in [0,getHeight())
|
||||
* @param width The width of the rectangle to crop.
|
||||
@@ -140,10 +146,6 @@ impl BinaryBitmap {
|
||||
self.binarizer
|
||||
.createBinarizer(newSource.expect("new lum source expected")),
|
||||
);
|
||||
// Self {
|
||||
// binarizer: self.binarizer.clone(),
|
||||
// matrix: Some(self.getBlackMatrix().crop(top, left, height, width)),
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,6 +159,8 @@ impl BinaryBitmap {
|
||||
* Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* Panics if the binarizer cannot be created.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
pub fn rotateCounterClockwise(&mut self) -> BinaryBitmap {
|
||||
@@ -165,19 +169,14 @@ impl BinaryBitmap {
|
||||
self.binarizer
|
||||
.createBinarizer(newSource.expect("new lum source expected")),
|
||||
);
|
||||
// let mut new_matrix = self.getBlackMatrix().clone();
|
||||
// new_matrix.rotate90();
|
||||
|
||||
// Self {
|
||||
// binarizer: self.binarizer.clone(),
|
||||
// matrix: Some(new_matrix),
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* Panics if the binarizer cannot be created.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {
|
||||
|
||||
@@ -54,46 +54,6 @@ impl BufferedImageLuminanceSource {
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Self {
|
||||
// if image.getType() == BufferedImage.TYPE_BYTE_GRAY {
|
||||
// this.image = image;
|
||||
// } else {
|
||||
// int sourceWidth = image.getWidth();
|
||||
// int sourceHeight = image.getHeight();
|
||||
// if (left + width > sourceWidth || top + height > sourceHeight) {
|
||||
// throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
|
||||
// }
|
||||
|
||||
// this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
|
||||
|
||||
// WritableRaster raster = this.image.getRaster();
|
||||
// int[] buffer = new int[width];
|
||||
// for (int y = top; y < top + height; y++) {
|
||||
// image.getRGB(left, y, width, 1, buffer, 0, sourceWidth);
|
||||
// for (int x = 0; x < width; x++) {
|
||||
// int pixel = buffer[x];
|
||||
|
||||
// // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent
|
||||
// // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a
|
||||
// // barcode image. Force any such pixel to be white:
|
||||
// if ((pixel & 0xFF000000) == 0) {
|
||||
// // white, so we know its luminance is 255
|
||||
// buffer[x] = 0xFF;
|
||||
// } else {
|
||||
// // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
|
||||
// // (306*R) >> 10 is approximately equal to R*0.299, and so on.
|
||||
// // 0x200 >> 10 is 0.5, it implements rounding.
|
||||
// buffer[x] =
|
||||
// (306 * ((pixel >> 16) & 0xFF) +
|
||||
// 601 * ((pixel >> 8) & 0xFF) +
|
||||
// 117 * (pixel & 0xFF) +
|
||||
// 0x200) >> 10;
|
||||
// }
|
||||
// }
|
||||
// raster.setPixels(left, y, width, 1, buffer);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
let img = image.to_rgba8();
|
||||
|
||||
let mut raster: ImageBuffer<_, Vec<_>> = ImageBuffer::new(image.width(), image.height());
|
||||
@@ -116,29 +76,6 @@ impl BufferedImageLuminanceSource {
|
||||
}
|
||||
}
|
||||
|
||||
// for pixel in img.pixels() {
|
||||
// // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent
|
||||
// // black (0 alpha, and then 0 RGB). They are often used, of course as the "white" area in a
|
||||
// // barcode image. Force any such pixel to be white:
|
||||
// let [red,green,blue,alpha] = pixel.0;
|
||||
// if (alpha & 0xFF) == 0 {
|
||||
// // white, so we know its luminance is 255
|
||||
// raster.push(0xFF);
|
||||
// // buffer[x] = 0xFF;
|
||||
// } else {
|
||||
// // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),
|
||||
// // (306*R) >> 10 is approximately equal to R*0.299, and so on.
|
||||
// // 0x200 >> 10 is 0.5, it implements rounding.
|
||||
// raster.push((
|
||||
// (306 * ((red as u32 >> 16) & 0xFF) +
|
||||
// 601 * ((green as u32 >> 8) & 0xFF) +
|
||||
// 117 * (blue as u32 & 0xFF) +
|
||||
// 0x200) >> 10) as u8);
|
||||
// }
|
||||
// }
|
||||
|
||||
// let ib:ImageBuffer<Luma<u8>, Vec<u8>> = ImageBuffer::from_raw(image.width() , image.height(), raster).unwrap();
|
||||
|
||||
Self {
|
||||
image: Rc::new(DynamicImage::from(raster)),
|
||||
width,
|
||||
@@ -146,14 +83,6 @@ impl BufferedImageLuminanceSource {
|
||||
left,
|
||||
top,
|
||||
}
|
||||
|
||||
// Self {
|
||||
// image: DynamicImage::from(image.to_luma8()),
|
||||
// width: width,
|
||||
// height: height,
|
||||
// left: left,
|
||||
// top: top,
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,20 +90,19 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
fn getRow(&self, y: usize) -> Vec<u8> {
|
||||
let width = self.getWidth(); // - self.left as usize;
|
||||
|
||||
let pixels: Vec<u8> = self
|
||||
.image
|
||||
.as_luma8()
|
||||
.unwrap()
|
||||
.rows()
|
||||
.nth(y + self.top as usize)
|
||||
.unwrap()
|
||||
.skip(self.left as usize)
|
||||
.take(width)
|
||||
.map(|&p| p.0[0])
|
||||
.collect();
|
||||
|
||||
// The underlying raster of image consists of bytes with the luminance values
|
||||
// row[..width].clone_from_slice(&pixels[..]);
|
||||
let pixels: Vec<u8> = || -> Option<Vec<u8>> {
|
||||
Some(
|
||||
self.image
|
||||
.as_luma8()?
|
||||
.rows()
|
||||
.nth(y + self.top as usize)?
|
||||
.skip(self.left as usize)
|
||||
.take(width)
|
||||
.map(|&p| p.0[0])
|
||||
.collect(),
|
||||
)
|
||||
}()
|
||||
.unwrap_or_default();
|
||||
|
||||
pixels
|
||||
}
|
||||
@@ -221,7 +149,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
}
|
||||
|
||||
fn invert(&mut self) {
|
||||
// self.image.borrow_mut().invert();
|
||||
let mut img = (*self.image).clone();
|
||||
img.invert();
|
||||
self.image = Rc::new(img);
|
||||
@@ -238,18 +165,7 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> {
|
||||
// Ok(Box::new(BufferedImageLuminanceSource::with_details(
|
||||
// self.image
|
||||
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
|
||||
// self.left + left as u32,
|
||||
// self.top + top as u32,
|
||||
// width,
|
||||
// height,
|
||||
// )))
|
||||
Ok(Box::new(Self {
|
||||
// image: self
|
||||
// .image
|
||||
// .crop_imm(left as u32, top as u32, width as u32, height as u32),
|
||||
image: self.image.clone(),
|
||||
width,
|
||||
height,
|
||||
@@ -265,9 +181,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
fn rotateCounterClockwise(
|
||||
&self,
|
||||
) -> Result<Box<dyn LuminanceSource>, crate::exceptions::Exceptions> {
|
||||
// Ok(Box::new(BufferedImageLuminanceSource::new(
|
||||
// self.image.rotate270(),
|
||||
// )))
|
||||
let img = self.image.rotate270();
|
||||
Ok(Box::new(Self {
|
||||
width: img.width() as usize,
|
||||
@@ -290,7 +203,6 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
|
||||
let new_img = DynamicImage::from(img);
|
||||
|
||||
// Ok(Box::new(BufferedImageLuminanceSource::new(new_img)))
|
||||
Ok(Box::new(Self {
|
||||
width: new_img.width() as usize,
|
||||
height: new_img.height() as usize,
|
||||
|
||||
@@ -50,17 +50,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
let note = ResultParser::matchSinglePrefixedField("MEMORY:", &rawText, '\r', false)
|
||||
.unwrap_or_default();
|
||||
let address = ResultParser::matchSinglePrefixedField("ADD:", &rawText, '\r', true);
|
||||
let addresses = if address.is_none() {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![address?]
|
||||
};
|
||||
let addresses = address.map_or_else(Vec::new, |add| vec![add]);
|
||||
|
||||
if let Ok(new_data) = AddressBookParsedRXingResult::with_details(
|
||||
if let Some(nm) = ResultParser::maybeWrap(name) {
|
||||
nm
|
||||
} else {
|
||||
Vec::new()
|
||||
},
|
||||
ResultParser::maybeWrap(name).unwrap_or_default(),
|
||||
Vec::new(),
|
||||
pronunciation.unwrap_or_default(),
|
||||
phoneNumbers,
|
||||
@@ -90,10 +83,12 @@ fn matchMultipleValuePrefix(prefix: &str, rawText: &str) -> Vec<String> {
|
||||
// for (int i = 1; i <= 3; i++) {
|
||||
let value =
|
||||
ResultParser::matchSinglePrefixedField(&format!("{prefix}{i}:"), rawText, '\r', true);
|
||||
if value.is_none() {
|
||||
|
||||
if let Some(value) = value {
|
||||
values.push(value)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
values.push(value.unwrap());
|
||||
}
|
||||
|
||||
values
|
||||
|
||||
@@ -43,35 +43,32 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
if !rawText.starts_with("MECARD:") {
|
||||
return None;
|
||||
}
|
||||
let rawName = ResultParser::match_do_co_mo_prefixed_field("N:", &rawText)?;
|
||||
let rawName = ResultParser::match_docomo_prefixed_field("N:", &rawText)?;
|
||||
|
||||
let name = parseName(&rawName[0]);
|
||||
let pronunciation =
|
||||
ResultParser::match_single_do_co_mo_prefixed_field("SOUND:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let phoneNumbers =
|
||||
ResultParser::match_do_co_mo_prefixed_field("TEL:", &rawText).unwrap_or_default();
|
||||
let emails =
|
||||
ResultParser::match_do_co_mo_prefixed_field("EMAIL:", &rawText).unwrap_or_default();
|
||||
let note = ResultParser::match_single_do_co_mo_prefixed_field("NOTE:", &rawText, false)
|
||||
let pronunciation = ResultParser::match_single_docomo_prefixed_field("SOUND:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let addresses =
|
||||
ResultParser::match_do_co_mo_prefixed_field("ADR:", &rawText).unwrap_or_default();
|
||||
let mut birthday = ResultParser::match_single_do_co_mo_prefixed_field("BDAY:", &rawText, true)
|
||||
let phoneNumbers =
|
||||
ResultParser::match_docomo_prefixed_field("TEL:", &rawText).unwrap_or_default();
|
||||
let emails = ResultParser::match_docomo_prefixed_field("EMAIL:", &rawText).unwrap_or_default();
|
||||
let note = ResultParser::match_single_docomo_prefixed_field("NOTE:", &rawText, false)
|
||||
.unwrap_or_default();
|
||||
let addresses = ResultParser::match_docomo_prefixed_field("ADR:", &rawText).unwrap_or_default();
|
||||
let mut birthday = ResultParser::match_single_docomo_prefixed_field("BDAY:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
if !ResultParser::isStringOfDigits(&birthday, 8) {
|
||||
// No reason to throw out the whole card because the birthday is formatted wrong.
|
||||
birthday = String::default();
|
||||
}
|
||||
let urls = ResultParser::match_do_co_mo_prefixed_field("URL:", &rawText).unwrap_or_default();
|
||||
let urls = ResultParser::match_docomo_prefixed_field("URL:", &rawText).unwrap_or_default();
|
||||
|
||||
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
|
||||
// honor it when found in the wild.
|
||||
let org = ResultParser::match_single_do_co_mo_prefixed_field("ORG:", &rawText, true)
|
||||
let org = ResultParser::match_single_docomo_prefixed_field("ORG:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Ok(new_adb) = AddressBookParsedRXingResult::with_details(
|
||||
ResultParser::maybeWrap(Some(name))?,
|
||||
ResultParser::maybeWrap(Some(name)).unwrap_or_default(),
|
||||
Vec::new(),
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
@@ -100,12 +97,4 @@ fn parseName(name: &str) -> String {
|
||||
} else {
|
||||
name.to_owned()
|
||||
}
|
||||
// let comma = name.indexOf(',');
|
||||
// if (comma >= 0) {
|
||||
// // Format may be last,first; switch it around
|
||||
// return name.substring(comma + 1) + ' ' + name.substring(0, comma);
|
||||
// }
|
||||
// return name;
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
@@ -41,36 +41,36 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let firstName = ResultParser::match_single_do_co_mo_prefixed_field("N:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let lastName = ResultParser::match_single_do_co_mo_prefixed_field("X:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let firstName =
|
||||
ResultParser::match_single_docomo_prefixed_field("N:", &rawText, true).unwrap_or_default();
|
||||
let lastName =
|
||||
ResultParser::match_single_docomo_prefixed_field("X:", &rawText, true).unwrap_or_default();
|
||||
let fullName = buildName(&firstName, &lastName);
|
||||
let title = ResultParser::match_single_do_co_mo_prefixed_field("T:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let org = ResultParser::match_single_do_co_mo_prefixed_field("C:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let addresses = ResultParser::match_do_co_mo_prefixed_field("A:", &rawText);
|
||||
let phoneNumber1 = ResultParser::match_single_do_co_mo_prefixed_field("B:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let phoneNumber2 = ResultParser::match_single_do_co_mo_prefixed_field("M:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let phoneNumber3 = ResultParser::match_single_do_co_mo_prefixed_field("F:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let email = ResultParser::match_single_do_co_mo_prefixed_field("E:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let title =
|
||||
ResultParser::match_single_docomo_prefixed_field("T:", &rawText, true).unwrap_or_default();
|
||||
let org =
|
||||
ResultParser::match_single_docomo_prefixed_field("C:", &rawText, true).unwrap_or_default();
|
||||
let addresses = ResultParser::match_docomo_prefixed_field("A:", &rawText);
|
||||
let phoneNumber1 =
|
||||
ResultParser::match_single_docomo_prefixed_field("B:", &rawText, true).unwrap_or_default();
|
||||
let phoneNumber2 =
|
||||
ResultParser::match_single_docomo_prefixed_field("M:", &rawText, true).unwrap_or_default();
|
||||
let phoneNumber3 =
|
||||
ResultParser::match_single_docomo_prefixed_field("F:", &rawText, true).unwrap_or_default();
|
||||
let email =
|
||||
ResultParser::match_single_docomo_prefixed_field("E:", &rawText, true).unwrap_or_default();
|
||||
|
||||
if let Ok(adb) = AddressBookParsedRXingResult::with_details(
|
||||
ResultParser::maybeWrap(Some(fullName))?,
|
||||
ResultParser::maybeWrap(Some(fullName)).unwrap_or_default(),
|
||||
Vec::new(),
|
||||
String::default(),
|
||||
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
|
||||
Vec::new(),
|
||||
ResultParser::maybeWrap(Some(email))?,
|
||||
ResultParser::maybeWrap(Some(email)).unwrap_or_default(),
|
||||
Vec::new(),
|
||||
String::default(),
|
||||
String::default(),
|
||||
addresses?,
|
||||
addresses.unwrap_or_default(),
|
||||
Vec::new(),
|
||||
org,
|
||||
String::default(),
|
||||
@@ -82,23 +82,6 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
// return new AddressBookParsedRXingResult(maybeWrap(fullName),
|
||||
// null,
|
||||
// null,
|
||||
// buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
|
||||
// null,
|
||||
// maybeWrap(email),
|
||||
// null,
|
||||
// null,
|
||||
// null,
|
||||
// addresses,
|
||||
// null,
|
||||
// org,
|
||||
// null,
|
||||
// title,
|
||||
// null,
|
||||
// null);
|
||||
}
|
||||
|
||||
fn buildPhoneNumbers(number1: String, number2: String, number3: String) -> Vec<String> {
|
||||
|
||||
@@ -30,20 +30,16 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
if !rawText.starts_with("MEBKM:") {
|
||||
return None;
|
||||
}
|
||||
let title = ResultParser::match_single_do_co_mo_prefixed_field("TITLE:", rawText, true);
|
||||
let rawUri = ResultParser::match_do_co_mo_prefixed_field("URL:", rawText);
|
||||
rawUri.as_ref()?;
|
||||
let uri = rawUri?[0].clone();
|
||||
if URIResultParser::is_basically_valid_uri(&uri) {
|
||||
let title = ResultParser::match_single_docomo_prefixed_field("TITLE:", rawText, true);
|
||||
let rawUri = ResultParser::match_docomo_prefixed_field("URL:", rawText)?;
|
||||
|
||||
let uri = &rawUri[0];
|
||||
if URIResultParser::is_basically_valid_uri(uri) {
|
||||
Some(ParsedClientResult::URIResult(URIParsedRXingResult::new(
|
||||
uri,
|
||||
uri.to_string(),
|
||||
title.unwrap_or_default(),
|
||||
)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
// return URIRXingResultParser.isBasicallyValidURI(uri) ? new URIParsedRXingResult(uri, title) : null;
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
@@ -112,7 +112,7 @@ impl CalendarParsedRXingResult {
|
||||
) -> Result<Self, Exceptions> {
|
||||
let start = Self::parseDate(startString.clone())?;
|
||||
let end = if endString.is_empty() {
|
||||
let durationMS = Self::parseDurationMS(&durationString);
|
||||
let durationMS = Self::parseDurationMS(&durationString)?;
|
||||
if durationMS < 0i64 {
|
||||
-1i64
|
||||
} else {
|
||||
@@ -165,7 +165,6 @@ impl CalendarParsedRXingResult {
|
||||
* @throws ParseException if not able to parse as a date
|
||||
*/
|
||||
fn parseDate(when: String) -> Result<i64, Exceptions> {
|
||||
// let date_time_regex = Regex::new(DATE_TIME).unwrap();
|
||||
if !DATE_TIME.is_match(&when) {
|
||||
return Err(Exceptions::ParseException(Some(when)));
|
||||
}
|
||||
@@ -178,37 +177,23 @@ impl CalendarParsedRXingResult {
|
||||
// http://code.google.com/p/android/issues/detail?id=8330
|
||||
return match Utc.datetime_from_str(&format!("{}T000000Z", &when,), date_format_string) {
|
||||
Ok(dtm) => Ok(dtm.timestamp()),
|
||||
Err(e) => panic!("{}", e),
|
||||
// Err(e) => Err(Exceptions::ParseException(format!(
|
||||
// "couldn't parse string: {}",
|
||||
// e
|
||||
// ))),
|
||||
Err(e) => Err(Exceptions::ParseException(Some(e.to_string()))),
|
||||
};
|
||||
// let dtm = DateTime::parse_from_str(&when, date_format_string).unwrap();
|
||||
// let dtm = dtm.with_timezone(&Utc);
|
||||
|
||||
// // format.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
// // return format.parse(when).getTime();
|
||||
// return Ok(dtm.timestamp());
|
||||
}
|
||||
// The when string can be local time, or UTC if it ends with a Z
|
||||
if when.len() == 16 && when.chars().nth(15).unwrap() == 'Z' {
|
||||
if when.len() == 16
|
||||
&& when
|
||||
.chars()
|
||||
.nth(15)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
== 'Z'
|
||||
{
|
||||
return match Utc.datetime_from_str(&when, "%Y%m%dT%H%M%SZ") {
|
||||
Ok(dtm) => Ok(dtm.with_timezone(&Utc).timestamp()),
|
||||
Err(e) => Err(Exceptions::ParseException(Some(format!(
|
||||
"couldn't parse string: {e}"
|
||||
)))),
|
||||
};
|
||||
// let dtm = DateTime::parse_from_str(&when, "%Y%m%dT%H%M%S").unwrap().with_timezone(&Utc);
|
||||
// //let milliseconds = Self::parseDateTimeString(&when[0..15]);
|
||||
// // Calendar calendar = new GregorianCalendar();
|
||||
// // // Account for time zone difference
|
||||
// // milliseconds += calendar.get(Calendar.ZONE_OFFSET);
|
||||
// // // Might need to correct for daylight savings time, but use target time since
|
||||
// // // now might be in DST but not then, or vice versa
|
||||
// // calendar.setTime(new Date(milliseconds));
|
||||
// // return milliseconds + calendar.get(Calendar.DST_OFFSET);
|
||||
// return Ok(dtm.timestamp());
|
||||
}
|
||||
// Try once more, with weird tz formatting
|
||||
if when.len() > 16 {
|
||||
@@ -258,9 +243,9 @@ impl CalendarParsedRXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn parseDurationMS(durationString: &str) -> i64 {
|
||||
fn parseDurationMS(durationString: &str) -> Result<i64, Exceptions> {
|
||||
if durationString.is_empty() {
|
||||
return -1;
|
||||
return Ok(-1);
|
||||
}
|
||||
// let regex = Regex::new(RFC2445_DURATION).unwrap();
|
||||
if let Some(m) = RFC2445_DURATION.captures(durationString) {
|
||||
@@ -270,13 +255,16 @@ impl CalendarParsedRXingResult {
|
||||
// for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {
|
||||
let fieldValue = m.get(i + 1);
|
||||
if let Some(parseable) = fieldValue {
|
||||
let z = parseable.as_str().parse::<i64>().unwrap();
|
||||
let z = parseable
|
||||
.as_str()
|
||||
.parse::<i64>()
|
||||
.map_err(|e| Exceptions::ParseException(Some(e.to_string())))?;
|
||||
durationMS += unit * z;
|
||||
}
|
||||
}
|
||||
durationMS
|
||||
Ok(durationMS)
|
||||
} else {
|
||||
-1
|
||||
Ok(-1)
|
||||
}
|
||||
// if (!m.matches()) {
|
||||
// return -1L;
|
||||
|
||||
@@ -41,8 +41,6 @@ use super::{
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
// let comma_regex = Regex::new(",").unwrap();
|
||||
// private static final Pattern COMMA = Pattern.compile(",");
|
||||
let rawText = ResultParser::getMassagedText(result);
|
||||
if rawText.starts_with("mailto:") || rawText.starts_with("MAILTO:") {
|
||||
// If it starts with mailto:, assume it is definitely trying to be an email address
|
||||
@@ -55,11 +53,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
// hostEmail = hostEmail.substring(0, queryStart);
|
||||
// }
|
||||
// try {
|
||||
let tmp = if let Ok(res) = ResultParser::urlDecode(hostEmail) {
|
||||
res
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let tmp = ResultParser::urlDecode(hostEmail).ok()?;
|
||||
hostEmail = tmp.as_str();
|
||||
// } catch (IllegalArgumentException iae) {
|
||||
// return null;
|
||||
|
||||
@@ -43,16 +43,16 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
if !rawText.starts_with("MATMSG:") {
|
||||
return None;
|
||||
}
|
||||
let tos = ResultParser::match_do_co_mo_prefixed_field("TO:", &rawText)?;
|
||||
let tos = ResultParser::match_docomo_prefixed_field("TO:", &rawText)?;
|
||||
|
||||
for to in &tos {
|
||||
if !isBasicallyValidEmailAddress(to, &ATEXT_ALPHANUMERIC) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let subject = ResultParser::match_single_do_co_mo_prefixed_field("SUB:", &rawText, false)
|
||||
let subject = ResultParser::match_single_docomo_prefixed_field("SUB:", &rawText, false)
|
||||
.unwrap_or_default();
|
||||
let body = ResultParser::match_single_do_co_mo_prefixed_field("BODY:", &rawText, false)
|
||||
let body = ResultParser::match_single_docomo_prefixed_field("BODY:", &rawText, false)
|
||||
.unwrap_or_default();
|
||||
Some(ParsedClientResult::EmailResult(
|
||||
EmailAddressParsedRXingResult::with_details(tos, Vec::new(), Vec::new(), subject, body),
|
||||
|
||||
@@ -110,47 +110,6 @@ impl ExpandedProductParsedRXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean equals(Object o) {
|
||||
// if (!(o instanceof ExpandedProductParsedRXingResult)) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// ExpandedProductParsedRXingResult other = (ExpandedProductParsedRXingResult) o;
|
||||
|
||||
// return Objects.equals(productID, other.productID)
|
||||
// && Objects.equals(sscc, other.sscc)
|
||||
// && Objects.equals(lotNumber, other.lotNumber)
|
||||
// && Objects.equals(productionDate, other.productionDate)
|
||||
// && Objects.equals(bestBeforeDate, other.bestBeforeDate)
|
||||
// && Objects.equals(expirationDate, other.expirationDate)
|
||||
// && Objects.equals(weight, other.weight)
|
||||
// && Objects.equals(weightType, other.weightType)
|
||||
// && Objects.equals(weightIncrement, other.weightIncrement)
|
||||
// && Objects.equals(price, other.price)
|
||||
// && Objects.equals(priceIncrement, other.priceIncrement)
|
||||
// && Objects.equals(priceCurrency, other.priceCurrency)
|
||||
// && Objects.equals(uncommonAIs, other.uncommonAIs);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// int hash = Objects.hashCode(productID);
|
||||
// hash ^= Objects.hashCode(sscc);
|
||||
// hash ^= Objects.hashCode(lotNumber);
|
||||
// hash ^= Objects.hashCode(productionDate);
|
||||
// hash ^= Objects.hashCode(bestBeforeDate);
|
||||
// hash ^= Objects.hashCode(expirationDate);
|
||||
// hash ^= Objects.hashCode(weight);
|
||||
// hash ^= Objects.hashCode(weightType);
|
||||
// hash ^= Objects.hashCode(weightIncrement);
|
||||
// hash ^= Objects.hashCode(price);
|
||||
// hash ^= Objects.hashCode(priceIncrement);
|
||||
// hash ^= Objects.hashCode(priceCurrency);
|
||||
// hash ^= Objects.hashCode(uncommonAIs);
|
||||
// return hash;
|
||||
// }
|
||||
|
||||
pub fn getRawText(&self) -> &str {
|
||||
&self.rawText
|
||||
}
|
||||
|
||||
@@ -24,16 +24,6 @@
|
||||
* http://www.piramidepse.com/
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.BarcodeFormat;
|
||||
// import com.google.zxing.RXingResult;
|
||||
// import org.junit.Assert;
|
||||
// import org.junit.Test;
|
||||
|
||||
// import java.util.HashMap;
|
||||
// import java.util.Map;
|
||||
|
||||
// /**
|
||||
// * @author Antonio Manuel Benjumea Conde, Servinform, S.A.
|
||||
// * @author Agustín Delgado, Servinform, S.A.
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn parse(result: &crate::RXingResult) -> Option<super::ParsedClientResult> {
|
||||
// return None;
|
||||
// }
|
||||
i += ai.len() + 2;
|
||||
let value = findValue(i, &rawText);
|
||||
let value = findValue(i, &rawText)?;
|
||||
i += value.len();
|
||||
match ai.as_str() {
|
||||
"00" => sscc = value,
|
||||
@@ -260,13 +260,13 @@ fn findAIvalue(i: usize, rawText: &str) -> Option<String> {
|
||||
Some(buf)
|
||||
}
|
||||
|
||||
fn findValue(i: usize, rawText: &str) -> String {
|
||||
fn findValue(i: usize, rawText: &str) -> Option<String> {
|
||||
let mut buf = String::new();
|
||||
let rawTextAux = &rawText[i..];
|
||||
|
||||
for index in 0..rawTextAux.len() {
|
||||
// for (int index = 0; index < rawTextAux.length(); index++) {
|
||||
let c = rawTextAux.chars().nth(index).unwrap();
|
||||
let c = rawTextAux.chars().nth(index)?;
|
||||
if c == '(' {
|
||||
// We look for a new AI. If it doesn't exist (ERROR), we continue
|
||||
// with the iteration
|
||||
@@ -281,5 +281,5 @@ fn findValue(i: usize, rawText: &str) -> String {
|
||||
buf.push(c);
|
||||
}
|
||||
}
|
||||
buf
|
||||
Some(buf)
|
||||
}
|
||||
|
||||
@@ -50,31 +50,41 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
|
||||
""
|
||||
};
|
||||
|
||||
let latitude = if let Some(la) = captures.get(1) {
|
||||
if let Ok(laf64) = la.as_str().parse::<f64>() {
|
||||
if !(-90.0..=90.0).contains(&laf64) {
|
||||
return None;
|
||||
}
|
||||
laf64
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
let latitude = captures.get(1)?.as_str().parse::<f64>().ok()?;
|
||||
if !(-90.0..=90.0).contains(&latitude) {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
|
||||
let longitude = if let Some(lo) = captures.get(2) {
|
||||
if let Ok(lof64) = lo.as_str().parse::<f64>() {
|
||||
if !(-180.0..=180.0).contains(&lof64) {
|
||||
return None;
|
||||
}
|
||||
lof64
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
// let latitude = if let Some(la) = captures.get(1) {
|
||||
// if let Ok(laf64) = la.as_str().parse::<f64>() {
|
||||
// if !(-90.0..=90.0).contains(&laf64) {
|
||||
// return None;
|
||||
// }
|
||||
// laf64
|
||||
// } else {
|
||||
// return None;
|
||||
// }
|
||||
// } else {
|
||||
// return None;
|
||||
// };
|
||||
|
||||
let longitude = captures.get(2)?.as_str().parse::<f64>().ok()?;
|
||||
if !(-180.0..=180.0).contains(&longitude) {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
|
||||
// let longitude = if let Some(lo) = captures.get(2) {
|
||||
// if let Ok(lof64) = lo.as_str().parse::<f64>() {
|
||||
// if !(-180.0..=180.0).contains(&lof64) {
|
||||
// return None;
|
||||
// }
|
||||
// lof64
|
||||
// } else {
|
||||
// return None;
|
||||
// }
|
||||
// } else {
|
||||
// return None;
|
||||
// };
|
||||
|
||||
let altitude = if let Some(al) = captures.get(3) {
|
||||
if let Ok(alf64) = al.as_str().parse::<f64>() {
|
||||
@@ -88,28 +98,6 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
// let longitude;
|
||||
// let altitude;
|
||||
// try {
|
||||
// // latitude = Double.parseDouble(matcher.group(1));
|
||||
// // if (latitude > 90.0 || latitude < -90.0) {
|
||||
// // return null;
|
||||
// // }
|
||||
// // longitude = Double.parseDouble(matcher.group(2));
|
||||
// // if (longitude > 180.0 || longitude < -180.0) {
|
||||
// // return null;
|
||||
// // }
|
||||
// // if (matcher.group(3) == null) {
|
||||
// // altitude = 0.0;
|
||||
// // } else {
|
||||
// // altitude = Double.parseDouble(matcher.group(3));
|
||||
// // if (altitude < 0.0) {
|
||||
// // return null;
|
||||
// // }
|
||||
// // }
|
||||
// } catch (NumberFormatException ignored) {
|
||||
// return null;
|
||||
// }
|
||||
Some(ParsedClientResult::GeoResult(GeoParsedRXingResult::new(
|
||||
latitude,
|
||||
longitude,
|
||||
@@ -119,10 +107,4 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
// Matcher matcher = GEO_URL_PATTERN.matcher(rawText);
|
||||
// if (!matcher.matches()) {
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
// }
|
||||
|
||||
@@ -36,4 +36,5 @@ pub enum ParsedRXingResultType {
|
||||
WIFI,
|
||||
ISBN,
|
||||
VIN,
|
||||
OTHER,
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let rawText = ResultParser::getMassagedText(result);
|
||||
if !ResultParser::isStringOfDigits(&rawText, rawText.len()) {
|
||||
return None;
|
||||
@@ -50,7 +51,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
// Expand UPC-E for purposes of searching
|
||||
if format == &BarcodeFormat::UPC_E && rawText.len() == 8 {
|
||||
// unimplemented!("UPCEReader is required to parse this");
|
||||
crate::oned::convertUPCEtoUPCA(&rawText)
|
||||
crate::oned::convertUPCEtoUPCA(&rawText)?
|
||||
} else {
|
||||
rawText.clone()
|
||||
};
|
||||
|
||||
@@ -102,11 +102,14 @@ const BYTE_ORDER_MARK: &str = "\u{feff}"; //private static final String BYTE_ORD
|
||||
// const EMPTY_STR_ARRAY: &'static str = "";
|
||||
|
||||
pub fn getMassagedText(result: &RXingResult) -> String {
|
||||
let mut text = result.getText().clone();
|
||||
if text.starts_with(BYTE_ORDER_MARK) {
|
||||
text = text[1..].to_owned();
|
||||
}
|
||||
text
|
||||
result
|
||||
.getText()
|
||||
.trim_start_matches(BYTE_ORDER_MARK)
|
||||
.to_owned()
|
||||
// if text.starts_with(BYTE_ORDER_MARK) {
|
||||
// text = &text[1..];
|
||||
// }
|
||||
// text.to_owned()
|
||||
}
|
||||
|
||||
pub fn parse_result_with_parsers(
|
||||
@@ -181,19 +184,18 @@ pub fn maybe_append_string(value: &str, result: &mut String) {
|
||||
}
|
||||
|
||||
pub fn maybe_append_multiple(value: &[String], result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
for s in value {
|
||||
// for (String s : value) {
|
||||
if !s.is_empty() {
|
||||
if !result.is_empty() {
|
||||
result.push('\n');
|
||||
}
|
||||
result.push_str(s);
|
||||
for s in value {
|
||||
// for (String s : value) {
|
||||
if !s.is_empty() {
|
||||
if !result.is_empty() {
|
||||
result.push('\n');
|
||||
}
|
||||
result.push_str(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn maybeWrap(value: Option<String>) -> Option<Vec<String>> {
|
||||
if value.is_none() {
|
||||
None
|
||||
@@ -207,14 +209,12 @@ pub fn unescapeBackslash(escaped: &str) -> String {
|
||||
if backslash.is_none() {
|
||||
return escaped.to_owned();
|
||||
}
|
||||
let max = escaped.len();
|
||||
let mut unescaped = String::with_capacity(max - 1);
|
||||
let max = escaped.chars().count();
|
||||
let backslash = backslash.unwrap_or(0);
|
||||
unescaped.push_str(&escaped[0..backslash]);
|
||||
let mut unescaped = escaped.chars().take(backslash).collect::<String>();
|
||||
unescaped.reserve(max - 1);
|
||||
let mut nextIsEscaped = false;
|
||||
for i in backslash..max {
|
||||
// for (int i = backslash; i < max; i++) {
|
||||
let c = escaped.chars().nth(i).unwrap();
|
||||
for c in escaped.chars().skip(backslash) {
|
||||
if nextIsEscaped || c != '\\' {
|
||||
unescaped.push(c);
|
||||
nextIsEscaped = false;
|
||||
@@ -239,6 +239,7 @@ pub fn parseHexDigit(c: char) -> i32 {
|
||||
-1
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn isStringOfDigits(value: &str, length: usize) -> bool {
|
||||
!value.is_empty() && length > 0 && length == value.len() && DIGITS.is_match(value)
|
||||
}
|
||||
@@ -249,10 +250,10 @@ pub fn isSubstringOfDigits(value: &str, offset: usize, length: usize) -> bool {
|
||||
}
|
||||
let max = offset + length;
|
||||
|
||||
let sub_seq = &value[offset..max];
|
||||
let sub_seq: String = value.chars().skip(offset).take(length).collect(); //&value[offset..max];
|
||||
|
||||
let is_a_match = if let Some(mtch) = DIGITS.find(sub_seq) {
|
||||
mtch.start() == 0 && mtch.end() == sub_seq.len()
|
||||
let is_a_match = if let Some(mtch) = DIGITS.find(&sub_seq) {
|
||||
mtch.start() == 0 && mtch.end() == sub_seq.chars().count()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
@@ -266,16 +267,11 @@ pub fn parseNameValuePairs(uri: &str) -> Option<HashMap<String, String>> {
|
||||
let mut result = HashMap::with_capacity(3);
|
||||
let paramStart = paramStart.unwrap_or(0);
|
||||
|
||||
let sub_str = &uri[paramStart + 1..];
|
||||
let sub_str = &uri[paramStart + 1..]; // This is likely ok because we're looking for a specific single byte charaacter
|
||||
let list = sub_str.split(AMPERSAND);
|
||||
for keyValue in list {
|
||||
appendKeyValue(keyValue, &mut result);
|
||||
}
|
||||
|
||||
// for keyValue in Self::AMPERSAND.split(uri[paramStart + 1..]) {
|
||||
// // for (String keyValue : AMPERSAND.split(uri.substring(paramStart + 1))) {
|
||||
// Self::appendKeyValue(keyValue, &mut result);
|
||||
// }
|
||||
Some(result)
|
||||
}
|
||||
|
||||
@@ -304,9 +300,9 @@ pub fn urlDecode(encoded: &str) -> Result<String, Exceptions> {
|
||||
if let Ok(decoded) = decode(encoded) {
|
||||
Ok(decoded.to_string())
|
||||
} else {
|
||||
Err(Exceptions::IllegalStateException(Some(
|
||||
"UnsupportedEncodingException".to_owned(),
|
||||
)))
|
||||
Err(Exceptions::IllegalStateException(Some(String::from(
|
||||
"UnsupportedEncodingException",
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +325,7 @@ pub fn matchPrefixedField(
|
||||
// if (i < 0) {
|
||||
// break;
|
||||
// }
|
||||
i += prefix.len(); // Skip past this prefix we found to start
|
||||
i += prefix.chars().count(); // Skip past this prefix we found to start
|
||||
let start = i; // Found the start of a match here
|
||||
let mut more = true;
|
||||
while more {
|
||||
@@ -337,7 +333,7 @@ pub fn matchPrefixedField(
|
||||
i += next_index;
|
||||
} else {
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
i = rawText.len();
|
||||
i = rawText.chars().count();
|
||||
more = false;
|
||||
continue;
|
||||
}
|
||||
@@ -411,11 +407,11 @@ pub fn matchSinglePrefixedField(
|
||||
// return matches == null ? null : matches[0];
|
||||
}
|
||||
|
||||
pub fn match_do_co_mo_prefixed_field(prefix: &str, raw_text: &str) -> Option<Vec<String>> {
|
||||
pub fn match_docomo_prefixed_field(prefix: &str, raw_text: &str) -> Option<Vec<String>> {
|
||||
matchPrefixedField(prefix, raw_text, ';', true)
|
||||
}
|
||||
|
||||
pub fn match_single_do_co_mo_prefixed_field(
|
||||
pub fn match_single_docomo_prefixed_field(
|
||||
prefix: &str,
|
||||
raw_text: &str,
|
||||
trim: bool,
|
||||
@@ -426,7 +422,9 @@ pub fn match_single_do_co_mo_prefixed_field(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
client::result::{ParsedClientResult, TextParsedRXingResult},
|
||||
client::result::{
|
||||
OtherParsedResult, ParsedClientResult, ParsedRXingResult, TextParsedRXingResult,
|
||||
},
|
||||
RXingResult,
|
||||
};
|
||||
|
||||
@@ -449,4 +447,32 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(p_res.to_string(), "parsed with parser");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_other_parser() {
|
||||
let result: RXingResult = RXingResult::new(
|
||||
"text",
|
||||
vec![12, 23, 54, 23],
|
||||
Vec::new(),
|
||||
crate::BarcodeFormat::EAN_13,
|
||||
);
|
||||
let p_res = parse_result_with_parser(&result, |v| {
|
||||
Some(ParsedClientResult::Other(OtherParsedResult::new(Box::new(
|
||||
v.getRawBytes().clone(),
|
||||
))))
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(p_res.getDisplayRXingResult(), "Any { .. }");
|
||||
|
||||
if let ParsedClientResult::Other(opr) = p_res {
|
||||
if let Some(d) = opr.get_data().downcast_ref::<Vec<u8>>() {
|
||||
assert_eq!(d, result.getRawBytes());
|
||||
} else {
|
||||
panic!("did not get vec<u8>");
|
||||
}
|
||||
} else {
|
||||
panic!("did not get ParsedClientResult::Other");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.Collection;
|
||||
// import java.util.List;
|
||||
// import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>Parses an "sms:" URI result, which specifies a number to SMS.
|
||||
* See <a href="http://tools.ietf.org/html/rfc5724"> RFC 5724</a> on this.</p>
|
||||
@@ -38,7 +29,6 @@
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class SMSMMSRXingResultParser extends RXingResultParser {
|
||||
use crate::RXingResult;
|
||||
|
||||
use super::{ParsedClientResult, ResultParser, SMSParsedRXingResult};
|
||||
@@ -121,21 +111,13 @@ fn add_number_via(numbers: &mut Vec<String>, vias: &mut Vec<String>, number_part
|
||||
return;
|
||||
}
|
||||
if let Some(number_end) = number_part.find(';') {
|
||||
// if numberEnd < 0 {
|
||||
numbers.push(number_part[..number_end].to_string());
|
||||
let maybe_via = &number_part[number_end + 1..];
|
||||
let via = if let Some(stripped) = maybe_via.strip_prefix("via=") {
|
||||
stripped
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let via = maybe_via.strip_prefix("via=").unwrap_or_default();
|
||||
if !via.is_empty() {
|
||||
vias.push(via.to_owned());
|
||||
}
|
||||
} else {
|
||||
numbers.push(number_part.to_owned());
|
||||
//vias.push(String::default());
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
@@ -49,11 +49,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
body = &number[body_start + 1..];
|
||||
number = &number[..body_start];
|
||||
}
|
||||
// let bodyStart = number.indexOf(':');
|
||||
// if (bodyStart >= 0) {
|
||||
// body = number.substring(bodyStart + 1);
|
||||
// number = number.substring(0, bodyStart);
|
||||
// }
|
||||
|
||||
Some(ParsedClientResult::SMSResult(
|
||||
SMSParsedRXingResult::with_singles(
|
||||
number.to_owned(),
|
||||
@@ -62,5 +58,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
body.to_owned(),
|
||||
),
|
||||
))
|
||||
// return new SMSParsedRXingResult(number, null, null, body);
|
||||
}
|
||||
|
||||
@@ -44,16 +44,7 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
subject = &subject[..new_colon];
|
||||
}
|
||||
}
|
||||
// let colon = emailAddress.indexOf(':');
|
||||
// if (colon >= 0) {
|
||||
// subject = emailAddress.substring(colon + 1);
|
||||
// emailAddress = emailAddress.substring(0, colon);
|
||||
// colon = subject.indexOf(':');
|
||||
// if (colon >= 0) {
|
||||
// body = subject.substring(colon + 1);
|
||||
// subject = subject.substring(0, colon);
|
||||
// }
|
||||
// }
|
||||
|
||||
Some(ParsedClientResult::EmailResult(
|
||||
EmailAddressParsedRXingResult::with_details(
|
||||
vec![emailAddress.to_owned()],
|
||||
@@ -63,9 +54,4 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
body.to_owned(),
|
||||
),
|
||||
))
|
||||
// return new EmailAddressParsedRXingResult(new String[] {emailAddress},
|
||||
// null,
|
||||
// null,
|
||||
// subject,
|
||||
// body);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ impl URIParsedRXingResult {
|
||||
let nextSlash = if let Some(pos) = uri[start..].find('/') {
|
||||
pos + start
|
||||
} else {
|
||||
uri.len()
|
||||
uri.chars().count()
|
||||
};
|
||||
// let nextSlash = uri.indexOf('/', start);
|
||||
// if (nextSlash < 0) {
|
||||
|
||||
@@ -39,18 +39,16 @@ static ALLOWED_URI_CHARS: Lazy<Regex> = Lazy::new(|| {
|
||||
});
|
||||
static USER_IN_HOST: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(":/*([^/@]+)@[^/]+").expect("Regex patterns should always copile"));
|
||||
|
||||
/// See http://www.ietf.org/rfc/rfc2396.txt
|
||||
static URL_WITH_PROTOCOL_PATTERN: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new("[a-zA-Z][a-zA-Z0-9+-.]+:").unwrap());
|
||||
|
||||
/// (host name elements; allow up to say 6 domain elements), (maybe port), (query, path or nothing)
|
||||
static URL_WITHOUT_PROTOCOL_PATTERN: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new("([a-zA-Z0-9\\-]+\\.){1,6}[a-zA-Z]{2,}(:\\d{1,5})?(/|\\?|$)").unwrap());
|
||||
|
||||
const ALLOWED_URI_CHARS_PATTERN: &str = "[-._~:/?#\\[\\]@!$&'()*+,;=%A-Za-z0-9]+";
|
||||
// const USER_IN_HOST: &'static str = ":/*([^/@]+)@[^/]+";
|
||||
/// See http://www.ietf.org/rfc/rfc2396.txt
|
||||
// const URL_WITH_PROTOCOL_PATTERN: &'static str = "[a-zA-Z][a-zA-Z0-9+-.]+:";
|
||||
/// (host name elements; allow up to say 6 domain elements), (maybe port), (query, path or nothing)
|
||||
// const URL_WITHOUT_PROTOCOL_PATTERN: &'static str =
|
||||
// "([a-zA-Z0-9\\-]+\\.){1,6}[a-zA-Z]{2,}(:\\d{1,5})?(/|\\?|$)";
|
||||
|
||||
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
let raw_text = ResultParser::getMassagedText(result);
|
||||
|
||||
@@ -14,20 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
// import java.io.ByteArrayOutputStream;
|
||||
// import java.io.UnsupportedEncodingException;
|
||||
// import java.net.URI;
|
||||
// import java.nio.charset.StandardCharsets;
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.Collection;
|
||||
// import java.util.List;
|
||||
// import java.util.regex.Matcher;
|
||||
// import java.util.regex.Pattern;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
@@ -14,13 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.BarcodeFormat;
|
||||
// import com.google.zxing.RXingResult;
|
||||
// import org.junit.Assert;
|
||||
// import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link VINParsedRXingResult}.
|
||||
*/
|
||||
|
||||
@@ -14,13 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.BarcodeFormat;
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
// import java.util.regex.Pattern;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use crate::{
|
||||
@@ -46,26 +39,18 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
|
||||
let raw_text_res = result.getText().trim();
|
||||
let raw_text = IOQ_MATCHER.replace_all(raw_text_res, "").to_string();
|
||||
// rawText = IOQ.matcher(rawText).replaceAll("").trim();
|
||||
|
||||
AZ09_MATCHER.find(&raw_text)?;
|
||||
// if !AZ09.matcher(rawText).matches() {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
let check_cs = check_checksum(&raw_text).unwrap_or(false);
|
||||
if !check_cs {
|
||||
return None;
|
||||
}
|
||||
let wmi = &raw_text[..3];
|
||||
// try {
|
||||
// if (!checkChecksum(rawText)) {
|
||||
// return null;
|
||||
// }
|
||||
// String wmi = rawText.substring(0, 3);
|
||||
|
||||
let country_code = country_code(wmi).unwrap_or("");
|
||||
let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_'));
|
||||
if model_year.is_err() {
|
||||
return None;
|
||||
}
|
||||
let model_year = model_year(raw_text.chars().nth(9).unwrap_or('_')).ok();
|
||||
|
||||
Some(ParsedClientResult::VINResult(VINParsedRXingResult::new(
|
||||
raw_text.to_owned(),
|
||||
wmi.to_owned(),
|
||||
@@ -73,22 +58,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
raw_text[9..17].to_owned(),
|
||||
country_code.to_owned(),
|
||||
raw_text[3..8].to_owned(),
|
||||
model_year.unwrap(),
|
||||
raw_text.chars().nth(10).unwrap(),
|
||||
model_year?,
|
||||
raw_text.chars().nth(10)?,
|
||||
raw_text[11..].to_owned(),
|
||||
)))
|
||||
// return new VINParsedRXingResult(rawText,
|
||||
// wmi,
|
||||
// rawText.substring(3, 9),
|
||||
// rawText.substring(9, 17),
|
||||
// countryCode(wmi),
|
||||
// rawText.substring(3, 8),
|
||||
// modelYear(rawText.charAt(9)),
|
||||
// rawText.charAt(10),
|
||||
// rawText.substring(11));
|
||||
// } catch (IllegalArgumentException iae) {
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
|
||||
const IOQ: &str = "[IOQ]";
|
||||
@@ -97,10 +70,17 @@ const AZ09: &str = "[A-Z0-9]{17}";
|
||||
fn check_checksum(vin: &str) -> Result<bool, Exceptions> {
|
||||
let mut sum = 0;
|
||||
for i in 0..vin.len() {
|
||||
// for (int i = 0; i < vin.length(); i++) {
|
||||
sum += vin_position_weight(i + 1)? as u32 * vin_char_value(vin.chars().nth(i).unwrap())?;
|
||||
sum += vin_position_weight(i + 1)? as u32
|
||||
* vin_char_value(
|
||||
vin.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?,
|
||||
)?;
|
||||
}
|
||||
let check_to_char = vin.chars().nth(8).unwrap();
|
||||
let check_to_char = vin
|
||||
.chars()
|
||||
.nth(8)
|
||||
.ok_or(Exceptions::IllegalArgumentException(None))?;
|
||||
let expected_check_char = check_char((sum % 11) as u8)?;
|
||||
Ok(check_to_char == expected_check_char)
|
||||
}
|
||||
@@ -115,21 +95,6 @@ fn vin_char_value(c: char) -> Result<u32, Exceptions> {
|
||||
"vin char out of range".to_owned(),
|
||||
))),
|
||||
}
|
||||
// if c >= 'A' && c <= 'I' {
|
||||
// return Ok((c as u8 as u32 - 'A' as u8 as u32) + 1);
|
||||
// }
|
||||
// if c >= 'J' && c <= 'R' {
|
||||
// return Ok((c as u8 as u32 - 'J' as u8 as u32) + 1);
|
||||
// }
|
||||
// if c >= 'S' && c <= 'Z' {
|
||||
// return Ok((c as u8 as u32 - 'S' as u8 as u32) + 2);
|
||||
// }
|
||||
// if c >= '0' && c <= '9' {
|
||||
// return Ok(c as u8 as u32 - '0' as u8 as u32);
|
||||
// }
|
||||
// Err(Exceptions::IllegalArgumentException(
|
||||
// "vin char out of range".to_owned(),
|
||||
// ))
|
||||
}
|
||||
|
||||
fn vin_position_weight(position: usize) -> Result<usize, Exceptions> {
|
||||
@@ -142,19 +107,6 @@ fn vin_position_weight(position: usize) -> Result<usize, Exceptions> {
|
||||
"vin position weight out of bounds".to_owned(),
|
||||
))),
|
||||
}
|
||||
// if position >= 1 && position <= 7 {
|
||||
// return 9 - position;
|
||||
// }
|
||||
// if position == 8 {
|
||||
// return 10;
|
||||
// }
|
||||
// if position == 9 {
|
||||
// return 0;
|
||||
// }
|
||||
// if position >= 10 && position <= 17 {
|
||||
// return 19 - position;
|
||||
// }
|
||||
// throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
fn check_char(remainder: u8) -> Result<char, Exceptions> {
|
||||
@@ -165,15 +117,6 @@ fn check_char(remainder: u8) -> Result<char, Exceptions> {
|
||||
"remainder too high".to_owned(),
|
||||
))),
|
||||
}
|
||||
// if remainder < 10 {
|
||||
// return Ok(('0' as u8 + remainder) as char);
|
||||
// }
|
||||
// if remainder == 10 {
|
||||
// return Ok('X');
|
||||
// }
|
||||
// Err(Exceptions::IllegalArgumentException(
|
||||
// "remainder too high".to_owned(),
|
||||
// ))
|
||||
}
|
||||
|
||||
fn model_year(c: char) -> Result<u32, Exceptions> {
|
||||
@@ -189,33 +132,11 @@ fn model_year(c: char) -> Result<u32, Exceptions> {
|
||||
"model year argument out of range",
|
||||
)))),
|
||||
}
|
||||
// if c >= 'E' && c <= 'H' {
|
||||
// return (c - 'E') + 1984;
|
||||
// }
|
||||
// if c >= 'J' && c <= 'N' {
|
||||
// return (c - 'J') + 1988;
|
||||
// }
|
||||
// if c == 'P' {
|
||||
// return 1993;
|
||||
// }
|
||||
// if c >= 'R' && c <= 'T' {
|
||||
// return (c - 'R') + 1994;
|
||||
// }
|
||||
// if c >= 'V' && c <= 'Y' {
|
||||
// return (c - 'V') + 1997;
|
||||
// }
|
||||
// if c >= '1' && c <= '9' {
|
||||
// return (c - '1') + 2001;
|
||||
// }
|
||||
// if c >= 'A' && c <= 'D' {
|
||||
// return (c - 'A') + 2010;
|
||||
// }
|
||||
// throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
fn country_code(wmi: &str) -> Option<&'static str> {
|
||||
let c1 = wmi.chars().next().unwrap();
|
||||
let c2 = wmi.chars().nth(1).unwrap();
|
||||
let c1 = wmi.chars().next()?;
|
||||
let c2 = wmi.chars().nth(1)?;
|
||||
match c1 {
|
||||
'1' | '4' | '5' => Some("US"),
|
||||
'2' => Some("CA"),
|
||||
|
||||
@@ -14,15 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
use crate::client::result::{ParsedClientResult, WifiParsedRXingResult};
|
||||
|
||||
use super::ResultParser;
|
||||
|
||||
// @SuppressWarnings("checkstyle:lineLength")
|
||||
/**
|
||||
* <p>Parses a WIFI configuration string. Strings will be of the form:</p>
|
||||
*
|
||||
@@ -40,9 +35,6 @@ use super::ResultParser;
|
||||
* @author Sean Owen
|
||||
* @author Steffen Kieß
|
||||
*/
|
||||
// pub struct WifiRXingResultParser {}
|
||||
|
||||
// impl RXingResultParser for WifiRXingResultParser {
|
||||
pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientResult> {
|
||||
const WIFI_TEST: &str = "WIFI:";
|
||||
|
||||
@@ -53,35 +45,29 @@ pub fn parse(theRXingResult: &crate::RXingResult) -> Option<super::ParsedClientR
|
||||
let rawText = rawText_unstripped[WIFI_TEST.len()..].to_owned();
|
||||
let ssid =
|
||||
ResultParser::matchSinglePrefixedField("S:", &rawText, ';', false).unwrap_or_default();
|
||||
|
||||
if ssid.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pass =
|
||||
ResultParser::matchSinglePrefixedField("P:", &rawText, ';', false).unwrap_or_default();
|
||||
let n_type =
|
||||
if let Some(nt) = ResultParser::matchSinglePrefixedField("T:", &rawText, ';', false) {
|
||||
nt
|
||||
} else {
|
||||
String::from("nopass")
|
||||
};
|
||||
|
||||
let n_type = ResultParser::matchSinglePrefixedField("T:", &rawText, ';', false)
|
||||
.unwrap_or(String::from("nopass"));
|
||||
|
||||
// Unfortunately, in the past, H: was not just used for boolean 'hidden', but 'phase 2 method'.
|
||||
// To try to retain backwards compatibility, we set one or the other based on whether the string
|
||||
// is 'true' or 'false':
|
||||
let mut hidden = false;
|
||||
let mut phase2Method = ResultParser::matchSinglePrefixedField("PH2:", &rawText, ';', false);
|
||||
let _hValue = if let Some(hv) =
|
||||
ResultParser::matchSinglePrefixedField("H:", &rawText, ';', false)
|
||||
{
|
||||
if let Some(hv) = ResultParser::matchSinglePrefixedField("H:", &rawText, ';', false) {
|
||||
// If PH2 was specified separately, or if the value is clearly boolean, interpret it as 'hidden'
|
||||
if phase2Method.is_some() || "true" == hv.to_lowercase() || "false" == hv.to_lowercase() {
|
||||
hidden = hv.parse().unwrap(); //Boolean.parseBoolean(hValue);
|
||||
hidden = hv.parse().ok()?;
|
||||
} else {
|
||||
phase2Method = Some(hv.clone());
|
||||
phase2Method = Some(hv);
|
||||
}
|
||||
hv
|
||||
} else {
|
||||
String::default()
|
||||
};
|
||||
|
||||
let identity =
|
||||
|
||||
@@ -60,6 +60,9 @@ pub use SMSParsedResult::*;
|
||||
pub use URIParsedResult::*;
|
||||
pub use VINParsedResult::*;
|
||||
|
||||
mod other_parsed_result;
|
||||
pub use other_parsed_result::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod AddressBookParsedResultTestCase;
|
||||
#[cfg(test)]
|
||||
@@ -102,6 +105,7 @@ pub enum ParsedClientResult {
|
||||
AddressBookResult(AddressBookParsedRXingResult),
|
||||
CalendarEventResult(CalendarParsedRXingResult),
|
||||
ExpandedProductResult(ExpandedProductParsedRXingResult),
|
||||
Other(OtherParsedResult),
|
||||
}
|
||||
|
||||
impl ParsedRXingResult for ParsedClientResult {
|
||||
@@ -120,6 +124,7 @@ impl ParsedRXingResult for ParsedClientResult {
|
||||
ParsedClientResult::AddressBookResult(a) => a.getType(),
|
||||
ParsedClientResult::CalendarEventResult(a) => a.getType(),
|
||||
ParsedClientResult::ExpandedProductResult(a) => a.getType(),
|
||||
ParsedClientResult::Other(a) => a.getType(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +143,7 @@ impl ParsedRXingResult for ParsedClientResult {
|
||||
ParsedClientResult::AddressBookResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::CalendarEventResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::ExpandedProductResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::Other(a) => a.getDisplayRXingResult(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
src/client/result/other_parsed_result.rs
Normal file
37
src/client/result/other_parsed_result.rs
Normal 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 {}
|
||||
@@ -39,7 +39,9 @@ fn test_random() {
|
||||
// }
|
||||
assert_eq!(
|
||||
encoding::all::UTF_8.name(),
|
||||
StringUtils::guessCharset(&bytes, &HashMap::new()).name()
|
||||
StringUtils::guessCharset(&bytes, &HashMap::new())
|
||||
.unwrap()
|
||||
.name()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,8 +102,8 @@ fn test_utf16_le() {
|
||||
}
|
||||
|
||||
fn do_test(bytes: &[u8], charset: EncodingRef, encoding: &str) {
|
||||
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new());
|
||||
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new());
|
||||
let guessedCharset = StringUtils::guessCharset(bytes, &HashMap::new()).unwrap();
|
||||
let guessedEncoding = StringUtils::guessEncoding(bytes, &HashMap::new()).unwrap();
|
||||
assert_eq!(charset.name(), guessedCharset.name());
|
||||
assert_eq!(encoding, guessedEncoding);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ impl BitArray {
|
||||
}
|
||||
}
|
||||
|
||||
// For testing only
|
||||
/// For testing only
|
||||
#[cfg(test)]
|
||||
pub fn with_initial_values(bits: Vec<u32>, size: usize) -> Self {
|
||||
Self { bits, size }
|
||||
|
||||
@@ -53,8 +53,8 @@ impl BitMatrix {
|
||||
*
|
||||
* @param dimension height and width
|
||||
*/
|
||||
pub fn with_single_dimension(dimension: u32) -> Self {
|
||||
Self::new(dimension, dimension).unwrap()
|
||||
pub fn with_single_dimension(dimension: u32) -> Result<Self, Exceptions> {
|
||||
Self::new(dimension, dimension)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,8 +134,16 @@ impl BitMatrix {
|
||||
let mut nRows = 0;
|
||||
let mut pos = 0;
|
||||
while pos < string_representation.chars().count() {
|
||||
if string_representation.chars().nth(pos).unwrap() == '\n'
|
||||
|| string_representation.chars().nth(pos).unwrap() == '\r'
|
||||
if string_representation
|
||||
.chars()
|
||||
.nth(pos)
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
== '\n'
|
||||
|| string_representation
|
||||
.chars()
|
||||
.nth(pos)
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
== '\r'
|
||||
{
|
||||
if bitsPos > rowStartPos {
|
||||
//if rowLength == -1 {
|
||||
@@ -181,15 +189,12 @@ impl BitMatrix {
|
||||
nRows += 1;
|
||||
}
|
||||
|
||||
let mut matrix = BitMatrix::new(rowLength.try_into().unwrap(), nRows)?;
|
||||
let mut matrix = BitMatrix::new(rowLength as u32, nRows)?;
|
||||
for (i, bit) in bits.iter().enumerate().take(bitsPos) {
|
||||
// for i in 0..bitsPos {
|
||||
//for (int i = 0; i < bitsPos; i++) {
|
||||
if *bit {
|
||||
matrix.set(
|
||||
(i % rowLength).try_into().unwrap(),
|
||||
(i / rowLength).try_into().unwrap(),
|
||||
);
|
||||
matrix.set((i % rowLength) as u32, (i / rowLength) as u32);
|
||||
}
|
||||
}
|
||||
Ok(matrix)
|
||||
|
||||
@@ -33,7 +33,7 @@ static BIT_MATRIX_POINTS: [u32; 6] = [1, 2, 2, 0, 3, 1];
|
||||
|
||||
#[test]
|
||||
fn test_get_set() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(33);
|
||||
let mut matrix = BitMatrix::with_single_dimension(33).expect("new");
|
||||
assert_eq!(33, matrix.getHeight());
|
||||
for y in 0..33 {
|
||||
// for (int y = 0; y < 33; y++) {
|
||||
@@ -55,7 +55,7 @@ fn test_get_set() {
|
||||
|
||||
#[test]
|
||||
fn test_set_region() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
|
||||
matrix.setRegion(1, 1, 3, 3).expect("must set");
|
||||
for y in 0..5 {
|
||||
// for (int y = 0; y < 5; y++) {
|
||||
@@ -71,7 +71,7 @@ fn test_set_region() {
|
||||
|
||||
#[test]
|
||||
fn test_enclosing() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
|
||||
assert!(matrix.getEnclosingRectangle().is_none());
|
||||
matrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
assert_eq!(vec![1, 1, 1, 1], matrix.getEnclosingRectangle().unwrap());
|
||||
@@ -83,7 +83,7 @@ fn test_enclosing() {
|
||||
|
||||
#[test]
|
||||
fn test_on_bit() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
let mut matrix = BitMatrix::with_single_dimension(5).expect("new");
|
||||
assert!(matrix.getTopLeftOnBit().is_none());
|
||||
assert!(matrix.getBottomRightOnBit().is_none());
|
||||
matrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
|
||||
@@ -90,13 +90,18 @@ impl GridSampler for DefaultGridSampler {
|
||||
let mut x = 0;
|
||||
while x < max {
|
||||
// for (int x = 0; x < max; x += 2) {
|
||||
if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight()
|
||||
{
|
||||
return Err(Exceptions::NotFoundException(Some(
|
||||
// if points[x] as u32 >= image.getWidth() || points[x + 1] as u32 >= image.getHeight()
|
||||
// {
|
||||
// return Err(Exceptions::NotFoundException(Some(
|
||||
// "index out of bounds, see documentation in file for explanation".to_owned(),
|
||||
// )));
|
||||
// }
|
||||
if image
|
||||
.try_get(points[x] as u32, points[x + 1] as u32)
|
||||
.ok_or(Exceptions::NotFoundException(Some(
|
||||
"index out of bounds, see documentation in file for explanation".to_owned(),
|
||||
)));
|
||||
}
|
||||
if image.get(points[x] as u32, points[x + 1] as u32) {
|
||||
)))?
|
||||
{
|
||||
// Black(-ish) pixel
|
||||
bits.set(x as u32 / 2, y);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//package com.google.zxing.common.detector;
|
||||
use std::{f32, i32};
|
||||
use std::{
|
||||
f32, i32,
|
||||
ops::{Add, Sub},
|
||||
};
|
||||
|
||||
/**
|
||||
* General math-related and numeric utility functions.
|
||||
@@ -32,32 +34,43 @@ use std::{f32, i32};
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn round(d: f32) -> i32 {
|
||||
(d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32
|
||||
// (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32
|
||||
d.round() as i32
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aX point A x coordinate
|
||||
* @param aY point A y coordinate
|
||||
* @param bX point B x coordinate
|
||||
* @param bY point B y coordinate
|
||||
* @return Euclidean distance between points A and B
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
|
||||
let xDiff: f64 = (aX - bX).into();
|
||||
let yDiff: f64 = (aY - bY).into();
|
||||
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
}
|
||||
// /**
|
||||
// * @param aX point A x coordinate
|
||||
// * @param aY point A y coordinate
|
||||
// * @param bX point B x coordinate
|
||||
// * @param bY point B y coordinate
|
||||
// * @return Euclidean distance between points A and B
|
||||
// */
|
||||
// #[inline(always)]
|
||||
// pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 {
|
||||
// let xDiff: f64 = (aX - bX).into();
|
||||
// let yDiff: f64 = (aY - bY).into();
|
||||
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @param aX point A x coordinate
|
||||
// * @param aY point A y coordinate
|
||||
// * @param bX point B x coordinate
|
||||
// * @param bY point B y coordinate
|
||||
// * @return Euclidean distance between points A and B
|
||||
// */
|
||||
// #[inline(always)]
|
||||
// pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
|
||||
// let xDiff: f64 = (aX - bX).into();
|
||||
// let yDiff: f64 = (aY - bY).into();
|
||||
// (xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param aX point A x coordinate
|
||||
* @param aY point A y coordinate
|
||||
* @param bX point B x coordinate
|
||||
* @param bY point B y coordinate
|
||||
* @return Euclidean distance between points A and B
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
|
||||
pub fn distance<T>(aX: T, aY: T, bX: T, bY: T) -> f32
|
||||
where
|
||||
T: Sub<T, Output = T> + Into<f64>,
|
||||
{
|
||||
let xDiff: f64 = (aX - bX).into();
|
||||
let yDiff: f64 = (aY - bY).into();
|
||||
(xDiff * xDiff + yDiff * yDiff).sqrt() as f32
|
||||
@@ -68,13 +81,11 @@ pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 {
|
||||
* @return sum of values in array
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn sum(array: &[i32]) -> i32 {
|
||||
pub fn sum<'a, T>(array: &'a [T]) -> T
|
||||
where
|
||||
T: Add + std::iter::Sum<&'a T>,
|
||||
{
|
||||
array.iter().sum()
|
||||
// let mut count = 0;
|
||||
// for a in array {
|
||||
// count += a;
|
||||
// }
|
||||
// count
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -112,15 +123,12 @@ mod tests {
|
||||
fn testDistance() {
|
||||
assert_eq!(
|
||||
(8.0f32).sqrt(),
|
||||
MathUtils::distance_float(1.0f32, 2.0f32, 3.0f32, 4.0f32)
|
||||
);
|
||||
assert_eq!(
|
||||
0.0f32,
|
||||
MathUtils::distance_float(1.0f32, 2.0f32, 1.0f32, 2.0f32)
|
||||
MathUtils::distance(1.0f32, 2.0f32, 3.0f32, 4.0f32)
|
||||
);
|
||||
assert_eq!(0.0f32, MathUtils::distance(1.0f32, 2.0f32, 1.0f32, 2.0f32));
|
||||
|
||||
assert_eq!((8.0f32).sqrt(), MathUtils::distance_int(1, 2, 3, 4));
|
||||
assert_eq!(0.0f32, MathUtils::distance_int(1, 2, 1, 2));
|
||||
assert_eq!((8.0f32).sqrt(), MathUtils::distance(1, 2, 3, 4));
|
||||
assert_eq!(0.0f32, MathUtils::distance(1, 2, 1, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -129,5 +137,7 @@ mod tests {
|
||||
assert_eq!(1, MathUtils::sum(&[1]));
|
||||
assert_eq!(4, MathUtils::sum(&[1, 3]));
|
||||
assert_eq!(0, MathUtils::sum(&[-1, 1]));
|
||||
assert_eq!(0.0, MathUtils::sum(&[-1.0, 1.0]));
|
||||
assert_eq!(4.0, MathUtils::sum(&[1.0, 3.0]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ impl<'a> WhiteRectangleDetector<'_> {
|
||||
b_x: f32,
|
||||
b_y: f32,
|
||||
) -> Option<RXingResultPoint> {
|
||||
let dist = MathUtils::round(MathUtils::distance_float(a_x, a_y, b_x, b_y));
|
||||
let dist = MathUtils::round(MathUtils::distance(a_x, a_y, b_x, b_y));
|
||||
let x_step: f32 = (b_x - a_x) / dist as f32;
|
||||
let y_step: f32 = (b_y - a_y) / dist as f32;
|
||||
|
||||
|
||||
@@ -210,14 +210,20 @@ impl ECIEncoderSet {
|
||||
self.encoders.is_empty()
|
||||
}
|
||||
|
||||
pub fn getCharsetName(&self, index: usize) -> &'static str {
|
||||
assert!(index < self.len());
|
||||
return self.encoders[index].name();
|
||||
pub fn getCharsetName(&self, index: usize) -> Option<&'static str> {
|
||||
if index < self.len() {
|
||||
Some(self.encoders[index].name())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getCharset(&self, index: usize) -> EncodingRef {
|
||||
assert!(index < self.len());
|
||||
self.encoders[index]
|
||||
pub fn getCharset(&self, index: usize) -> Option<EncodingRef> {
|
||||
if index < self.len() {
|
||||
Some(self.encoders[index])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getECIValue(&self, encoderIndex: usize) -> u32 {
|
||||
@@ -233,25 +239,35 @@ impl ECIEncoderSet {
|
||||
self.priorityEncoderIndex
|
||||
}
|
||||
|
||||
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> bool {
|
||||
assert!(encoderIndex < self.len());
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
|
||||
pub fn canEncode(&self, c: &str, encoderIndex: usize) -> Option<bool> {
|
||||
if encoderIndex < self.len() {
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
|
||||
|
||||
enc_data.is_ok()
|
||||
Some(enc_data.is_ok())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Vec<u8> {
|
||||
assert!(encoderIndex < self.len());
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
|
||||
assert!(enc_data.is_ok());
|
||||
enc_data.unwrap()
|
||||
pub fn encode_char(&self, c: &str, encoderIndex: usize) -> Option<Vec<u8>> {
|
||||
if encoderIndex < self.len() {
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
let enc_data = encoder.encode(c, encoding::EncoderTrap::Strict);
|
||||
enc_data.ok()
|
||||
// assert!(enc_data.is_ok());
|
||||
// enc_data.unwrap()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Vec<u8> {
|
||||
assert!(encoderIndex < self.len());
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
encoder.encode(s, encoding::EncoderTrap::Replace).unwrap()
|
||||
pub fn encode_string(&self, s: &str, encoderIndex: usize) -> Option<Vec<u8>> {
|
||||
if encoderIndex < self.len() {
|
||||
let encoder = self.encoders[encoderIndex];
|
||||
encoder.encode(s, encoding::EncoderTrap::Strict).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,5 +106,5 @@ pub trait ECIInput: Display {
|
||||
* if the value at the {@code index} argument is not an ECI (@see #isECI)
|
||||
*/
|
||||
fn getECIValue(&self, index: usize) -> Result<i32, Exceptions>;
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> bool;
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions>;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ impl ECIStringBuilder {
|
||||
pub fn with_capacity(initial_capacity: usize) -> Self {
|
||||
Self {
|
||||
current_bytes: Vec::with_capacity(initial_capacity),
|
||||
result: String::new(),
|
||||
result: String::with_capacity(initial_capacity),
|
||||
current_charset: Some(encoding::all::ISO_8859_1),
|
||||
}
|
||||
}
|
||||
@@ -121,31 +121,25 @@ impl ECIStringBuilder {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Finishes encoding anything in the buffer using the current ECI and resets.
|
||||
///
|
||||
/// This function can panic
|
||||
pub fn encodeCurrentBytesIfAny(&mut self) {
|
||||
if let Some(encoder) = self.current_charset {
|
||||
if encoder.name() == encoding::all::UTF_8.name() {
|
||||
if !self.current_bytes.is_empty() {
|
||||
// if result == null {
|
||||
// result = currentBytes;
|
||||
// currentBytes = new StringBuilder();
|
||||
// } else {
|
||||
self.result.push_str(
|
||||
&String::from_utf8(std::mem::take(&mut self.current_bytes)).unwrap(),
|
||||
);
|
||||
self.current_bytes.clear();
|
||||
// }
|
||||
}
|
||||
} else if !self.current_bytes.is_empty() {
|
||||
let bytes = std::mem::take(&mut self.current_bytes);
|
||||
self.current_bytes.clear();
|
||||
// if (result == null) {
|
||||
// result = new StringBuilder(new String(bytes, currentCharset));
|
||||
// } else {
|
||||
let encoded_value = encoder
|
||||
.decode(&bytes, encoding::DecoderTrap::Strict)
|
||||
.unwrap();
|
||||
self.result.push_str(&encoded_value);
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
for byte in &self.current_bytes {
|
||||
@@ -172,7 +166,7 @@ impl ECIStringBuilder {
|
||||
*/
|
||||
pub fn len(&mut self) -> usize {
|
||||
self.encodeCurrentBytesIfAny(); //return toString().length();
|
||||
self.result.len()
|
||||
self.result.chars().count()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,11 +102,6 @@ impl Binarizer for GlobalHistogramBinarizer {
|
||||
|
||||
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
|
||||
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> {
|
||||
// if self.black_matrix.is_none() {
|
||||
// self.black_matrix =
|
||||
// Some(Self::build_black_matrix(&self.source).expect("matrix must generate"))
|
||||
// }
|
||||
// Ok(self.black_matrix.as_ref().unwrap())
|
||||
let matrix = self
|
||||
.black_matrix
|
||||
.get_or_try_init(|| Self::build_black_matrix(&self.source))?;
|
||||
|
||||
@@ -144,22 +144,22 @@ pub trait GridSampler {
|
||||
// for (int offset = 0; offset < maxOffset && nudged; offset += 2) {
|
||||
let x = points[offset] as i32;
|
||||
let y = points[offset + 1] as i32;
|
||||
if x < -1 || x > width.try_into().unwrap() || y < -1 || y > height.try_into().unwrap() {
|
||||
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
nudged = false;
|
||||
if x == -1 {
|
||||
points[offset] = 0.0f32;
|
||||
points[offset] = 0.0;
|
||||
nudged = true;
|
||||
} else if x == width.try_into().unwrap() {
|
||||
points[offset] = width as f32 - 1f32;
|
||||
} else if x == width as i32 {
|
||||
points[offset] = width as f32 - 1.0;
|
||||
nudged = true;
|
||||
}
|
||||
if y == -1 {
|
||||
points[offset + 1] = 0.0f32;
|
||||
points[offset + 1] = 0.0;
|
||||
nudged = true;
|
||||
} else if y == height.try_into().unwrap() {
|
||||
points[offset + 1] = height as f32 - 1f32;
|
||||
} else if y == height as i32 {
|
||||
points[offset + 1] = height as f32 - 1.0;
|
||||
nudged = true;
|
||||
}
|
||||
offset += 2;
|
||||
@@ -171,22 +171,22 @@ pub trait GridSampler {
|
||||
// for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
|
||||
let x = points[offset as usize] as i32;
|
||||
let y = points[offset as usize + 1] as i32;
|
||||
if x < -1 || x > width.try_into().unwrap() || y < -1 || y > height.try_into().unwrap() {
|
||||
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
nudged = false;
|
||||
if x == -1 {
|
||||
points[offset as usize] = 0.0f32;
|
||||
points[offset as usize] = 0.0;
|
||||
nudged = true;
|
||||
} else if x == width.try_into().unwrap() {
|
||||
points[offset as usize] = width as f32 - 1f32;
|
||||
} else if x == width as i32 {
|
||||
points[offset as usize] = width as f32 - 1.0;
|
||||
nudged = true;
|
||||
}
|
||||
if y == -1 {
|
||||
points[offset as usize + 1] = 0.0f32;
|
||||
points[offset as usize + 1] = 0.0;
|
||||
nudged = true;
|
||||
} else if y == height.try_into().unwrap() {
|
||||
points[offset as usize + 1] = height as f32 - 1f32;
|
||||
} else if y == height as i32 {
|
||||
points[offset as usize + 1] = height as f32 - 1.0;
|
||||
nudged = true;
|
||||
}
|
||||
offset += -2;
|
||||
|
||||
@@ -67,13 +67,6 @@ impl Binarizer for HybridBinarizer {
|
||||
* profiling easier, and not doing heavy lifting when callers don't expect it.
|
||||
*/
|
||||
fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> {
|
||||
// if self.black_matrix.is_none() {
|
||||
// self.black_matrix = Some(
|
||||
// Self::calculateBlackMatrix(&mut self.ghb)
|
||||
// .expect("generate black matrix must complete"),
|
||||
// )
|
||||
// }
|
||||
// Ok(self.black_matrix.as_ref().unwrap())
|
||||
let matrix = self
|
||||
.black_matrix
|
||||
.get_or_try_init(|| Self::calculateBlackMatrix(&self.ghb))?;
|
||||
@@ -200,6 +193,7 @@ impl HybridBinarizer {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cap(value: u32, max: u32) -> u32 {
|
||||
if value < 2 {
|
||||
2
|
||||
|
||||
@@ -14,12 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.common;
|
||||
|
||||
// import java.nio.charset.Charset;
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.List;
|
||||
|
||||
use std::{fmt, rc::Rc};
|
||||
|
||||
use encoding::EncodingRef;
|
||||
@@ -174,17 +168,17 @@ impl ECIInput for MinimalECIInput {
|
||||
Ok((self.bytes[index] as u32 - 256) as i32)
|
||||
}
|
||||
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> bool {
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions> {
|
||||
if index + n > self.bytes.len() {
|
||||
return false;
|
||||
return Ok(false);
|
||||
}
|
||||
for i in 0..n {
|
||||
// for (int i = 0; i < n; i++) {
|
||||
if self.isECI(index as u32 + i as u32).unwrap() {
|
||||
return false;
|
||||
if self.isECI(index as u32 + i as u32)? {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
true
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
impl MinimalECIInput {
|
||||
@@ -209,10 +203,14 @@ impl MinimalECIInput {
|
||||
let bytes = if encoderSet.len() == 1 {
|
||||
//optimization for the case when all can be encoded without ECI in ISO-8859-1
|
||||
let mut bytes_hld = vec![0; stringToEncode.len()];
|
||||
for (i, byt) in bytes_hld.iter_mut().enumerate().take(stringToEncode.len()) {
|
||||
for (byt, c) in bytes_hld
|
||||
.iter_mut()
|
||||
.zip(&stringToEncode)
|
||||
.take(stringToEncode.len())
|
||||
{
|
||||
// for i in 0..stringToEncode.len() {
|
||||
// for (int i = 0; i < bytes.length; i++) {
|
||||
let c = stringToEncode.get(i).unwrap();
|
||||
// let c = stringToEncode.get(i).unwrap();
|
||||
*byt = if fnc1.is_some() && c == fnc1.as_ref().unwrap() {
|
||||
1000
|
||||
} else {
|
||||
@@ -287,7 +285,9 @@ impl MinimalECIInput {
|
||||
if encoderSet.getPriorityEncoderIndex().is_some()
|
||||
&& ((fnc1.is_some()
|
||||
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap())
|
||||
|| encoderSet.canEncode(ch, encoderSet.getPriorityEncoderIndex().unwrap()))
|
||||
|| encoderSet
|
||||
.canEncode(ch, encoderSet.getPriorityEncoderIndex().unwrap())
|
||||
.unwrap())
|
||||
{
|
||||
start = encoderSet.getPriorityEncoderIndex().unwrap();
|
||||
end = start + 1;
|
||||
@@ -298,7 +298,7 @@ impl MinimalECIInput {
|
||||
// for (int i = start; i < end; i++) {
|
||||
if (fnc1.is_some()
|
||||
&& ch.chars().next().unwrap() == fnc1.as_ref().unwrap().chars().next().unwrap())
|
||||
|| encoderSet.canEncode(ch, i)
|
||||
|| encoderSet.canEncode(ch, i).unwrap()
|
||||
{
|
||||
Self::addEdge(
|
||||
edges,
|
||||
@@ -309,6 +309,9 @@ impl MinimalECIInput {
|
||||
}
|
||||
}
|
||||
|
||||
/// Minimially encode a string with the given characterset.
|
||||
///
|
||||
/// Function can panic if the string cannot be encoded.
|
||||
pub fn encodeMinimally(
|
||||
stringToEncode: &str,
|
||||
encoderSet: &ECIEncoderSet,
|
||||
@@ -360,6 +363,7 @@ impl MinimalECIInput {
|
||||
} else {
|
||||
let bytes: Vec<u16> = encoderSet
|
||||
.encode_char(&c.c, c.encoderIndex)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|x| *x as u16)
|
||||
.collect();
|
||||
@@ -414,7 +418,7 @@ impl InputEdge {
|
||||
let mut size = if c == Self::FNC1_UNICODE {
|
||||
1
|
||||
} else {
|
||||
encoderSet.encode_char(c, encoderIndex).len()
|
||||
encoderSet.encode_char(c, encoderIndex).unwrap().len()
|
||||
};
|
||||
|
||||
//let fnc1Str = String::from_utf16(&[fnc1]).unwrap();
|
||||
|
||||
@@ -404,7 +404,7 @@ fn test_encode_decode_random(field: GenericGFRef, dataSize: usize, ecSize: usize
|
||||
ecSize > 0 && ecSize + dataSize <= field.getSize(),
|
||||
"Invalid ECC size for {field}"
|
||||
);
|
||||
let mut encoder = ReedSolomonEncoder::new(field);
|
||||
let mut encoder = ReedSolomonEncoder::new(field).expect("new");
|
||||
let mut message = vec![0; dataSize + ecSize];
|
||||
let mut dataWords: Vec<i32> = vec![0; dataSize];
|
||||
let mut ecWords = vec![0; ecSize];
|
||||
@@ -440,7 +440,7 @@ fn test_encode_decode(field: GenericGFRef, dataWords: &Vec<i32>, ecWords: &Vec<i
|
||||
}
|
||||
|
||||
fn test_encoder(field: GenericGFRef, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
||||
let mut encoder = ReedSolomonEncoder::new(field);
|
||||
let mut encoder = ReedSolomonEncoder::new(field).expect("new");
|
||||
let mut messageExpected = vec![0; dataWords.len() + ecWords.len()];
|
||||
let mut message = vec![0; dataWords.len() + ecWords.len()];
|
||||
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
||||
|
||||
@@ -49,9 +49,9 @@ impl GenericGFPoly {
|
||||
*/
|
||||
pub fn new(field: GenericGFRef, coefficients: &[i32]) -> Result<Self, Exceptions> {
|
||||
if coefficients.is_empty() {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"coefficients.len()".to_owned(),
|
||||
)));
|
||||
return Err(Exceptions::IllegalArgumentException(Some(String::from(
|
||||
"coefficients cannot be empty",
|
||||
))));
|
||||
}
|
||||
Ok(Self {
|
||||
field,
|
||||
|
||||
@@ -61,7 +61,7 @@ impl ReedSolomonDecoder {
|
||||
* @throws ReedSolomonException if decoding fails for any reason
|
||||
*/
|
||||
pub fn decode(&self, received: &mut Vec<i32>, twoS: i32) -> Result<usize, Exceptions> {
|
||||
let poly = GenericGFPoly::new(self.field, received).unwrap();
|
||||
let poly = GenericGFPoly::new(self.field, received)?;
|
||||
let mut syndromeCoefficients = vec![0; twoS as usize];
|
||||
let mut noError = true;
|
||||
for i in 0..twoS {
|
||||
@@ -87,7 +87,7 @@ impl ReedSolomonDecoder {
|
||||
let sigma = &sigmaOmega[0];
|
||||
let omega = &sigmaOmega[1];
|
||||
let errorLocations = self.findErrorLocations(sigma)?;
|
||||
let errorMagnitudes = self.findErrorMagnitudes(omega, &errorLocations);
|
||||
let errorMagnitudes = self.findErrorMagnitudes(omega, &errorLocations)?;
|
||||
for i in 0..errorLocations.len() {
|
||||
//for (int i = 0; i < errorLocations.length; i++) {
|
||||
let log_value = self.field.log(errorLocations[i] as i32)?;
|
||||
@@ -145,62 +145,17 @@ impl ReedSolomonDecoder {
|
||||
r = rLastLast;
|
||||
let mut q = r.getZero();
|
||||
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
|
||||
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
|
||||
Ok(inv) => inv,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"ArithmetricException".to_owned(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
let dltInverse = self.field.inverse(denominatorLeadingTerm)?;
|
||||
while r.getDegree() >= rLast.getDegree() && !r.isZero() {
|
||||
let degreeDiff = r.getDegree() - rLast.getDegree();
|
||||
let scale = self
|
||||
.field
|
||||
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
|
||||
q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale))
|
||||
{
|
||||
Ok(res) => res,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"IllegalArgumentException".to_owned(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
r = match r.addOrSubtract(&match rLast.multiply_by_monomial(degreeDiff, scale) {
|
||||
Ok(res) => res,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"IllegalArgumentException".to_owned(),
|
||||
)))
|
||||
}
|
||||
}) {
|
||||
Ok(res) => res,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"IllegalArgumentException".to_owned(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
q = q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale))?;
|
||||
r = r.addOrSubtract(&rLast.multiply_by_monomial(degreeDiff, scale)?)?;
|
||||
}
|
||||
|
||||
t = match (match q.multiply(&tLast) {
|
||||
Ok(res) => res,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"IllegalArgumentException".to_owned(),
|
||||
)))
|
||||
}
|
||||
})
|
||||
.addOrSubtract(&tLastLast)
|
||||
{
|
||||
Ok(res) => res,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"IllegalArgumentException".to_owned(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
t = (q.multiply(&tLast)?).addOrSubtract(&tLastLast)?;
|
||||
|
||||
if r.getDegree() >= rLast.getDegree() {
|
||||
return Err(Exceptions::ReedSolomonException(Some(format!(
|
||||
@@ -245,14 +200,7 @@ impl ReedSolomonDecoder {
|
||||
break;
|
||||
}
|
||||
if errorLocator.evaluateAt(i) == 0 {
|
||||
result[e] = match self.field.inverse(i as i32) {
|
||||
Ok(res) => res as usize,
|
||||
Err(_err) => {
|
||||
return Err(Exceptions::ReedSolomonException(Some(
|
||||
"ArithmetricException".to_owned(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
result[e] = self.field.inverse(i as i32)? as usize;
|
||||
e += 1;
|
||||
}
|
||||
}
|
||||
@@ -268,13 +216,13 @@ impl ReedSolomonDecoder {
|
||||
&self,
|
||||
errorEvaluator: &GenericGFPoly,
|
||||
errorLocations: &Vec<usize>,
|
||||
) -> Vec<i32> {
|
||||
) -> Result<Vec<i32>, Exceptions> {
|
||||
// This is directly applying Forney's Formula
|
||||
let s = errorLocations.len();
|
||||
let mut result = vec![0; s];
|
||||
for i in 0..s {
|
||||
//for (int i = 0; i < s; i++) {
|
||||
let xiInverse = self.field.inverse(errorLocations[i] as i32).unwrap();
|
||||
let xiInverse = self.field.inverse(errorLocations[i] as i32)?;
|
||||
let mut denominator = 1;
|
||||
for (j, loc) in errorLocations.iter().enumerate().take(s) {
|
||||
// for j in 0..s {
|
||||
@@ -295,12 +243,12 @@ impl ReedSolomonDecoder {
|
||||
}
|
||||
result[i] = self.field.multiply(
|
||||
errorEvaluator.evaluateAt(xiInverse as usize),
|
||||
self.field.inverse(denominator).unwrap(),
|
||||
self.field.inverse(denominator)?,
|
||||
);
|
||||
if self.field.getGeneratorBase() != 0 {
|
||||
result[i] = self.field.multiply(result[i], xiInverse);
|
||||
}
|
||||
}
|
||||
result
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,17 +35,17 @@ pub struct ReedSolomonEncoder {
|
||||
}
|
||||
|
||||
impl ReedSolomonEncoder {
|
||||
pub fn new(field: GenericGFRef) -> Self {
|
||||
pub fn new(field: GenericGFRef) -> Result<Self, Exceptions> {
|
||||
let n = field;
|
||||
Self {
|
||||
cachedGenerators: vec![GenericGFPoly::new(n, &[1]).unwrap()],
|
||||
Ok(Self {
|
||||
cachedGenerators: vec![GenericGFPoly::new(n, &[1])?],
|
||||
field: n,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn buildGenerator(&mut self, degree: usize) -> &GenericGFPoly {
|
||||
fn buildGenerator(&mut self, degree: usize) -> Option<&GenericGFPoly> {
|
||||
if degree >= self.cachedGenerators.len() {
|
||||
let mut lastGenerator = self.cachedGenerators.last().unwrap();
|
||||
let mut lastGenerator = self.cachedGenerators.last()?;
|
||||
let cg_len = self.cachedGenerators.len();
|
||||
let mut nextGenerator;
|
||||
for d in cg_len..=degree {
|
||||
@@ -59,16 +59,16 @@ impl ReedSolomonEncoder {
|
||||
self.field.exp(d as i32 - 1 + self.field.getGeneratorBase()),
|
||||
],
|
||||
)
|
||||
.unwrap(),
|
||||
.ok()?,
|
||||
)
|
||||
.unwrap();
|
||||
.ok()?;
|
||||
self.cachedGenerators.push(nextGenerator);
|
||||
lastGenerator = self.cachedGenerators.get(d).unwrap();
|
||||
lastGenerator = self.cachedGenerators.get(d)?;
|
||||
//lastGenerator = &nextGenerator;
|
||||
}
|
||||
}
|
||||
let rv = self.cachedGenerators.get(degree).unwrap();
|
||||
rv
|
||||
let rv = self.cachedGenerators.get(degree)?;
|
||||
Some(rv)
|
||||
}
|
||||
|
||||
pub fn encode(&mut self, to_encode: &mut Vec<i32>, ec_bytes: usize) -> Result<(), Exceptions> {
|
||||
@@ -90,7 +90,9 @@ impl ReedSolomonEncoder {
|
||||
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
||||
let mut info = GenericGFPoly::new(fld, &info_coefficients)?;
|
||||
info = info.multiply_by_monomial(ec_bytes, 1)?;
|
||||
let remainder = &info.divide(generator)?.1;
|
||||
let remainder = &info
|
||||
.divide(generator.ok_or(Exceptions::ReedSolomonException(None))?)?
|
||||
.1;
|
||||
let coefficients = remainder.getCoefficients();
|
||||
let num_zero_coefficients = ec_bytes - coefficients.len();
|
||||
for i in 0..num_zero_coefficients {
|
||||
|
||||
@@ -14,12 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// package com.google.zxing.common;
|
||||
|
||||
// import java.nio.charset.Charset;
|
||||
// import java.nio.charset.StandardCharsets;
|
||||
// import java.util.Map;
|
||||
|
||||
use encoding::{Encoding, EncodingRef};
|
||||
|
||||
use crate::{DecodeHintType, DecodeHintValue, DecodingHintDictionary};
|
||||
@@ -71,20 +65,16 @@ impl StringUtils {
|
||||
* "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none
|
||||
* of these can possibly be correct
|
||||
*/
|
||||
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> &'static str {
|
||||
let c = StringUtils::guessCharset(bytes, hints);
|
||||
if c.name()
|
||||
== encoding::label::encoding_from_whatwg_label("SJIS")
|
||||
.unwrap()
|
||||
.name()
|
||||
{
|
||||
"SJIS"
|
||||
pub fn guessEncoding(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<&'static str> {
|
||||
let c = StringUtils::guessCharset(bytes, hints)?;
|
||||
if c.name() == encoding::label::encoding_from_whatwg_label("SJIS")?.name() {
|
||||
Some("SJIS")
|
||||
} else if c.name() == encoding::all::UTF_8.name() {
|
||||
"UTF8"
|
||||
Some("UTF8")
|
||||
} else if c.name() == encoding::all::ISO_8859_1.name() {
|
||||
"ISO8859_1"
|
||||
Some("ISO8859_1")
|
||||
} else {
|
||||
c.name()
|
||||
Some(c.name())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,12 +87,12 @@ impl StringUtils {
|
||||
* or the platform default encoding if
|
||||
* none of these can possibly be correct
|
||||
*/
|
||||
pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> EncodingRef {
|
||||
pub fn guessCharset(bytes: &[u8], hints: &DecodingHintDictionary) -> Option<EncodingRef> {
|
||||
if let Some(DecodeHintValue::CharacterSet(cs_name)) =
|
||||
hints.get(&DecodeHintType::CHARACTER_SET)
|
||||
{
|
||||
// if let DecodeHintValue::CharacterSet(cs_name) = hint {
|
||||
return encoding::label::encoding_from_whatwg_label(cs_name).unwrap();
|
||||
return encoding::label::encoding_from_whatwg_label(cs_name);
|
||||
// }
|
||||
}
|
||||
// if hints.contains_key(&DecodeHintType::CHARACTER_SET) {
|
||||
@@ -114,9 +104,9 @@ impl StringUtils {
|
||||
&& ((bytes[0] == 0xFE && bytes[1] == 0xFF) || (bytes[0] == 0xFF && bytes[1] == 0xFE))
|
||||
{
|
||||
if bytes[0] == 0xFE && bytes[1] == 0xFF {
|
||||
return encoding::all::UTF_16BE;
|
||||
return Some(encoding::all::UTF_16BE);
|
||||
} else {
|
||||
return encoding::all::UTF_16LE;
|
||||
return Some(encoding::all::UTF_16LE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +224,7 @@ impl StringUtils {
|
||||
|
||||
// Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done
|
||||
if can_be_utf8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) {
|
||||
return encoding::all::UTF_8;
|
||||
return Some(encoding::all::UTF_8);
|
||||
}
|
||||
// Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done
|
||||
if can_be_shift_jis
|
||||
@@ -242,7 +232,7 @@ impl StringUtils {
|
||||
|| sjis_max_katakana_word_length >= 3
|
||||
|| sjis_max_double_bytes_word_length >= 3)
|
||||
{
|
||||
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||
return encoding::label::encoding_from_whatwg_label("SJIS");
|
||||
}
|
||||
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:
|
||||
// - If we saw
|
||||
@@ -253,23 +243,23 @@ impl StringUtils {
|
||||
return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2)
|
||||
|| iso_high_other * 10 >= length
|
||||
{
|
||||
encoding::label::encoding_from_whatwg_label("SJIS").unwrap()
|
||||
encoding::label::encoding_from_whatwg_label("SJIS")
|
||||
} else {
|
||||
encoding::all::ISO_8859_1
|
||||
Some(encoding::all::ISO_8859_1)
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding
|
||||
if can_be_iso88591 {
|
||||
return encoding::all::ISO_8859_1;
|
||||
return Some(encoding::all::ISO_8859_1);
|
||||
}
|
||||
if can_be_shift_jis {
|
||||
return encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||
return Some(encoding::label::encoding_from_whatwg_label("SJIS").unwrap());
|
||||
}
|
||||
if can_be_utf8 {
|
||||
return encoding::all::UTF_8;
|
||||
return Some(encoding::all::UTF_8);
|
||||
}
|
||||
// Otherwise, we take a wild guess with platform encoding
|
||||
encoding::all::UTF_8
|
||||
Some(encoding::all::UTF_8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,15 +169,10 @@ impl Writer for DataMatrixWriter {
|
||||
symbolInfo.getSymbolDataWidth()? as usize,
|
||||
symbolInfo.getSymbolDataHeight()? as usize,
|
||||
);
|
||||
placement.place();
|
||||
placement.place()?;
|
||||
|
||||
//4. step: low-level encoding
|
||||
Self::encodeLowLevel(
|
||||
&placement,
|
||||
symbolInfo,
|
||||
width.try_into().unwrap(),
|
||||
height.try_into().unwrap(),
|
||||
)
|
||||
Self::encodeLowLevel(&placement, symbolInfo, width as u32, height as u32)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ impl BitMatrixParser {
|
||||
let mut row = 4;
|
||||
let mut column = 0;
|
||||
|
||||
let numRows = self.mappingBitMatrix.getHeight().try_into().unwrap();
|
||||
let numColumns = self.mappingBitMatrix.getWidth().try_into().unwrap();
|
||||
let numRows = self.mappingBitMatrix.getHeight() as isize;
|
||||
let numColumns = self.mappingBitMatrix.getWidth() as isize;
|
||||
|
||||
let mut corner1Read = false;
|
||||
let mut corner2Read = false;
|
||||
@@ -497,11 +497,3 @@ impl BitMatrixParser {
|
||||
Ok(bitMatrixWithoutAlignment)
|
||||
}
|
||||
}
|
||||
|
||||
// const IS_MOSTLY_BLACK_RATIO : f32= 0.5;
|
||||
|
||||
// fn is_mostly_black(array: &[bool]) -> bool {
|
||||
// let array_len = array.len() as f32;
|
||||
// let true_count = array.iter().fold(0, |acc,b| acc + i32::from(*b)) as f32;
|
||||
// (array_len / true_count ) > IS_MOSTLY_BLACK_RATIO
|
||||
// }
|
||||
|
||||
@@ -206,12 +206,6 @@ pub fn decode(bytes: &[u8], is_flipped: bool) -> Result<DecoderRXingResult, Exce
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
||||
// return new DecoderRXingResult(bytes,
|
||||
// result.toString(),
|
||||
// byteSegments.isEmpty() ? null : byteSegments,
|
||||
// null,
|
||||
// symbologyModifier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +232,9 @@ fn decodeAsciiSegment(
|
||||
oneByte += 128;
|
||||
//upperShift = false;
|
||||
}
|
||||
result.append_char(char::from_u32(oneByte - 1).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(oneByte - 1).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
return Ok(Mode::ASCII_ENCODE);
|
||||
}
|
||||
129 => return Ok(Mode::PAD_ENCODE), // Pad
|
||||
@@ -249,7 +245,6 @@ fn decodeAsciiSegment(
|
||||
// pad with '0' for single digit values
|
||||
result.append_char('0');
|
||||
}
|
||||
//result.append_char(char::from_u32(value).unwrap());
|
||||
result.append_string(&format!("{value}"));
|
||||
}
|
||||
230 =>
|
||||
@@ -391,7 +386,10 @@ fn decodeC40Segment(
|
||||
} else if cValue < C40_BASIC_SET_CHARS.len() as u32 {
|
||||
let c40char = C40_BASIC_SET_CHARS[cValue as usize];
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(c40char as u32 + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(c40char as u32 + 128)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(c40char);
|
||||
@@ -402,10 +400,14 @@ fn decodeC40Segment(
|
||||
}
|
||||
1 => {
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(cValue + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 128).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(char::from_u32(cValue).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
}
|
||||
shift = 0;
|
||||
}
|
||||
@@ -413,7 +415,10 @@ fn decodeC40Segment(
|
||||
if cValue < C40_SHIFT2_SET_CHARS.len() as u32 {
|
||||
let c40char = C40_SHIFT2_SET_CHARS[cValue as usize];
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(c40char as u32 + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(c40char as u32 + 128)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(c40char);
|
||||
@@ -438,10 +443,14 @@ fn decodeC40Segment(
|
||||
}
|
||||
3 => {
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(cValue + 224).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 224).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(char::from_u32(cValue + 96).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 96).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
}
|
||||
shift = 0;
|
||||
}
|
||||
@@ -494,7 +503,10 @@ fn decodeTextSegment(
|
||||
} else if cValue < TEXT_BASIC_SET_CHARS.len() as u32 {
|
||||
let textChar = TEXT_BASIC_SET_CHARS[cValue as usize];
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(textChar as u32 + 128)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(textChar);
|
||||
@@ -505,10 +517,14 @@ fn decodeTextSegment(
|
||||
}
|
||||
1 => {
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(cValue + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 128).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(char::from_u32(cValue).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
}
|
||||
shift = 0;
|
||||
}
|
||||
@@ -518,7 +534,10 @@ fn decodeTextSegment(
|
||||
if cValue < TEXT_SHIFT2_SET_CHARS.len() as u32 {
|
||||
let textChar = TEXT_SHIFT2_SET_CHARS[cValue as usize];
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(textChar as u32 + 128)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(textChar);
|
||||
@@ -545,7 +564,10 @@ fn decodeTextSegment(
|
||||
if cValue < TEXT_SHIFT3_SET_CHARS.len() as u32 {
|
||||
let textChar = TEXT_SHIFT3_SET_CHARS[cValue as usize];
|
||||
if upperShift {
|
||||
result.append_char(char::from_u32(textChar as u32 + 128).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(textChar as u32 + 128)
|
||||
.ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
upperShift = false;
|
||||
} else {
|
||||
result.append_char(textChar);
|
||||
@@ -622,10 +644,14 @@ fn decodeAnsiX12Segment(
|
||||
_ => {
|
||||
if cValue < 14 {
|
||||
// 0 - 9
|
||||
result.append_char(char::from_u32(cValue + 44).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 44).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else if cValue < 40 {
|
||||
// A - Z
|
||||
result.append_char(char::from_u32(cValue + 51).unwrap());
|
||||
result.append_char(
|
||||
char::from_u32(cValue + 51).ok_or(Exceptions::ParseException(None))?,
|
||||
);
|
||||
} else {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
@@ -682,7 +708,8 @@ fn decodeEdifactSegment(
|
||||
// no 1 in the leading (6th) bit
|
||||
edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value
|
||||
}
|
||||
result.append_char(char::from_u32(edifactValue).unwrap());
|
||||
result
|
||||
.append_char(char::from_u32(edifactValue).ok_or(Exceptions::ParseException(None))?);
|
||||
}
|
||||
|
||||
if bits.available() == 0 {
|
||||
@@ -724,8 +751,6 @@ fn decodeBase256Segment(
|
||||
|
||||
let mut bytes = vec![0u8; count as usize];
|
||||
for byte in bytes.iter_mut().take(count as usize) {
|
||||
// for i in 0..count as usize {
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// Have seen this particular error in the wild, such as at
|
||||
// http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
|
||||
if bits.available() < 8 {
|
||||
@@ -737,10 +762,9 @@ fn decodeBase256Segment(
|
||||
result.append_string(
|
||||
&encoding::all::ISO_8859_1
|
||||
.decode(&bytes, encoding::DecoderTrap::Strict)
|
||||
.expect("decode"),
|
||||
.map_err(|e| Exceptions::ParseException(Some(e.to_string())))?,
|
||||
);
|
||||
byteSegments.push(bytes);
|
||||
// result.append_string(&encoding::all::ISO_8859_1.decode(&bytes, encoding::DecoderTrap::Strict).expect("decode"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -768,30 +792,6 @@ fn decodeECISegment(
|
||||
|
||||
result.appendECI((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1)?;
|
||||
Ok((firstByte - 192) * 64516 + 16383 + (secondByte - 1) * 254 + thirdByte - 1 > 900)
|
||||
|
||||
// if bits.available() < 8 {
|
||||
// return Err(Exceptions::FormatException(None));
|
||||
// }
|
||||
// let c1 = bits.readBits(8)?;
|
||||
// if c1 <= 127 {
|
||||
// result.appendECI(c1 - 1)?;
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
//currently we only support character set ECIs
|
||||
/*} else {
|
||||
if (bits.available() < 8) {
|
||||
throw FormatException.getFormatInstance();
|
||||
}
|
||||
int c2 = bits.readBits(8);
|
||||
if (c1 >= 128 && c1 <= 191) {
|
||||
} else {
|
||||
if (bits.available() < 8) {
|
||||
throw FormatException.getFormatInstance();
|
||||
}
|
||||
int c3 = bits.readBits(8);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,17 +60,6 @@ impl Version {
|
||||
acc + ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords)
|
||||
})
|
||||
},
|
||||
// totalCodewords: {
|
||||
// // Calculate the total number of codewords
|
||||
// let mut total = 0;
|
||||
// let ecCodewords = &ecBlocks.getECCodewords();
|
||||
// let ecbArray = ecBlocks.getECBlocks();
|
||||
// for ecBlock in ecbArray {
|
||||
// total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
|
||||
// }
|
||||
|
||||
// total
|
||||
// },
|
||||
ecBlocks,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ impl<'a> Detector<'_> {
|
||||
/**
|
||||
* Calculates the corner position of the white top right module.
|
||||
*/
|
||||
fn correctTopRight(&self, points: &[RXingResultPoint]) -> Option<RXingResultPoint> {
|
||||
fn correctTopRight(&self, points: &[RXingResultPoint; 4]) -> Option<RXingResultPoint> {
|
||||
// A..D
|
||||
// | :
|
||||
// B--C
|
||||
|
||||
@@ -249,7 +249,7 @@ fn Scan(
|
||||
CHECK!(res.is_ok());
|
||||
|
||||
return Ok(DatamatrixDetectorResult::new(
|
||||
res.unwrap(),
|
||||
res?,
|
||||
sourcePoints.points().to_vec(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -30,14 +30,6 @@ impl Default for DMRegressionLine {
|
||||
}
|
||||
|
||||
impl RegressionLine for DMRegressionLine {
|
||||
// fn intersect<T: RegressionLine, T2: RegressionLine>(
|
||||
// &self,
|
||||
// l1: &T,
|
||||
// l2: &T2,
|
||||
// ) -> RXingResultPoint {
|
||||
// int
|
||||
// }
|
||||
|
||||
fn points(&self) -> &[RXingResultPoint] {
|
||||
&self.points
|
||||
}
|
||||
@@ -272,7 +264,14 @@ impl DMRegressionLine {
|
||||
|
||||
// calculate the (expected average) distance of two adjacent pixels
|
||||
let unitPixelDist = RXingResultPoint::length(RXingResultPoint::bresenhamDirection(
|
||||
&(*self.points.last().unwrap() - *self.points.first().unwrap()),
|
||||
&(*self
|
||||
.points
|
||||
.last()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
- *self
|
||||
.points
|
||||
.first()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
)) as f64;
|
||||
|
||||
// calculate the width of 2 modules (first black pixel to first black pixel)
|
||||
@@ -291,8 +290,17 @@ impl DMRegressionLine {
|
||||
}
|
||||
}
|
||||
|
||||
modSizes
|
||||
.push(sumFront + self.distance(end, &self.project(self.points.last().unwrap())) as f64);
|
||||
modSizes.push(
|
||||
sumFront
|
||||
+ self.distance(
|
||||
end,
|
||||
&self.project(
|
||||
self.points
|
||||
.last()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
),
|
||||
) as f64,
|
||||
);
|
||||
modSizes[0] = 0.0; // the first element is an invalid sumBack value, would be pop_front() if vector supported this
|
||||
let lineLength = self.distance(beg, end) as f64 - unitPixelDist;
|
||||
let mut meanModSize = Self::average(&modSizes, |_: f64| true);
|
||||
|
||||
@@ -272,7 +272,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p) + **line.points().first().as_ref().unwrap()),
|
||||
&(self.p - line.project(&self.p)
|
||||
+ **line
|
||||
.points()
|
||||
.first()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -296,10 +301,24 @@ impl<'a> EdgeTracer<'_> {
|
||||
let mut gaps = 0;
|
||||
loop {
|
||||
// detect an endless loop (lack of progress). if encountered, please report.
|
||||
if !(line.points().is_empty() || &&self.p != line.points().last().as_ref().unwrap()) {
|
||||
if !(line.points().is_empty()
|
||||
|| &&self.p
|
||||
!= line
|
||||
.points()
|
||||
.last()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?)
|
||||
{
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
if !line.points().is_empty() && &&self.p == line.points().last().as_ref().unwrap() {
|
||||
if !line.points().is_empty()
|
||||
&& &&self.p
|
||||
== line
|
||||
.points()
|
||||
.last()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
// log(p);
|
||||
@@ -340,7 +359,12 @@ impl<'a> EdgeTracer<'_> {
|
||||
// to prevent a dead lock. see #245.png
|
||||
while RXingResultPoint::distance(
|
||||
np,
|
||||
line.project(line.points().last().as_ref().unwrap()),
|
||||
line.project(
|
||||
line.points()
|
||||
.last()
|
||||
.as_ref()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
),
|
||||
) < 1.0
|
||||
{
|
||||
np += self.d;
|
||||
@@ -352,7 +376,11 @@ impl<'a> EdgeTracer<'_> {
|
||||
} else {
|
||||
RXingResultPoint::dot(
|
||||
RXingResultPoint::mainDirection(self.d),
|
||||
self.p - line.points().last().unwrap(),
|
||||
self.p
|
||||
- line
|
||||
.points()
|
||||
.last()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)
|
||||
};
|
||||
line.add(&self.p)?;
|
||||
@@ -364,7 +392,11 @@ impl<'a> EdgeTracer<'_> {
|
||||
return Ok(false);
|
||||
}
|
||||
if !self.updateDirectionFromOrigin(
|
||||
&(self.p - line.project(&self.p) + *line.points().first().unwrap()),
|
||||
&(self.p - line.project(&self.p)
|
||||
+ *line
|
||||
.points()
|
||||
.first()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?),
|
||||
) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ impl Encoder for ASCIIEncoder {
|
||||
.getMessage()
|
||||
.chars()
|
||||
.nth(context.pos as usize)
|
||||
.unwrap(),
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
context
|
||||
.getMessage()
|
||||
.chars()
|
||||
.nth(context.pos as usize + 1)
|
||||
.unwrap(),
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
)? as u8);
|
||||
context.pos += 2;
|
||||
} else {
|
||||
|
||||
@@ -51,19 +51,36 @@ impl Encoder for Base256Encoder {
|
||||
let lengthFieldSize = 1;
|
||||
let currentSize = context.getCodewordCount() + dataCount + lengthFieldSize;
|
||||
context.updateSymbolInfoWithLength(currentSize);
|
||||
let mustPad = (context.getSymbolInfo().unwrap().getDataCapacity() - currentSize as u32) > 0;
|
||||
let mustPad = (context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity()
|
||||
- currentSize as u32)
|
||||
> 0;
|
||||
if context.hasMoreCharacters() || mustPad {
|
||||
if dataCount <= 249 {
|
||||
buffer.replace_range(0..1, &char::from_u32(dataCount as u32).unwrap().to_string());
|
||||
buffer.replace_range(
|
||||
0..1,
|
||||
&char::from_u32(dataCount as u32)
|
||||
.ok_or(Exceptions::ParseException(None))?
|
||||
.to_string(),
|
||||
);
|
||||
} else if dataCount <= 1555 {
|
||||
buffer.replace_range(
|
||||
0..1,
|
||||
&char::from_u32((dataCount as u32 / 250) + 249)
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::ParseException(None))?
|
||||
.to_string(),
|
||||
);
|
||||
let (ci_pos, _) = buffer.char_indices().nth(1).unwrap();
|
||||
buffer.insert(ci_pos, char::from_u32(dataCount as u32 % 250).unwrap());
|
||||
let (ci_pos, _) = buffer
|
||||
.char_indices()
|
||||
.nth(1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
buffer.insert(
|
||||
ci_pos,
|
||||
char::from_u32(dataCount as u32 % 250)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
);
|
||||
} else {
|
||||
return Err(Exceptions::IllegalStateException(Some(format!(
|
||||
"Message length not in valid ranges: {dataCount}"
|
||||
@@ -73,10 +90,16 @@ impl Encoder for Base256Encoder {
|
||||
let c = buffer.chars().count();
|
||||
for i in 0..c {
|
||||
// for (int i = 0, c = buffer.length(); i < c; i++) {
|
||||
context.writeCodeword(Self::randomize255State(
|
||||
buffer.chars().nth(i).unwrap(),
|
||||
context.getCodewordCount() as u32 + 1,
|
||||
) as u8);
|
||||
context.writeCodeword(
|
||||
Self::randomize255State(
|
||||
buffer
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
context.getCodewordCount() as u32 + 1,
|
||||
)
|
||||
.ok_or(Exceptions::ParseException(None))? as u8,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -85,13 +108,13 @@ impl Base256Encoder {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
fn randomize255State(ch: char, codewordPosition: u32) -> char {
|
||||
fn randomize255State(ch: char, codewordPosition: u32) -> Option<char> {
|
||||
let pseudoRandom = ((149 * codewordPosition) % 255) + 1;
|
||||
let tempVariable = ch as u32 + pseudoRandom;
|
||||
if tempVariable <= 255 {
|
||||
char::from_u32(tempVariable).unwrap()
|
||||
char::from_u32(tempVariable)
|
||||
} else {
|
||||
char::from_u32(tempVariable - 256).unwrap()
|
||||
char::from_u32(tempVariable - 256)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,11 @@ impl C40Encoder {
|
||||
|
||||
let curCodewordCount = context.getCodewordCount() + unwritten;
|
||||
context.updateSymbolInfoWithLength(curCodewordCount);
|
||||
let available =
|
||||
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
|
||||
let available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity() as usize
|
||||
- curCodewordCount;
|
||||
|
||||
if !context.hasMoreCharacters() {
|
||||
//Avoid having a single C40 value in the last triplet
|
||||
@@ -107,7 +110,7 @@ impl C40Encoder {
|
||||
handleEOD(context, &mut buffer)
|
||||
}
|
||||
|
||||
pub fn encodeMaximalC40(&self, context: &mut EncoderContext) {
|
||||
pub fn encodeMaximalC40(&self, context: &mut EncoderContext) -> Result<(), Exceptions> {
|
||||
self.encodeMaximal(context, &Self::encodeChar_c40, &Self::handleEOD_c40)
|
||||
}
|
||||
|
||||
@@ -116,7 +119,7 @@ impl C40Encoder {
|
||||
context: &mut EncoderContext,
|
||||
encodeChar: &dyn Fn(char, &mut String) -> u32,
|
||||
handleEOD: &dyn Fn(&mut EncoderContext, &mut String) -> Result<(), Exceptions>,
|
||||
) {
|
||||
) -> Result<(), Exceptions> {
|
||||
let mut buffer = String::new();
|
||||
let mut lastCharSize = 0;
|
||||
let mut backtrackStartPosition = context.pos;
|
||||
@@ -135,8 +138,11 @@ impl C40Encoder {
|
||||
|
||||
let curCodewordCount = context.getCodewordCount() + unwritten + 1; // +1 for the latch to C40
|
||||
context.updateSymbolInfoWithLength(curCodewordCount);
|
||||
let available =
|
||||
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
|
||||
let available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity() as usize
|
||||
- curCodewordCount;
|
||||
let rest = buffer.chars().count() % 3;
|
||||
if (rest == 2 && available != 2) || (rest == 1 && (lastCharSize > 3 || available != 1))
|
||||
{
|
||||
@@ -149,7 +155,9 @@ impl C40Encoder {
|
||||
context.writeCodeword(LATCH_TO_C40);
|
||||
}
|
||||
|
||||
handleEOD(context, &mut buffer).expect("eod");
|
||||
handleEOD(context, &mut buffer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn backtrackOneCharacter(
|
||||
@@ -170,10 +178,16 @@ impl C40Encoder {
|
||||
lastCharSize
|
||||
}
|
||||
|
||||
pub(super) fn writeNextTriplet(context: &mut EncoderContext, buffer: &mut String) {
|
||||
context.writeCodewords(&Self::encodeToCodewords(buffer));
|
||||
pub(super) fn writeNextTriplet(
|
||||
context: &mut EncoderContext,
|
||||
buffer: &mut String,
|
||||
) -> Result<(), Exceptions> {
|
||||
context.writeCodewords(
|
||||
&Self::encodeToCodewords(buffer).ok_or(Exceptions::FormatException(None))?,
|
||||
);
|
||||
buffer.replace_range(0..3, "");
|
||||
// buffer.delete(0, 3);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,20 +205,23 @@ impl C40Encoder {
|
||||
|
||||
let curCodewordCount = context.getCodewordCount() + unwritten;
|
||||
context.updateSymbolInfoWithLength(curCodewordCount);
|
||||
let available =
|
||||
context.getSymbolInfo().unwrap().getDataCapacity() as usize - curCodewordCount;
|
||||
let available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity() as usize
|
||||
- curCodewordCount;
|
||||
|
||||
if rest == 2 {
|
||||
buffer.push('\0'); //Shift 1
|
||||
while buffer.chars().count() >= 3 {
|
||||
C40Encoder::writeNextTriplet(context, buffer);
|
||||
C40Encoder::writeNextTriplet(context, buffer)?;
|
||||
}
|
||||
if context.hasMoreCharacters() {
|
||||
context.writeCodeword(C40_UNLATCH);
|
||||
}
|
||||
} else if available == 1 && rest == 1 {
|
||||
while buffer.chars().count() >= 3 {
|
||||
C40Encoder::writeNextTriplet(context, buffer);
|
||||
C40Encoder::writeNextTriplet(context, buffer)?;
|
||||
}
|
||||
if context.hasMoreCharacters() {
|
||||
context.writeCodeword(C40_UNLATCH);
|
||||
@@ -213,7 +230,7 @@ impl C40Encoder {
|
||||
context.pos -= 1;
|
||||
} else if rest == 0 {
|
||||
while buffer.chars().count() >= 3 {
|
||||
C40Encoder::writeNextTriplet(context, buffer);
|
||||
C40Encoder::writeNextTriplet(context, buffer)?;
|
||||
}
|
||||
if available > 0 || context.hasMoreCharacters() {
|
||||
context.writeCodeword(C40_UNLATCH);
|
||||
@@ -273,16 +290,18 @@ impl C40Encoder {
|
||||
len
|
||||
}
|
||||
|
||||
fn encodeToCodewords(sb: &str) -> String {
|
||||
let v = (1600 * sb.chars().next().unwrap() as u32)
|
||||
+ (40 * sb.chars().nth(1).unwrap() as u32)
|
||||
+ sb.chars().nth(2).unwrap() as u32
|
||||
fn encodeToCodewords(sb: &str) -> Option<String> {
|
||||
let v = (1600 * sb.chars().next()? as u32)
|
||||
+ (40 * sb.chars().nth(1)? as u32)
|
||||
+ sb.chars().nth(2)? as u32
|
||||
+ 1;
|
||||
let cw1 = v / 256;
|
||||
let cw2 = v % 256;
|
||||
[char::from_u32(cw1).unwrap(), char::from_u32(cw2).unwrap()]
|
||||
.into_iter()
|
||||
.collect()
|
||||
Some(
|
||||
[char::from_u32(cw1)?, char::from_u32(cw2)?]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
)
|
||||
// return new String(new char[] {cw1, cw2});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
const EMPTY_BIT_VAL: u8 = 13;
|
||||
|
||||
/**
|
||||
@@ -71,7 +73,7 @@ impl DefaultPlacement {
|
||||
self.bits[row * self.numcols + col] == EMPTY_BIT_VAL
|
||||
}
|
||||
|
||||
pub fn place(&mut self) {
|
||||
pub fn place(&mut self) -> Result<(), Exceptions> {
|
||||
let mut pos = 0;
|
||||
let mut row = 4_isize;
|
||||
let mut col = 0_isize;
|
||||
@@ -79,19 +81,19 @@ impl DefaultPlacement {
|
||||
loop {
|
||||
// repeatedly first check for one of the special corner cases, then...
|
||||
if (row == self.numrows as isize) && (col == 0) {
|
||||
self.corner1(pos);
|
||||
self.corner1(pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
if (row == self.numrows as isize - 2) && (col == 0) && ((self.numcols % 4) != 0) {
|
||||
self.corner2(pos);
|
||||
self.corner2(pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
if (row == self.numrows as isize - 2) && (col == 0) && (self.numcols % 8 == 4) {
|
||||
self.corner3(pos);
|
||||
self.corner3(pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
if (row == self.numrows as isize + 4) && (col == 2) && ((self.numcols % 8) == 0) {
|
||||
self.corner4(pos);
|
||||
self.corner4(pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
// sweep upward diagonally, inserting successive characters...
|
||||
@@ -100,7 +102,7 @@ impl DefaultPlacement {
|
||||
&& (col >= 0)
|
||||
&& self.noBit(col as usize, row as usize)
|
||||
{
|
||||
self.utah(row, col, pos);
|
||||
self.utah(row, col, pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
row -= 2;
|
||||
@@ -118,7 +120,7 @@ impl DefaultPlacement {
|
||||
&& (col < self.numcols as isize)
|
||||
&& self.noBit(col as usize, row as usize)
|
||||
{
|
||||
self.utah(row, col, pos);
|
||||
self.utah(row, col, pos)?;
|
||||
pos += 1;
|
||||
}
|
||||
row += 2;
|
||||
@@ -142,9 +144,10 @@ impl DefaultPlacement {
|
||||
self.setBit(self.numcols - 1, self.numrows - 1, true);
|
||||
self.setBit(self.numcols - 2, self.numrows - 2, true);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn module(&mut self, row: isize, col: isize, pos: usize, bit: u32) {
|
||||
fn module(&mut self, row: isize, col: isize, pos: usize, bit: u32) -> Result<(), Exceptions> {
|
||||
let mut row = row;
|
||||
let mut col = col;
|
||||
|
||||
@@ -157,9 +160,15 @@ impl DefaultPlacement {
|
||||
row += 4 - ((self.numcols + 4) % 8) as isize;
|
||||
}
|
||||
// Note the conversion:
|
||||
let mut v = self.codewords.chars().nth(pos).unwrap() as u32;
|
||||
let mut v = self
|
||||
.codewords
|
||||
.chars()
|
||||
.nth(pos)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as u32;
|
||||
v &= 1 << (8 - bit);
|
||||
self.setBit(col as usize, row as usize, v != 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,59 +178,64 @@ impl DefaultPlacement {
|
||||
* @param col the column
|
||||
* @param pos character position
|
||||
*/
|
||||
fn utah(&mut self, row: isize, col: isize, pos: usize) {
|
||||
self.module(row - 2, col - 2, pos, 1);
|
||||
self.module(row - 2, col - 1, pos, 2);
|
||||
self.module(row - 1, col - 2, pos, 3);
|
||||
self.module(row - 1, col - 1, pos, 4);
|
||||
self.module(row - 1, col, pos, 5);
|
||||
self.module(row, col - 2, pos, 6);
|
||||
self.module(row, col - 1, pos, 7);
|
||||
self.module(row, col, pos, 8);
|
||||
fn utah(&mut self, row: isize, col: isize, pos: usize) -> Result<(), Exceptions> {
|
||||
self.module(row - 2, col - 2, pos, 1)?;
|
||||
self.module(row - 2, col - 1, pos, 2)?;
|
||||
self.module(row - 1, col - 2, pos, 3)?;
|
||||
self.module(row - 1, col - 1, pos, 4)?;
|
||||
self.module(row - 1, col, pos, 5)?;
|
||||
self.module(row, col - 2, pos, 6)?;
|
||||
self.module(row, col - 1, pos, 7)?;
|
||||
self.module(row, col, pos, 8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn corner1(&mut self, pos: usize) {
|
||||
self.module(self.numrows as isize - 1, 0, pos, 1);
|
||||
self.module(self.numrows as isize - 1, 1, pos, 2);
|
||||
self.module(self.numrows as isize - 1, 2, pos, 3);
|
||||
self.module(0, self.numcols as isize - 2, pos, 4);
|
||||
self.module(0, self.numcols as isize - 1, pos, 5);
|
||||
self.module(1, self.numcols as isize - 1, pos, 6);
|
||||
self.module(2, self.numcols as isize - 1, pos, 7);
|
||||
self.module(3, self.numcols as isize - 1, pos, 8);
|
||||
fn corner1(&mut self, pos: usize) -> Result<(), Exceptions> {
|
||||
self.module(self.numrows as isize - 1, 0, pos, 1)?;
|
||||
self.module(self.numrows as isize - 1, 1, pos, 2)?;
|
||||
self.module(self.numrows as isize - 1, 2, pos, 3)?;
|
||||
self.module(0, self.numcols as isize - 2, pos, 4)?;
|
||||
self.module(0, self.numcols as isize - 1, pos, 5)?;
|
||||
self.module(1, self.numcols as isize - 1, pos, 6)?;
|
||||
self.module(2, self.numcols as isize - 1, pos, 7)?;
|
||||
self.module(3, self.numcols as isize - 1, pos, 8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn corner2(&mut self, pos: usize) {
|
||||
self.module(self.numrows as isize - 3, 0, pos, 1);
|
||||
self.module(self.numrows as isize - 2, 0, pos, 2);
|
||||
self.module(self.numrows as isize - 1, 0, pos, 3);
|
||||
self.module(0, self.numcols as isize - 4, pos, 4);
|
||||
self.module(0, self.numcols as isize - 3, pos, 5);
|
||||
self.module(0, self.numcols as isize - 2, pos, 6);
|
||||
self.module(0, self.numcols as isize - 1, pos, 7);
|
||||
self.module(1, self.numcols as isize - 1, pos, 8);
|
||||
fn corner2(&mut self, pos: usize) -> Result<(), Exceptions> {
|
||||
self.module(self.numrows as isize - 3, 0, pos, 1)?;
|
||||
self.module(self.numrows as isize - 2, 0, pos, 2)?;
|
||||
self.module(self.numrows as isize - 1, 0, pos, 3)?;
|
||||
self.module(0, self.numcols as isize - 4, pos, 4)?;
|
||||
self.module(0, self.numcols as isize - 3, pos, 5)?;
|
||||
self.module(0, self.numcols as isize - 2, pos, 6)?;
|
||||
self.module(0, self.numcols as isize - 1, pos, 7)?;
|
||||
self.module(1, self.numcols as isize - 1, pos, 8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn corner3(&mut self, pos: usize) {
|
||||
self.module(self.numrows as isize - 3, 0, pos, 1);
|
||||
self.module(self.numrows as isize - 2, 0, pos, 2);
|
||||
self.module(self.numrows as isize - 1, 0, pos, 3);
|
||||
self.module(0, self.numcols as isize - 2, pos, 4);
|
||||
self.module(0, self.numcols as isize - 1, pos, 5);
|
||||
self.module(1, self.numcols as isize - 1, pos, 6);
|
||||
self.module(2, self.numcols as isize - 1, pos, 7);
|
||||
self.module(3, self.numcols as isize - 1, pos, 8);
|
||||
fn corner3(&mut self, pos: usize) -> Result<(), Exceptions> {
|
||||
self.module(self.numrows as isize - 3, 0, pos, 1)?;
|
||||
self.module(self.numrows as isize - 2, 0, pos, 2)?;
|
||||
self.module(self.numrows as isize - 1, 0, pos, 3)?;
|
||||
self.module(0, self.numcols as isize - 2, pos, 4)?;
|
||||
self.module(0, self.numcols as isize - 1, pos, 5)?;
|
||||
self.module(1, self.numcols as isize - 1, pos, 6)?;
|
||||
self.module(2, self.numcols as isize - 1, pos, 7)?;
|
||||
self.module(3, self.numcols as isize - 1, pos, 8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn corner4(&mut self, pos: usize) {
|
||||
self.module(self.numrows as isize - 1, 0, pos, 1);
|
||||
self.module(self.numrows as isize - 1, self.numcols as isize - 1, pos, 2);
|
||||
self.module(0, self.numcols as isize - 3, pos, 3);
|
||||
self.module(0, self.numcols as isize - 2, pos, 4);
|
||||
self.module(0, self.numcols as isize - 1, pos, 5);
|
||||
self.module(1, self.numcols as isize - 3, pos, 6);
|
||||
self.module(1, self.numcols as isize - 2, pos, 7);
|
||||
self.module(1, self.numcols as isize - 1, pos, 8);
|
||||
fn corner4(&mut self, pos: usize) -> Result<(), Exceptions> {
|
||||
self.module(self.numrows as isize - 1, 0, pos, 1)?;
|
||||
self.module(self.numrows as isize - 1, self.numcols as isize - 1, pos, 2)?;
|
||||
self.module(0, self.numcols as isize - 3, pos, 3)?;
|
||||
self.module(0, self.numcols as isize - 2, pos, 4)?;
|
||||
self.module(0, self.numcols as isize - 1, pos, 5)?;
|
||||
self.module(1, self.numcols as isize - 3, pos, 6)?;
|
||||
self.module(1, self.numcols as isize - 2, pos, 7)?;
|
||||
self.module(1, self.numcols as isize - 1, pos, 8)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -257,7 +271,7 @@ mod test_placement {
|
||||
fn testPlacement() {
|
||||
let codewords = unvisualize("66 74 78 66 74 78 129 56 35 102 192 96 226 100 156 1 107 221"); //"AIMAIM" encoded
|
||||
let mut placement = DefaultPlacement::new(codewords, 12, 12);
|
||||
placement.place();
|
||||
placement.place().expect("msg");
|
||||
let expected = [
|
||||
"011100001111",
|
||||
"001010101000",
|
||||
|
||||
@@ -29,7 +29,7 @@ impl Encoder for EdifactEncoder {
|
||||
let mut buffer = String::new();
|
||||
while context.hasMoreCharacters() {
|
||||
let c = context.getCurrentChar();
|
||||
Self::encodeChar(c, &mut buffer);
|
||||
Self::encodeChar(c, &mut buffer)?;
|
||||
context.pos += 1;
|
||||
|
||||
let count = buffer.chars().count();
|
||||
@@ -74,13 +74,19 @@ impl EdifactEncoder {
|
||||
if count == 1 {
|
||||
//Only an unlatch at the end
|
||||
context.updateSymbolInfo();
|
||||
let mut available = context.getSymbolInfo().unwrap().getDataCapacity()
|
||||
let mut available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity()
|
||||
- context.getCodewordCount() as u32;
|
||||
let remaining = context.getRemainingCharacters();
|
||||
// The following two lines are a hack inspired by the 'fix' from https://sourceforge.net/p/barcode4j/svn/221/
|
||||
if remaining > available {
|
||||
context.updateSymbolInfoWithLength(context.getCodewordCount() + 1);
|
||||
available = context.getSymbolInfo().unwrap().getDataCapacity()
|
||||
available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity()
|
||||
- context.getCodewordCount() as u32;
|
||||
}
|
||||
if remaining <= available && available <= 2 {
|
||||
@@ -100,7 +106,10 @@ impl EdifactEncoder {
|
||||
|
||||
if restChars <= 2 {
|
||||
context.updateSymbolInfoWithLength(context.getCodewordCount() + restChars);
|
||||
let available = context.getSymbolInfo().unwrap().getDataCapacity()
|
||||
let available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity()
|
||||
- context.getCodewordCount() as u32;
|
||||
if available >= 3 {
|
||||
restInAscii = false;
|
||||
@@ -126,14 +135,15 @@ impl EdifactEncoder {
|
||||
res
|
||||
}
|
||||
|
||||
fn encodeChar(c: char, sb: &mut String) {
|
||||
fn encodeChar(c: char, sb: &mut String) -> Result<(), Exceptions> {
|
||||
if (' '..='?').contains(&c) {
|
||||
sb.push(c);
|
||||
} else if ('@'..='^').contains(&c) {
|
||||
sb.push((c as u8 - 64) as char);
|
||||
} else {
|
||||
high_level_encoder::illegalCharacter(c).expect("");
|
||||
high_level_encoder::illegalCharacter(c)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn encodeToCodewords(sb: &str) -> Result<String, Exceptions> {
|
||||
@@ -143,19 +153,28 @@ impl EdifactEncoder {
|
||||
"StringBuilder must not be empty".to_owned(),
|
||||
)));
|
||||
}
|
||||
let c1 = sb.chars().next().unwrap();
|
||||
let c1 = sb
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
let c2 = if len >= 2 {
|
||||
sb.chars().nth(1).unwrap()
|
||||
sb.chars()
|
||||
.nth(1)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
} else {
|
||||
0 as char
|
||||
};
|
||||
let c3 = if len >= 3 {
|
||||
sb.chars().nth(2).unwrap()
|
||||
sb.chars()
|
||||
.nth(2)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
} else {
|
||||
0 as char
|
||||
};
|
||||
let c4 = if len >= 4 {
|
||||
sb.chars().nth(3).unwrap()
|
||||
sb.chars()
|
||||
.nth(3)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
} else {
|
||||
0 as char
|
||||
};
|
||||
@@ -165,12 +184,12 @@ impl EdifactEncoder {
|
||||
let cw2 = (v >> 8) & 255;
|
||||
let cw3 = v & 255;
|
||||
let mut res = String::with_capacity(3);
|
||||
res.push(char::from_u32(cw1).unwrap());
|
||||
res.push(char::from_u32(cw1).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
|
||||
if len >= 2 {
|
||||
res.push(char::from_u32(cw2).unwrap());
|
||||
res.push(char::from_u32(cw2).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
|
||||
}
|
||||
if len >= 3 {
|
||||
res.push(char::from_u32(cw3).unwrap());
|
||||
res.push(char::from_u32(cw3).ok_or(Exceptions::IndexOutOfBoundsException(None))?);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
|
||||
@@ -62,7 +62,11 @@ impl<'a> EncoderContext<'_> {
|
||||
{
|
||||
ISO_8859_1_ENCODER
|
||||
.decode(&encoded_bytes, encoding::DecoderTrap::Strict)
|
||||
.expect("round trip decode should always work")
|
||||
.map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!(
|
||||
"round trip decode should always work: {e}"
|
||||
)))
|
||||
})?
|
||||
} else {
|
||||
return Err(Exceptions::IllegalArgumentException(Some(
|
||||
"Message contains characters outside ISO-8859-1 encoding.".to_owned(),
|
||||
@@ -99,13 +103,13 @@ impl<'a> EncoderContext<'_> {
|
||||
self.skipAtEnd = count;
|
||||
}
|
||||
|
||||
/// panics if current position is out of bounds
|
||||
pub fn getCurrentChar(&self) -> char {
|
||||
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
|
||||
self.msg.chars().nth(self.pos as usize).unwrap()
|
||||
}
|
||||
|
||||
/// panics if current position is out of bounds
|
||||
pub fn getCurrent(&self) -> char {
|
||||
// self.msg.graphemes(true).nth(self.pos as usize).unwrap()
|
||||
self.msg.chars().nth(self.pos as usize).unwrap()
|
||||
}
|
||||
|
||||
@@ -157,6 +161,9 @@ impl<'a> EncoderContext<'_> {
|
||||
self.updateSymbolInfoWithLength(self.getCodewordCount());
|
||||
}
|
||||
|
||||
/// Update symbol info with the length
|
||||
///
|
||||
/// This function can panic
|
||||
pub fn updateSymbolInfoWithLength(&mut self, len: usize) {
|
||||
if self.symbolInfo.is_none()
|
||||
|| len > self.symbolInfo.as_ref().unwrap().getDataCapacity() as usize
|
||||
|
||||
@@ -35,61 +35,61 @@ const FACTOR_SETS: [u32; 16] = [5, 7, 10, 11, 12, 14, 18, 20, 24, 28, 36, 42, 48
|
||||
*/
|
||||
static FACTORS: Lazy<[Vec<u32>; 16]> = Lazy::new(|| {
|
||||
[
|
||||
Vec::from([228, 48, 15, 111, 62]),
|
||||
Vec::from([23, 68, 144, 134, 240, 92, 254]),
|
||||
Vec::from([28, 24, 185, 166, 223, 248, 116, 255, 110, 61]),
|
||||
Vec::from([175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120]),
|
||||
Vec::from([41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242]),
|
||||
Vec::from([
|
||||
vec![228, 48, 15, 111, 62],
|
||||
vec![23, 68, 144, 134, 240, 92, 254],
|
||||
vec![28, 24, 185, 166, 223, 248, 116, 255, 110, 61],
|
||||
vec![175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120],
|
||||
vec![41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242],
|
||||
vec![
|
||||
156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48, 90, 188,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186,
|
||||
172,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12,
|
||||
181, 184, 96, 50, 193,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121, 17, 138, 110,
|
||||
213, 141, 136, 120, 151, 233, 168, 93, 255,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182, 229, 18,
|
||||
2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25, 225, 98, 81, 112,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8, 175, 95, 100, 9,
|
||||
167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, 248, 202, 69, 50, 150, 177, 226,
|
||||
5, 9, 5,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, 191, 106,
|
||||
16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138, 186, 240, 82, 44, 176,
|
||||
87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235, 150, 159,
|
||||
36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232, 144, 238, 22, 150,
|
||||
201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, 155, 43, 203, 107, 233, 53,
|
||||
143, 46,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, 185, 112,
|
||||
134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71, 161, 44, 147, 6, 27,
|
||||
218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31, 176, 170, 4, 107, 232, 7, 94, 166, 224,
|
||||
124, 86, 47, 11, 204,
|
||||
]),
|
||||
Vec::from([
|
||||
],
|
||||
vec![
|
||||
220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127, 213, 136,
|
||||
248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236, 66, 139, 153, 185,
|
||||
202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239, 181, 241, 59, 52, 172, 25,
|
||||
49, 232, 211, 189, 64, 54, 108, 153, 132, 63, 96, 103, 82, 186,
|
||||
]),
|
||||
],
|
||||
]
|
||||
});
|
||||
|
||||
@@ -181,7 +181,12 @@ pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String,
|
||||
let mut d = block;
|
||||
while d < symbolInfo.getDataCapacity() as usize {
|
||||
// for (int d = block; d < symbolInfo.getDataCapacity(); d += blockCount) {
|
||||
temp.push(codewords.chars().nth(d).unwrap());
|
||||
temp.push(
|
||||
codewords
|
||||
.chars()
|
||||
.nth(d)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?,
|
||||
);
|
||||
|
||||
d += blockCount;
|
||||
}
|
||||
@@ -193,10 +198,13 @@ pub fn encodeECC200(codewords: &str, symbolInfo: &SymbolInfo) -> Result<String,
|
||||
let (char_index, replace_char) = sb
|
||||
.char_indices()
|
||||
.nth(symbolInfo.getDataCapacity() as usize + e)
|
||||
.unwrap();
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
sb.replace_range(
|
||||
char_index..(replace_char.len_utf8()),
|
||||
&ecc.chars().nth(pos).unwrap().to_string(),
|
||||
&ecc.chars()
|
||||
.nth(pos)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_string(),
|
||||
);
|
||||
// sb.setCharAt(symbolInfo.getDataCapacity() + e, ecc.charAt(pos));
|
||||
pos += 1;
|
||||
@@ -232,20 +240,25 @@ fn createECCBlock(codewords: &str, numECWords: usize) -> Result<String, Exceptio
|
||||
// }
|
||||
for i in 0..codewords.chars().count() {
|
||||
// for (int i = 0; i < codewords.length(); i++) {
|
||||
let m = ecc[numECWords - 1] as usize ^ codewords.chars().nth(i).unwrap() as usize;
|
||||
let m = ecc[numECWords - 1] as usize
|
||||
^ codewords
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))? as usize;
|
||||
for k in (1..numECWords).rev() {
|
||||
// for (int k = numECWords - 1; k > 0; k--) {
|
||||
if m != 0 && poly[k] != 0 {
|
||||
ecc[k] = char::from_u32(
|
||||
ecc[k - 1] as u32 ^ ALOG[(LOG[m] + LOG[poly[k] as usize]) as usize % 255],
|
||||
)
|
||||
.unwrap();
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else {
|
||||
ecc[k] = ecc[k - 1];
|
||||
}
|
||||
}
|
||||
if m != 0 && poly[0] != 0 {
|
||||
ecc[0] = char::from_u32(ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255]).unwrap();
|
||||
ecc[0] = char::from_u32(ALOG[(LOG[m] + LOG[poly[0] as usize]) as usize % 255])
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
} else {
|
||||
ecc[0] = 0 as char;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ fn randomize253State(codewordPosition: u32) -> String {
|
||||
} else {
|
||||
char::from_u32(tempVariable - 254)
|
||||
}
|
||||
.expect("must become a char")
|
||||
// .expect("must become a char")
|
||||
.unwrap_or(char::default())
|
||||
.to_string()
|
||||
// return (char) (tempVariable <= 254 ? tempVariable : tempVariable - 254);
|
||||
}
|
||||
@@ -219,21 +220,28 @@ pub fn encodeHighLevelWithDimensionForceC40WithSymbolInfoLookup(
|
||||
let mut encodingMode = ASCII_ENCODATION; //Default mode
|
||||
|
||||
if forceC40 {
|
||||
c40Encoder.encodeMaximalC40(&mut context);
|
||||
encodingMode = context.getNewEncoding().unwrap();
|
||||
c40Encoder.encodeMaximalC40(&mut context)?;
|
||||
encodingMode = context
|
||||
.getNewEncoding()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?;
|
||||
context.resetEncoderSignal();
|
||||
}
|
||||
|
||||
while context.hasMoreCharacters() {
|
||||
encoders[encodingMode].encode(&mut context)?;
|
||||
if context.getNewEncoding().is_some() {
|
||||
encodingMode = context.getNewEncoding().unwrap();
|
||||
encodingMode = context
|
||||
.getNewEncoding()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?;
|
||||
context.resetEncoderSignal();
|
||||
}
|
||||
}
|
||||
let len = context.getCodewordCount();
|
||||
context.updateSymbolInfo();
|
||||
let capacity = context.getSymbolInfo().unwrap().getDataCapacity();
|
||||
let capacity = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity();
|
||||
if len < capacity as usize
|
||||
&& encodingMode != ASCII_ENCODATION
|
||||
&& encodingMode != BASE256_ENCODATION
|
||||
@@ -289,8 +297,10 @@ pub fn lookAheadTest(msg: &str, startpos: u32, currentMode: u32) -> usize {
|
||||
let endpos = (startpos + 3).min(msg.chars().count() as u32);
|
||||
for i in startpos..endpos {
|
||||
// for (int i = startpos; i < endpos; i++) {
|
||||
if !isNativeX12(msg.chars().nth(i as usize).unwrap()) {
|
||||
return ASCII_ENCODATION;
|
||||
if let Some(c) = msg.chars().nth(i as usize) {
|
||||
if !isNativeX12(c) {
|
||||
return ASCII_ENCODATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if currentMode as usize == EDIFACT_ENCODATION && newMode == EDIFACT_ENCODATION {
|
||||
@@ -298,8 +308,10 @@ pub fn lookAheadTest(msg: &str, startpos: u32, currentMode: u32) -> usize {
|
||||
let endpos = (startpos + 4).min(msg.chars().count() as u32);
|
||||
for i in startpos..endpos {
|
||||
// for (int i = startpos; i < endpos; i++) {
|
||||
if !isNativeEDIFACT(msg.chars().nth(i as usize).unwrap()) {
|
||||
return ASCII_ENCODATION;
|
||||
if let Some(c) = msg.chars().nth(i as usize) {
|
||||
if !isNativeEDIFACT(c) {
|
||||
return ASCII_ENCODATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,15 +364,11 @@ fn lookAheadTestIntern(msg: &str, startpos: u32, currentMode: u32) -> usize {
|
||||
return C40_ENCODATION;
|
||||
}
|
||||
|
||||
// let c = msg
|
||||
// .graphemes(true)
|
||||
// .nth((startpos + charsProcessed) as usize)
|
||||
// .unwrap();
|
||||
// let c = msg.charAt(startpos + charsProcessed);
|
||||
let c = msg
|
||||
.chars()
|
||||
.nth((startpos + charsProcessed) as usize)
|
||||
.unwrap();
|
||||
let Some(c) = msg
|
||||
.chars()
|
||||
.nth((startpos + charsProcessed) as usize) else {
|
||||
break 0;
|
||||
};
|
||||
charsProcessed += 1;
|
||||
|
||||
//step L
|
||||
@@ -593,7 +601,8 @@ pub fn determineConsecutiveDigitCount(msg: &str, startpos: u32) -> u32 {
|
||||
let len = msg.chars().count(); //len();
|
||||
let mut idx = startpos;
|
||||
// let graphemes = msg.graphemes(true);
|
||||
while (idx as usize) < len && isDigit(msg.chars().nth(idx as usize).unwrap()) {
|
||||
while (idx as usize) < len && isDigit(msg.chars().nth(idx as usize).unwrap_or(char::default()))
|
||||
{
|
||||
idx += 1;
|
||||
}
|
||||
idx - startpos
|
||||
|
||||
@@ -218,7 +218,7 @@ fn addEdge(edges: &mut [Vec<Option<Rc<Edge>>>], edge: Rc<Edge>) -> Result<(), Ex
|
||||
if edges[vertexIndex][edge.getEndMode()?.ordinal()].is_none()
|
||||
|| edges[vertexIndex][edge.getEndMode()?.ordinal()]
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.cachedTotalSize
|
||||
> edge.cachedTotalSize
|
||||
{
|
||||
@@ -296,7 +296,7 @@ fn addEdges(
|
||||
//not possible to unlatch a full EDF edge to something
|
||||
//else
|
||||
if high_level_encoder::isDigit(ch)
|
||||
&& input.haveNCharacters(from as usize, 2)
|
||||
&& input.haveNCharacters(from as usize, 2)?
|
||||
&& high_level_encoder::isDigit(input.charAt(from as usize + 1)?)
|
||||
{
|
||||
// two digits ASCII encoded
|
||||
@@ -344,7 +344,7 @@ fn addEdges(
|
||||
}
|
||||
}
|
||||
|
||||
if input.haveNCharacters(from as usize, 3)
|
||||
if input.haveNCharacters(from as usize, 3)?
|
||||
&& high_level_encoder::isNativeX12(input.charAt(from as usize)?)
|
||||
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 1)?)
|
||||
&& high_level_encoder::isNativeX12(input.charAt(from as usize + 2)?)
|
||||
@@ -379,7 +379,7 @@ fn addEdges(
|
||||
while i < 3 {
|
||||
// for (i = 0; i < 3; i++) {
|
||||
let pos = from + i;
|
||||
if input.haveNCharacters(pos as usize, 1)
|
||||
if input.haveNCharacters(pos as usize, 1)?
|
||||
&& high_level_encoder::isNativeEDIFACT(input.charAt(pos as usize)?)
|
||||
{
|
||||
addEdge(
|
||||
@@ -398,7 +398,7 @@ fn addEdges(
|
||||
i += 1;
|
||||
}
|
||||
if i == 3
|
||||
&& input.haveNCharacters(from as usize, 4)
|
||||
&& input.haveNCharacters(from as usize, 4)?
|
||||
&& high_level_encoder::isNativeEDIFACT(input.charAt(from as usize + 3)?)
|
||||
{
|
||||
addEdge(
|
||||
@@ -604,9 +604,7 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
|
||||
addEdges(input.clone(), &mut edges, 0, None)?;
|
||||
|
||||
for i in 1..=inputLength {
|
||||
// for (int i = 1; i <= inputLength; i++) {
|
||||
for j in 0..6 {
|
||||
// for (int j = 0; j < 6; j++) {
|
||||
if edges[i][j].is_some() && i < inputLength {
|
||||
let edge = edges[i][j].clone();
|
||||
addEdges(input.clone(), &mut edges, i as u32, edge)?;
|
||||
@@ -614,7 +612,6 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
|
||||
}
|
||||
//optimize memory by removing edges that have been passed.
|
||||
for j in 0..6 {
|
||||
// for (int j = 0; j < 6; j++) {
|
||||
edges[i - 1][j] = None;
|
||||
}
|
||||
}
|
||||
@@ -622,7 +619,6 @@ fn encodeMinimally(input: Rc<Input>) -> Result<RXingResult, Exceptions> {
|
||||
let mut minimalJ: i32 = -1;
|
||||
let mut minimalSize = i32::MAX;
|
||||
for j in 0..6 {
|
||||
// for (int j = 0; j < 6; j++) {
|
||||
if edges[inputLength][j].is_some() {
|
||||
let edge = edges[inputLength][j].as_ref().unwrap();
|
||||
let size = if (1..=3).contains(&j) {
|
||||
@@ -672,12 +668,9 @@ impl Edge {
|
||||
characterLength: u32,
|
||||
previous: Option<Rc<Edge>>,
|
||||
) -> Result<Self, Exceptions> {
|
||||
// this.input = input;
|
||||
// this.mode = mode;
|
||||
// this.fromPosition = fromPosition;
|
||||
// this.characterLength = characterLength;
|
||||
// this.previous = previous;
|
||||
assert!(fromPosition + characterLength <= input.length() as u32);
|
||||
if fromPosition + characterLength > input.length() as u32 {
|
||||
return Err(Exceptions::FormatException(None));
|
||||
}
|
||||
|
||||
let mut size = if let Some(previous) = previous.clone() {
|
||||
previous.cachedTotalSize
|
||||
@@ -704,11 +697,9 @@ impl Edge {
|
||||
match mode {
|
||||
Mode::Ascii => {
|
||||
size += 1;
|
||||
if input.isECI(fromPosition).expect("bool")
|
||||
if input.isECI(fromPosition)?
|
||||
|| isExtendedASCII(
|
||||
input
|
||||
.charAt(fromPosition as usize)
|
||||
.expect("char must exist)"),
|
||||
input.charAt(fromPosition as usize)?,
|
||||
input.getFNC1Character(),
|
||||
)
|
||||
{
|
||||
@@ -748,9 +739,7 @@ impl Edge {
|
||||
fromPosition,
|
||||
mode == Mode::C40,
|
||||
&mut charLen,
|
||||
)
|
||||
.expect("works")
|
||||
* 2;
|
||||
)? * 2;
|
||||
}
|
||||
|
||||
if previousMode == Mode::Ascii || previousMode == Mode::B256 {
|
||||
@@ -1382,10 +1371,9 @@ impl RXingResult {
|
||||
|
||||
pub fn applyRandomPattern(bytesAL: &mut [u8], startPosition: u32, length: u32) {
|
||||
for i in 0..length as usize {
|
||||
// for (int i = 0; i < length; i++) {
|
||||
//See "B.1 253-state algorithm
|
||||
let Pad_codeword_position = startPosition as usize + i;
|
||||
let Pad_codeword_value = bytesAL.get(Pad_codeword_position).expect("known to exist");
|
||||
let Pad_codeword_value = bytesAL.get(Pad_codeword_position).unwrap_or(&0);
|
||||
let pseudo_random_number = ((149 * (Pad_codeword_position + 1)) % 255) + 1;
|
||||
let temp_variable: u16 = *Pad_codeword_value as u16 + pseudo_random_number as u16;
|
||||
bytesAL[Pad_codeword_position] = if temp_variable <= 255 {
|
||||
@@ -1452,7 +1440,7 @@ impl Input {
|
||||
Some(self.internal.getFNC1Character() as u8 as char)
|
||||
}
|
||||
}
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> bool {
|
||||
fn haveNCharacters(&self, index: usize, n: usize) -> Result<bool, Exceptions> {
|
||||
self.internal.haveNCharacters(index, n)
|
||||
}
|
||||
fn isFNC1(&self, index: usize) -> Result<bool, Exceptions> {
|
||||
|
||||
@@ -132,19 +132,6 @@ impl SymbolInfo {
|
||||
"Cannot handle this number of data regions".to_owned(),
|
||||
))),
|
||||
}
|
||||
// switch (dataRegions) {
|
||||
// case 1:
|
||||
// return 1;
|
||||
// case 2:
|
||||
// case 4:
|
||||
// return 2;
|
||||
// case 16:
|
||||
// return 4;
|
||||
// case 36:
|
||||
// return 6;
|
||||
// default:
|
||||
// throw new IllegalStateException("Cannot handle this number of data regions");
|
||||
// }
|
||||
}
|
||||
|
||||
fn getVerticalDataRegions(&self) -> Result<u32, Exceptions> {
|
||||
@@ -157,19 +144,6 @@ impl SymbolInfo {
|
||||
"Cannot handle this number of data regions".to_owned(),
|
||||
))),
|
||||
}
|
||||
// switch (dataRegions) {
|
||||
// case 1:
|
||||
// case 2:
|
||||
// return 1;
|
||||
// case 4:
|
||||
// return 2;
|
||||
// case 16:
|
||||
// return 4;
|
||||
// case 36:
|
||||
// return 6;
|
||||
// default:
|
||||
// throw new IllegalStateException("Cannot handle this number of data regions");
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn getSymbolDataWidth(&self) -> Result<u32, Exceptions> {
|
||||
@@ -223,15 +197,6 @@ impl SymbolInfo {
|
||||
pub fn getErrorLengthForInterleavedBlock(&self, _index: u32) -> u32 {
|
||||
self.rsBlockError
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public final String toString() {
|
||||
// return (rectangular ? "Rectangular Symbol:" : "Square Symbol:") +
|
||||
// " data region " + matrixWidth + 'x' + matrixHeight +
|
||||
// ", symbol size " + getSymbolWidth() + 'x' + getSymbolHeight() +
|
||||
// ", symbol data size " + getSymbolDataWidth() + 'x' + getSymbolDataHeight() +
|
||||
// ", codewords " + dataCapacity + '+' + errorCodewords;
|
||||
// }
|
||||
}
|
||||
|
||||
impl fmt::Display for SymbolInfo {
|
||||
@@ -424,7 +389,7 @@ mod tests {
|
||||
assert_eq!(24, info.getSymbolWidth().expect("return"));
|
||||
assert_eq!(24, info.getSymbolHeight().expect("return"));
|
||||
|
||||
let fixedSize = Dimension::new(26, 26).expect("new dimension");
|
||||
let fixedSize = Dimension::new(26, 26);
|
||||
let info = LOOKUP
|
||||
.lookup_with_codewords_shape_size_fail(
|
||||
35,
|
||||
@@ -451,7 +416,7 @@ mod tests {
|
||||
assert!(info.is_none());
|
||||
|
||||
let minSize = fixedSize;
|
||||
let maxSize = Dimension::new(32, 32).expect("new dimension");
|
||||
let maxSize = Dimension::new(32, 32);
|
||||
|
||||
let info = LOOKUP
|
||||
.lookup_with_codewords_shape_size_fail(
|
||||
|
||||
@@ -31,11 +31,11 @@ impl Encoder for X12Encoder {
|
||||
let c = context.getCurrentChar();
|
||||
context.pos += 1;
|
||||
|
||||
Self::encodeChar(c, &mut buffer);
|
||||
Self::encodeChar(c, &mut buffer)?;
|
||||
|
||||
let count = buffer.chars().count();
|
||||
if (count % 3) == 0 {
|
||||
C40Encoder::writeNextTriplet(context, &mut buffer);
|
||||
C40Encoder::writeNextTriplet(context, &mut buffer)?;
|
||||
|
||||
let newMode = high_level_encoder::lookAheadTest(
|
||||
context.getMessage(),
|
||||
@@ -58,7 +58,7 @@ impl X12Encoder {
|
||||
Self(C40Encoder::new())
|
||||
}
|
||||
|
||||
fn encodeChar(c: char, sb: &mut String) -> u32 {
|
||||
fn encodeChar(c: char, sb: &mut String) -> Result<u32, Exceptions> {
|
||||
match c {
|
||||
'\r' => sb.push('\0'),
|
||||
'*' => sb.push('\u{1}'),
|
||||
@@ -70,17 +70,20 @@ impl X12Encoder {
|
||||
} else if ('A'..='Z').contains(&c) {
|
||||
sb.push((c as u8 - 65 + 14) as char);
|
||||
} else {
|
||||
high_level_encoder::illegalCharacter(c).expect("detect_illegal_character");
|
||||
high_level_encoder::illegalCharacter(c)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
fn handleEOD(context: &mut EncoderContext, buffer: &mut str) -> Result<(), Exceptions> {
|
||||
context.updateSymbolInfo();
|
||||
let available =
|
||||
context.getSymbolInfo().unwrap().getDataCapacity() - context.getCodewordCount() as u32;
|
||||
let available = context
|
||||
.getSymbolInfo()
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
.getDataCapacity()
|
||||
- context.getCodewordCount() as u32;
|
||||
let count = buffer.chars().count();
|
||||
context.pos -= count as u32;
|
||||
if context.getRemainingCharacters() > 1
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -31,8 +29,8 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct Dimension(usize, usize);
|
||||
|
||||
impl Dimension {
|
||||
pub fn new(width: usize, height: usize) -> Result<Self, Exceptions> {
|
||||
Ok(Self(width, height))
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
Self(width, height)
|
||||
}
|
||||
|
||||
pub fn getWidth(&self) -> usize {
|
||||
|
||||
@@ -68,7 +68,7 @@ impl fmt::Display for Exceptions {
|
||||
Exceptions::RuntimeException(None) => write!(f, "RuntimeException"),
|
||||
Exceptions::ParseException(None) => write!(f, "ParseException"),
|
||||
|
||||
Exceptions::ReaderDecodeException() => write!(f, "ReaderDecodeException - -"),
|
||||
Exceptions::ReaderDecodeException() => write!(f, "ReaderDecodeException"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,9 @@ pub fn detect_multiple_in_file_with_hints(
|
||||
file_name: &str,
|
||||
hints: &mut DecodingHintDictionary,
|
||||
) -> Result<Vec<RXingResult>, Exceptions> {
|
||||
let img = image::open(file_name).unwrap();
|
||||
let img = image::open(file_name).map_err(|e| {
|
||||
Exceptions::RuntimeException(Some(format!("couldn't read {file_name}: {e}")))
|
||||
})?;
|
||||
let multi_format_reader = MultiFormatReader::default();
|
||||
let mut scanner = GenericMultipleBarcodeReader::new(multi_format_reader);
|
||||
|
||||
|
||||
@@ -34,12 +34,8 @@ pub use barcode_format::*;
|
||||
mod encode_hints;
|
||||
pub use encode_hints::*;
|
||||
|
||||
/**
|
||||
* Callback which is invoked when a possible result point (significant
|
||||
* point in the barcode image such as a corner) is found.
|
||||
*
|
||||
* @see DecodeHintType#NEED_RESULT_POINT_CALLBACK
|
||||
*/
|
||||
/// Callback which is invoked when a possible result point (significant
|
||||
/// point in the barcode image such as a corner) is found.
|
||||
pub type RXingResultPointCallback = Rc<dyn Fn(&dyn ResultPoint)>;
|
||||
|
||||
mod decode_hints;
|
||||
|
||||
@@ -104,15 +104,12 @@ impl LuminanceSource for Luma8LuminanceSource {
|
||||
impl Luma8LuminanceSource {
|
||||
fn reverseColumns(&mut self) {
|
||||
for i in 0..self.getWidth() {
|
||||
// for (int i = 0; i < C; i++)
|
||||
let mut j = 0;
|
||||
let mut k = self.getWidth() - 1;
|
||||
while j < k {
|
||||
// for (int j = 0, k = C - 1; j < k; j++, k--)
|
||||
let offset_a = (self.getWidth() * i) + j;
|
||||
let offset_b = (self.getWidth() * i) + k;
|
||||
self.data.swap(offset_a, offset_b);
|
||||
// swap(arr[j][i], arr[k][i]);
|
||||
j += 1;
|
||||
k -= 1;
|
||||
}
|
||||
@@ -121,13 +118,10 @@ impl Luma8LuminanceSource {
|
||||
|
||||
fn transpose(&mut self) {
|
||||
for i in 0..self.getHeight() {
|
||||
// for (int i = 0; i < R; i++)
|
||||
for j in i..self.getWidth() {
|
||||
// for (int j = i; j < C; j++)
|
||||
let offset_a = (self.getWidth() * i) + j;
|
||||
let offset_b = (self.getWidth() * j) + i;
|
||||
self.data.swap(offset_a, offset_b);
|
||||
// swap(arr[i][j], arr[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,9 @@ fn getPostCode3(bytes: &[u8]) -> String {
|
||||
let mut graphemes = SETS[0].graphemes(true);
|
||||
for p3bytes in &POSTCODE_3_BYTES {
|
||||
// for (byte[] p3bytes : POSTCODE_3_BYTES) {
|
||||
sb.push_str(graphemes.nth(getInt(bytes, p3bytes) as usize).unwrap());
|
||||
if let Some(c) = graphemes.nth(getInt(bytes, p3bytes) as usize) {
|
||||
sb.push_str(c);
|
||||
}
|
||||
}
|
||||
sb
|
||||
}
|
||||
@@ -178,7 +180,7 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
|
||||
// for i in start..(start+len) {
|
||||
// for (int i = start; i < start + len; i++) {
|
||||
let mut set_graphemes = SETS[set].graphemes(true);
|
||||
let c = set_graphemes.nth(bytes[i as usize] as usize).unwrap();
|
||||
let Some(c) = set_graphemes.nth(bytes[i as usize] as usize) else { break; };
|
||||
match c {
|
||||
LATCHA => {
|
||||
set = 0;
|
||||
@@ -234,11 +236,6 @@ fn getMessage(bytes: &[u8], start: u32, len: u32) -> String {
|
||||
}
|
||||
|
||||
String::from(sb.trim_end_matches(PAD))
|
||||
// while sb.len() > 0 && sb.chars().nth(sb.len() - 1).unwrap() == PAD {
|
||||
// sb.setLength(sb.length() - 1);
|
||||
// }
|
||||
|
||||
// sb
|
||||
}
|
||||
|
||||
fn subtract_two_single_char_strings(str1: &str, str2: &str) -> usize {
|
||||
|
||||
@@ -97,16 +97,13 @@ fn correctErrors(
|
||||
// First read into an array of ints
|
||||
let mut codewordsInts = vec![0i32; (codewords / divisor) as usize];
|
||||
for i in 0..codewords {
|
||||
// for (int i = 0; i < codewords; i++) {
|
||||
if (mode == ALL) || (i % 2 == (mode - 1)) {
|
||||
codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32;
|
||||
}
|
||||
}
|
||||
// try {
|
||||
|
||||
RS_DECODER.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?;
|
||||
// } catch (ReedSolomonException ignored) {
|
||||
// throw ChecksumException.getChecksumInstance();
|
||||
// }
|
||||
|
||||
// Copy back into array of bytes -- only need to worry about the bytes that were data
|
||||
// We don't care about errors in the error-correction codewords
|
||||
for i in 0..dataCodewords {
|
||||
|
||||
@@ -155,8 +155,8 @@ impl Circle<'_> {
|
||||
*length_set = (length, rotation, points);
|
||||
}
|
||||
lengths.sort_by_key(|e| e.0);
|
||||
let major_axis = lengths.last().unwrap();
|
||||
let minor_axis = lengths.first().unwrap();
|
||||
let Some(major_axis) = lengths.last() else {return (false, (0,0),0,0,0)};
|
||||
let Some(minor_axis) = lengths.first() else {return (false, (0,0),0,0,0)};
|
||||
|
||||
// // find foci
|
||||
let linear_eccentricity = ((major_axis.0 / 2).pow(2) - (minor_axis.0 / 2).pow(2)).sqrt();
|
||||
@@ -348,8 +348,8 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
|
||||
|
||||
let [tl, bl, tr, br] = &symbol_box.0;
|
||||
|
||||
let target_width = MathUtils::distance_float(tl.0, tl.1, tr.0, tr.1);
|
||||
let target_height = MathUtils::distance_float(br.0, br.1, tr.0, tr.1);
|
||||
let target_width = MathUtils::distance(tl.0, tl.1, tr.0, tr.1);
|
||||
let target_height = MathUtils::distance(br.0, br.1, tr.0, tr.1);
|
||||
|
||||
// let target_width = (tr.0 - tl.0).round().abs() as u32;
|
||||
// let target_height = (br.1 - tr.1).round().abs() as u32;
|
||||
@@ -1045,12 +1045,16 @@ fn compare_circle(a: &Circle, b: &Circle) -> std::cmp::Ordering {
|
||||
let a_var = a.calculate_circle_variance();
|
||||
let b_var = b.calculate_circle_variance();
|
||||
|
||||
a_var.partial_cmp(&b_var).unwrap()
|
||||
a_var
|
||||
.partial_cmp(&b_var)
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
}
|
||||
|
||||
/// Read appropriate bits from a bitmatrix for the maxicode decoder
|
||||
pub fn read_bits(image: &BitMatrix) -> Result<BitMatrix, Exceptions> {
|
||||
let enclosingRectangle = image.getEnclosingRectangle().unwrap();
|
||||
let enclosingRectangle = image
|
||||
.getEnclosingRectangle()
|
||||
.ok_or(Exceptions::NotFoundException(None))?;
|
||||
|
||||
let left = enclosingRectangle[0];
|
||||
let top = enclosingRectangle[1];
|
||||
|
||||
@@ -129,7 +129,8 @@ impl MaxiCodeReader {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
let enclosingRectangle = enclosingRectangleOption.unwrap();
|
||||
let enclosingRectangle =
|
||||
enclosingRectangleOption.ok_or(Exceptions::NotFoundException(None))?;
|
||||
|
||||
let left = enclosingRectangle[0];
|
||||
let top = enclosingRectangle[1];
|
||||
|
||||
@@ -46,24 +46,21 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
let halfWidth = width / 2;
|
||||
let halfHeight = height / 2;
|
||||
|
||||
// try {
|
||||
let attempt = self
|
||||
.0
|
||||
.decode_with_hints(&mut image.crop(0, 0, halfWidth, halfHeight), hints);
|
||||
// No need to call makeAbsolute as results will be relative to original top left here
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match attempt {
|
||||
// Ok() => return attempt,
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
_ => return attempt,
|
||||
}
|
||||
// } catch (NotFoundException re) {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// try {
|
||||
let result = self
|
||||
.0
|
||||
.decode_with_hints(&mut image.crop(halfWidth, 0, halfWidth, halfHeight), hints);
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), halfWidth as f32, 0.0);
|
||||
@@ -72,15 +69,11 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
_ => return result,
|
||||
}
|
||||
// makeAbsolute(result.getRXingResultPoints(), halfWidth, 0);
|
||||
// return result;
|
||||
// } catch (NotFoundException re) {
|
||||
// continue
|
||||
// }
|
||||
|
||||
let result = self
|
||||
.0
|
||||
.decode_with_hints(&mut image.crop(0, halfHeight, halfWidth, halfHeight), hints);
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(res.getRXingResultPoints(), 0.0, halfHeight as f32);
|
||||
@@ -89,18 +82,12 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
Err(Exceptions::NotFoundException(_)) => {}
|
||||
_ => return result,
|
||||
}
|
||||
// try {
|
||||
// RXingResult result = delegate.decode(image.crop(0, halfHeight, halfWidth, halfHeight), hints);
|
||||
// makeAbsolute(result.getRXingResultPoints(), 0, halfHeight);
|
||||
// return result;
|
||||
// } catch (NotFoundException re) {
|
||||
// // continue
|
||||
// }
|
||||
|
||||
let result = self.0.decode_with_hints(
|
||||
&mut image.crop(halfWidth, halfHeight, halfWidth, halfHeight),
|
||||
hints,
|
||||
);
|
||||
// This is a match because only NotFoundExceptions should be ignored
|
||||
match result {
|
||||
Ok(res) => {
|
||||
let points = Self::makeAbsolute(
|
||||
@@ -114,14 +101,6 @@ impl<T: Reader> Reader for ByQuadrantReader<T> {
|
||||
_ => return result,
|
||||
}
|
||||
|
||||
// try {
|
||||
// RXingResult result = delegate.decode(image.crop(halfWidth, halfHeight, halfWidth, halfHeight), hints);
|
||||
// makeAbsolute(result.getRXingResultPoints(), halfWidth, halfHeight);
|
||||
// return result;
|
||||
// } catch (NotFoundException re) {
|
||||
// // continue
|
||||
// }
|
||||
|
||||
let quarterWidth = halfWidth / 2;
|
||||
let quarterHeight = halfHeight / 2;
|
||||
let mut center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
|
||||
@@ -150,19 +129,22 @@ impl<T: Reader> ByQuadrantReader<T> {
|
||||
leftOffset: f32,
|
||||
topOffset: f32,
|
||||
) -> Vec<RXingResultPoint> {
|
||||
let mut result = Vec::new();
|
||||
if !points.is_empty() {
|
||||
for relative in points {
|
||||
// for (int i = 0; i < points.length; i++) {
|
||||
// let relative = points[i];
|
||||
// if relative != null {
|
||||
result.push(RXingResultPoint::new(
|
||||
relative.getX() + leftOffset,
|
||||
relative.getY() + topOffset,
|
||||
));
|
||||
// }
|
||||
}
|
||||
}
|
||||
result
|
||||
// let mut result = Vec::new();
|
||||
// if !points.is_empty() {
|
||||
|
||||
// // for relative in points {
|
||||
// // result.push(RXingResultPoint::new(
|
||||
// // relative.getX() + leftOffset,
|
||||
// // relative.getY() + topOffset,
|
||||
// // ));
|
||||
// // }
|
||||
// }
|
||||
// result
|
||||
points
|
||||
.iter()
|
||||
.map(|relative| {
|
||||
RXingResultPoint::new(relative.getX() + leftOffset, relative.getY() + topOffset)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,17 +182,24 @@ impl<T: Reader> GenericMultipleBarcodeReader<T> {
|
||||
if oldRXingResultPoints.is_empty() {
|
||||
return result;
|
||||
}
|
||||
let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len()); //new RXingResultPoint[oldRXingResultPoints.length];
|
||||
for oldPoint in oldRXingResultPoints {
|
||||
// for (int i = 0; i < oldRXingResultPoints.length; i++) {
|
||||
// RXingResultPoint oldPoint = oldRXingResultPoints[i];
|
||||
// if (oldPoint != null) {
|
||||
newRXingResultPoints.push(RXingResultPoint::new(
|
||||
oldPoint.getX() + xOffset as f32,
|
||||
oldPoint.getY() + yOffset as f32,
|
||||
));
|
||||
// }
|
||||
}
|
||||
|
||||
let newRXingResultPoints: Vec<RXingResultPoint> = oldRXingResultPoints
|
||||
.iter()
|
||||
.map(|oldPoint| {
|
||||
RXingResultPoint::new(
|
||||
oldPoint.getX() + xOffset as f32,
|
||||
oldPoint.getY() + yOffset as f32,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// let mut newRXingResultPoints = Vec::with_capacity(oldRXingResultPoints.len());
|
||||
// for oldPoint in oldRXingResultPoints {
|
||||
// newRXingResultPoints.push(RXingResultPoint::new(
|
||||
// oldPoint.getX() + xOffset as f32,
|
||||
// oldPoint.getY() + yOffset as f32,
|
||||
// ));
|
||||
// }
|
||||
let mut newRXingResult = RXingResult::new_complex(
|
||||
result.getText(),
|
||||
result.getRawBytes().clone(),
|
||||
|
||||
@@ -61,11 +61,6 @@ impl<'a> MultiDetector<'_> {
|
||||
if let Ok(potential) = self.0.processFinderPatternInfo(info) {
|
||||
result.push(potential);
|
||||
}
|
||||
// try {
|
||||
// result.add(processFinderPatternInfo(info));
|
||||
// } catch (ReaderException e) {
|
||||
// // ignore
|
||||
// }
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
||||
@@ -56,9 +56,9 @@ const DIFF_MODSIZE_CUTOFF: f32 = 0.5_f32;
|
||||
* @author Sean Owen
|
||||
* @author Hannes Erven
|
||||
*/
|
||||
pub struct MultiFinderPatternFinder(FinderPatternFinder);
|
||||
pub struct MultiFinderPatternFinder<'a>(FinderPatternFinder<'a>);
|
||||
|
||||
impl MultiFinderPatternFinder {
|
||||
impl<'a> MultiFinderPatternFinder<'_> {
|
||||
// private static final FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0];
|
||||
// private static final FinderPattern[] EMPTY_FP_ARRAY = new FinderPattern[0];
|
||||
// private static final FinderPattern[][] EMPTY_FP_2D_ARRAY = new FinderPattern[0][];
|
||||
@@ -66,9 +66,12 @@ impl MultiFinderPatternFinder {
|
||||
// TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for
|
||||
// since it limits the number of regions to decode
|
||||
|
||||
pub fn new(image: &BitMatrix, resultPointCallback: Option<RXingResultPointCallback>) -> Self {
|
||||
Self(FinderPatternFinder::with_callback(
|
||||
image.clone(),
|
||||
pub fn new(
|
||||
image: &'a BitMatrix,
|
||||
resultPointCallback: Option<RXingResultPointCallback>,
|
||||
) -> MultiFinderPatternFinder<'a> {
|
||||
MultiFinderPatternFinder(FinderPatternFinder::with_callback(
|
||||
image,
|
||||
resultPointCallback,
|
||||
))
|
||||
}
|
||||
@@ -80,7 +83,7 @@ impl MultiFinderPatternFinder {
|
||||
* @throws NotFoundException if 3 such finder patterns do not exist
|
||||
*/
|
||||
fn selectMultipleBestPatterns(&self) -> Result<Vec<[FinderPattern; 3]>, Exceptions> {
|
||||
let mut possibleCenters = Vec::new(); //new ArrayList<>();
|
||||
let mut possibleCenters = Vec::new();
|
||||
for fp in self.0.getPossibleCenters() {
|
||||
if fp.getCount() >= 2 {
|
||||
possibleCenters.push(*fp);
|
||||
@@ -125,19 +128,18 @@ impl MultiFinderPatternFinder {
|
||||
* So, if the layout seems right, lets have the decoder try to decode.
|
||||
*/
|
||||
|
||||
let mut results = Vec::new(); //new ArrayList<>(); // holder for the results
|
||||
let mut results = Vec::new(); // holder for the results
|
||||
|
||||
for i1 in 0..(size - 2) {
|
||||
// for (int i1 = 0; i1 < (size - 2); i1++) {
|
||||
let Some(p1) = possibleCenters.get(i1)else {
|
||||
continue;
|
||||
};
|
||||
let Some(p1) = possibleCenters.get(i1) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
for i2 in (i1 + 1)..(size - 1) {
|
||||
// for (int i2 = i1 + 1; i2 < (size - 1); i2++) {
|
||||
let Some(p2) = possibleCenters.get(i2) else {
|
||||
continue;
|
||||
};
|
||||
continue;
|
||||
};
|
||||
|
||||
// Compare the expected module sizes; if they are really off, skip
|
||||
let vModSize12 = (p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize())
|
||||
@@ -151,9 +153,9 @@ impl MultiFinderPatternFinder {
|
||||
|
||||
for i3 in (i2 + 1)..size {
|
||||
// for (int i3 = i2 + 1; i3 < size; i3++) {
|
||||
let Some( p3) = possibleCenters.get(i3)else {
|
||||
continue;
|
||||
};
|
||||
let Some( p3) = possibleCenters.get(i3) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Compare the expected module sizes; if they are really off, skip
|
||||
let vModSize23 = (p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize())
|
||||
|
||||
@@ -58,18 +58,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
|
||||
hints,
|
||||
)?;
|
||||
let mut points = detectorRXingResult.getPoints().to_vec();
|
||||
|
||||
// If the code was mirrored: swap the bottom-left and the top-right points.
|
||||
if let Some(other) = decoderRXingResult.getOther() {
|
||||
if other.is::<QRCodeDecoderMetaData>() {
|
||||
(other
|
||||
.downcast::<QRCodeDecoderMetaData>()
|
||||
.expect("must downcast to QRCodeDecoderMetaData"))
|
||||
.applyMirroredCorrection(&mut points);
|
||||
if let Some(oth) = other.downcast_ref::<QRCodeDecoderMetaData>() {
|
||||
oth.applyMirroredCorrection(&mut points);
|
||||
}
|
||||
}
|
||||
// if (decoderRXingResult.getOther() instanceof QRCodeDecoderMetaData) {
|
||||
// ((QRCodeDecoderMetaData) decoderRXingResult.getOther()).applyMirroredCorrection(points);
|
||||
// }
|
||||
|
||||
let mut result = RXingResult::new(
|
||||
decoderRXingResult.getText(),
|
||||
decoderRXingResult.getRawBytes().clone(),
|
||||
@@ -77,14 +73,14 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
let byteSegments = decoderRXingResult.getByteSegments();
|
||||
// if (byteSegments != null) {
|
||||
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::BYTE_SEGMENTS,
|
||||
RXingResultMetadataValue::ByteSegments(byteSegments.clone()),
|
||||
);
|
||||
// }
|
||||
|
||||
let ecLevel = decoderRXingResult.getECLevel();
|
||||
// if (ecLevel != null) {
|
||||
|
||||
result.putMetadata(
|
||||
RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
|
||||
RXingResultMetadataValue::ErrorCorrectionLevel(ecLevel.to_owned()),
|
||||
@@ -115,7 +111,7 @@ impl MultipleBarcodeReader for QRCodeMultiReader {
|
||||
// ignore and continue
|
||||
continue;
|
||||
} else {
|
||||
return Err(output.err().unwrap());
|
||||
return Err(output.err().unwrap_or(Exceptions::NotFoundException(None)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,11 +73,9 @@ impl Reader for MultiFormatReader {
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
// if (readers != null) {
|
||||
for reader in self.readers.iter_mut() {
|
||||
reader.reset();
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +107,13 @@ impl MultiFormatReader {
|
||||
* @param hints The set of hints to use for subsequent calls to decode(image)
|
||||
*/
|
||||
pub fn set_ints(&mut self, hints: &DecodingHintDictionary) {
|
||||
self.hints = hints.clone(); // {hint} else {HashMap::new()};
|
||||
self.hints = hints.clone();
|
||||
|
||||
let tryHarder = matches!(
|
||||
self.hints.get(&DecodeHintType::TRY_HARDER),
|
||||
Some(DecodeHintValue::TryHarder(true))
|
||||
);
|
||||
|
||||
let tryHarder = self.hints.contains_key(&DecodeHintType::TRY_HARDER);
|
||||
//@SuppressWarnings("unchecked")
|
||||
let formats = hints.get(&DecodeHintType::POSSIBLE_FORMATS);
|
||||
let mut readers: Vec<Box<dyn Reader>> = Vec::new();
|
||||
if let Some(DecodeHintValue::PossibleFormats(formats)) = formats {
|
||||
@@ -161,48 +162,33 @@ impl MultiFormatReader {
|
||||
readers.push(Box::<AztecReader>::default());
|
||||
readers.push(Box::<PDF417Reader>::default());
|
||||
readers.push(Box::<MaxiCodeReader>::default());
|
||||
// unimplemented!("");
|
||||
|
||||
if tryHarder {
|
||||
readers.push(Box::new(MultiFormatOneDReader::new(hints)));
|
||||
}
|
||||
}
|
||||
self.readers = readers; //Vec::new(); //readers.toArray(EMPTY_READER_ARRAY);
|
||||
self.readers = readers;
|
||||
}
|
||||
|
||||
pub fn decode_internal(&mut self, image: &mut BinaryBitmap) -> Result<RXingResult, Exceptions> {
|
||||
if !self.readers.is_empty() {
|
||||
for reader in self.readers.iter_mut() {
|
||||
// I'm not sure how to model this in rust
|
||||
// if (Thread.currentThread().isInterrupted()) {
|
||||
// throw NotFoundException.getNotFoundInstance();
|
||||
// }
|
||||
//try {
|
||||
let res = reader.decode_with_hints(image, &self.hints);
|
||||
if res.is_ok() {
|
||||
return res;
|
||||
}
|
||||
//} catch (ReaderException re) {
|
||||
// continue
|
||||
//}
|
||||
}
|
||||
if self.hints.contains_key(&DecodeHintType::ALSO_INVERTED) {
|
||||
if matches!(
|
||||
self.hints.get(&DecodeHintType::ALSO_INVERTED),
|
||||
Some(DecodeHintValue::AlsoInverted(true))
|
||||
) {
|
||||
// Calling all readers again with inverted image
|
||||
// let mut image = image.clone();
|
||||
image.getBlackMatrixMut().flip_self();
|
||||
for reader in self.readers.iter_mut() {
|
||||
// if (Thread.currentThread().isInterrupted()) {
|
||||
// throw NotFoundException.getNotFoundInstance();
|
||||
// }
|
||||
let res = reader.decode_with_hints(image, &self.hints);
|
||||
if res.is_ok() {
|
||||
return res;
|
||||
}
|
||||
// try {
|
||||
// return reader.decode(image, hints);
|
||||
// } catch (ReaderException re) {
|
||||
// // continue
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,66 +80,3 @@ impl Writer for MultiFormatWriter {
|
||||
writer.encode_with_hints(contents, format, width, height, hints)
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public BitMatrix encode(String contents,
|
||||
// BarcodeFormat format,
|
||||
// int width,
|
||||
// int height) throws WriterException {
|
||||
// return encode(contents, format, width, height, null);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public BitMatrix encode(String contents,
|
||||
// BarcodeFormat format,
|
||||
// int width, int height,
|
||||
// Map<EncodeHintType,?> hints) throws WriterException {
|
||||
|
||||
// Writer writer;
|
||||
// switch (format) {
|
||||
// case EAN_8:
|
||||
// writer = new EAN8Writer();
|
||||
// break;
|
||||
// case UPC_E:
|
||||
// writer = new UPCEWriter();
|
||||
// break;
|
||||
// case EAN_13:
|
||||
// writer = new EAN13Writer();
|
||||
// break;
|
||||
// case UPC_A:
|
||||
// writer = new UPCAWriter();
|
||||
// break;
|
||||
// case QR_CODE:
|
||||
// writer = new QRCodeWriter();
|
||||
// break;
|
||||
// case CODE_39:
|
||||
// writer = new Code39Writer();
|
||||
// break;
|
||||
// case CODE_93:
|
||||
// writer = new Code93Writer();
|
||||
// break;
|
||||
// case CODE_128:
|
||||
// writer = new Code128Writer();
|
||||
// break;
|
||||
// case ITF:
|
||||
// writer = new ITFWriter();
|
||||
// break;
|
||||
// case PDF_417:
|
||||
// writer = new PDF417Writer();
|
||||
// break;
|
||||
// case CODABAR:
|
||||
// writer = new CodaBarWriter();
|
||||
// break;
|
||||
// case DATA_MATRIX:
|
||||
// writer = new DataMatrixWriter();
|
||||
// break;
|
||||
// case AZTEC:
|
||||
// writer = new AztecWriter();
|
||||
// break;
|
||||
// default:
|
||||
// throw new IllegalArgumentException("No encoder available for format " + format);
|
||||
// }
|
||||
// return writer.encode(contents, format, width, height, hints);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
@@ -18,6 +18,7 @@ use rxing_one_d_proc_derive::OneDReader;
|
||||
|
||||
use crate::common::BitArray;
|
||||
use crate::BarcodeFormat;
|
||||
use crate::DecodeHintValue;
|
||||
use crate::Exceptions;
|
||||
use crate::RXingResult;
|
||||
|
||||
@@ -70,7 +71,7 @@ impl OneDReader for CodaBarReader {
|
||||
// StringBuilder, so that we can access the decoded patterns in
|
||||
// validatePattern. We'll translate to the actual characters later.
|
||||
self.decodeRowRXingResult
|
||||
.push(char::from_u32(charOffset as u32).unwrap());
|
||||
.push(char::from_u32(charOffset as u32).ok_or(Exceptions::ParseException(None))?);
|
||||
nextStart += 8;
|
||||
// Stop as soon as we see the end character.
|
||||
if self.decodeRowRXingResult.chars().count() > 1
|
||||
@@ -81,16 +82,16 @@ impl OneDReader for CodaBarReader {
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// no fixed end pattern so keep on reading while data is available
|
||||
if nextStart >= self.counterLength {
|
||||
break;
|
||||
} // no fixed end pattern so keep on reading while data is available
|
||||
} //while (nextStart < counterLength); // no fixed end pattern so keep on reading while data is available
|
||||
|
||||
}
|
||||
}
|
||||
// Look for whitespace after pattern:
|
||||
let trailingWhitespace = self.counters[nextStart - 1];
|
||||
let mut lastPatternSize = 0;
|
||||
for i in -8isize..-1isize {
|
||||
// for (int i = -8; i < -1; i++) {
|
||||
for i in -8isize..-1 {
|
||||
lastPatternSize += self.counters[(nextStart as isize + i) as usize];
|
||||
}
|
||||
|
||||
@@ -108,13 +109,21 @@ impl OneDReader for CodaBarReader {
|
||||
// for (int i = 0; i < decodeRowRXingResult.length(); i++) {
|
||||
self.decodeRowRXingResult.replace_range(
|
||||
i..=i,
|
||||
&Self::ALPHABET[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]
|
||||
&Self::ALPHABET[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize]
|
||||
.to_string(),
|
||||
);
|
||||
// self.decodeRowRXingResult.setCharAt(i, Self::ALPHABET[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize]);
|
||||
}
|
||||
// Ensure a valid start and end character
|
||||
let startchar = self.decodeRowRXingResult.chars().next().unwrap();
|
||||
let startchar = self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if !Self::arrayContains(&Self::STARTEND_ENCODING, startchar) {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -122,7 +131,7 @@ impl OneDReader for CodaBarReader {
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(self.decodeRowRXingResult.chars().count() - 1)
|
||||
.unwrap();
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
if !Self::arrayContains(&Self::STARTEND_ENCODING, endchar) {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
@@ -133,23 +142,29 @@ impl OneDReader for CodaBarReader {
|
||||
return Err(Exceptions::NotFoundException(None));
|
||||
}
|
||||
|
||||
if !hints.contains_key(&DecodeHintType::RETURN_CODABAR_START_END) {
|
||||
// self.decodeRowRXingResult.deleteCharAt(self.decodeRowRXingResult.chars().count() - 1);
|
||||
// self.decodeRowRXingResult.deleteCharAt(0);
|
||||
if !matches!(
|
||||
hints.get(&DecodeHintType::RETURN_CODABAR_START_END),
|
||||
Some(DecodeHintValue::ReturnCodabarStartEnd(true))
|
||||
) {
|
||||
self.decodeRowRXingResult =
|
||||
self.decodeRowRXingResult[1..self.decodeRowRXingResult.len() - 1].to_owned();
|
||||
}
|
||||
|
||||
let mut runningCount = 0;
|
||||
for i in 0..startOffset {
|
||||
// for (int i = 0; i < startOffset; i++) {
|
||||
runningCount += self.counters[i];
|
||||
}
|
||||
runningCount += self.counters.iter().take(startOffset).sum::<u32>();
|
||||
// for i in 0..startOffset {
|
||||
// runningCount += self.counters[i];
|
||||
// }
|
||||
let left: f32 = runningCount as f32;
|
||||
for i in startOffset..(nextStart - 1) {
|
||||
// for (int i = startOffset; i < nextStart - 1; i++) {
|
||||
runningCount += self.counters[i];
|
||||
}
|
||||
runningCount += self
|
||||
.counters
|
||||
.iter()
|
||||
.skip(startOffset)
|
||||
.take(nextStart)
|
||||
.sum::<u32>();
|
||||
// for i in startOffset..(nextStart - 1) {
|
||||
// runningCount += self.counters[i];
|
||||
// }
|
||||
let right: f32 = runningCount as f32;
|
||||
|
||||
let mut result = RXingResult::new(
|
||||
@@ -224,10 +239,13 @@ impl CodaBarReader {
|
||||
let mut pos = start;
|
||||
for i in 0..=end {
|
||||
// for (int i = 0; i <= end; i++) {
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS
|
||||
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize];
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize];
|
||||
for j in (0_usize..=6).rev() {
|
||||
// for (int j = 6; j >= 0; j--) {
|
||||
// Even j = bars, while odd j = spaces. Categories 2 and 3 are for
|
||||
// long stripes, while 0 and 1 are for short stripes.
|
||||
let category = (j & 1) + ((pattern as usize) & 1) * 2;
|
||||
@@ -260,10 +278,13 @@ impl CodaBarReader {
|
||||
pos = start;
|
||||
for i in 0..=end {
|
||||
// for (int i = 0; i <= end; i++) {
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS
|
||||
[self.decodeRowRXingResult.chars().nth(i).unwrap() as usize];
|
||||
let mut pattern = Self::CHARACTER_ENCODINGS[self
|
||||
.decodeRowRXingResult
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as usize];
|
||||
for j in (0usize..=6).rev() {
|
||||
// for (int j = 6; j >= 0; j--) {
|
||||
// Even j = bars, while odd j = spaces. Categories 2 and 3 are for
|
||||
// long stripes, while 0 and 1 are for short stripes.
|
||||
let category = (j & 1) + ((pattern as usize) & 1) * 2;
|
||||
@@ -312,9 +333,8 @@ impl CodaBarReader {
|
||||
self.counters[self.counterLength] = e;
|
||||
self.counterLength += 1;
|
||||
if self.counterLength >= self.counters.len() {
|
||||
let mut temp = vec![0; self.counterLength * 2]; //new int[counterLength * 2];
|
||||
let mut temp = vec![0; self.counterLength * 2];
|
||||
temp[0..self.counterLength].clone_from_slice(&self.counters[..]);
|
||||
// System.arraycopy(counters, 0, temp, 0, counterLength);
|
||||
self.counters = temp;
|
||||
}
|
||||
}
|
||||
@@ -334,7 +354,6 @@ impl CodaBarReader {
|
||||
// We make an exception if the whitespace is the first element.
|
||||
let mut patternSize = 0;
|
||||
for j in i..(i + 7) {
|
||||
// for (int j = i; j < i + 7; j++) {
|
||||
patternSize += self.counters[j];
|
||||
}
|
||||
if i == 1 || self.counters[i - 1] >= patternSize / 2 {
|
||||
@@ -348,14 +367,7 @@ impl CodaBarReader {
|
||||
}
|
||||
|
||||
pub fn arrayContains(array: &[char], key: char) -> bool {
|
||||
// if (array != null) {
|
||||
for c in array {
|
||||
if c == &key {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// }
|
||||
false
|
||||
array.contains(&key)
|
||||
}
|
||||
|
||||
// Assumes that counters[position] is a bar.
|
||||
@@ -371,7 +383,6 @@ impl CodaBarReader {
|
||||
let mut minBar = u32::MAX;
|
||||
let mut j = position;
|
||||
while j < end {
|
||||
// for (int j = position; j < end; j += 2) {
|
||||
let currentCounter = theCounters[j];
|
||||
if currentCounter < minBar {
|
||||
minBar = currentCounter;
|
||||
@@ -388,14 +399,9 @@ impl CodaBarReader {
|
||||
let mut minSpace = u32::MAX;
|
||||
let mut j = position + 1;
|
||||
while j < end {
|
||||
// for (int j = position + 1; j < end; j += 2) {
|
||||
let currentCounter = theCounters[j];
|
||||
if currentCounter < minSpace {
|
||||
minSpace = currentCounter;
|
||||
}
|
||||
if currentCounter > maxSpace {
|
||||
maxSpace = currentCounter;
|
||||
}
|
||||
minSpace = std::cmp::min(currentCounter, minSpace);
|
||||
maxSpace = std::cmp::max(currentCounter, maxSpace);
|
||||
|
||||
j += 2;
|
||||
}
|
||||
@@ -404,7 +410,6 @@ impl CodaBarReader {
|
||||
let mut bitmask = 1 << 7;
|
||||
let mut pattern = 0;
|
||||
for i in 0..7 {
|
||||
// for (int i = 0; i < 7; i++) {
|
||||
let threshold = if (i & 1) == 0 {
|
||||
thresholdBar
|
||||
} else {
|
||||
@@ -417,7 +422,6 @@ impl CodaBarReader {
|
||||
}
|
||||
|
||||
for i in 0..Self::CHARACTER_ENCODINGS.len() {
|
||||
// for (int i = 0; i < CHARACTER_ENCODINGS.length; i++) {
|
||||
if Self::CHARACTER_ENCODINGS[i] == pattern {
|
||||
return i as i32;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,15 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
format!("{DEFAULT_GUARD}{contents}{DEFAULT_GUARD}")
|
||||
} else {
|
||||
// Verify input and calculate decoded length.
|
||||
let firstChar = contents.chars().next().unwrap().to_ascii_uppercase();
|
||||
let firstChar = contents
|
||||
.chars()
|
||||
.next()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
let lastChar = contents
|
||||
.chars()
|
||||
.nth(contents.chars().count() - 1)
|
||||
.unwrap()
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
let startsNormal = CodaBarReader::arrayContains(&START_END_CHARS, firstChar);
|
||||
let endsNormal = CodaBarReader::arrayContains(&START_END_CHARS, lastChar);
|
||||
@@ -80,9 +84,7 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
|
||||
// The start character and the end character are decoded to 10 length each.
|
||||
let mut resultLength = 20;
|
||||
//for i in 1..contents.chars().count() {
|
||||
for ch in contents[1..contents.chars().count() - 1].chars() {
|
||||
// for (int i = 1; i < contents.length() - 1; i++) {
|
||||
if ch.is_ascii_digit() || ch == '-' || ch == '$' {
|
||||
resultLength += 9;
|
||||
} else if CodaBarReader::arrayContains(
|
||||
@@ -103,7 +105,11 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
let mut position = 0;
|
||||
for index in 0..contents.chars().count() {
|
||||
// for (int index = 0; index < contents.length(); index++) {
|
||||
let mut c = contents.chars().nth(index).unwrap().to_ascii_uppercase();
|
||||
let mut c = contents
|
||||
.chars()
|
||||
.nth(index)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
.to_ascii_uppercase();
|
||||
if index == 0 || index == contents.chars().count() - 1 {
|
||||
// The start/end chars are not in the CodaBarReader.ALPHABET.
|
||||
c = match c {
|
||||
@@ -116,7 +122,6 @@ impl OneDimensionalCodeWriter for CodaBarWriter {
|
||||
}
|
||||
let mut code = 0;
|
||||
for i in 0..CodaBarReader::ALPHABET.len() {
|
||||
// for (int i = 0; i < CodaBarReader::ALPHABET.length; i++) {
|
||||
// Found any, because I checked above.
|
||||
if c == CodaBarReader::ALPHABET[i] {
|
||||
code = CodaBarReader::CHARACTER_ENCODINGS[i];
|
||||
|
||||
@@ -98,11 +98,6 @@ impl OneDReader for Code128Reader {
|
||||
|
||||
nextStart += counters.iter().sum::<u32>() as usize;
|
||||
|
||||
// for counter in counters {
|
||||
// // for (int counter : counters) {
|
||||
// nextStart += counter;
|
||||
// }
|
||||
|
||||
// Take care of illegal start codes
|
||||
match code {
|
||||
CODE_START_A | CODE_START_B | CODE_START_C => {
|
||||
@@ -328,11 +323,6 @@ impl OneDReader for Code128Reader {
|
||||
};
|
||||
let new_str = result.chars().take(len_trim).collect();
|
||||
result = new_str;
|
||||
// if codeSet == CODE_CODE_C {
|
||||
// result.delete(resultLength - 2, resultLength);
|
||||
// } else {
|
||||
// result.delete(resultLength - 1, resultLength);
|
||||
// }
|
||||
}
|
||||
|
||||
let left: f32 = (startPatternInfo[1] + startPatternInfo[0]) as f32 / 2.0;
|
||||
@@ -341,8 +331,9 @@ impl OneDReader for Code128Reader {
|
||||
let rawCodesSize = rawCodes.len();
|
||||
let mut rawBytes = vec![0u8; rawCodesSize];
|
||||
for (i, rawByte) in rawBytes.iter_mut().enumerate().take(rawCodesSize) {
|
||||
// for (int i = 0; i < rawCodesSize; i++) {
|
||||
*rawByte = *rawCodes.get(i).unwrap();
|
||||
*rawByte = *rawCodes
|
||||
.get(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?;
|
||||
}
|
||||
let mut resultObject = RXingResult::new(
|
||||
&result,
|
||||
@@ -374,7 +365,6 @@ impl Code128Reader {
|
||||
let patternLength = counters.len();
|
||||
|
||||
for i in rowOffset..width {
|
||||
// for (int i = rowOffset; i < width; i++) {
|
||||
if row.get(i) != isWhite {
|
||||
counters[counterPosition] += 1;
|
||||
} else {
|
||||
@@ -382,7 +372,6 @@ impl Code128Reader {
|
||||
let mut bestVariance = MAX_AVG_VARIANCE;
|
||||
let mut bestMatch = -1_isize;
|
||||
for startCode in CODE_START_A..=CODE_START_C {
|
||||
// for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
|
||||
let variance = one_d_reader::patternMatchVariance(
|
||||
&counters,
|
||||
&CODE_PATTERNS[startCode as usize],
|
||||
@@ -407,7 +396,6 @@ impl Code128Reader {
|
||||
patternStart += (counters[0] + counters[1]) as usize;
|
||||
|
||||
counters.copy_within(2..(counterPosition - 1 + 2), 0);
|
||||
// System.arraycopy(counters, 2, counters, 0, counterPosition - 1);
|
||||
counters[counterPosition - 1] = 0;
|
||||
counters[counterPosition] = 0;
|
||||
counterPosition -= 1;
|
||||
@@ -432,7 +420,6 @@ impl Code128Reader {
|
||||
let mut bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
|
||||
let mut bestMatch = -1_isize;
|
||||
for d in 0..CODE_PATTERNS.len() {
|
||||
// for (int d = 0; d < CODE_PATTERNS.len(); d++) {
|
||||
let pattern = &CODE_PATTERNS[d];
|
||||
let variance =
|
||||
one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
|
||||
|
||||
@@ -73,13 +73,17 @@ impl OneDimensionalCodeWriter for Code128Writer {
|
||||
) -> Result<Vec<bool>, Exceptions> {
|
||||
let forcedCodeSet = check(contents, hints)?;
|
||||
|
||||
let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) =
|
||||
hints.get(&EncodeHintType::CODE128_COMPACT)
|
||||
{
|
||||
*compat
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let hasCompactionHint = matches!(
|
||||
hints.get(&EncodeHintType::CODE128_COMPACT),
|
||||
Some(EncodeHintValue::Code128Compact(true))
|
||||
);
|
||||
// let hasCompactionHint = if let Some(EncodeHintValue::Code128Compact(compat)) =
|
||||
// hints.get(&EncodeHintType::CODE128_COMPACT)
|
||||
// {
|
||||
// *compat
|
||||
// } else {
|
||||
// false
|
||||
// };
|
||||
// let hasCompactionHint = hints != null && hints.containsKey(EncodeHintType::CODE128_COMPACT) &&
|
||||
// Boolean.parseBoolean(hints.get(EncodeHintType::CODE128_COMPACT).toString());
|
||||
|
||||
@@ -103,7 +107,7 @@ fn check(contents: &str, hints: &crate::EncodingHintDictionary) -> Result<i32, E
|
||||
// Check for forced code set hint.
|
||||
let mut forcedCodeSet = -1_i32;
|
||||
if hints.contains_key(&EncodeHintType::FORCE_CODE_SET) {
|
||||
let Some(EncodeHintValue::ForceCodeSet(codeSetHint)) = hints.get(&EncodeHintType::FORCE_CODE_SET) else { panic!("This must exist by checks previous")};
|
||||
let Some(EncodeHintValue::ForceCodeSet(codeSetHint)) = hints.get(&EncodeHintType::FORCE_CODE_SET) else { return Err(Exceptions::IllegalStateException(None)) };
|
||||
match codeSetHint.as_str() {
|
||||
"A" => forcedCodeSet = CODE_CODE_A as i32,
|
||||
"B" => forcedCodeSet = CODE_CODE_B as i32,
|
||||
@@ -192,6 +196,7 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
//Select code to use
|
||||
let newCodeSet = if forcedCodeSet == -1 {
|
||||
chooseCode(contents, position, codeSet)
|
||||
.ok_or(Exceptions::IllegalStateException(None))?
|
||||
} else {
|
||||
forcedCodeSet as usize // THIS IS RISKY
|
||||
};
|
||||
@@ -201,7 +206,11 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
if newCodeSet == codeSet {
|
||||
// Encode the current character
|
||||
// First handle escapes
|
||||
match contents.chars().nth(position).unwrap() {
|
||||
match contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
ESCAPE_FNC_1 => patternIndex = CODE_FNC_1 as isize,
|
||||
ESCAPE_FNC_2 => patternIndex = CODE_FNC_2 as isize,
|
||||
ESCAPE_FNC_3 => patternIndex = CODE_FNC_3 as isize,
|
||||
@@ -217,16 +226,24 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
{
|
||||
match codeSet {
|
||||
CODE_CODE_A => {
|
||||
patternIndex =
|
||||
contents.chars().nth(position).unwrap() as isize - ' ' as isize;
|
||||
patternIndex = contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize;
|
||||
if patternIndex < 0 {
|
||||
// everything below a space character comes behind the underscore in the code patterns table
|
||||
patternIndex += '`' as isize;
|
||||
}
|
||||
}
|
||||
CODE_CODE_B => {
|
||||
patternIndex =
|
||||
contents.chars().nth(position).unwrap() as isize - ' ' as isize
|
||||
patternIndex = contents
|
||||
.chars()
|
||||
.nth(position)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize
|
||||
}
|
||||
_ => {
|
||||
// CODE_CODE_C
|
||||
@@ -242,9 +259,9 @@ fn encodeFast(contents: &str, forcedCodeSet: i32) -> Result<Vec<bool>, Exception
|
||||
.take(2)
|
||||
.map(|(_u, c)| c)
|
||||
.collect();
|
||||
patternIndex = s.parse::<isize>().unwrap();
|
||||
// contents[position..position + 2].parse::<isize>().unwrap();
|
||||
// patternIndex = Integer.parseInt(contents.substring(position, position + 2));
|
||||
patternIndex = s.parse::<isize>().map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!("issue parsing {s}: {e}")))
|
||||
})?;
|
||||
position += 1;
|
||||
} // Also incremented below
|
||||
}
|
||||
@@ -308,11 +325,7 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
|
||||
// Compute code width
|
||||
let mut codeWidth = 0_usize;
|
||||
for pattern in &mut *patterns {
|
||||
// for (int[] pattern : patterns) {
|
||||
for width in pattern {
|
||||
// for (int width : pattern) {
|
||||
codeWidth += *width;
|
||||
}
|
||||
codeWidth += pattern.iter().sum::<usize>();
|
||||
}
|
||||
|
||||
// Compute result
|
||||
@@ -326,99 +339,99 @@ fn produceRXingResult(patterns: &mut Vec<Vec<usize>>, checkSum: usize) -> Vec<bo
|
||||
result
|
||||
}
|
||||
|
||||
fn findCType(value: &str, start: usize) -> CType {
|
||||
fn findCType(value: &str, start: usize) -> Option<CType> {
|
||||
let last = value.chars().count();
|
||||
if start >= last {
|
||||
return CType::Uncodable;
|
||||
return Some(CType::Uncodable);
|
||||
}
|
||||
let c = value.chars().nth(start).unwrap();
|
||||
let c = value.chars().nth(start)?;
|
||||
if c == ESCAPE_FNC_1 {
|
||||
return CType::Fnc1;
|
||||
return Some(CType::Fnc1);
|
||||
}
|
||||
if !('0'..='9').contains(&c) {
|
||||
return CType::Uncodable;
|
||||
return Some(CType::Uncodable);
|
||||
}
|
||||
if start + 1 >= last {
|
||||
return CType::OneDigit;
|
||||
return Some(CType::OneDigit);
|
||||
}
|
||||
let c = value.chars().nth(start + 1).unwrap();
|
||||
let c = value.chars().nth(start + 1)?;
|
||||
if !('0'..='9').contains(&c) {
|
||||
return CType::OneDigit;
|
||||
return Some(CType::OneDigit);
|
||||
}
|
||||
CType::TwoDigits
|
||||
Some(CType::TwoDigits)
|
||||
}
|
||||
|
||||
fn chooseCode(value: &str, start: usize, oldCode: usize) -> usize {
|
||||
let mut lookahead = findCType(value, start);
|
||||
fn chooseCode(value: &str, start: usize, oldCode: usize) -> Option<usize> {
|
||||
let mut lookahead = findCType(value, start)?;
|
||||
if lookahead == CType::OneDigit {
|
||||
if oldCode == CODE_CODE_A {
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
return CODE_CODE_B;
|
||||
return Some(CODE_CODE_B);
|
||||
}
|
||||
if lookahead == CType::Uncodable {
|
||||
if start < value.chars().count() {
|
||||
let c = value.chars().nth(start).unwrap();
|
||||
let c = value.chars().nth(start)?;
|
||||
if c < ' '
|
||||
|| (oldCode == CODE_CODE_A && (c < '`' || (c >= ESCAPE_FNC_1 && c <= ESCAPE_FNC_4)))
|
||||
{
|
||||
// can continue in code A, encodes ASCII 0 to 95 or FNC1 to FNC4
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
}
|
||||
return CODE_CODE_B; // no choice
|
||||
return Some(CODE_CODE_B); // no choice
|
||||
}
|
||||
if oldCode == CODE_CODE_A && lookahead == CType::Fnc1 {
|
||||
return CODE_CODE_A;
|
||||
return Some(CODE_CODE_A);
|
||||
}
|
||||
if oldCode == CODE_CODE_C {
|
||||
// can continue in code C
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
}
|
||||
if oldCode == CODE_CODE_B {
|
||||
if lookahead == CType::Fnc1 {
|
||||
return CODE_CODE_B; // can continue in code B
|
||||
return Some(CODE_CODE_B); // can continue in code B
|
||||
}
|
||||
// Seen two consecutive digits, see what follows
|
||||
lookahead = findCType(value, start + 2);
|
||||
lookahead = findCType(value, start + 2)?;
|
||||
if lookahead == CType::Uncodable || lookahead == CType::OneDigit {
|
||||
return CODE_CODE_B; // not worth switching now
|
||||
return Some(CODE_CODE_B); // not worth switching now
|
||||
}
|
||||
if lookahead == CType::Fnc1 {
|
||||
// two digits, then FNC_1...
|
||||
lookahead = findCType(value, start + 3);
|
||||
lookahead = findCType(value, start + 3)?;
|
||||
if lookahead == CType::TwoDigits {
|
||||
// then two more digits, switch
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
} else {
|
||||
return CODE_CODE_B; // otherwise not worth switching
|
||||
return Some(CODE_CODE_B); // otherwise not worth switching
|
||||
}
|
||||
}
|
||||
// At this point, there are at least 4 consecutive digits.
|
||||
// Look ahead to choose whether to switch now or on the next round.
|
||||
let mut index = start + 4;
|
||||
let mut lookahead = findCType(value, index);
|
||||
let mut lookahead = findCType(value, index)?;
|
||||
while lookahead == CType::TwoDigits {
|
||||
// while (lookahead = findCType(value, index)) == CType::TWO_DIGITS {
|
||||
index += 2;
|
||||
lookahead = findCType(value, index);
|
||||
lookahead = findCType(value, index)?;
|
||||
}
|
||||
if lookahead == CType::OneDigit {
|
||||
// odd number of digits, switch later
|
||||
return CODE_CODE_B;
|
||||
return Some(CODE_CODE_B);
|
||||
}
|
||||
return CODE_CODE_C; // even number of digits, switch now
|
||||
return Some(CODE_CODE_C); // even number of digits, switch now
|
||||
}
|
||||
// Here oldCode == 0, which means we are choosing the initial code
|
||||
if lookahead == CType::Fnc1 {
|
||||
// ignore FNC_1
|
||||
lookahead = findCType(value, start + 1);
|
||||
lookahead = findCType(value, start + 1)?;
|
||||
}
|
||||
if lookahead == CType::TwoDigits {
|
||||
// at least two digits, start in code C
|
||||
return CODE_CODE_C;
|
||||
return Some(CODE_CODE_C);
|
||||
}
|
||||
CODE_CODE_B
|
||||
Some(CODE_CODE_B)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -520,7 +533,12 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
Latch::None => { /* skip */ }
|
||||
}
|
||||
if charset == Charset::C {
|
||||
if contents.chars().nth(i).unwrap() == ESCAPE_FNC_1 {
|
||||
if contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
== ESCAPE_FNC_1
|
||||
{
|
||||
addPattern(
|
||||
&mut patterns,
|
||||
CODE_FNC_1,
|
||||
@@ -537,7 +555,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
.collect();
|
||||
addPattern(
|
||||
&mut patterns,
|
||||
s.parse::<usize>().unwrap(),
|
||||
s.parse::<usize>().map_err(|e| {
|
||||
Exceptions::ParseException(Some(format!("unable to parse {s} {e}")))
|
||||
})?,
|
||||
&mut checkSum,
|
||||
&mut checkWeight,
|
||||
i,
|
||||
@@ -549,7 +569,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
}
|
||||
} else {
|
||||
// charset A or B
|
||||
let mut patternIndex = match contents.chars().nth(i).unwrap() {
|
||||
let mut patternIndex = match contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
{
|
||||
ESCAPE_FNC_1 => CODE_FNC_1 as isize,
|
||||
ESCAPE_FNC_2 => CODE_FNC_2 as isize,
|
||||
ESCAPE_FNC_3 => CODE_FNC_3 as isize,
|
||||
@@ -562,7 +586,14 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
CODE_FNC_4_B as isize
|
||||
}
|
||||
}
|
||||
_ => contents.chars().nth(i).unwrap() as isize - ' ' as isize,
|
||||
_ => {
|
||||
contents
|
||||
.chars()
|
||||
.nth(i)
|
||||
.ok_or(Exceptions::IndexOutOfBoundsException(None))?
|
||||
as isize
|
||||
- ' ' as isize
|
||||
}
|
||||
};
|
||||
if ((charset == Charset::A && latch != Latch::Shift)
|
||||
|| (charset == Charset::B && latch == Latch::Shift))
|
||||
@@ -611,7 +642,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
}
|
||||
|
||||
fn canEncode(contents: &str, charset: Charset, position: usize) -> bool {
|
||||
let c = contents.chars().nth(position).unwrap();
|
||||
let Some(c) = contents.chars().nth(position) else {
|
||||
return false;
|
||||
};
|
||||
match charset {
|
||||
Charset::A => {
|
||||
c == ESCAPE_FNC_1
|
||||
@@ -628,10 +661,11 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
|| B.find(c).is_some()
|
||||
}
|
||||
Charset::C => {
|
||||
let Some(c_p_1) = contents.chars().nth(position + 1) else {
|
||||
return false;
|
||||
};
|
||||
c == ESCAPE_FNC_1
|
||||
|| (position + 1 < contents.chars().count()
|
||||
&& isDigit(c)
|
||||
&& isDigit(contents.chars().nth(position + 1).unwrap()))
|
||||
|| (position + 1 < contents.chars().count() && isDigit(c) && isDigit(c_p_1))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -647,7 +681,9 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
memoizedCost: &mut Vec<Vec<u32>>,
|
||||
minPath: &mut Vec<Vec<Latch>>,
|
||||
) -> Result<u32, Exceptions> {
|
||||
assert!(position < contents.chars().count());
|
||||
if position >= contents.chars().count() {
|
||||
return Err(Exceptions::IllegalStateException(None));
|
||||
}
|
||||
let mCost = memoizedCost[charset.ordinal()][position];
|
||||
if mCost > 0 {
|
||||
return Ok(mCost);
|
||||
@@ -665,7 +701,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
let mut latch = Latch::None;
|
||||
if charset != sets[i] {
|
||||
cost += 1;
|
||||
latch = sets[i].into(); //Latch::valueOf(sets[i].toString());
|
||||
latch = sets[i].into();
|
||||
}
|
||||
if !atEnd {
|
||||
cost += encode_with_start_position(
|
||||
@@ -707,7 +743,7 @@ stuvwxyz{|}~\u{007F}\u{00FF}";
|
||||
cost += 1;
|
||||
latch = Latch::C;
|
||||
}
|
||||
let advance = if contents.chars().nth(position).unwrap() == ESCAPE_FNC_1 {
|
||||
let advance = if contents.chars().nth(position).unwrap_or_default() == ESCAPE_FNC_1 {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user