From 2de4061f8b6c2aa015ebdd33731f76c3ba7b5d4c Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Wed, 14 Dec 2022 17:52:11 -0600 Subject: [PATCH] begin port of rss_expanded --- src/oned/code_128_reader.rs | 5 +- src/oned/code_39_reader.rs | 2 +- src/oned/code_93_reader.rs | 2 +- src/oned/itf_reader.rs | 12 +- src/oned/one_d_reader.rs | 141 +++--- src/oned/rss/abstract_rss_reader.rs | 7 +- src/oned/rss/data_character.rs | 2 +- src/oned/rss/expanded/BinaryUtil.java | 84 ---- src/oned/rss/expanded/BinaryUtilTest.java | 90 ---- src/oned/rss/expanded/BitArrayBuilder.java | 85 ---- .../rss/expanded/BitArrayBuilderTest.java | 85 ---- src/oned/rss/expanded/ExpandedPair.java | 90 ---- src/oned/rss/expanded/binary_util.rs | 148 ++++++ src/oned/rss/expanded/bit_array_builder.rs | 145 ++++++ .../decoders/AbstractExpandedDecoder.java | 93 ---- .../expanded/decoders/DecodedInformation.java | 64 --- .../rss/expanded/decoders/FieldParser.java | 239 --------- .../expanded/decoders/FieldParserTest.java | 54 -- .../decoders/GeneralAppIdDecoder.java | 470 ------------------ .../decoders/abstract_expanded_decoder.rs | 95 ++++ ...ndOtherAIs.java => ai_01_and_other_ais.rs} | 53 +- .../{AI01decoder.java => ai_01_decoder.rs} | 71 ++- ...rsedResult.java => block_parsed_result.rs} | 46 +- ...ingState.java => current_parsing_state.rs} | 107 ++-- .../{DecodedChar.java => decoded_char.rs} | 44 +- ...dedNumeric.java => decoded_information.rs} | 77 +-- .../rss/expanded/decoders/decoded_numeric.rs | 83 ++++ .../{DecodedObject.java => decoded_object.rs} | 14 +- .../rss/expanded/decoders/field_parser.rs | 308 ++++++++++++ .../decoders/general_app_id_decoder.rs | 469 +++++++++++++++++ src/oned/rss/expanded/decoders/mod.rs | 26 + src/oned/rss/expanded/expanded_pair.rs | 85 ++++ src/oned/rss/expanded/mod.rs | 6 + src/oned/rss/rss_14_reader.rs | 17 +- src/oned/upc_ean_reader.rs | 11 +- tests/rss_14_blackbox.rs | 33 +- 36 files changed, 1691 insertions(+), 1672 deletions(-) delete mode 100644 src/oned/rss/expanded/BinaryUtil.java delete mode 100644 src/oned/rss/expanded/BinaryUtilTest.java delete mode 100644 src/oned/rss/expanded/BitArrayBuilder.java delete mode 100644 src/oned/rss/expanded/BitArrayBuilderTest.java delete mode 100644 src/oned/rss/expanded/ExpandedPair.java create mode 100644 src/oned/rss/expanded/binary_util.rs create mode 100644 src/oned/rss/expanded/bit_array_builder.rs delete mode 100644 src/oned/rss/expanded/decoders/AbstractExpandedDecoder.java delete mode 100644 src/oned/rss/expanded/decoders/DecodedInformation.java delete mode 100644 src/oned/rss/expanded/decoders/FieldParser.java delete mode 100644 src/oned/rss/expanded/decoders/FieldParserTest.java delete mode 100644 src/oned/rss/expanded/decoders/GeneralAppIdDecoder.java create mode 100644 src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs rename src/oned/rss/expanded/decoders/{AI01AndOtherAIs.java => ai_01_and_other_ais.rs} (50%) rename src/oned/rss/expanded/decoders/{AI01decoder.java => ai_01_decoder.rs} (50%) rename src/oned/rss/expanded/decoders/{BlockParsedResult.java => block_parsed_result.rs} (64%) rename src/oned/rss/expanded/decoders/{CurrentParsingState.java => current_parsing_state.rs} (50%) rename src/oned/rss/expanded/decoders/{DecodedChar.java => decoded_char.rs} (68%) rename src/oned/rss/expanded/decoders/{DecodedNumeric.java => decoded_information.rs} (53%) create mode 100644 src/oned/rss/expanded/decoders/decoded_numeric.rs rename src/oned/rss/expanded/decoders/{DecodedObject.java => decoded_object.rs} (80%) create mode 100644 src/oned/rss/expanded/decoders/field_parser.rs create mode 100644 src/oned/rss/expanded/decoders/general_app_id_decoder.rs create mode 100644 src/oned/rss/expanded/expanded_pair.rs diff --git a/src/oned/code_128_reader.rs b/src/oned/code_128_reader.rs index ad0f7e6..1035432 100644 --- a/src/oned/code_128_reader.rs +++ b/src/oned/code_128_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult}; -use super::{OneDReader, one_d_reader}; +use super::{one_d_reader, OneDReader}; /** *

Decodes Code 128 barcodes.

@@ -434,7 +434,8 @@ impl Code128Reader { 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); + let variance = + one_d_reader::patternMatchVariance(counters, &pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = d as isize; diff --git a/src/oned/code_39_reader.rs b/src/oned/code_39_reader.rs index 85f0115..490f8c4 100644 --- a/src/oned/code_39_reader.rs +++ b/src/oned/code_39_reader.rs @@ -19,7 +19,7 @@ use one_d_reader_derive::OneDReader; use crate::common::BitArray; use crate::{BarcodeFormat, Exceptions, RXingResult}; -use super::{OneDReader, one_d_reader}; +use super::{one_d_reader, OneDReader}; /** *

Decodes Code 39 barcodes. Supports "Full ASCII Code 39" if USE_CODE_39_EXTENDED_MODE is set.

diff --git a/src/oned/code_93_reader.rs b/src/oned/code_93_reader.rs index fa98390..60fc3e2 100644 --- a/src/oned/code_93_reader.rs +++ b/src/oned/code_93_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, Exceptions, RXingResult}; -use super::{OneDReader, one_d_reader}; +use super::{one_d_reader, OneDReader}; /** *

Decodes Code 93 barcodes.

diff --git a/src/oned/itf_reader.rs b/src/oned/itf_reader.rs index c505328..7d283ed 100644 --- a/src/oned/itf_reader.rs +++ b/src/oned/itf_reader.rs @@ -18,7 +18,7 @@ use one_d_reader_derive::OneDReader; use crate::{common::BitArray, BarcodeFormat, DecodeHintValue, Exceptions, RXingResult}; -use super::{OneDReader, one_d_reader}; +use super::{one_d_reader, OneDReader}; const MAX_AVG_VARIANCE: f32 = 0.38; const MAX_INDIVIDUAL_VARIANCE: f32 = 0.5; @@ -375,8 +375,11 @@ impl ITFReader { counters[counterPosition] += 1; } else { if counterPosition == patternLength - 1 { - if one_d_reader::patternMatchVariance(&counters, pattern, MAX_INDIVIDUAL_VARIANCE) - < MAX_AVG_VARIANCE + if one_d_reader::patternMatchVariance( + &counters, + pattern, + MAX_INDIVIDUAL_VARIANCE, + ) < MAX_AVG_VARIANCE { return Ok([patternStart, x]); } @@ -412,7 +415,8 @@ impl ITFReader { for i in 0..max { // for (int i = 0; i < max; i++) { let pattern = &PATTERNS[i]; - let variance = one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); + let variance = + one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = i as isize; diff --git a/src/oned/one_d_reader.rs b/src/oned/one_d_reader.rs index 60af80f..80f43c7 100644 --- a/src/oned/one_d_reader.rs +++ b/src/oned/one_d_reader.rs @@ -166,7 +166,6 @@ pub trait OneDReader: Reader { ) -> Result; } - /** * Determines how closely a set of observed counts of runs of black/white values matches a given * target pattern. This is reported as the ratio of the total variance from the expected pattern @@ -177,11 +176,7 @@ pub trait OneDReader: Reader { * @param maxIndividualVariance The most any counter can differ before we give up * @return ratio of total variance between counters and pattern compared to total pattern size */ -pub fn patternMatchVariance( - counters: &[u32], - pattern: &[u32], - maxIndividualVariance: f32, -) -> f32 { +pub fn patternMatchVariance(counters: &[u32], pattern: &[u32], maxIndividualVariance: f32) -> f32 { let mut maxIndividualVariance = maxIndividualVariance; let numCounters = counters.len(); let mut total = 0.0; @@ -218,76 +213,72 @@ pub fn patternMatchVariance( return totalVariance / total; } - /** - * Records the size of successive runs of white and black pixels in a row, starting at a given point. - * The values are recorded in the given array, and the number of runs recorded is equal to the size - * of the array. If the row starts on a white pixel at the given start point, then the first count - * recorded is the run of white pixels starting from that point; likewise it is the count of a run - * of black pixels if the row begin on a black pixels at that point. - * - * @param row row to count from - * @param start offset into row to start at - * @param counters array into which to record counts - * @throws NotFoundException if counters cannot be filled entirely from row before running out - * of pixels - */ - pub fn recordPattern( - row: &BitArray, - start: usize, - counters: &mut [u32], - ) -> Result<(), Exceptions> { - let numCounters = counters.len(); - // Arrays.fill(counters, 0, numCounters, 0); - counters.fill(0); - let end = row.getSize(); - if start >= end { - return Err(Exceptions::NotFoundException("".to_owned())); - } - let mut isWhite = !row.get(start); - let mut counterPosition = 0; - let mut i = start; - while i < end { - if row.get(i) != isWhite { - counters[counterPosition] += 1; - } else { - counterPosition += 1; - if counterPosition == numCounters { - break; - } else { - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - i += 1; - } - // If we read fully the last section of pixels and filled up our counters -- or filled - // the last counter but ran off the side of the image, OK. Otherwise, a problem. - if !(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)) { - return Err(Exceptions::NotFoundException("".to_owned())); - } - Ok(()) +/** + * Records the size of successive runs of white and black pixels in a row, starting at a given point. + * The values are recorded in the given array, and the number of runs recorded is equal to the size + * of the array. If the row starts on a white pixel at the given start point, then the first count + * recorded is the run of white pixels starting from that point; likewise it is the count of a run + * of black pixels if the row begin on a black pixels at that point. + * + * @param row row to count from + * @param start offset into row to start at + * @param counters array into which to record counts + * @throws NotFoundException if counters cannot be filled entirely from row before running out + * of pixels + */ +pub fn recordPattern(row: &BitArray, start: usize, counters: &mut [u32]) -> Result<(), Exceptions> { + let numCounters = counters.len(); + // Arrays.fill(counters, 0, numCounters, 0); + counters.fill(0); + let end = row.getSize(); + if start >= end { + return Err(Exceptions::NotFoundException("".to_owned())); } - - pub fn recordPatternInReverse( - row: &BitArray, - start: usize, - counters: &mut [u32], - ) -> Result<(), Exceptions> { - let mut start = start; - // This could be more efficient I guess - let mut numTransitionsLeft = counters.len() as isize; - let mut last = row.get(start); - while start > 0 && numTransitionsLeft >= 0 { - start -= 1; - if row.get(start) != last { - numTransitionsLeft -= 1; - last = !last; + let mut isWhite = !row.get(start); + let mut counterPosition = 0; + let mut i = start; + while i < end { + if row.get(i) != isWhite { + counters[counterPosition] += 1; + } else { + counterPosition += 1; + if counterPosition == numCounters { + break; + } else { + counters[counterPosition] = 1; + isWhite = !isWhite; } } - if numTransitionsLeft >= 0 { - return Err(Exceptions::NotFoundException("".to_owned())); - } - recordPattern(row, start + 1, counters)?; + i += 1; + } + // If we read fully the last section of pixels and filled up our counters -- or filled + // the last counter but ran off the side of the image, OK. Otherwise, a problem. + if !(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)) { + return Err(Exceptions::NotFoundException("".to_owned())); + } + Ok(()) +} - Ok(()) - } \ No newline at end of file +pub fn recordPatternInReverse( + row: &BitArray, + start: usize, + counters: &mut [u32], +) -> Result<(), Exceptions> { + let mut start = start; + // This could be more efficient I guess + let mut numTransitionsLeft = counters.len() as isize; + let mut last = row.get(start); + while start > 0 && numTransitionsLeft >= 0 { + start -= 1; + if row.get(start) != last { + numTransitionsLeft -= 1; + last = !last; + } + } + if numTransitionsLeft >= 0 { + return Err(Exceptions::NotFoundException("".to_owned())); + } + recordPattern(row, start + 1, counters)?; + + Ok(()) +} diff --git a/src/oned/rss/abstract_rss_reader.rs b/src/oned/rss/abstract_rss_reader.rs index 729b7e4..7a0727a 100644 --- a/src/oned/rss/abstract_rss_reader.rs +++ b/src/oned/rss/abstract_rss_reader.rs @@ -14,7 +14,10 @@ * limitations under the License. */ -use crate::{oned::{OneDReader, one_d_reader}, Exceptions}; +use crate::{ + oned::{one_d_reader, OneDReader}, + Exceptions, +}; /** * Superclass of {@link OneDReader} implementations that read barcodes in the RSS family @@ -97,7 +100,7 @@ pub trait AbstractRSSReaderTrait: OneDReader { array[index] -= 1; } - fn isFinderPattern( counters: &[u32]) -> bool { + fn isFinderPattern(counters: &[u32]) -> bool { let firstTwoSum = counters[0] + counters[1]; let sum = firstTwoSum + counters[2] + counters[3]; let ratio: f32 = (firstTwoSum as f32) / (sum as f32); diff --git a/src/oned/rss/data_character.rs b/src/oned/rss/data_character.rs index 6d333bc..95a188f 100644 --- a/src/oned/rss/data_character.rs +++ b/src/oned/rss/data_character.rs @@ -25,7 +25,7 @@ pub(crate) trait DataCharacterTrait: Display + Eq + PartialEq + Hash { /** * Encapsulates a since character value in an RSS barcode, including its checksum information. */ -#[derive(Hash, PartialEq, Eq)] +#[derive(Hash, PartialEq, Eq, Debug)] pub struct DataCharacter { value: u32, checksumPortion: u32, diff --git a/src/oned/rss/expanded/BinaryUtil.java b/src/oned/rss/expanded/BinaryUtil.java deleted file mode 100644 index 8e84c38..0000000 --- a/src/oned/rss/expanded/BinaryUtil.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.common.BitArray; - -import java.util.regex.Pattern; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -public final class BinaryUtil { - - private static final Pattern ONE = Pattern.compile("1"); - private static final Pattern ZERO = Pattern.compile("0"); - private static final Pattern SPACE = Pattern.compile(" "); - - private BinaryUtil() { - } - - /* - * Constructs a BitArray from a String like the one returned from BitArray.toString() - */ - public static BitArray buildBitArrayFromString(CharSequence data) { - CharSequence dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll("."); - BitArray binary = new BitArray(SPACE.matcher(dotsAndXs).replaceAll("").length()); - int counter = 0; - - for (int i = 0; i < dotsAndXs.length(); ++i) { - if (i % 9 == 0) { // spaces - if (dotsAndXs.charAt(i) != ' ') { - throw new IllegalStateException("space expected"); - } - continue; - } - - char currentChar = dotsAndXs.charAt(i); - if (currentChar == 'X' || currentChar == 'x') { - binary.set(counter); - } - counter++; - } - return binary; - } - - public static BitArray buildBitArrayFromStringWithoutSpaces(CharSequence data) { - StringBuilder sb = new StringBuilder(); - CharSequence dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll("."); - int current = 0; - while (current < dotsAndXs.length()) { - sb.append(' '); - for (int i = 0; i < 8 && current < dotsAndXs.length(); ++i) { - sb.append(dotsAndXs.charAt(current)); - current++; - } - } - return buildBitArrayFromString(sb.toString()); - } - -} diff --git a/src/oned/rss/expanded/BinaryUtilTest.java b/src/oned/rss/expanded/BinaryUtilTest.java deleted file mode 100644 index f7be304..0000000 --- a/src/oned/rss/expanded/BinaryUtilTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.common.BitArray; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.regex.Pattern; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -public final class BinaryUtilTest extends Assert { - - private static final Pattern SPACE = Pattern.compile(" "); - - @Test - public void testBuildBitArrayFromString() { - - CharSequence data = " ..X..X.. ..XXX... XXXXXXXX ........"; - check(data); - - data = " XXX..X.."; - check(data); - - data = " XX"; - check(data); - - data = " ....XX.. ..XX"; - check(data); - - data = " ....XX.. ..XX..XX ....X.X. ........"; - check(data); - } - - private static void check(CharSequence data) { - BitArray binary = BinaryUtil.buildBitArrayFromString(data); - assertEquals(data, binary.toString()); - } - - @Test - public void testBuildBitArrayFromStringWithoutSpaces() { - CharSequence data = " ..X..X.. ..XXX... XXXXXXXX ........"; - checkWithoutSpaces(data); - - data = " XXX..X.."; - checkWithoutSpaces(data); - - data = " XX"; - checkWithoutSpaces(data); - - data = " ....XX.. ..XX"; - checkWithoutSpaces(data); - - data = " ....XX.. ..XX..XX ....X.X. ........"; - checkWithoutSpaces(data); - } - - private static void checkWithoutSpaces(CharSequence data) { - CharSequence dataWithoutSpaces = SPACE.matcher(data).replaceAll(""); - BitArray binary = BinaryUtil.buildBitArrayFromStringWithoutSpaces(dataWithoutSpaces); - assertEquals(data, binary.toString()); - } -} diff --git a/src/oned/rss/expanded/BitArrayBuilder.java b/src/oned/rss/expanded/BitArrayBuilder.java deleted file mode 100644 index 293af30..0000000 --- a/src/oned/rss/expanded/BitArrayBuilder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.common.BitArray; - -import java.util.List; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class BitArrayBuilder { - - private BitArrayBuilder() { - } - - static BitArray buildBitArray(List pairs) { - int charNumber = (pairs.size() * 2) - 1; - if (pairs.get(pairs.size() - 1).getRightChar() == null) { - charNumber -= 1; - } - - int size = 12 * charNumber; - - BitArray binary = new BitArray(size); - int accPos = 0; - - ExpandedPair firstPair = pairs.get(0); - int firstValue = firstPair.getRightChar().getValue(); - for (int i = 11; i >= 0; --i) { - if ((firstValue & (1 << i)) != 0) { - binary.set(accPos); - } - accPos++; - } - - for (int i = 1; i < pairs.size(); ++i) { - ExpandedPair currentPair = pairs.get(i); - - int leftValue = currentPair.getLeftChar().getValue(); - for (int j = 11; j >= 0; --j) { - if ((leftValue & (1 << j)) != 0) { - binary.set(accPos); - } - accPos++; - } - - if (currentPair.getRightChar() != null) { - int rightValue = currentPair.getRightChar().getValue(); - for (int j = 11; j >= 0; --j) { - if ((rightValue & (1 << j)) != 0) { - binary.set(accPos); - } - accPos++; - } - } - } - return binary; - } -} diff --git a/src/oned/rss/expanded/BitArrayBuilderTest.java b/src/oned/rss/expanded/BitArrayBuilderTest.java deleted file mode 100644 index 609c911..0000000 --- a/src/oned/rss/expanded/BitArrayBuilderTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.common.BitArray; -import com.google.zxing.oned.rss.DataCharacter; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -public final class BitArrayBuilderTest extends Assert { - - @Test - public void testBuildBitArray1() { - int[][] pairValues = {{19}, {673, 16}}; - - String expected = " .......X ..XX..X. X.X....X .......X ...."; - - checkBinary(pairValues, expected); - } - - private static void checkBinary(int[][] pairValues, String expected) { - BitArray binary = buildBitArray(pairValues); - assertEquals(expected, binary.toString()); - } - - private static BitArray buildBitArray(int[][] pairValues) { - List pairs = new ArrayList<>(); - for (int i = 0; i < pairValues.length; ++i) { - int [] pair = pairValues[i]; - - DataCharacter leftChar; - if (i == 0) { - leftChar = null; - } else { - leftChar = new DataCharacter(pair[0], 0); - } - - DataCharacter rightChar; - if (i == 0) { - rightChar = new DataCharacter(pair[0], 0); - } else if (pair.length == 2) { - rightChar = new DataCharacter(pair[1], 0); - } else { - rightChar = null; - } - - ExpandedPair expandedPair = new ExpandedPair(leftChar, rightChar, null); - pairs.add(expandedPair); - } - - return BitArrayBuilder.buildBitArray(pairs); - } -} diff --git a/src/oned/rss/expanded/ExpandedPair.java b/src/oned/rss/expanded/ExpandedPair.java deleted file mode 100644 index e22b5e3..0000000 --- a/src/oned/rss/expanded/ExpandedPair.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded; - -import com.google.zxing.oned.rss.DataCharacter; -import com.google.zxing.oned.rss.FinderPattern; - -import java.util.Objects; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - */ -final class ExpandedPair { - - private final DataCharacter leftChar; - private final DataCharacter rightChar; - private final FinderPattern finderPattern; - - ExpandedPair(DataCharacter leftChar, - DataCharacter rightChar, - FinderPattern finderPattern) { - this.leftChar = leftChar; - this.rightChar = rightChar; - this.finderPattern = finderPattern; - } - - DataCharacter getLeftChar() { - return this.leftChar; - } - - DataCharacter getRightChar() { - return this.rightChar; - } - - FinderPattern getFinderPattern() { - return this.finderPattern; - } - - boolean mustBeLast() { - return this.rightChar == null; - } - - @Override - public String toString() { - return - "[ " + leftChar + " , " + rightChar + " : " + - (finderPattern == null ? "null" : finderPattern.getValue()) + " ]"; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof ExpandedPair)) { - return false; - } - ExpandedPair that = (ExpandedPair) o; - return Objects.equals(leftChar, that.leftChar) && - Objects.equals(rightChar, that.rightChar) && - Objects.equals(finderPattern, that.finderPattern); - } - - @Override - public int hashCode() { - return Objects.hashCode(leftChar) ^ Objects.hashCode(rightChar) ^ Objects.hashCode(finderPattern); - } - -} diff --git a/src/oned/rss/expanded/binary_util.rs b/src/oned/rss/expanded/binary_util.rs new file mode 100644 index 0000000..22b49ff --- /dev/null +++ b/src/oned/rss/expanded/binary_util.rs @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + */ +use lazy_static::lazy_static; +use regex::Regex; + +use crate::{common::BitArray, Exceptions}; + +lazy_static! { + static ref ONE: Regex = Regex::new("1").unwrap(); + static ref ZERO: Regex = Regex::new("0").unwrap(); + static ref SPACE: Regex = Regex::new(" ").unwrap(); +} + +/* + * Constructs a BitArray from a String like the one returned from BitArray.toString() + */ +pub fn buildBitArrayFromString(data: &str) -> Result { + let dotsAndXs = ZERO + .replace_all(&ONE.replace_all(data, "X"), ".") + .to_string(); + let mut binary = BitArray::with_size(SPACE.replace_all(&dotsAndXs, "").chars().count()); + let mut counter = 0; + + for i in 0..dotsAndXs.chars().count() { + // for (int i = 0; i < dotsAndXs.length(); ++i) { + if i % 9 == 0 { + // spaces + if dotsAndXs.chars().nth(i).unwrap() != ' ' { + return Err(Exceptions::IllegalStateException( + "space expected".to_owned(), + )); + } + continue; + } + + let currentChar = dotsAndXs.chars().nth(i).unwrap(); + if currentChar == 'X' || currentChar == 'x' { + binary.set(counter); + } + counter += 1; + } + Ok(binary) +} + +pub fn buildBitArrayFromStringWithoutSpaces(data: &str) -> Result { + let mut sb = String::new(); + + // let dotsAndXs = ZERO.matcher(ONE.matcher(data).replaceAll("X")).replaceAll("."); + let dotsAndXs = ZERO + .replace_all(&ONE.replace_all(data, "X"), ".") + .to_string(); + let mut current = 0; + while current < dotsAndXs.chars().count() { + sb.push(' '); + let mut i = 0; + while i < 8 && current < dotsAndXs.chars().count() { + // for (int i = 0; i < 8 && current < dotsAndXs.length(); ++i) { + sb.push(dotsAndXs.chars().nth(current).unwrap()); + current += 1; + + i += 1; + } + } + + buildBitArrayFromString(&sb) +} + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + */ +#[cfg(test)] +mod BinaryUtilTest { + + #[test] + fn testBuildBitArrayFromString() { + let data = " ..X..X.. ..XXX... XXXXXXXX ........"; + check(data); + + let data = " XXX..X.."; + check(data); + + let data = " XX"; + check(data); + + let data = " ....XX.. ..XX"; + check(data); + + let data = " ....XX.. ..XX..XX ....X.X. ........"; + check(data); + } + + fn check(data: &str) { + let binary = super::buildBitArrayFromString(data).expect("check"); + assert_eq!(data, binary.to_string()); + } + + #[test] + fn testBuildBitArrayFromStringWithoutSpaces() { + let data = " ..X..X.. ..XXX... XXXXXXXX ........"; + checkWithoutSpaces(data); + + let data = " XXX..X.."; + checkWithoutSpaces(data); + + let data = " XX"; + checkWithoutSpaces(data); + + let data = " ....XX.. ..XX"; + checkWithoutSpaces(data); + + let data = " ....XX.. ..XX..XX ....X.X. ........"; + checkWithoutSpaces(data); + } + + fn checkWithoutSpaces(data: &str) { + let dataWithoutSpaces = super::SPACE.replace_all(data, ""); + let binary = + super::buildBitArrayFromStringWithoutSpaces(&dataWithoutSpaces).expect("success"); + assert_eq!(data, binary.to_string()); + } +} diff --git a/src/oned/rss/expanded/bit_array_builder.rs b/src/oned/rss/expanded/bit_array_builder.rs new file mode 100644 index 0000000..b9a658a --- /dev/null +++ b/src/oned/rss/expanded/bit_array_builder.rs @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use crate::{common::BitArray, oned::rss::DataCharacterTrait}; + +use super::ExpandedPair; + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ + +pub fn buildBitArray(pairs: &Vec) -> BitArray { + let mut charNumber = (pairs.len() * 2) - 1; + if pairs.get(pairs.len() - 1).unwrap().getRightChar().is_none() { + charNumber -= 1; + } + + let size = 12 * charNumber; + + let mut binary = BitArray::with_size(size); + let mut accPos = 0; + + let firstPair = pairs.get(0).unwrap(); + let Some(rp) = firstPair.getRightChar() else { panic!("first char must exist");}; + let firstValue = rp.getValue(); + let mut i = 11; + while i >= 0 { + // for (int i = 11; i >= 0; --i) { + if (firstValue & (1 << i)) != 0 { + binary.set(accPos); + } + accPos += 1; + + i -= 1; + } + + for i in 1..pairs.len() { + // for (int i = 1; i < pairs.size(); ++i) { + let currentPair = pairs.get(i).unwrap(); + let Some(lv) = currentPair.getLeftChar() else { panic!("I'm not sure how we get here ");}; + let leftValue = lv.getValue(); + let mut j = 11; + while j >= 0 { + // for (int j = 11; j >= 0; --j) { + if (leftValue & (1 << j)) != 0 { + binary.set(accPos); + } + accPos += 1; + + j -= 1; + } + + if let Some(rc) = currentPair.getRightChar() { + let rightValue = rc.getValue(); //currentPair.getRightChar().getValue(); + let mut j = 11; + while j >= 0 { + // for (int j = 11; j >= 0; --j) { + if (rightValue & (1 << j)) != 0 { + binary.set(accPos); + } + accPos += 1; + + j -= 1; + } + } + } + return binary; +} + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ +#[cfg(test)] +mod BitArrayBuilderTest { + use crate::{ + common::BitArray, + oned::rss::{expanded::ExpandedPair, DataCharacter}, + }; + + #[test] + fn testBuildBitArray1() { + let pairValues = vec![vec![19], vec![673, 16]]; + + let expected = " .......X ..XX..X. X.X....X .......X ...."; + + checkBinary(&pairValues, expected); + } + + fn checkBinary(pairValues: &Vec>, expected: &str) { + let binary = buildBitArray(pairValues); + assert_eq!(expected, binary.to_string()); + } + + fn buildBitArray(pairValues: &Vec>) -> BitArray { + let mut pairs = Vec::new(); //new ArrayList<>(); + for i in 0..pairValues.len() { + // for (int i = 0; i < pairValues.length; ++i) { + let pair = &pairValues[i]; + + let leftChar = if i == 0 { + None + } else { + Some(DataCharacter::new(pair[0], 0)) + }; + + let rightChar = if i == 0 { + Some(DataCharacter::new(pair[0], 0)) + } else if pair.len() == 2 { + Some(DataCharacter::new(pair[1], 0)) + } else { + None + }; + + let expandedPair = ExpandedPair::new(leftChar, rightChar, None); + pairs.push(expandedPair); + } + + super::buildBitArray(&pairs) + } +} diff --git a/src/oned/rss/expanded/decoders/AbstractExpandedDecoder.java b/src/oned/rss/expanded/decoders/AbstractExpandedDecoder.java deleted file mode 100644 index 771b42b..0000000 --- a/src/oned/rss/expanded/decoders/AbstractExpandedDecoder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -public abstract class AbstractExpandedDecoder { - - private final BitArray information; - private final GeneralAppIdDecoder generalDecoder; - - AbstractExpandedDecoder(BitArray information) { - this.information = information; - this.generalDecoder = new GeneralAppIdDecoder(information); - } - - protected final BitArray getInformation() { - return information; - } - - protected final GeneralAppIdDecoder getGeneralDecoder() { - return generalDecoder; - } - - public abstract String parseInformation() throws NotFoundException, FormatException; - - public static AbstractExpandedDecoder createDecoder(BitArray information) { - if (information.get(1)) { - return new AI01AndOtherAIs(information); - } - if (!information.get(2)) { - return new AnyAIDecoder(information); - } - - int fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4); - - switch (fourBitEncodationMethod) { - case 4: return new AI013103decoder(information); - case 5: return new AI01320xDecoder(information); - } - - int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5); - switch (fiveBitEncodationMethod) { - case 12: return new AI01392xDecoder(information); - case 13: return new AI01393xDecoder(information); - } - - int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7); - switch (sevenBitEncodationMethod) { - case 56: return new AI013x0x1xDecoder(information, "310", "11"); - case 57: return new AI013x0x1xDecoder(information, "320", "11"); - case 58: return new AI013x0x1xDecoder(information, "310", "13"); - case 59: return new AI013x0x1xDecoder(information, "320", "13"); - case 60: return new AI013x0x1xDecoder(information, "310", "15"); - case 61: return new AI013x0x1xDecoder(information, "320", "15"); - case 62: return new AI013x0x1xDecoder(information, "310", "17"); - case 63: return new AI013x0x1xDecoder(information, "320", "17"); - } - - throw new IllegalStateException("unknown decoder: " + information); - } - -} diff --git a/src/oned/rss/expanded/decoders/DecodedInformation.java b/src/oned/rss/expanded/decoders/DecodedInformation.java deleted file mode 100644 index 0ed90fd..0000000 --- a/src/oned/rss/expanded/decoders/DecodedInformation.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class DecodedInformation extends DecodedObject { - - private final String newString; - private final int remainingValue; - private final boolean remaining; - - DecodedInformation(int newPosition, String newString) { - super(newPosition); - this.newString = newString; - this.remaining = false; - this.remainingValue = 0; - } - - DecodedInformation(int newPosition, String newString, int remainingValue) { - super(newPosition); - this.remaining = true; - this.remainingValue = remainingValue; - this.newString = newString; - } - - String getNewString() { - return this.newString; - } - - boolean isRemaining() { - return this.remaining; - } - - int getRemainingValue() { - return this.remainingValue; - } -} diff --git a/src/oned/rss/expanded/decoders/FieldParser.java b/src/oned/rss/expanded/decoders/FieldParser.java deleted file mode 100644 index 13206bc..0000000 --- a/src/oned/rss/expanded/decoders/FieldParser.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.NotFoundException; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class FieldParser { - - private static final Map TWO_DIGIT_DATA_LENGTH = new HashMap<>(); - static { - TWO_DIGIT_DATA_LENGTH.put("00", DataLength.fixed(18)); - TWO_DIGIT_DATA_LENGTH.put("01", DataLength.fixed(14)); - TWO_DIGIT_DATA_LENGTH.put("02", DataLength.fixed(14)); - TWO_DIGIT_DATA_LENGTH.put("10", DataLength.variable(20)); - TWO_DIGIT_DATA_LENGTH.put("11", DataLength.fixed(6)); - TWO_DIGIT_DATA_LENGTH.put("12", DataLength.fixed(6)); - TWO_DIGIT_DATA_LENGTH.put("13", DataLength.fixed(6)); - TWO_DIGIT_DATA_LENGTH.put("15", DataLength.fixed(6)); - TWO_DIGIT_DATA_LENGTH.put("17", DataLength.fixed(6)); - TWO_DIGIT_DATA_LENGTH.put("20", DataLength.fixed(2)); - TWO_DIGIT_DATA_LENGTH.put("21", DataLength.variable(20)); - TWO_DIGIT_DATA_LENGTH.put("22", DataLength.variable(29)); - TWO_DIGIT_DATA_LENGTH.put("30", DataLength.variable(8)); - TWO_DIGIT_DATA_LENGTH.put("37", DataLength.variable(8)); - //internal company codes - for (int i = 90; i <= 99; i++) { - TWO_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.variable(30)); - } - } - - private static final Map THREE_DIGIT_DATA_LENGTH = new HashMap<>(); - static { - THREE_DIGIT_DATA_LENGTH.put("240", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("241", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("242", DataLength.variable(6)); - THREE_DIGIT_DATA_LENGTH.put("250", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("251", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("253", DataLength.variable(17)); - THREE_DIGIT_DATA_LENGTH.put("254", DataLength.variable(20)); - THREE_DIGIT_DATA_LENGTH.put("400", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("401", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("402", DataLength.fixed(17)); - THREE_DIGIT_DATA_LENGTH.put("403", DataLength.variable(30)); - THREE_DIGIT_DATA_LENGTH.put("410", DataLength.fixed(13)); - THREE_DIGIT_DATA_LENGTH.put("411", DataLength.fixed(13)); - THREE_DIGIT_DATA_LENGTH.put("412", DataLength.fixed(13)); - THREE_DIGIT_DATA_LENGTH.put("413", DataLength.fixed(13)); - THREE_DIGIT_DATA_LENGTH.put("414", DataLength.fixed(13)); - THREE_DIGIT_DATA_LENGTH.put("420", DataLength.variable(20)); - THREE_DIGIT_DATA_LENGTH.put("421", DataLength.variable(15)); - THREE_DIGIT_DATA_LENGTH.put("422", DataLength.fixed(3)); - THREE_DIGIT_DATA_LENGTH.put("423", DataLength.variable(15)); - THREE_DIGIT_DATA_LENGTH.put("424", DataLength.fixed(3)); - THREE_DIGIT_DATA_LENGTH.put("425", DataLength.fixed(3)); - THREE_DIGIT_DATA_LENGTH.put("426", DataLength.fixed(3)); - } - - private static final Map THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = new HashMap<>(); - static { - for (int i = 310; i <= 316; i++) { - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6)); - } - for (int i = 320; i <= 336; i++) { - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6)); - } - for (int i = 340; i <= 357; i++) { - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6)); - } - for (int i = 360; i <= 369; i++) { - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put(String.valueOf(i), DataLength.fixed(6)); - } - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("390", DataLength.variable(15)); - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("391", DataLength.variable(18)); - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("392", DataLength.variable(15)); - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("393", DataLength.variable(18)); - THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.put("703", DataLength.variable(30)); - } - - private static final Map FOUR_DIGIT_DATA_LENGTH = new HashMap<>(); - static { - FOUR_DIGIT_DATA_LENGTH.put("7001", DataLength.fixed(13)); - FOUR_DIGIT_DATA_LENGTH.put("7002", DataLength.variable(30)); - FOUR_DIGIT_DATA_LENGTH.put("7003", DataLength.fixed(10)); - FOUR_DIGIT_DATA_LENGTH.put("8001", DataLength.fixed(14)); - FOUR_DIGIT_DATA_LENGTH.put("8002", DataLength.variable(20)); - FOUR_DIGIT_DATA_LENGTH.put("8003", DataLength.variable(30)); - FOUR_DIGIT_DATA_LENGTH.put("8004", DataLength.variable(30)); - FOUR_DIGIT_DATA_LENGTH.put("8005", DataLength.fixed(6)); - FOUR_DIGIT_DATA_LENGTH.put("8006", DataLength.fixed(18)); - FOUR_DIGIT_DATA_LENGTH.put("8007", DataLength.variable(30)); - FOUR_DIGIT_DATA_LENGTH.put("8008", DataLength.variable(12)); - FOUR_DIGIT_DATA_LENGTH.put("8018", DataLength.fixed(18)); - FOUR_DIGIT_DATA_LENGTH.put("8020", DataLength.variable(25)); - FOUR_DIGIT_DATA_LENGTH.put("8100", DataLength.fixed(6)); - FOUR_DIGIT_DATA_LENGTH.put("8101", DataLength.fixed(10)); - FOUR_DIGIT_DATA_LENGTH.put("8102", DataLength.fixed(2)); - FOUR_DIGIT_DATA_LENGTH.put("8110", DataLength.variable(70)); - FOUR_DIGIT_DATA_LENGTH.put("8200", DataLength.variable(70)); - } - - private FieldParser() { - } - - static String parseFieldsInGeneralPurpose(String rawInformation) throws NotFoundException { - if (rawInformation.isEmpty()) { - return null; - } - - // Processing 2-digit AIs - - if (rawInformation.length() < 2) { - throw NotFoundException.getNotFoundInstance(); - } - - DataLength twoDigitDataLength = TWO_DIGIT_DATA_LENGTH.get(rawInformation.substring(0, 2)); - if (twoDigitDataLength != null) { - if (twoDigitDataLength.variable) { - return processVariableAI(2, twoDigitDataLength.length, rawInformation); - } - return processFixedAI(2, twoDigitDataLength.length, rawInformation); - } - - if (rawInformation.length() < 3) { - throw NotFoundException.getNotFoundInstance(); - } - - String firstThreeDigits = rawInformation.substring(0, 3); - DataLength threeDigitDataLength = THREE_DIGIT_DATA_LENGTH.get(firstThreeDigits); - if (threeDigitDataLength != null) { - if (threeDigitDataLength.variable) { - return processVariableAI(3, threeDigitDataLength.length, rawInformation); - } - return processFixedAI(3, threeDigitDataLength.length, rawInformation); - } - - if (rawInformation.length() < 4) { - throw NotFoundException.getNotFoundInstance(); - } - - DataLength threeDigitPlusDigitDataLength = THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.get(firstThreeDigits); - if (threeDigitPlusDigitDataLength != null) { - if (threeDigitPlusDigitDataLength.variable) { - return processVariableAI(4, threeDigitPlusDigitDataLength.length, rawInformation); - } - return processFixedAI(4, threeDigitPlusDigitDataLength.length, rawInformation); - } - - DataLength firstFourDigitLength = FOUR_DIGIT_DATA_LENGTH.get(rawInformation.substring(0, 4)); - if (firstFourDigitLength != null) { - if (firstFourDigitLength.variable) { - return processVariableAI(4, firstFourDigitLength.length, rawInformation); - } - return processFixedAI(4, firstFourDigitLength.length, rawInformation); - } - - throw NotFoundException.getNotFoundInstance(); - } - - private static String processFixedAI(int aiSize, int fieldSize, String rawInformation) throws NotFoundException { - if (rawInformation.length() < aiSize) { - throw NotFoundException.getNotFoundInstance(); - } - - String ai = rawInformation.substring(0, aiSize); - - if (rawInformation.length() < aiSize + fieldSize) { - throw NotFoundException.getNotFoundInstance(); - } - - String field = rawInformation.substring(aiSize, aiSize + fieldSize); - String remaining = rawInformation.substring(aiSize + fieldSize); - String result = '(' + ai + ')' + field; - String parsedAI = parseFieldsInGeneralPurpose(remaining); - return parsedAI == null ? result : result + parsedAI; - } - - private static String processVariableAI(int aiSize, int variableFieldSize, String rawInformation) - throws NotFoundException { - String ai = rawInformation.substring(0, aiSize); - int maxSize = Math.min(rawInformation.length(), aiSize + variableFieldSize); - String field = rawInformation.substring(aiSize, maxSize); - String remaining = rawInformation.substring(maxSize); - String result = '(' + ai + ')' + field; - String parsedAI = parseFieldsInGeneralPurpose(remaining); - return parsedAI == null ? result : result + parsedAI; - } - - private static final class DataLength { - - final boolean variable; - final int length; - - private DataLength(boolean variable, int length) { - this.variable = variable; - this.length = length; - } - - static DataLength fixed(int length) { - return new DataLength(false, length); - } - - static DataLength variable(int length) { - return new DataLength(true, length); - } - - } - -} diff --git a/src/oned/rss/expanded/decoders/FieldParserTest.java b/src/oned/rss/expanded/decoders/FieldParserTest.java deleted file mode 100644 index 9a40ceb..0000000 --- a/src/oned/rss/expanded/decoders/FieldParserTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.NotFoundException; -import org.junit.Assert; -import org.junit.Test; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -public final class FieldParserTest extends Assert { - - private static void checkFields(String expected) throws NotFoundException { - String field = expected.replace("(", "").replace(")",""); - String actual = FieldParser.parseFieldsInGeneralPurpose(field); - assertEquals(expected, actual); - } - - @Test - public void testParseField() throws Exception { - checkFields("(15)991231(3103)001750(10)12A"); - } - - @Test - public void testParseField2() throws Exception { - checkFields("(15)991231(15)991231(3103)001750(10)12A"); - } -} diff --git a/src/oned/rss/expanded/decoders/GeneralAppIdDecoder.java b/src/oned/rss/expanded/decoders/GeneralAppIdDecoder.java deleted file mode 100644 index 477684b..0000000 --- a/src/oned/rss/expanded/decoders/GeneralAppIdDecoder.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; - -/** - * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - */ -final class GeneralAppIdDecoder { - - private final BitArray information; - private final CurrentParsingState current = new CurrentParsingState(); - private final StringBuilder buffer = new StringBuilder(); - - GeneralAppIdDecoder(BitArray information) { - this.information = information; - } - - String decodeAllCodes(StringBuilder buff, int initialPosition) throws NotFoundException, FormatException { - int currentPosition = initialPosition; - String remaining = null; - do { - DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining); - String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString()); - if (parsedFields != null) { - buff.append(parsedFields); - } - if (info.isRemaining()) { - remaining = String.valueOf(info.getRemainingValue()); - } else { - remaining = null; - } - - if (currentPosition == info.getNewPosition()) { // No step forward! - break; - } - currentPosition = info.getNewPosition(); - } while (true); - - return buff.toString(); - } - - private boolean isStillNumeric(int pos) { - // It's numeric if it still has 7 positions - // and one of the first 4 bits is "1". - if (pos + 7 > this.information.getSize()) { - return pos + 4 <= this.information.getSize(); - } - - for (int i = pos; i < pos + 3; ++i) { - if (this.information.get(i)) { - return true; - } - } - - return this.information.get(pos + 3); - } - - private DecodedNumeric decodeNumeric(int pos) throws FormatException { - if (pos + 7 > this.information.getSize()) { - int numeric = extractNumericValueFromBitArray(pos, 4); - if (numeric == 0) { - return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1); - } - return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1); - } - int numeric = extractNumericValueFromBitArray(pos, 7); - - int digit1 = (numeric - 8) / 11; - int digit2 = (numeric - 8) % 11; - - return new DecodedNumeric(pos + 7, digit1, digit2); - } - - int extractNumericValueFromBitArray(int pos, int bits) { - return extractNumericValueFromBitArray(this.information, pos, bits); - } - - static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) { - int value = 0; - for (int i = 0; i < bits; ++i) { - if (information.get(pos + i)) { - value |= 1 << (bits - i - 1); - } - } - - return value; - } - - DecodedInformation decodeGeneralPurposeField(int pos, String remaining) throws FormatException { - this.buffer.setLength(0); - - if (remaining != null) { - this.buffer.append(remaining); - } - - this.current.setPosition(pos); - - DecodedInformation lastDecoded = parseBlocks(); - if (lastDecoded != null && lastDecoded.isRemaining()) { - return new DecodedInformation(this.current.getPosition(), - this.buffer.toString(), lastDecoded.getRemainingValue()); - } - return new DecodedInformation(this.current.getPosition(), this.buffer.toString()); - } - - private DecodedInformation parseBlocks() throws FormatException { - boolean isFinished; - BlockParsedRXingResult result; - do { - int initialPosition = current.getPosition(); - - if (current.isAlpha()) { - result = parseAlphaBlock(); - isFinished = result.isFinished(); - } else if (current.isIsoIec646()) { - result = parseIsoIec646Block(); - isFinished = result.isFinished(); - } else { // it must be numeric - result = parseNumericBlock(); - isFinished = result.isFinished(); - } - - boolean positionChanged = initialPosition != current.getPosition(); - if (!positionChanged && !isFinished) { - break; - } - } while (!isFinished); - - return result.getDecodedInformation(); - } - - private BlockParsedRXingResult parseNumericBlock() throws FormatException { - while (isStillNumeric(current.getPosition())) { - DecodedNumeric numeric = decodeNumeric(current.getPosition()); - current.setPosition(numeric.getNewPosition()); - - if (numeric.isFirstDigitFNC1()) { - DecodedInformation information; - if (numeric.isSecondDigitFNC1()) { - information = new DecodedInformation(current.getPosition(), buffer.toString()); - } else { - information = new DecodedInformation(current.getPosition(), buffer.toString(), numeric.getSecondDigit()); - } - return new BlockParsedRXingResult(information, true); - } - buffer.append(numeric.getFirstDigit()); - - if (numeric.isSecondDigitFNC1()) { - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedRXingResult(information, true); - } - buffer.append(numeric.getSecondDigit()); - } - - if (isNumericToAlphaNumericLatch(current.getPosition())) { - current.setAlpha(); - current.incrementPosition(4); - } - return new BlockParsedRXingResult(); - } - - private BlockParsedRXingResult parseIsoIec646Block() throws FormatException { - while (isStillIsoIec646(current.getPosition())) { - DecodedChar iso = decodeIsoIec646(current.getPosition()); - current.setPosition(iso.getNewPosition()); - - if (iso.isFNC1()) { - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedRXingResult(information, true); - } - buffer.append(iso.getValue()); - } - - if (isAlphaOr646ToNumericLatch(current.getPosition())) { - current.incrementPosition(3); - current.setNumeric(); - } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) { - if (current.getPosition() + 5 < this.information.getSize()) { - current.incrementPosition(5); - } else { - current.setPosition(this.information.getSize()); - } - - current.setAlpha(); - } - return new BlockParsedRXingResult(); - } - - private BlockParsedRXingResult parseAlphaBlock() { - while (isStillAlpha(current.getPosition())) { - DecodedChar alpha = decodeAlphanumeric(current.getPosition()); - current.setPosition(alpha.getNewPosition()); - - if (alpha.isFNC1()) { - DecodedInformation information = new DecodedInformation(current.getPosition(), buffer.toString()); - return new BlockParsedRXingResult(information, true); //end of the char block - } - - buffer.append(alpha.getValue()); - } - - if (isAlphaOr646ToNumericLatch(current.getPosition())) { - current.incrementPosition(3); - current.setNumeric(); - } else if (isAlphaTo646ToAlphaLatch(current.getPosition())) { - if (current.getPosition() + 5 < this.information.getSize()) { - current.incrementPosition(5); - } else { - current.setPosition(this.information.getSize()); - } - - current.setIsoIec646(); - } - return new BlockParsedRXingResult(); - } - - private boolean isStillIsoIec646(int pos) { - if (pos + 5 > this.information.getSize()) { - return false; - } - - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue >= 5 && fiveBitValue < 16) { - return true; - } - - if (pos + 7 > this.information.getSize()) { - return false; - } - - int sevenBitValue = extractNumericValueFromBitArray(pos, 7); - if (sevenBitValue >= 64 && sevenBitValue < 116) { - return true; - } - - if (pos + 8 > this.information.getSize()) { - return false; - } - - int eightBitValue = extractNumericValueFromBitArray(pos, 8); - return eightBitValue >= 232 && eightBitValue < 253; - - } - - private DecodedChar decodeIsoIec646(int pos) throws FormatException { - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue == 15) { - return new DecodedChar(pos + 5, DecodedChar.FNC1); - } - - if (fiveBitValue >= 5 && fiveBitValue < 15) { - return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5)); - } - - int sevenBitValue = extractNumericValueFromBitArray(pos, 7); - - if (sevenBitValue >= 64 && sevenBitValue < 90) { - return new DecodedChar(pos + 7, (char) (sevenBitValue + 1)); - } - - if (sevenBitValue >= 90 && sevenBitValue < 116) { - return new DecodedChar(pos + 7, (char) (sevenBitValue + 7)); - } - - int eightBitValue = extractNumericValueFromBitArray(pos, 8); - char c; - switch (eightBitValue) { - case 232: - c = '!'; - break; - case 233: - c = '"'; - break; - case 234: - c = '%'; - break; - case 235: - c = '&'; - break; - case 236: - c = '\''; - break; - case 237: - c = '('; - break; - case 238: - c = ')'; - break; - case 239: - c = '*'; - break; - case 240: - c = '+'; - break; - case 241: - c = ','; - break; - case 242: - c = '-'; - break; - case 243: - c = '.'; - break; - case 244: - c = '/'; - break; - case 245: - c = ':'; - break; - case 246: - c = ';'; - break; - case 247: - c = '<'; - break; - case 248: - c = '='; - break; - case 249: - c = '>'; - break; - case 250: - c = '?'; - break; - case 251: - c = '_'; - break; - case 252: - c = ' '; - break; - default: - throw FormatException.getFormatInstance(); - } - return new DecodedChar(pos + 8, c); - } - - private boolean isStillAlpha(int pos) { - if (pos + 5 > this.information.getSize()) { - return false; - } - - // We now check if it's a valid 5-bit value (0..9 and FNC1) - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue >= 5 && fiveBitValue < 16) { - return true; - } - - if (pos + 6 > this.information.getSize()) { - return false; - } - - int sixBitValue = extractNumericValueFromBitArray(pos, 6); - return sixBitValue >= 16 && sixBitValue < 63; // 63 not included - } - - private DecodedChar decodeAlphanumeric(int pos) { - int fiveBitValue = extractNumericValueFromBitArray(pos, 5); - if (fiveBitValue == 15) { - return new DecodedChar(pos + 5, DecodedChar.FNC1); - } - - if (fiveBitValue >= 5 && fiveBitValue < 15) { - return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5)); - } - - int sixBitValue = extractNumericValueFromBitArray(pos, 6); - - if (sixBitValue >= 32 && sixBitValue < 58) { - return new DecodedChar(pos + 6, (char) (sixBitValue + 33)); - } - - char c; - switch (sixBitValue) { - case 58: - c = '*'; - break; - case 59: - c = ','; - break; - case 60: - c = '-'; - break; - case 61: - c = '.'; - break; - case 62: - c = '/'; - break; - default: - throw new IllegalStateException("Decoding invalid alphanumeric value: " + sixBitValue); - } - return new DecodedChar(pos + 6, c); - } - - private boolean isAlphaTo646ToAlphaLatch(int pos) { - if (pos + 1 > this.information.getSize()) { - return false; - } - - for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) { - if (i == 2) { - if (!this.information.get(pos + 2)) { - return false; - } - } else if (this.information.get(pos + i)) { - return false; - } - } - - return true; - } - - private boolean isAlphaOr646ToNumericLatch(int pos) { - // Next is alphanumeric if there are 3 positions and they are all zeros - if (pos + 3 > this.information.getSize()) { - return false; - } - - for (int i = pos; i < pos + 3; ++i) { - if (this.information.get(i)) { - return false; - } - } - return true; - } - - private boolean isNumericToAlphaNumericLatch(int pos) { - // Next is alphanumeric if there are 4 positions and they are all zeros, or - // if there is a subset of this just before the end of the symbol - if (pos + 1 > this.information.getSize()) { - return false; - } - - for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) { - if (this.information.get(pos + i)) { - return false; - } - } - return true; - } -} diff --git a/src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs b/src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs new file mode 100644 index 0000000..d531e27 --- /dev/null +++ b/src/oned/rss/expanded/decoders/abstract_expanded_decoder.rs @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use crate::{Exceptions, common::BitArray}; + +use super::GeneralAppIdDecoder; + + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ + + +pub trait AbstractExpandedDecoder { + + // private final BitArray information; + // private final GeneralAppIdDecoder generalDecoder; + + // AbstractExpandedDecoder(BitArray information) { + // this.information = information; + // this.generalDecoder = new GeneralAppIdDecoder(information); + // } + + // protected final BitArray getInformation() { + // return information; + // } + + // protected final GeneralAppIdDecoder getGeneralDecoder() { + // return generalDecoder; + // } + + fn parseInformation(&mut self) -> Result; + fn getGeneralDecoder(&self) -> &GeneralAppIdDecoder; + // fn new(information:&BitArray) -> Self where Self:Sized; +} + +// pub fn createDecoder( information:&BitArray) -> Box{ +// if information.get(1) { +// return new AI01AndOtherAIs(information); +// } +// if !information.get(2) { +// return new AnyAIDecoder(information); +// } + +// let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4); + +// switch (fourBitEncodationMethod) { +// case 4: return new AI013103decoder(information); +// case 5: return new AI01320xDecoder(information); +// } + +// int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5); +// switch (fiveBitEncodationMethod) { +// case 12: return new AI01392xDecoder(information); +// case 13: return new AI01393xDecoder(information); +// } + +// int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7); +// switch (sevenBitEncodationMethod) { +// case 56: return new AI013x0x1xDecoder(information, "310", "11"); +// case 57: return new AI013x0x1xDecoder(information, "320", "11"); +// case 58: return new AI013x0x1xDecoder(information, "310", "13"); +// case 59: return new AI013x0x1xDecoder(information, "320", "13"); +// case 60: return new AI013x0x1xDecoder(information, "310", "15"); +// case 61: return new AI013x0x1xDecoder(information, "320", "15"); +// case 62: return new AI013x0x1xDecoder(information, "310", "17"); +// case 63: return new AI013x0x1xDecoder(information, "320", "17"); +// } + +// throw new IllegalStateException("unknown decoder: " + information); +// } \ No newline at end of file diff --git a/src/oned/rss/expanded/decoders/AI01AndOtherAIs.java b/src/oned/rss/expanded/decoders/ai_01_and_other_ais.rs similarity index 50% rename from src/oned/rss/expanded/decoders/AI01AndOtherAIs.java rename to src/oned/rss/expanded/decoders/ai_01_and_other_ais.rs index 27222a3..0648009 100644 --- a/src/oned/rss/expanded/decoders/AI01AndOtherAIs.java +++ b/src/oned/rss/expanded/decoders/ai_01_and_other_ais.rs @@ -24,35 +24,42 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; +use crate::common::BitArray; -import com.google.zxing.FormatException; -import com.google.zxing.NotFoundException; -import com.google.zxing.common.BitArray; +use super::{AI01decoder, AbstractExpandedDecoder, GeneralAppIdDecoder}; /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) */ -final class AI01AndOtherAIs extends AI01decoder { +pub struct AI01AndOtherAIs<'a>(&'a BitArray,GeneralAppIdDecoder<'a>); +impl<'a> AI01decoder for AI01AndOtherAIs<'_> {} +impl AbstractExpandedDecoder for AI01AndOtherAIs<'_> { + fn parseInformation(&mut self) -> Result { + let mut buff = String::new();//new StringBuilder(); - private static final int HEADER_SIZE = 1 + 1 + 2; //first bit encodes the linkage flag, - //the second one is the encodation method, and the other two are for the variable length - AI01AndOtherAIs(BitArray information) { - super(information); - } + buff.push_str("(01)"); + let initialGtinPosition = buff.chars().count(); + let firstGtinDigit = self.getGeneralDecoder().extractNumericValueFromBitArray(Self::HEADER_SIZE, 4); + buff.push_str(&firstGtinDigit.to_string()); + + self.encodeCompressedGtinWithoutAI(&mut buff, Self::HEADER_SIZE + 4, initialGtinPosition); + + self.1.decodeAllCodes(buff, Self::HEADER_SIZE + 44) + } - @Override - public String parseInformation() throws NotFoundException, FormatException { - StringBuilder buff = new StringBuilder(); - - buff.append("(01)"); - int initialGtinPosition = buff.length(); - int firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(HEADER_SIZE, 4); - buff.append(firstGtinDigit); - - this.encodeCompressedGtinWithoutAI(buff, HEADER_SIZE + 4, initialGtinPosition); - - return this.getGeneralDecoder().decodeAllCodes(buff, HEADER_SIZE + 44); - } + fn getGeneralDecoder(&self) -> &super::GeneralAppIdDecoder { + &self.1 + } +} +impl<'a> AI01AndOtherAIs<'_> { + fn new(information:&'a BitArray) -> AI01AndOtherAIs<'a> { + AI01AndOtherAIs( information,GeneralAppIdDecoder::new(information)) +} + + const HEADER_SIZE : usize = 1 + 1 + 2; //first bit encodes the linkage flag, + //the second one is the encodation method, and the other two are for the variable length + // AI01AndOtherAIs(BitArray information) { + // super(information); + // } } diff --git a/src/oned/rss/expanded/decoders/AI01decoder.java b/src/oned/rss/expanded/decoders/ai_01_decoder.rs similarity index 50% rename from src/oned/rss/expanded/decoders/AI01decoder.java rename to src/oned/rss/expanded/decoders/ai_01_decoder.rs index 0034500..4e9e52e 100644 --- a/src/oned/rss/expanded/decoders/AI01decoder.java +++ b/src/oned/rss/expanded/decoders/ai_01_decoder.rs @@ -24,58 +24,57 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; +use super::AbstractExpandedDecoder; -import com.google.zxing.common.BitArray; /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) */ -abstract class AI01decoder extends AbstractExpandedDecoder { +pub trait AI01decoder : AbstractExpandedDecoder { - static final int GTIN_SIZE = 40; + const GTIN_SIZE : u32 = 40; - AI01decoder(BitArray information) { - super(information); + fn encodeCompressedGtin(&self, buf:&mut String, currentPos:usize) { + buf.push_str("(01)"); + let initialPosition = buf.chars().count(); + buf.push('9'); + + self.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition); } - final void encodeCompressedGtin(StringBuilder buf, int currentPos) { - buf.append("(01)"); - int initialPosition = buf.length(); - buf.append('9'); - - encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition); - } - - final void encodeCompressedGtinWithoutAI(StringBuilder buf, int currentPos, int initialBufferPosition) { - for (int i = 0; i < 4; ++i) { - int currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10); - if (currentBlock / 100 == 0) { - buf.append('0'); + fn encodeCompressedGtinWithoutAI(&self, buf:&mut String, currentPos:usize, initialBufferPosition:usize) { + for i in 0..4 { + // for (int i = 0; i < 4; ++i) { + let currentBlock = self.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10); + if currentBlock / 100 == 0 { + buf.push('0'); } - if (currentBlock / 10 == 0) { - buf.append('0'); + if currentBlock / 10 == 0 { + buf.push('0'); } - buf.append(currentBlock); + buf.push_str(¤tBlock.to_string()); } appendCheckDigit(buf, initialBufferPosition); } - private static void appendCheckDigit(StringBuilder buf, int currentPos) { - int checkDigit = 0; - for (int i = 0; i < 13; i++) { - int digit = buf.charAt(i + currentPos) - '0'; - checkDigit += (i & 0x01) == 0 ? 3 * digit : digit; - } - - checkDigit = 10 - (checkDigit % 10); - if (checkDigit == 10) { - checkDigit = 0; - } - - buf.append(checkDigit); - } + } + +pub(super) fn appendCheckDigit( buf:&mut String, currentPos:usize) { + let mut checkDigit = 0; + for i in 0..13 { + // for (int i = 0; i < 13; i++) { + let digit = buf.chars().nth(i + currentPos).unwrap() as u32 - '0' as u32; + checkDigit += if (i & 0x01) == 0 {3 * digit} else {digit}; + } + + checkDigit = 10 - (checkDigit % 10); + if checkDigit == 10 { + checkDigit = 0; + } + + buf.push_str(&checkDigit.to_string()); +} \ No newline at end of file diff --git a/src/oned/rss/expanded/decoders/BlockParsedResult.java b/src/oned/rss/expanded/decoders/block_parsed_result.rs similarity index 64% rename from src/oned/rss/expanded/decoders/BlockParsedResult.java rename to src/oned/rss/expanded/decoders/block_parsed_result.rs index c6744ac..f0fd4b9 100644 --- a/src/oned/rss/expanded/decoders/BlockParsedResult.java +++ b/src/oned/rss/expanded/decoders/block_parsed_result.rs @@ -24,31 +24,33 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; +use super::DecodedInformation; /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) */ -final class BlockParsedRXingResult { - - private final DecodedInformation decodedInformation; - private final boolean finished; - - BlockParsedRXingResult() { - this(null, false); - } - - BlockParsedRXingResult(DecodedInformation information, boolean finished) { - this.finished = finished; - this.decodedInformation = information; - } - - DecodedInformation getDecodedInformation() { - return this.decodedInformation; - } - - boolean isFinished() { - return this.finished; - } +pub struct BlockParsedRXingResult { + decodedInformation: Option, + finished: bool, +} +impl BlockParsedRXingResult { + pub fn new() -> Self { + Self::with_information(None, false) + } + + pub fn with_information(information: Option, finished: bool) -> Self { + Self { + decodedInformation: information, + finished, + } + } + + pub fn getDecodedInformation(&self) -> &Option { + &self.decodedInformation + } + + pub fn isFinished(&self) -> bool { + self.finished + } } diff --git a/src/oned/rss/expanded/decoders/CurrentParsingState.java b/src/oned/rss/expanded/decoders/current_parsing_state.rs similarity index 50% rename from src/oned/rss/expanded/decoders/CurrentParsingState.java rename to src/oned/rss/expanded/decoders/current_parsing_state.rs index 34e92e1..9f0e236 100644 --- a/src/oned/rss/expanded/decoders/CurrentParsingState.java +++ b/src/oned/rss/expanded/decoders/current_parsing_state.rs @@ -23,61 +23,62 @@ * * http://www.piramidepse.com/ */ - -package com.google.zxing.oned.rss.expanded.decoders; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum State { + NUMERIC, + ALPHA, + ISO_IEC_646, +} /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) */ -final class CurrentParsingState { - - private int position; - private State encoding; - - private enum State { - NUMERIC, - ALPHA, - ISO_IEC_646 - } - - CurrentParsingState() { - this.position = 0; - this.encoding = State.NUMERIC; - } - - int getPosition() { - return position; - } - - void setPosition(int position) { - this.position = position; - } - - void incrementPosition(int delta) { - position += delta; - } - - boolean isAlpha() { - return this.encoding == State.ALPHA; - } - - boolean isNumeric() { - return this.encoding == State.NUMERIC; - } - - boolean isIsoIec646() { - return this.encoding == State.ISO_IEC_646; - } - - void setNumeric() { - this.encoding = State.NUMERIC; - } - - void setAlpha() { - this.encoding = State.ALPHA; - } - - void setIsoIec646() { - this.encoding = State.ISO_IEC_646; - } +pub struct CurrentParsingState { + position: usize, + encoding: State, +} + +impl CurrentParsingState { + pub fn new() -> Self { + Self { + position: 0, + encoding: State::NUMERIC, + } + } + + pub fn getPosition(&self) -> usize { + self.position + } + + pub fn setPosition(&mut self, position: usize) { + self.position = position + } + + pub fn incrementPosition(&mut self, delta: usize) { + self.position += delta; + } + + pub fn isAlpha(&self) -> bool { + self.encoding == State::ALPHA + } + + pub fn isNumeric(&self) -> bool { + self.encoding == State::NUMERIC + } + + pub fn isIsoIec646(&self) -> bool { + self.encoding == State::ISO_IEC_646 + } + + pub fn setNumeric(&mut self) { + self.encoding = State::NUMERIC; + } + + pub fn setAlpha(&mut self) { + self.encoding = State::ALPHA; + } + + pub fn setIsoIec646(&mut self) { + self.encoding = State::ISO_IEC_646; + } } diff --git a/src/oned/rss/expanded/decoders/DecodedChar.java b/src/oned/rss/expanded/decoders/decoded_char.rs similarity index 68% rename from src/oned/rss/expanded/decoders/DecodedChar.java rename to src/oned/rss/expanded/decoders/decoded_char.rs index 2dd8995..6f730ff 100644 --- a/src/oned/rss/expanded/decoders/DecodedChar.java +++ b/src/oned/rss/expanded/decoders/decoded_char.rs @@ -24,29 +24,33 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; +use super::DecodedObject; /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) */ -final class DecodedChar extends DecodedObject { - - private final char value; - - static final char FNC1 = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset - - DecodedChar(int newPosition, char value) { - super(newPosition); - this.value = value; - } - - char getValue() { - return this.value; - } - - boolean isFNC1() { - return this.value == FNC1; - } - +pub struct DecodedChar { + value: char, + newPosition: usize, +} +impl DecodedObject for DecodedChar { + fn getNewPosition(&self) -> usize { + self.newPosition + } +} +impl DecodedChar { + pub const FNC1: char = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset + + pub fn new(newPosition: usize, value: char) -> Self { + Self { value, newPosition } + } + + pub fn getValue(&self) -> char { + self.value + } + + pub fn isFNC1(&self) -> bool { + self.value == Self::FNC1 + } } diff --git a/src/oned/rss/expanded/decoders/DecodedNumeric.java b/src/oned/rss/expanded/decoders/decoded_information.rs similarity index 53% rename from src/oned/rss/expanded/decoders/DecodedNumeric.java rename to src/oned/rss/expanded/decoders/decoded_information.rs index 7b8f25a..5b48dce 100644 --- a/src/oned/rss/expanded/decoders/DecodedNumeric.java +++ b/src/oned/rss/expanded/decoders/decoded_information.rs @@ -24,50 +24,57 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; - -import com.google.zxing.FormatException; +use super::DecodedObject; /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) */ -final class DecodedNumeric extends DecodedObject { +#[derive(Clone)] +pub struct DecodedInformation { + newPosition: usize, + newString: String, + remainingValue: u32, + remaining: bool, +} - private final int firstDigit; - private final int secondDigit; - - static final int FNC1 = 10; - - DecodedNumeric(int newPosition, int firstDigit, int secondDigit) throws FormatException { - super(newPosition); - - if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) { - throw FormatException.getFormatInstance(); +impl DecodedObject for DecodedInformation { + fn getNewPosition(&self) -> usize { + self.newPosition + } +} +impl DecodedInformation { + pub fn new(newPosition: usize, newString: String) -> Self { + Self { + newPosition, + newString, + remainingValue: 0, + remaining: false, + } } - this.firstDigit = firstDigit; - this.secondDigit = secondDigit; - } + pub fn with_remaining_value( + newPosition: usize, + newString: String, + remainingValue: u32, + ) -> Self { + Self { + newPosition, + newString, + remainingValue, + remaining: true, + } + } - int getFirstDigit() { - return this.firstDigit; - } + pub fn getNewString(&self) -> &str { + &self.newString + } - int getSecondDigit() { - return this.secondDigit; - } - - int getValue() { - return this.firstDigit * 10 + this.secondDigit; - } - - boolean isFirstDigitFNC1() { - return this.firstDigit == FNC1; - } - - boolean isSecondDigitFNC1() { - return this.secondDigit == FNC1; - } + pub fn isRemaining(&self) -> bool { + self.remaining + } + pub fn getRemainingValue(&self) -> u32 { + self.remainingValue + } } diff --git a/src/oned/rss/expanded/decoders/decoded_numeric.rs b/src/oned/rss/expanded/decoders/decoded_numeric.rs new file mode 100644 index 0000000..1e2e993 --- /dev/null +++ b/src/oned/rss/expanded/decoders/decoded_numeric.rs @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use crate::Exceptions; + +use super::DecodedObject; + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ +pub struct DecodedNumeric { + newPosition: usize, + firstDigit: u32, + secondDigit: u32, +} +impl DecodedObject for DecodedNumeric { + fn getNewPosition(&self) -> usize { + self.newPosition + } +} +impl DecodedNumeric { + pub const FNC1: u32 = 10; + + pub fn new(newPosition: usize, firstDigit: u32, secondDigit: u32) -> Result { + // super(newPosition); + + if firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10 { + return Err(Exceptions::FormatException( + ".getFormatInstance();".to_owned(), + )); + } + + Ok(Self { + newPosition, + firstDigit, + secondDigit, + }) + } + + pub fn getFirstDigit(&self) -> u32 { + self.firstDigit + } + + pub fn getSecondDigit(&self) -> u32 { + self.secondDigit + } + + pub fn getValue(&self) -> u32 { + self.firstDigit * 10 + self.secondDigit + } + + pub fn isFirstDigitFNC1(&self) -> bool { + self.firstDigit == Self::FNC1 + } + + pub fn isSecondDigitFNC1(&self) -> bool { + self.secondDigit == Self::FNC1 + } +} diff --git a/src/oned/rss/expanded/decoders/DecodedObject.java b/src/oned/rss/expanded/decoders/decoded_object.rs similarity index 80% rename from src/oned/rss/expanded/decoders/DecodedObject.java rename to src/oned/rss/expanded/decoders/decoded_object.rs index cf7d7da..15816f7 100644 --- a/src/oned/rss/expanded/decoders/DecodedObject.java +++ b/src/oned/rss/expanded/decoders/decoded_object.rs @@ -24,21 +24,13 @@ * http://www.piramidepse.com/ */ -package com.google.zxing.oned.rss.expanded.decoders; + /** * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) */ -abstract class DecodedObject { +pub trait DecodedObject { - private final int newPosition; - - DecodedObject(int newPosition) { - this.newPosition = newPosition; - } - - final int getNewPosition() { - return this.newPosition; - } + fn getNewPosition(&self) -> usize; } diff --git a/src/oned/rss/expanded/decoders/field_parser.rs b/src/oned/rss/expanded/decoders/field_parser.rs new file mode 100644 index 0000000..ae67977 --- /dev/null +++ b/src/oned/rss/expanded/decoders/field_parser.rs @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use std::collections::HashMap; + +use crate::Exceptions; + +use lazy_static::lazy_static; + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ + +lazy_static! { + + static ref TWO_DIGIT_DATA_LENGTH : HashMap = { + let mut hm = HashMap::new(); + hm.insert("00".to_owned(), DataLength::fixed(18)); + hm.insert("01".to_owned(), DataLength::fixed(14)); + hm.insert("02".to_owned(), DataLength::fixed(14)); + hm.insert("10".to_owned(), DataLength::variable(20)); + hm.insert("11".to_owned(), DataLength::fixed(6)); + hm.insert("12".to_owned(), DataLength::fixed(6)); + hm.insert("13".to_owned(), DataLength::fixed(6)); + hm.insert("15".to_owned(), DataLength::fixed(6)); + hm.insert("17".to_owned(), DataLength::fixed(6)); + hm.insert("20".to_owned(), DataLength::fixed(2)); + hm.insert("21".to_owned(), DataLength::variable(20)); + hm.insert("22".to_owned(), DataLength::variable(29)); + hm.insert("30".to_owned(), DataLength::variable(8)); + hm.insert("37".to_owned(), DataLength::variable(8)); + //internal company codes + for i in 90..=99 { + // for (int i = 90; i <= 99; i++) { + hm.insert(i.to_string(), DataLength::variable(30)); + } + hm + }; + + static ref THREE_DIGIT_DATA_LENGTH : HashMap= + { + let mut hm = HashMap::new(); + hm.insert("240".to_owned(), DataLength::variable(30)); + hm.insert("241".to_owned(), DataLength::variable(30)); + hm.insert("242".to_owned(), DataLength::variable(6)); + hm.insert("250".to_owned(), DataLength::variable(30)); + hm.insert("251".to_owned(), DataLength::variable(30)); + hm.insert("253".to_owned(), DataLength::variable(17)); + hm.insert("254".to_owned(), DataLength::variable(20)); + hm.insert("400".to_owned(), DataLength::variable(30)); + hm.insert("401".to_owned(), DataLength::variable(30)); + hm.insert("402".to_owned(), DataLength::fixed(17)); + hm.insert("403".to_owned(), DataLength::variable(30)); + hm.insert("410".to_owned(), DataLength::fixed(13)); + hm.insert("411".to_owned(), DataLength::fixed(13)); + hm.insert("412".to_owned(), DataLength::fixed(13)); + hm.insert("413".to_owned(), DataLength::fixed(13)); + hm.insert("414".to_owned(), DataLength::fixed(13)); + hm.insert("420".to_owned(), DataLength::variable(20)); + hm.insert("421".to_owned(), DataLength::variable(15)); + hm.insert("422".to_owned(), DataLength::fixed(3)); + hm.insert("423".to_owned(), DataLength::variable(15)); + hm.insert("424".to_owned(), DataLength::fixed(3)); + hm.insert("425".to_owned(), DataLength::fixed(3)); + hm.insert("426".to_owned(), DataLength::fixed(3)); + + hm + }; + + static ref THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH:HashMap = { + let mut hm = HashMap::new(); + for i in 310..=316 { + // for (int i = 310; i <= 316; i++) { + hm.insert(i.to_string(), DataLength::fixed(6)); + } + for i in 320..=336 { + // for (int i = 320; i <= 336; i++) { + hm.insert(i.to_string(), DataLength::fixed(6)); + } + for i in 340..=357 { + // for (int i = 340; i <= 357; i++) { + hm.insert(i.to_string(), DataLength::fixed(6)); + } + for i in 360..=369 { + // for (int i = 360; i <= 369; i++) { + hm.insert(i.to_string(), DataLength::fixed(6)); + } + hm.insert("390".to_owned(), DataLength::variable(15)); + hm.insert("391".to_owned(), DataLength::variable(18)); + hm.insert("392".to_owned(), DataLength::variable(15)); + hm.insert("393".to_owned(), DataLength::variable(18)); + hm.insert("703".to_owned(), DataLength::variable(30)); + + hm + }; + + static ref FOUR_DIGIT_DATA_LENGTH : HashMap={ + let mut hm = HashMap::new(); + hm.insert("7001".to_owned(), DataLength::fixed(13)); + hm.insert("7002".to_owned(), DataLength::variable(30)); + hm.insert("7003".to_owned(), DataLength::fixed(10)); + hm.insert("8001".to_owned(), DataLength::fixed(14)); + hm.insert("8002".to_owned(), DataLength::variable(20)); + hm.insert("8003".to_owned(), DataLength::variable(30)); + hm.insert("8004".to_owned(), DataLength::variable(30)); + hm.insert("8005".to_owned(), DataLength::fixed(6)); + hm.insert("8006".to_owned(), DataLength::fixed(18)); + hm.insert("8007".to_owned(), DataLength::variable(30)); + hm.insert("8008".to_owned(), DataLength::variable(12)); + hm.insert("8018".to_owned(), DataLength::fixed(18)); + hm.insert("8020".to_owned(), DataLength::variable(25)); + hm.insert("8100".to_owned(), DataLength::fixed(6)); + hm.insert("8101".to_owned(), DataLength::fixed(10)); + hm.insert("8102".to_owned(), DataLength::fixed(2)); + hm.insert("8110".to_owned(), DataLength::variable(70)); + hm.insert("8200".to_owned(), DataLength::variable(70)); + + hm + }; +} + +pub fn parseFieldsInGeneralPurpose(rawInformation: &str) -> Result { + if rawInformation.is_empty() { + return Ok("".to_owned()); + } + + // Processing 2-digit AIs + + if rawInformation.chars().count() < 2 { + return Err(Exceptions::NotFoundException("".to_owned())); + } + + let lookup: String = rawInformation.chars().take(2).collect(); + let twoDigitDataLength = TWO_DIGIT_DATA_LENGTH.get(&lookup); + if let Some(tddl) = twoDigitDataLength { + if tddl.variable { + return processVariableAI(2, tddl.length, rawInformation); + } + return processFixedAI(2, tddl.length, rawInformation); + } + + if rawInformation.chars().count() < 3 { + return Err(Exceptions::NotFoundException("".to_owned())); + } + + let firstThreeDigits: String = rawInformation.chars().take(3).collect(); //rawInformation.substring(0, 3); + let threeDigitDataLength = THREE_DIGIT_DATA_LENGTH.get(&firstThreeDigits); + if let Some(tddl) = threeDigitDataLength { + if tddl.variable { + return processVariableAI(3, tddl.length, rawInformation); + } + return processFixedAI(3, tddl.length, rawInformation); + } + + if rawInformation.chars().count() < 4 { + return Err(Exceptions::NotFoundException("".to_owned())); + } + + let threeDigitPlusDigitDataLength = THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.get(&firstThreeDigits); + if let Some(tdpddl) = threeDigitPlusDigitDataLength { + if tdpddl.variable { + return processVariableAI(4, tdpddl.length, rawInformation); + } + return processFixedAI(4, tdpddl.length, rawInformation); + } + + let lookup: String = rawInformation.chars().take(4).collect(); + let firstFourDigitLength = FOUR_DIGIT_DATA_LENGTH.get(&lookup /*(0, 4)*/); + if let Some(ffdl) = firstFourDigitLength { + if ffdl.variable { + return processVariableAI(4, ffdl.length, rawInformation); + } + return processFixedAI(4, ffdl.length, rawInformation); + } + + return Err(Exceptions::NotFoundException("".to_owned())); +} + +fn processFixedAI( + aiSize: usize, + fieldSize: usize, + rawInformation: &str, +) -> Result { + if rawInformation.chars().count() < aiSize { + return Err(Exceptions::NotFoundException("".to_owned())); + } + + let ai: String = rawInformation.chars().take(aiSize).collect(); + + if rawInformation.chars().count() < aiSize + fieldSize { + return Err(Exceptions::NotFoundException("".to_owned())); + } + + let field: String = rawInformation + .chars() + .skip(aiSize) + .take(fieldSize) + .collect(); //rawInformation.substring(aiSize, aiSize + fieldSize); + let remaining: String = rawInformation.chars().skip(aiSize + fieldSize).collect(); // rawInformation.substring(aiSize + fieldSize); + let result = format!("({}){}", ai, field); + let parsedAI = parseFieldsInGeneralPurpose(&remaining)?; + + Ok(if parsedAI.is_empty() { + result + } else { + format!("{}{}", result, parsedAI) + }) +} + +fn processVariableAI( + aiSize: usize, + variableFieldSize: usize, + rawInformation: &str, +) -> Result { + let ai: String = rawInformation.chars().take(aiSize as usize).collect(); //rawInformation.substring(0, aiSize); + let maxSize = rawInformation + .chars() + .count() + .min(aiSize + variableFieldSize); + let field: String = rawInformation + .chars() + .skip(aiSize as usize) + .take(maxSize) + .collect(); // (aiSize, maxSize); + let remaining: String = rawInformation.chars().skip(maxSize).collect(); + let result = format!("({}){}", ai, field); //'(' + ai + ')' + field; + let parsedAI = parseFieldsInGeneralPurpose(&remaining)?; + + Ok(if parsedAI.is_empty() { + result + } else { + format!("{}{}", result, parsedAI) + }) +} + +struct DataLength { + pub variable: bool, + pub length: usize, +} +impl DataLength { + // fn new( variable:bool, length:u32) -> Self{ + // Self(variable,length) + // } + + pub fn fixed(length: usize) -> Self { + Self { + variable: false, + length, + } + } + + pub fn variable(length: usize) -> Self { + Self { + variable: true, + length, + } + } +} + + + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ +#[cfg(test)] + mod FieldParserTest { + + fn checkFields( expected:&str) { + let field = expected.replace("(", "").replace(")",""); + let actual = super::parseFieldsInGeneralPurpose(&field).expect("parse"); + assert_eq!(expected, actual); + } + + #[test] + fn testParseField() { + checkFields("(15)991231(3103)001750(10)12A"); + } + + #[test] + fn testParseField2() { + checkFields("(15)991231(15)991231(3103)001750(10)12A"); + } +} diff --git a/src/oned/rss/expanded/decoders/general_app_id_decoder.rs b/src/oned/rss/expanded/decoders/general_app_id_decoder.rs new file mode 100644 index 0000000..c1af427 --- /dev/null +++ b/src/oned/rss/expanded/decoders/general_app_id_decoder.rs @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use crate::{common::BitArray, Exceptions}; + +use super::{CurrentParsingState, DecodedChar, DecodedNumeric, DecodedInformation, BlockParsedRXingResult, DecodedObject, field_parser}; + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) + */ +pub struct GeneralAppIdDecoder<'a> { + + information:&'a BitArray, + current : CurrentParsingState, //= new CurrentParsingState(); + buffer :String, //= new StringBuilder(); +} + +impl<'a> GeneralAppIdDecoder<'_> { + pub fn new( information:&'a BitArray) -> GeneralAppIdDecoder<'a>{ + GeneralAppIdDecoder{ + information, + current: CurrentParsingState::new(), + buffer: String::new(), + } + } + + pub fn decodeAllCodes(&mut self, buff:String, initialPosition:usize) -> Result { + let mut buff = buff; + let mut currentPosition = initialPosition; + let mut remaining = "".to_owned(); + loop { + let info = self.decodeGeneralPurposeField(currentPosition, &remaining)?; + let parsedFields =field_parser::parseFieldsInGeneralPurpose(info.getNewString())?; + if !parsedFields.is_empty() { + buff.push_str(&parsedFields); + } + if info.isRemaining() { + remaining = info.getRemainingValue().to_string(); + } else { + remaining = "".to_owned(); + } + + if currentPosition == info.getNewPosition() { // No step forward! + break; + } + currentPosition = info.getNewPosition(); + } + + Ok(buff) + } + + fn isStillNumeric(&self, pos:usize) -> bool{ + // It's numeric if it still has 7 positions + // and one of the first 4 bits is "1". + if pos + 7 > self.information.getSize() { + return pos + 4 <= self.information.getSize(); + } + + for i in pos..pos+3 { + // for (int i = pos; i < pos + 3; ++i) { + if self.information.get(i) { + return true; + } + } + + self.information.get(pos + 3) + } + + fn decodeNumeric(&self, pos:usize) -> Result { + if pos + 7 > self.information.getSize() { + let numeric = self.extractNumericValueFromBitArray(pos, 4); + if numeric == 0 { + return DecodedNumeric::new(self.information.getSize(), DecodedNumeric::FNC1, DecodedNumeric::FNC1); + } + return DecodedNumeric::new(self.information.getSize(), numeric - 1, DecodedNumeric::FNC1); + } + let numeric = self.extractNumericValueFromBitArray(pos, 7); + + let digit1 = (numeric - 8) / 11; + let digit2 = (numeric - 8) % 11; + + DecodedNumeric::new(pos + 7, digit1, digit2) + } + + pub fn extractNumericValueFromBitArray(&self, pos:usize, bits:u32) -> u32{ + Self::extractNumericValueFromBitArrayWithInformation(&self.information, pos, bits) + } + + pub fn extractNumericValueFromBitArrayWithInformation( information:&BitArray, pos:usize, bits:u32) ->u32{ + let mut value = 0; + for i in 0..bits { + // for (int i = 0; i < bits; ++i) { + if information.get(pos + i as usize) { + value |= 1 << (bits - i - 1); + } + } + + value + } + + pub fn decodeGeneralPurposeField(&mut self, pos:usize, remaining:&str) -> Result { + self.buffer.clear(); + + if !remaining.is_empty() { + self.buffer.push_str(remaining); + } + + self.current.setPosition(pos); + + if let Ok(lastDecoded) = self.parseBlocks(){ + if lastDecoded.isRemaining() { + return Ok(DecodedInformation::with_remaining_value(self.current.getPosition(), + self.buffer.clone(), lastDecoded.getRemainingValue())); + }} + Ok(DecodedInformation::new(self.current.getPosition(), self.buffer.clone())) + } + + fn parseBlocks(&mut self) -> Result { + let mut isFinished; + let mut result:BlockParsedRXingResult; + loop { + let initialPosition = self.current.getPosition(); + + if self.current.isAlpha() { + result =self. parseAlphaBlock()?; + isFinished = result.isFinished(); + } else if self.current.isIsoIec646() { + result = self.parseIsoIec646Block()?; + isFinished = result.isFinished(); + } else { // it must be numeric + result = self.parseNumericBlock()?; + isFinished = result.isFinished(); + } + + let positionChanged = initialPosition != self.current.getPosition(); + if !positionChanged && !isFinished { + break; + } + + if !(!isFinished) { break; } + } //while (!isFinished); + + Ok(result.getDecodedInformation().as_ref().unwrap().clone()) + } + + fn parseNumericBlock(&mut self) -> Result { + while self.isStillNumeric(self.current.getPosition()) { + let numeric = self.decodeNumeric(self.current.getPosition())?; + self.current.setPosition(numeric.getNewPosition()); + + if numeric.isFirstDigitFNC1() { + let information= + if numeric.isSecondDigitFNC1() { + DecodedInformation::new(self.current.getPosition(), self.buffer.clone()) + } else { + DecodedInformation::with_remaining_value(self.current.getPosition(), self.buffer.clone(), numeric.getSecondDigit()) + }; + return Ok(BlockParsedRXingResult::with_information(Some(information), true)); + } + self.buffer.push_str(&numeric.getFirstDigit().to_string()); + + if numeric.isSecondDigitFNC1() { + let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone()); + return Ok(BlockParsedRXingResult::with_information(Some(information), true)); + } + self.buffer.push_str(&numeric.getSecondDigit().to_string()); + } + + if self.isNumericToAlphaNumericLatch(self.current.getPosition()) { + self.current.setAlpha(); + self.current.incrementPosition(4); + } + + Ok(BlockParsedRXingResult::new()) + } + + fn parseIsoIec646Block(&mut self) -> Result { + while self.isStillIsoIec646(self.current.getPosition()) { + let iso = self.decodeIsoIec646(self.current.getPosition())?; + self.current.setPosition(iso.getNewPosition()); + + if iso.isFNC1() { + let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone()); + return Ok(BlockParsedRXingResult::with_information(Some(information), true)); + } + self.buffer.push_str(&iso.getValue().to_string()); + } + + if self.isAlphaOr646ToNumericLatch(self.current.getPosition()) { + self.current.incrementPosition(3); + self.current.setNumeric(); + } else if self.isAlphaTo646ToAlphaLatch(self.current.getPosition()) { + if self.current.getPosition() + 5 < self.information.getSize() { + self. current.incrementPosition(5); + } else { + self.current.setPosition(self.information.getSize()); + } + + self.current.setAlpha(); + } + Ok(BlockParsedRXingResult::new()) + } + + fn parseAlphaBlock(&mut self) -> Result { + while self.isStillAlpha(self.current.getPosition()) { + let alpha = self.decodeAlphanumeric(self.current.getPosition())?; + self.current.setPosition(alpha.getNewPosition()); + + if alpha.isFNC1() { + let information = DecodedInformation::new(self.current.getPosition(), self.buffer.clone()); + return Ok(BlockParsedRXingResult::with_information(Some(information), true)); //end of the char block + } + + self.buffer.push_str(&alpha.getValue().to_string()); + } + + if self.isAlphaOr646ToNumericLatch(self.current.getPosition()) { + self.current.incrementPosition(3); + self.current.setNumeric(); + } else if self.isAlphaTo646ToAlphaLatch(self.current.getPosition()) { + if self.current.getPosition() + 5 < self.information.getSize() { + self.current.incrementPosition(5); + } else { + self.current.setPosition(self.information.getSize()); + } + + self.current.setIsoIec646(); + } + + Ok(BlockParsedRXingResult::new()) + } + + fn isStillIsoIec646(&self, pos:usize) -> bool{ + if pos + 5 > self.information.getSize() { + return false; + } + + let fiveBitValue =self. extractNumericValueFromBitArray(pos, 5); + if fiveBitValue >= 5 && fiveBitValue < 16 { + return true; + } + + if pos + 7 > self.information.getSize() { + return false; + } + + let sevenBitValue = self.extractNumericValueFromBitArray(pos, 7); + if sevenBitValue >= 64 && sevenBitValue < 116 { + return true; + } + + if pos + 8 > self.information.getSize() { + return false; + } + + let eightBitValue = self.extractNumericValueFromBitArray(pos, 8); + + eightBitValue >= 232 && eightBitValue < 253 + + } + + fn decodeIsoIec646(&self, pos:usize) -> Result { + let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5); + if fiveBitValue == 15 { + return Ok(DecodedChar::new(pos + 5, DecodedChar::FNC1)); + } + + if fiveBitValue >= 5 && fiveBitValue < 15 { + return Ok(DecodedChar::new(pos + 5, char::from_u32 ('0' as u32 + fiveBitValue - 5).unwrap())); + } + + let sevenBitValue = self.extractNumericValueFromBitArray(pos, 7); + + if sevenBitValue >= 64 && sevenBitValue < 90 { + return Ok(DecodedChar::new(pos + 7, char::from_u32 (sevenBitValue + 1).unwrap())); + } + + if sevenBitValue >= 90 && sevenBitValue < 116 { + return Ok(DecodedChar::new(pos + 7, char::from_u32 (sevenBitValue + 7).unwrap())); + } + + let eightBitValue = self.extractNumericValueFromBitArray(pos, 8); + let c= + match eightBitValue { + 232=> + '!', + 233=> + '"', + 234=> + '%', + 235=> + '&', + 236=> + '\'', + 237=> + '(', + 238=> + ')', + 239=> + '*', + 240=> + '+', + 241=> + ',', + 242=> + '-', + 243=> + '.', + 244=> + '/', + 245=> + ':', + 246=> + ';', + 247=> + '<', + 248=> + '=', + 249=> + '>', + 250=> + '?', + 251=> + '_', + 252=> + ' ', + _=> + return Err(Exceptions::FormatException("".to_owned())), + }; + + Ok(DecodedChar::new(pos + 8, c)) + } + + fn isStillAlpha(&self, pos:usize) -> bool{ + if pos + 5 > self.information.getSize() { + return false; + } + + // We now check if it's a valid 5-bit value (0..9 and FNC1) + let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5); + if fiveBitValue >= 5 && fiveBitValue < 16 { + return true; + } + + if pos + 6 > self.information.getSize() { + return false; + } + + let sixBitValue = self.extractNumericValueFromBitArray(pos, 6); + + sixBitValue >= 16 && sixBitValue < 63 // 63 not included + } + + fn decodeAlphanumeric(&self, pos:usize) -> Result { + let fiveBitValue = self.extractNumericValueFromBitArray(pos, 5); + if fiveBitValue == 15 { + return Ok(DecodedChar::new(pos + 5, DecodedChar::FNC1)); + } + + if fiveBitValue >= 5 && fiveBitValue < 15 { + return Ok(DecodedChar::new(pos + 5, char::from_u32 ('0' as u32 + fiveBitValue - 5).unwrap())); + } + + let sixBitValue = self.extractNumericValueFromBitArray(pos, 6); + + if sixBitValue >= 32 && sixBitValue < 58 { + return Ok(DecodedChar::new(pos + 6, char::from_u32 (sixBitValue + 33).unwrap())); + } + + let c = + match sixBitValue { + 58=> + '*', + 59=> + ',', + 60=> + '-', + 61=> + '.', + 62=> + '/', + _=> + return Err(Exceptions::IllegalStateException(format!("Decoding invalid alphanumeric value: {}" , sixBitValue))), + }; + + Ok(DecodedChar::new(pos + 6, c)) + } + + fn isAlphaTo646ToAlphaLatch(&self, pos:usize)-> bool { + if pos + 1 > self.information.getSize() { + return false; + } + + let mut i = 0; + while i < 5 && i + pos < self.information.getSize() { + // for (int i = 0; i < 5 && i + pos < this.information.getSize(); ++i) { + if i == 2 { + if !self.information.get(pos + 2) { + return false; + } + } else if self.information.get(pos + i) { + return false; + } + + i+=1; + } + + true + } + + fn isAlphaOr646ToNumericLatch(&self, pos:usize) -> bool{ + // Next is alphanumeric if there are 3 positions and they are all zeros + if pos + 3 > self.information.getSize() { + return false; + } + + for i in pos..pos+3 { + // for (int i = pos; i < pos + 3; ++i) { + if self.information.get(i) { + return false; + } + } + + true + } + + fn isNumericToAlphaNumericLatch(&self, pos:usize) -> bool{ + // Next is alphanumeric if there are 4 positions and they are all zeros, or + // if there is a subset of this just before the end of the symbol + if pos + 1 > self.information.getSize() { + return false; + } + + let mut i = 0; + while i < 4 && pos < self.information.getSize() { + // for (int i = 0; i < 4 && i + pos < this.information.getSize(); ++i) { + if self.information.get(pos + i) { + return false; + } + i+=1; + } + + true + } +} diff --git a/src/oned/rss/expanded/decoders/mod.rs b/src/oned/rss/expanded/decoders/mod.rs index 8b13789..e010fd4 100644 --- a/src/oned/rss/expanded/decoders/mod.rs +++ b/src/oned/rss/expanded/decoders/mod.rs @@ -1 +1,27 @@ + +pub mod abstract_expanded_decoder; +pub use abstract_expanded_decoder::AbstractExpandedDecoder; +mod ai_01_and_other_ais; +pub use ai_01_and_other_ais::*; +mod ai_01_decoder; +pub use ai_01_decoder::*; +mod general_app_id_decoder; +pub use general_app_id_decoder::*; +mod current_parsing_state; +pub use current_parsing_state::*; +mod decoded_object; +pub use decoded_object::*; +mod decoded_char; +pub use decoded_char::*; + +mod decoded_information; +pub use decoded_information::*; + +mod decoded_numeric; +pub use decoded_numeric::*; + +mod block_parsed_result; +pub use block_parsed_result::*; + +pub mod field_parser; \ No newline at end of file diff --git a/src/oned/rss/expanded/expanded_pair.rs b/src/oned/rss/expanded/expanded_pair.rs new file mode 100644 index 0000000..1d51288 --- /dev/null +++ b/src/oned/rss/expanded/expanded_pair.rs @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * These authors would like to acknowledge the Spanish Ministry of Industry, + * Tourism and Trade, for the support in the project TSI020301-2008-2 + * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled + * Mobile Dynamic Environments", led by Treelogic + * ( http://www.treelogic.com/ ): + * + * http://www.piramidepse.com/ + */ + +use std::fmt::Display; + +use crate::oned::rss::{DataCharacter, FinderPattern}; + +/** + * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) + */ +#[derive(PartialEq, Eq, Hash)] +pub struct ExpandedPair { + leftChar: Option, + rightChar: Option, + finderPattern: Option, +} + +impl ExpandedPair { + pub fn new( + leftChar: Option, + rightChar: Option, + finderPattern: Option, + ) -> Self { + Self { + leftChar, + rightChar, + finderPattern, + } + } + + pub fn getLeftChar(&self) -> &Option { + &self.leftChar + } + + pub fn getRightChar(&self) -> &Option { + &self.rightChar + } + + pub fn getFinderPattern(&self) -> &Option { + &self.finderPattern + } + + pub fn mustBeLast(&self) -> bool { + self.rightChar.is_none() + } +} + +impl Display for ExpandedPair { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "[ {:?} , {:?} : {} ]", + self.leftChar, + self.rightChar, + if let Some(fp) = &self.finderPattern { + fp.getValue().to_string() + } else { + "null".to_owned() + } + ) + } +} diff --git a/src/oned/rss/expanded/mod.rs b/src/oned/rss/expanded/mod.rs index 819ec6e..1951a66 100644 --- a/src/oned/rss/expanded/mod.rs +++ b/src/oned/rss/expanded/mod.rs @@ -1 +1,7 @@ pub mod decoders; + +pub mod binary_util; +pub mod bit_array_builder; + +mod expanded_pair; +pub use expanded_pair::*; diff --git a/src/oned/rss/rss_14_reader.rs b/src/oned/rss/rss_14_reader.rs index d2ba498..cfe949f 100644 --- a/src/oned/rss/rss_14_reader.rs +++ b/src/oned/rss/rss_14_reader.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use crate::{ common::{detector::MathUtils, BitArray}, - oned::{OneDReader, one_d_reader}, + oned::{one_d_reader, OneDReader}, BarcodeFormat, DecodeHintType, DecodingHintDictionary, Exceptions, RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint, }; @@ -293,11 +293,10 @@ impl RSS14Reader { pattern: &FinderPattern, outsideChar: bool, ) -> Result { - let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters(); - //Arrays.fill(counters, 0); - // counters.fill(0); - counters.fill(0); - + let counters = &mut self.dataCharacterCounters; //[0_u32; 8]; //self.getDataCharacterCounters(); + //Arrays.fill(counters, 0); + // counters.fill(0); + counters.fill(0); if outsideChar { one_d_reader::recordPatternInReverse(row, pattern.getStartEnd()[0], &mut counters[..])?; @@ -305,7 +304,7 @@ impl RSS14Reader { one_d_reader::recordPattern(row, pattern.getStartEnd()[1], &mut counters[..])?; // reverse it let mut i = 0; - let mut j = counters.len() -1; + let mut j = counters.len() - 1; while i < j { // for (int i = 0, j = counters.length - 1; i < j; i++, j--) { let temp = counters[i]; @@ -468,13 +467,13 @@ impl RSS14Reader { let firstCounter = startEnd[0] - firstElementStart as usize; let mut counters = &mut self.decodeFinderCounters; let counter_len = counters.len(); - let slc = counters[0..counter_len-1].to_vec(); + let slc = counters[0..counter_len - 1].to_vec(); counters[1..counter_len].copy_from_slice(&slc); // Make 'counters' hold 1-4 // let counters = self.getDecodeFinderCounters(); // System.arraycopy(counters, 0, counters, 1, counters.length - 1); // counters.fill(0); - + counters[0] = firstCounter as u32; let value = Self::parseFinderValue(counters, &Self::FINDER_PATTERNS)?; let mut start = firstElementStart as usize; diff --git a/src/oned/upc_ean_reader.rs b/src/oned/upc_ean_reader.rs index cd2868c..1a5cd42 100644 --- a/src/oned/upc_ean_reader.rs +++ b/src/oned/upc_ean_reader.rs @@ -19,7 +19,7 @@ use crate::{ RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader, }; -use super::{EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport, one_d_reader}; +use super::{one_d_reader, EANManufacturerOrgSupport, OneDReader, UPCEANExtensionSupport}; use lazy_static::lazy_static; @@ -433,8 +433,11 @@ pub trait UPCEANReader: OneDReader { counters[counterPosition] += 1; } else { if counterPosition == patternLength - 1 { - if one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) - < MAX_AVG_VARIANCE + if one_d_reader::patternMatchVariance( + counters, + pattern, + MAX_INDIVIDUAL_VARIANCE, + ) < MAX_AVG_VARIANCE { return Ok([patternStart, x]); } @@ -483,7 +486,7 @@ pub trait UPCEANReader: OneDReader { // for (int i = 0; i < max; i++) { let pattern = &patterns[i]; let variance: f32 = - one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); + one_d_reader::patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); if variance < bestVariance { bestVariance = variance; bestMatch = i as isize; diff --git a/tests/rss_14_blackbox.rs b/tests/rss_14_blackbox.rs index ac45d3f..ed980ce 100644 --- a/tests/rss_14_blackbox.rs +++ b/tests/rss_14_blackbox.rs @@ -1,4 +1,3 @@ - /* * Copyright 2008 ZXing authors * @@ -15,15 +14,15 @@ * limitations under the License. */ - use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader}; +use rxing::{maxicode::MaxiCodeReader, BarcodeFormat, DecodeHintType, MultiFormatReader}; - mod common; - - /** - * @author Sean Owen - */ - #[test] - fn rss14_black_box1_test_case() { +mod common; + +/** + * @author Sean Owen + */ +#[test] +fn rss14_black_box1_test_case() { let mut tester = common::AbstractBlackBoxTestCase::new( "test_resources/blackbox/rss14-1", MultiFormatReader::default(), @@ -31,15 +30,13 @@ ); // super("src/test/resources/blackbox/rss14-1", new MultiFormatReader(), BarcodeFormat.RSS_14); - tester.add_test(6, 6, 0.0); - tester.add_test(6, 6, 180.0); + tester.add_test(6, 6, 0.0); + tester.add_test(6, 6, 180.0); - tester.test_black_box() - } - - + tester.test_black_box() +} - /** +/** * @author Sean Owen */ #[test] @@ -55,6 +52,4 @@ fn rss14_black_box2_test_case() { tester.add_test_complex(3, 8, 0, 1, 180.0); tester.test_black_box() - } - - \ No newline at end of file +}