From 9f7a41f81cf6a1c61cd680c99537a95da1a6ba0b Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Tue, 10 Jan 2023 14:33:47 -0600 Subject: [PATCH] many small rustifications --- src/aztec/AztecDetectorResult.rs | 4 +- src/aztec/DecoderTest.rs | 10 +-- src/aztec/EncoderTest.rs | 12 ++-- src/aztec/aztec_writer.rs | 2 +- src/aztec/detector.rs | 58 ++++++++--------- src/aztec/encoder/encoder.rs | 64 +++++++++++-------- src/common/bit_array.rs | 9 +-- src/common/bit_matrix.rs | 53 ++++++++------- src/common/default_grid_sampler.rs | 3 +- src/common/detector/MathUtils.rs | 15 +++-- .../detector/monochrome_rectangle_detector.rs | 24 ++++--- .../detector/white_rectangle_detector.rs | 29 +++++---- src/common/minimal_eci_input.rs | 37 +++++------ src/common/perspective_transform.rs | 11 ++-- src/datamatrix/decoder/data_block.rs | 7 +- .../decoder/decoded_bit_stream_parser.rs | 12 ++-- src/datamatrix/decoder/decoder.rs | 8 +-- src/datamatrix/decoder/version.rs | 21 ++++-- src/datamatrix/detector/detector.rs | 4 +- src/qrcode/decoder/decoder.rs | 9 ++- src/qrcode/detector/finder_pattern_finder.rs | 9 ++- src/qrcode/encoder/encoder.rs | 2 +- src/rxing_result_point.rs | 2 +- 23 files changed, 218 insertions(+), 187 deletions(-) diff --git a/src/aztec/AztecDetectorResult.rs b/src/aztec/AztecDetectorResult.rs index 3aff5f7..695ff15 100644 --- a/src/aztec/AztecDetectorResult.rs +++ b/src/aztec/AztecDetectorResult.rs @@ -52,14 +52,14 @@ impl DetectorRXingResult for AztecDetectorRXingResult { impl AztecDetectorRXingResult { pub fn new( bits: BitMatrix, - points: Vec, + points: [RXingResultPoint; 4], compact: bool, nbDatablocks: u32, nbLayers: u32, ) -> Self { Self { bits, - points, + points: points.to_vec(), compact, nbDatablocks, nbLayers, diff --git a/src/aztec/DecoderTest.rs b/src/aztec/DecoderTest.rs index 14d3900..b59ac1a 100644 --- a/src/aztec/DecoderTest.rs +++ b/src/aztec/DecoderTest.rs @@ -38,7 +38,7 @@ use super::{decoder, AztecDetectorResult::AztecDetectorRXingResult}; * Tests {@link Decoder}. */ -const NO_POINTS: &[RXingResultPoint] = &[RXingResultPoint { x: 0.0, y: 0.0 }; 0]; +const NO_POINTS: [RXingResultPoint; 4] = [RXingResultPoint { x: 0.0, y: 0.0 }; 4]; #[test] fn test_high_level_decode() { @@ -113,7 +113,7 @@ X X X X X X X X X X X X X X " ", ) .expect("Bitmatrix should init"); - let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.to_vec(), false, 30, 2); + let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.clone(), false, 30, 2); let result = decoder::decode(&r).expect("decoder should init"); assert_eq!("88888TTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", result.getText()); assert_eq!( @@ -173,7 +173,7 @@ X X X X X X X X ", " ", ) .expect("string parse success"); - let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.to_vec(), false, 15, 1); + let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.clone(), false, 15, 1); let result = decoder::decode(&r).expect("decode success"); assert_eq!("Français", result.getText()); } @@ -214,7 +214,7 @@ X X . X . X . . . X . X . . . . X X . X . . X X . . . ", ". ", ) .expect("parse string failed"); - let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.to_vec(), true, 16, 4); + let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.clone(), true, 16, 4); assert!(decoder::decode(&r).is_ok()); } @@ -254,7 +254,7 @@ X X . . . X X . . X . X . . . . X X . X . . X . X . X ", ". ", ) .expect("String Parse failed"); - let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.to_vec(), true, 16, 4); + let r = AztecDetectorRXingResult::new(matrix, NO_POINTS.clone(), true, 16, 4); assert!(decoder::decode(&r).is_ok()); } diff --git a/src/aztec/EncoderTest.rs b/src/aztec/EncoderTest.rs index 6de0ddf..d2ad3a1 100644 --- a/src/aztec/EncoderTest.rs +++ b/src/aztec/EncoderTest.rs @@ -50,7 +50,7 @@ const WINDOWS_1252: EncodingRef = encoding::all::WINDOWS_1252; //Charset.forName // const DOTX: &str = "[^.X]"; // const SPACES: &str = "\\s+"; -const NO_POINTS: Vec = Vec::new(); +const NO_POINTS: [RXingResultPoint; 4] = [RXingResultPoint { x: 0.0, y: 0.0 }; 4]; // real life tests @@ -671,7 +671,7 @@ fn testEncodeDecode(data: &str, compact: bool, layers: u32) { let mut matrix = aztec.getMatrix().clone(); let mut r = AztecDetectorRXingResult::new( matrix.clone(), - NO_POINTS, + NO_POINTS.clone(), aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), @@ -698,7 +698,7 @@ fn testEncodeDecode(data: &str, compact: bool, layers: u32) { ); r = AztecDetectorRXingResult::new( matrix, - NO_POINTS, + NO_POINTS.clone(), aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), @@ -751,7 +751,7 @@ fn testWriter( let mut r = AztecDetectorRXingResult::new( matrix.clone(), - NO_POINTS, + NO_POINTS.clone(), aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), @@ -780,7 +780,7 @@ fn testWriter( } r = AztecDetectorRXingResult::new( matrix, - NO_POINTS, + NO_POINTS.clone(), aztec.isCompact(), aztec.getCodeWords(), aztec.getLayers(), @@ -794,7 +794,7 @@ fn getPseudoRandom() -> rand::rngs::ThreadRng { } fn testModeMessageComplex(compact: bool, layers: u32, words: u32, expected: &str) { - let indata = encoder::generateModeMessage(compact, layers, words); + let indata = encoder::generateModeMessage(compact, layers, words).expect("generate mode"); assert_eq!( stripSpace(expected), stripSpace(&indata.to_string()), diff --git a/src/aztec/aztec_writer.rs b/src/aztec/aztec_writer.rs index 0f1fc24..d4a2e5e 100644 --- a/src/aztec/aztec_writer.rs +++ b/src/aztec/aztec_writer.rs @@ -107,7 +107,7 @@ fn encode( ) -> Result { if format != BarcodeFormat::AZTEC { return Err(Exceptions::IllegalArgumentException(Some(format!( - "Can only encode AZTEC, but got {:?}", + "can only encode AZTEC, but got {:?}", format )))); } diff --git a/src/aztec/detector.rs b/src/aztec/detector.rs index 55399dc..7820487 100644 --- a/src/aztec/detector.rs +++ b/src/aztec/detector.rs @@ -272,7 +272,7 @@ impl<'a> Detector<'_> { fn get_bulls_eye_corners( &mut self, pCenter: Point, - ) -> Result, Exceptions> { + ) -> Result<[RXingResultPoint; 4], Exceptions> { let mut pina = pCenter; let mut pinb = pCenter; let mut pinc = pCenter; @@ -355,10 +355,10 @@ impl<'a> Detector<'_> { * @return the center point */ fn get_matrix_center(&self) -> Point { - let mut point_a = RXingResultPoint { x: 0.0, y: 0.0 }; - let mut point_b = RXingResultPoint { x: 0.0, y: 0.0 }; - let mut point_c = RXingResultPoint { x: 0.0, y: 0.0 }; - let mut point_d = RXingResultPoint { x: 0.0, y: 0.0 }; + let mut point_a = RXingResultPoint::default(); // { x: 0.0, y: 0.0 }; + let mut point_b = RXingResultPoint::default(); // { x: 0.0, y: 0.0 }; + let mut point_c = RXingResultPoint::default(); // { x: 0.0, y: 0.0 }; + let mut point_d = RXingResultPoint::default(); // { x: 0.0, y: 0.0 }; let mut fnd = false; @@ -376,20 +376,20 @@ impl<'a> Detector<'_> { // This exception can be in case the initial rectangle is white // In that case, surely in the bull's eye, we try to expand the rectangle. if !fnd { - let cx: i32 = (self.image.getWidth() / 2).try_into().unwrap(); - let cy: i32 = (self.image.getHeight() / 2).try_into().unwrap(); + let cx: i32 = (self.image.getWidth() / 2) as i32; + let cy: i32 = (self.image.getHeight() / 2) as i32; point_a = self .get_first_different(&Point::new(cx + 7, cy - 7), false, 1, -1) - .to_rxing_result_point(); + .into(); point_b = self .get_first_different(&Point::new(cx + 7, cy + 7), false, 1, 1) - .to_rxing_result_point(); + .into(); point_c = self .get_first_different(&Point::new(cx - 7, cy + 7), false, -1, 1) - .to_rxing_result_point(); + .into(); point_d = self .get_first_different(&Point::new(cx - 7, cy - 7), false, -1, -1) - .to_rxing_result_point(); + .into(); } // try { @@ -438,16 +438,16 @@ impl<'a> Detector<'_> { if !fnd { point_a = self .get_first_different(&Point::new(cx + 7, cy - 7), false, 1, -1) - .to_rxing_result_point(); + .into(); point_b = self .get_first_different(&Point::new(cx + 7, cy + 7), false, 1, 1) - .to_rxing_result_point(); + .into(); point_c = self .get_first_different(&Point::new(cx - 7, cy + 7), false, -1, 1) - .to_rxing_result_point(); + .into(); point_d = self .get_first_different(&Point::new(cx - 7, cy - 7), false, -1, -1) - .to_rxing_result_point(); + .into(); } // try { // RXingResultPoint[] cornerPoints = new WhiteRectangleDetector(image, 15, cx, cy).detect(); @@ -484,7 +484,7 @@ impl<'a> Detector<'_> { fn get_matrix_corner_points( &self, bulls_eye_corners: &[RXingResultPoint], - ) -> Vec { + ) -> [RXingResultPoint; 4] { Self::expand_square( bulls_eye_corners, 2 * self.nb_center_layers, @@ -505,7 +505,7 @@ impl<'a> Detector<'_> { bottom_right: &RXingResultPoint, bottom_left: &RXingResultPoint, ) -> Result { - let sampler = DefaultGridSampler {}; + let sampler = DefaultGridSampler::default(); let dimension = self.get_dimension(); let low = dimension as f32 / 2.0f32 - self.nb_center_layers as f32; @@ -700,7 +700,7 @@ impl<'a> Detector<'_> { corner_points: &[RXingResultPoint], old_side: u32, new_side: u32, - ) -> Vec { + ) -> [RXingResultPoint; 4] { let ratio = new_side as f32 / (2.0f32 * old_side as f32); let mut dx = corner_points[0].getX() - corner_points[2].getX(); let mut dy = corner_points[0].getY() - corner_points[2].getY(); @@ -717,14 +717,11 @@ impl<'a> Detector<'_> { let result1 = RXingResultPoint::new(centerx + ratio * dx, centery + ratio * dy); let result3 = RXingResultPoint::new(centerx - ratio * dx, centery - ratio * dy); - vec![result0, result1, result2, result3] + [result0, result1, result2, result3] } fn is_valid_points(&self, x: i32, y: i32) -> bool { - x >= 0 - && x < self.image.getWidth().try_into().unwrap() - && y >= 0 - && y < self.image.getHeight().try_into().unwrap() + x >= 0 && x < self.image.getWidth() as i32 && y >= 0 && y < self.image.getHeight() as i32 } fn is_valid(&self, point: &RXingResultPoint) -> bool { @@ -743,9 +740,10 @@ impl<'a> Detector<'_> { fn get_dimension(&self) -> u32 { if self.compact { - return 4 * self.nb_layers + 11; + 4 * self.nb_layers + 11 + } else { + 4 * self.nb_layers + 2 * ((2 * self.nb_layers + 6) / 15) + 15 } - 4 * self.nb_layers + 2 * ((2 * self.nb_layers + 6) / 15) + 15 } } @@ -756,10 +754,6 @@ pub struct Point { } impl Point { - pub fn to_rxing_result_point(&self) -> RXingResultPoint { - RXingResultPoint::new(self.x as f32, self.y as f32) - } - pub fn new(x: i32, y: i32) -> Self { Self { x, y } } @@ -773,6 +767,12 @@ impl Point { } } +impl From for RXingResultPoint { + fn from(value: Point) -> Self { + RXingResultPoint::new(value.x as f32, value.y as f32) + } +} + impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "<{} {}>", &self.x, &self.y) diff --git a/src/aztec/encoder/encoder.rs b/src/aztec/encoder/encoder.rs index 6b6b1a8..693a645 100644 --- a/src/aztec/encoder/encoder.rs +++ b/src/aztec/encoder/encoder.rs @@ -51,9 +51,10 @@ pub const WORD_SIZE: [u32; 33] = [ * @return Aztec symbol matrix with metadata */ pub fn encode_simple(data: &str) -> Result { - let bytes = encoding::all::ISO_8859_1 - .encode(data, encoding::EncoderTrap::Replace) - .unwrap(); + let Ok(bytes) = encoding::all::ISO_8859_1 + .encode(data, encoding::EncoderTrap::Replace) else { + return Err(Exceptions::IllegalArgumentException(Some(format!("'{}' cannot be encoded as ISO_8859_1", data)))); + }; encode_bytes_simple(&bytes) } @@ -71,10 +72,14 @@ pub fn encode( minECCPercent: u32, userSpecifiedLayers: i32, ) -> Result { - let bytes = encoding::all::ISO_8859_1 - .encode(data, encoding::EncoderTrap::Strict) - .expect("must encode cleanly in ISO_8859_1"); - encode_bytes(&bytes, minECCPercent, userSpecifiedLayers) + if let Ok(bytes) = encoding::all::ISO_8859_1.encode(data, encoding::EncoderTrap::Strict) { + encode_bytes(&bytes, minECCPercent, userSpecifiedLayers) + } else { + Err(Exceptions::IllegalArgumentException(Some(format!( + "'{}' cannot be encoded as ISO_8859_1", + data + )))) + } } /** @@ -95,10 +100,14 @@ pub fn encode_with_charset( userSpecifiedLayers: i32, charset: encoding::EncodingRef, ) -> Result { - let bytes = charset - .encode(data, encoding::EncoderTrap::Strict) - .expect("must be encodeable"); //data.getBytes(null != charset ? charset : StandardCharsets.ISO_8859_1); - encode_bytes_with_charset(&bytes, minECCPercent, userSpecifiedLayers, charset) + if let Ok(bytes) = charset.encode(data, encoding::EncoderTrap::Strict) { + encode_bytes_with_charset(&bytes, minECCPercent, userSpecifiedLayers, charset) + } else { + Err(Exceptions::IllegalArgumentException(Some(format!( + "'{}' cannot be encoded as ISO_8859_1", + data + )))) + } } /** @@ -235,11 +244,11 @@ pub fn encode_bytes_with_charset( &stuffed_bits, total_bits_in_layer_var as usize, word_size as usize, - ); + )?; // generate mode message let messageSizeInWords = stuffed_bits.getSize() as u32 / word_size; - let modeMessage = generateModeMessage(compact, layers, messageSizeInWords); + let modeMessage = generateModeMessage(compact, layers, messageSizeInWords)?; // allocate symbol let baseMatrixSize = (if compact { 11 } else { 14 }) + layers * 4; // not including alignment lines @@ -372,7 +381,11 @@ fn drawBullsEye(matrix: &mut BitMatrix, center: u32, size: u32) { matrix.set(center + size, center + size - 1); } -pub fn generateModeMessage(compact: bool, layers: u32, messageSizeInWords: u32) -> BitArray { +pub fn generateModeMessage( + compact: bool, + layers: u32, + messageSizeInWords: u32, +) -> Result { let mut mode_message = BitArray::new(); if compact { mode_message @@ -381,7 +394,7 @@ pub fn generateModeMessage(compact: bool, layers: u32, messageSizeInWords: u32) mode_message .appendBits(messageSizeInWords - 1, 6) .expect("should append"); - mode_message = generateCheckWords(&mode_message, 28, 4); + mode_message = generateCheckWords(&mode_message, 28, 4)?; } else { mode_message .appendBits(layers - 1, 5) @@ -389,9 +402,9 @@ pub fn generateModeMessage(compact: bool, layers: u32, messageSizeInWords: u32) mode_message .appendBits(messageSizeInWords - 1, 11) .expect("should append"); - mode_message = generateCheckWords(&mode_message, 40, 4); + mode_message = generateCheckWords(&mode_message, 40, 4)?; } - mode_message + Ok(mode_message) } fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeMessage: BitArray) { @@ -433,25 +446,26 @@ fn drawModeMessage(matrix: &mut BitMatrix, compact: bool, matrixSize: u32, modeM } } -fn generateCheckWords(bitArray: &BitArray, totalBits: usize, wordSize: usize) -> BitArray { +fn generateCheckWords( + bitArray: &BitArray, + totalBits: usize, + wordSize: usize, +) -> Result { // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed let message_size_in_words = bitArray.getSize() / wordSize; - let mut rs = ReedSolomonEncoder::new(getGF(wordSize).expect("Should never have bad value")); + let mut rs = ReedSolomonEncoder::new(getGF(wordSize)?); let total_words = totalBits / wordSize; let mut message_words = bitsToWords(bitArray, wordSize, total_words); - rs.encode(&mut message_words, total_words - message_size_in_words) - .expect("must encode ok"); + rs.encode(&mut message_words, total_words - message_size_in_words)?; let start_pad = totalBits % wordSize; let mut message_bits = BitArray::new(); message_bits.appendBits(0, start_pad).expect("must append"); for message_word in message_words { // for (int messageWord : messageWords) { - message_bits - .appendBits(message_word as u32, wordSize) - .expect("must append"); + message_bits.appendBits(message_word as u32, wordSize)? } // dbg!(message_bits.to_string()); - message_bits + Ok(message_bits) } fn bitsToWords(stuffedBits: &BitArray, wordSize: usize, totalWords: usize) -> Vec { diff --git a/src/common/bit_array.rs b/src/common/bit_array.rs index c3ba94b..676e80f 100644 --- a/src/common/bit_array.rs +++ b/src/common/bit_array.rs @@ -51,6 +51,7 @@ impl BitArray { } // For testing only + #[cfg(test)] pub fn with_initial_values(bits: Vec, size: usize) -> Self { Self { bits, size } } @@ -253,7 +254,7 @@ impl BitArray { pub fn appendBits(&mut self, value: u32, num_bits: usize) -> Result<(), Exceptions> { if num_bits > 32 { return Err(Exceptions::IllegalArgumentException(Some( - "Num bits must be between 0 and 32".to_owned(), + "num bits must be between 0 and 32".to_owned(), ))); } @@ -310,15 +311,15 @@ impl BitArray { let mut bitOffset = bitOffset; for i in 0..numBytes { //for (int i = 0; i < numBytes; i++) { - let mut theByte = 0; + let mut the_byte = 0; for j in 0..8 { //for (int j = 0; j < 8; j++) { if self.get(bitOffset) { - theByte |= 1 << (7 - j); + the_byte |= 1 << (7 - j); } bitOffset += 1; } - array[offset + i] = theByte; + array[offset + i] = the_byte; } } diff --git a/src/common/bit_matrix.rs b/src/common/bit_matrix.rs index 5ad9157..3c638c8 100644 --- a/src/common/bit_matrix.rs +++ b/src/common/bit_matrix.rs @@ -203,12 +203,18 @@ impl BitMatrix { * @return value of given bit in matrix */ pub fn get(&self, x: u32, y: u32) -> bool { - let offset = y as usize * self.row_size + (x as usize / 32); + let offset = self.get_offset(y, x); ((self.bits[offset] >> (x & 0x1f)) & 1) != 0 } - pub fn try_get(&self, x: u32, y: u32) -> Result { + #[inline(always)] + fn get_offset(&self, y: u32, x: u32) -> usize { let offset = y as usize * self.row_size + (x as usize / 32); + offset + } + + pub fn try_get(&self, x: u32, y: u32) -> Result { + let offset = self.get_offset(y, x); if offset > self.bits.len() { return Err(Exceptions::IndexOutOfBoundsException(None)); } @@ -217,7 +223,7 @@ impl BitMatrix { /// Confusingly returns true if the requested element is out of bounds pub fn check_in_bounds(&self, x: u32, y: u32) -> bool { - (y as usize * self.row_size + (x as usize / 32)) > self.bits.len() + (self.get_offset(y, x)) > self.bits.len() } /** @@ -227,12 +233,12 @@ impl BitMatrix { * @param y The vertical component (i.e. which row) */ pub fn set(&mut self, x: u32, y: u32) { - let offset = y as usize * self.row_size + (x as usize / 32); + let offset = self.get_offset(y, x); self.bits[offset] |= 1 << (x & 0x1f); } pub fn unset(&mut self, x: u32, y: u32) { - let offset = y as usize * self.row_size + (x as usize / 32); + let offset = self.get_offset(y, x); self.bits[offset] &= !(1 << (x & 0x1f)); } @@ -243,7 +249,7 @@ impl BitMatrix { * @param y The vertical component (i.e. which row) */ pub fn flip_coords(&mut self, x: u32, y: u32) { - let offset = y as usize * self.row_size + (x as usize / 32); + let offset = self.get_offset(y, x); self.bits[offset] ^= 1 << (x & 0x1f); } @@ -252,9 +258,8 @@ impl BitMatrix { */ pub fn flip_self(&mut self) { let max = self.bits.len(); - for i in 0..max { - //for (int i = 0; i < max; i++) { - self.bits[i] = !self.bits[i]; + for bit_set in self.bits.iter_mut().take(max) { + *bit_set = !*bit_set; } } @@ -320,14 +325,14 @@ impl BitMatrix { // } if height < 1 || width < 1 { return Err(Exceptions::IllegalArgumentException(Some( - "Height and width must be at least 1".to_owned(), + "height and width must be at least 1".to_owned(), ))); } let right = left + width; let bottom = top + height; if bottom > self.height || right > self.width { return Err(Exceptions::IllegalArgumentException(Some( - "The region must fit inside the matrix".to_owned(), + "the region must fit inside the matrix".to_owned(), ))); } for y in top..bottom { @@ -374,8 +379,8 @@ impl BitMatrix { * @param row {@link BitArray} to copy from */ pub fn setRow(&mut self, y: u32, row: &BitArray) { - return self.bits[y as usize * self.row_size..y as usize * self.row_size + self.row_size] - .clone_from_slice(&row.getBitArray()[0..self.row_size]); + self.bits[y as usize * self.row_size..y as usize * self.row_size + self.row_size] + .clone_from_slice(&row.getBitArray()[0..self.row_size]) //System.arraycopy(row.getBitArray(), 0, self.bits, y * self.rowSize, self.rowSize); } @@ -438,7 +443,7 @@ impl BitMatrix { //for (int y = 0; y < height; y++) { for x in 0..self.width { //for (int x = 0; x < width; x++) { - let offset = y as usize * self.row_size + (x as usize / 32); + let offset = self.get_offset(y, x); if ((self.bits[offset] >> (x & 0x1f)) & 1) != 0 { let newOffset: usize = ((newHeight - 1 - x) * newRowSize + (y / 32)) as usize; newBits[newOffset] |= 1 << (y & 0x1f); @@ -456,7 +461,7 @@ impl BitMatrix { * * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white */ - pub fn getEnclosingRectangle(&self) -> Option> { + pub fn getEnclosingRectangle(&self) -> Option<[u32; 4]> { let mut left = self.width; let mut top = self.height; // let right = -1; @@ -476,22 +481,22 @@ impl BitMatrix { if y > bottom { bottom = y; } - if x32 * 32 < left.try_into().unwrap() { + if x32 * 32 < left as usize { let mut bit = 0; while (theBits << (31 - bit)) == 0 { bit += 1; } - if (x32 * 32 + bit) < left.try_into().unwrap() { - left = (x32 * 32 + bit).try_into().unwrap(); + if (x32 * 32 + bit) < left as usize { + left = (x32 * 32 + bit) as u32; } } - if x32 * 32 + 31 > right.try_into().unwrap() { + if x32 * 32 + 31 > right as usize { let mut bit = 31; while (theBits >> bit) == 0 { bit -= 1; } - if (x32 * 32 + bit) > right.try_into().unwrap() { - right = (x32 * 32 + bit).try_into().unwrap(); + if (x32 * 32 + bit) > right as usize { + right = (x32 * 32 + bit) as u32; } } } @@ -502,7 +507,7 @@ impl BitMatrix { return None; } - Some(vec![left, top, right - left + 1, bottom - top + 1]) + Some([left, top, right - left + 1, bottom - top + 1]) } /** @@ -530,7 +535,7 @@ impl BitMatrix { Some(vec![x as u32, y as u32]) } - pub fn getBottomRightOnBit(&self) -> Option> { + pub fn getBottomRightOnBit(&self) -> Option<[u32; 2]> { let mut bitsOffset = self.bits.len() as i64 - 1; while bitsOffset >= 0 && self.bits[bitsOffset as usize] == 0 { bitsOffset -= 1; @@ -549,7 +554,7 @@ impl BitMatrix { } x += bit; - Some(vec![x as u32, y as u32]) + Some([x as u32, y as u32]) } /** diff --git a/src/common/default_grid_sampler.rs b/src/common/default_grid_sampler.rs index af48c34..9e8335a 100644 --- a/src/common/default_grid_sampler.rs +++ b/src/common/default_grid_sampler.rs @@ -25,7 +25,8 @@ use super::{BitMatrix, GridSampler, PerspectiveTransform}; /** * @author Sean Owen */ -pub struct DefaultGridSampler {} +#[derive(Default)] +pub struct DefaultGridSampler; impl GridSampler for DefaultGridSampler { fn sample_grid_detailed( diff --git a/src/common/detector/MathUtils.rs b/src/common/detector/MathUtils.rs index d6183a0..35bd86a 100644 --- a/src/common/detector/MathUtils.rs +++ b/src/common/detector/MathUtils.rs @@ -30,6 +30,7 @@ use std::{f32, i32}; * @param d real value to round * @return nearest {@code int} */ +#[inline(always)] pub fn round(d: f32) -> i32 { (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32 } @@ -41,6 +42,7 @@ pub fn round(d: f32) -> i32 { * @param bY point B y coordinate * @return Euclidean distance between points A and B */ +#[inline(always)] pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 { let xDiff: f64 = (aX - bX).into(); let yDiff: f64 = (aY - bY).into(); @@ -54,6 +56,7 @@ pub fn distance_float(aX: f32, aY: f32, bX: f32, bY: f32) -> f32 { * @param bY point B y coordinate * @return Euclidean distance between points A and B */ +#[inline(always)] pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 { let xDiff: f64 = (aX - bX).into(); let yDiff: f64 = (aY - bY).into(); @@ -64,12 +67,14 @@ pub fn distance_int(aX: i32, aY: i32, bX: i32, bY: i32) -> f32 { * @param array values to sum * @return sum of values in array */ +#[inline(always)] pub fn sum(array: &[i32]) -> i32 { - let mut count = 0; - for a in array { - count += a; - } - count + array.iter().sum() + // let mut count = 0; + // for a in array { + // count += a; + // } + // count } #[cfg(test)] diff --git a/src/common/detector/monochrome_rectangle_detector.rs b/src/common/detector/monochrome_rectangle_detector.rs index 1ddbf54..bc3665f 100644 --- a/src/common/detector/monochrome_rectangle_detector.rs +++ b/src/common/detector/monochrome_rectangle_detector.rs @@ -29,15 +29,13 @@ use crate::{common::BitMatrix, Exceptions, RXingResultPoint, ResultPoint}; */ const MAX_MODULES: i32 = 32; #[deprecated] -pub struct MonochromeRectangleDetector { - image: BitMatrix, +pub struct MonochromeRectangleDetector<'a> { + image: &'a BitMatrix, } -impl MonochromeRectangleDetector { - pub fn new(image: &BitMatrix) -> Self { - Self { - image: image.clone(), - } +impl<'a> MonochromeRectangleDetector<'_> { + pub fn new(image: &'a BitMatrix) -> MonochromeRectangleDetector<'a> { + MonochromeRectangleDetector { image: image } } /** @@ -50,7 +48,7 @@ impl MonochromeRectangleDetector { * third, the rightmost * @throws NotFoundException if no Data Matrix Code can be found */ - pub fn detect(&self) -> Result, Exceptions> { + pub fn detect(&self) -> Result<[RXingResultPoint; 4], Exceptions> { let height = self.image.getHeight() as i32; let width = self.image.getWidth() as i32; let halfHeight = height / 2; @@ -124,7 +122,7 @@ impl MonochromeRectangleDetector { halfWidth / 4, )?; - Ok(vec![pointA, pointB, pointC, pointD]) + Ok([pointA, pointB, pointC, pointD]) } /** @@ -157,11 +155,11 @@ impl MonochromeRectangleDetector { bottom: i32, maxWhiteRun: i32, ) -> Result { - let mut lastRange_z: Option> = None; + let mut lastRange_z: Option<[i32; 2]> = None; let mut y: i32 = centerY; let mut x: i32 = centerX; while y < bottom && y >= top && x < right && x >= left { - let range: Option> = if deltaX == 0 { + let range: Option<[i32; 2]> = if deltaX == 0 { // horizontal slices, up and down self.blackWhiteRange(y, maxWhiteRun, left, right, true) } else { @@ -231,7 +229,7 @@ impl MonochromeRectangleDetector { minDim: i32, maxDim: i32, horizontal: bool, - ) -> Option> { + ) -> Option<[i32; 2]> { let center = (minDim + maxDim) / 2; // Scan left/up first @@ -295,7 +293,7 @@ impl MonochromeRectangleDetector { end -= 1; if end > start { - Some(vec![start, end]) + Some([start, end]) } else { None } diff --git a/src/common/detector/white_rectangle_detector.rs b/src/common/detector/white_rectangle_detector.rs index c38337f..afd9dde 100644 --- a/src/common/detector/white_rectangle_detector.rs +++ b/src/common/detector/white_rectangle_detector.rs @@ -32,8 +32,8 @@ use super::MathUtils; */ const INIT_SIZE: i32 = 10; const CORR: i32 = 1; -pub struct WhiteRectangleDetector { - image: BitMatrix, +pub struct WhiteRectangleDetector<'a> { + image: &'a BitMatrix, height: i32, width: i32, leftInit: i32, @@ -42,9 +42,9 @@ pub struct WhiteRectangleDetector { upInit: i32, } -impl WhiteRectangleDetector { - pub fn new_from_image(image: &BitMatrix) -> Result { - Self::new( +impl<'a> WhiteRectangleDetector<'_> { + pub fn new_from_image(image: &'a BitMatrix) -> Result, Exceptions> { + WhiteRectangleDetector::new( image, INIT_SIZE, image.getWidth() as i32 / 2, @@ -59,7 +59,12 @@ impl WhiteRectangleDetector { * @param y y position of search center * @throws NotFoundException if image is too small to accommodate {@code initSize} */ - pub fn new(image: &BitMatrix, initSize: i32, x: i32, y: i32) -> Result { + pub fn new( + image: &'a BitMatrix, + initSize: i32, + x: i32, + y: i32, + ) -> Result, Exceptions> { let halfsize = initSize / 2; let leftInit = x - halfsize; @@ -75,8 +80,8 @@ impl WhiteRectangleDetector { return Err(Exceptions::NotFoundException(None)); } - Ok(Self { - image: image.clone(), + Ok(WhiteRectangleDetector { + image: image, height: image.getHeight() as i32, width: image.getWidth() as i32, leftInit, @@ -100,7 +105,7 @@ impl WhiteRectangleDetector { * leftmost and the third, the rightmost * @throws NotFoundException if no Data Matrix Code can be found */ - pub fn detect(&self) -> Result, Exceptions> { + pub fn detect(&self) -> Result<[RXingResultPoint; 4], Exceptions> { let mut left: i32 = self.leftInit; let mut right: i32 = self.rightInit; let mut up: i32 = self.upInit; @@ -321,7 +326,7 @@ impl WhiteRectangleDetector { z: &RXingResultPoint, x: &RXingResultPoint, t: &RXingResultPoint, - ) -> Vec { + ) -> [RXingResultPoint; 4] { // // t t // z x @@ -339,14 +344,14 @@ impl WhiteRectangleDetector { let tj = t.getY(); if yi < self.width as f32 / 2.0f32 { - vec![ + [ RXingResultPoint::new(ti - CORR as f32, tj + CORR as f32), RXingResultPoint::new(zi + CORR as f32, zj + CORR as f32), RXingResultPoint::new(xi - CORR as f32, xj - CORR as f32), RXingResultPoint::new(yi + CORR as f32, yj - CORR as f32), ] } else { - vec![ + [ RXingResultPoint::new(ti + CORR as f32, tj + CORR as f32), RXingResultPoint::new(zi + CORR as f32, zj - CORR as f32), RXingResultPoint::new(xi - CORR as f32, xj + CORR as f32), diff --git a/src/common/minimal_eci_input.rs b/src/common/minimal_eci_input.rs index feb22f9..e5581d5 100644 --- a/src/common/minimal_eci_input.rs +++ b/src/common/minimal_eci_input.rs @@ -112,9 +112,7 @@ impl ECIInput for MinimalECIInput { */ fn subSequence(&self, start: usize, end: usize) -> Result, Exceptions> { if start > end || end > self.length() { - return Err(Exceptions::IndexOutOfBoundsException(Some( - start.to_string(), - ))); + return Err(Exceptions::IndexOutOfBoundsException(None)); } let mut result = String::new(); for i in start..end { @@ -143,9 +141,7 @@ impl ECIInput for MinimalECIInput { */ fn isECI(&self, index: u32) -> Result { if index >= self.length() as u32 { - return Err(Exceptions::IndexOutOfBoundsException(Some( - index.to_string(), - ))); + return Err(Exceptions::IndexOutOfBoundsException(None)); } Ok(self.bytes[index as usize] > 255) // && self.bytes[index as usize] <= u16::MAX) } @@ -170,9 +166,7 @@ impl ECIInput for MinimalECIInput { */ fn getECIValue(&self, index: usize) -> Result { if index >= self.length() { - return Err(Exceptions::IndexOutOfBoundsException(Some( - index.to_string(), - ))); + return Err(Exceptions::IndexOutOfBoundsException(None)); } if !self.isECI(index as u32)? { return Err(Exceptions::IllegalArgumentException(Some(format!( @@ -261,9 +255,7 @@ impl MinimalECIInput { */ pub fn isFNC1(&self, index: usize) -> Result { if index >= self.length() { - return Err(Exceptions::IndexOutOfBoundsException(Some( - index.to_string(), - ))); + return Err(Exceptions::IndexOutOfBoundsException(None)); } Ok(self.bytes[index] == 1000) } @@ -271,7 +263,8 @@ impl MinimalECIInput { fn addEdge(edges: &mut [Vec>>], to: usize, edge: Rc) { if edges[to][edge.encoderIndex].is_none() || edges[to][edge.encoderIndex] - .clone() + // .clone() + .as_ref() .unwrap() .cachedTotalSize > edge.cachedTotalSize @@ -359,7 +352,7 @@ impl MinimalECIInput { } } if minimalJ < 0 { - panic!("Internal error: failed to encode \"{}\"", stringToEncode); + panic!("internal error: failed to encode \"{}\"", stringToEncode); } let mut intsAL: Vec = Vec::new(); let mut current = edges[inputLength][minimalJ as usize].clone(); @@ -395,13 +388,13 @@ impl MinimalECIInput { } current = c.previous.clone(); } - let mut ints = vec![0; intsAL.len()]; + //let mut ints = vec![0; intsAL.len()]; // for i in 0..ints.len() { // // for (int i = 0; i < ints.length; i++) { // ints[i] = *intsAL.get(i).unwrap(); // } - ints[..].copy_from_slice(&intsAL[..]); - ints + //ints[..].copy_from_slice(&intsAL[..]); + intsAL } } @@ -412,6 +405,8 @@ struct InputEdge { cachedTotalSize: usize, } impl InputEdge { + const FNC1_UNICODE: &str = "\u{1000}"; + pub fn new( c: &str, encoderSet: &ECIEncoderSet, @@ -419,7 +414,7 @@ impl InputEdge { previous: Option>, fnc1: Option<&str>, ) -> Self { - let mut size = if c == "\u{1000}" { + let mut size = if c == Self::FNC1_UNICODE { 1 } else { encoderSet.encode_char(c, encoderIndex).len() @@ -436,7 +431,7 @@ impl InputEdge { Self { c: if fnc1.is_some() && &c == fnc1.as_ref().unwrap() { - String::from("\u{1000}") + String::from(Self::FNC1_UNICODE) } else { String::from(c) }, @@ -452,7 +447,7 @@ impl InputEdge { Self { c: if fnc1.is_some() && &c == fnc1.as_ref().unwrap() { - String::from("\u{1000}") + String::from(Self::FNC1_UNICODE) } else { String::from(c) }, @@ -489,7 +484,7 @@ impl InputEdge { } pub fn isFNC1(&self) -> bool { - self.c == "\u{1000}" + self.c == Self::FNC1_UNICODE } } diff --git a/src/common/perspective_transform.rs b/src/common/perspective_transform.rs index 7bde969..39f8d19 100644 --- a/src/common/perspective_transform.rs +++ b/src/common/perspective_transform.rs @@ -109,13 +109,12 @@ impl PerspectiveTransform { pub fn transform_points_double(&self, x_values: &mut [f32], y_valuess: &mut [f32]) { let n = x_values.len(); - for i in 0..n { + // for i in 0..n { + for (x, y) in x_values.iter_mut().zip(y_valuess.iter_mut()).take(n) { // for (int i = 0; i < n; i++) { - let x = x_values[i]; - let y = y_valuess[i]; - let denominator = self.a13 * x + self.a23 * y + self.a33; - x_values[i] = (self.a11 * x + self.a21 * y + self.a31) / denominator; - y_valuess[i] = (self.a12 * x + self.a22 * y + self.a32) / denominator; + let denominator = self.a13 * *x + self.a23 * *y + self.a33; + *x = (self.a11 * *x + self.a21 * *y + self.a31) / denominator; + *y = (self.a12 * *x + self.a22 * *y + self.a32) / denominator; } } diff --git a/src/datamatrix/decoder/data_block.rs b/src/datamatrix/decoder/data_block.rs index df208f5..469a802 100644 --- a/src/datamatrix/decoder/data_block.rs +++ b/src/datamatrix/decoder/data_block.rs @@ -56,11 +56,10 @@ impl DataBlock { let ecBlocks = version.getECBlocks(); // First count the total number of data blocks - let mut totalBlocks = 0_usize; let ecBlockArray = ecBlocks.getECBlocks(); - for ecBlock in ecBlockArray { - totalBlocks += ecBlock.getCount() as usize; - } + let totalBlocks = ecBlockArray.iter().fold(0, |acc, ecBlock| { + acc + ecBlock.getCount() as usize + }); // Now establish DataBlocks of the appropriate size and number of data codewords let mut result = Vec::with_capacity(totalBlocks); diff --git a/src/datamatrix/decoder/decoded_bit_stream_parser.rs b/src/datamatrix/decoder/decoded_bit_stream_parser.rs index 02793a3..32a6b75 100644 --- a/src/datamatrix/decoder/decoded_bit_stream_parser.rs +++ b/src/datamatrix/decoder/decoded_bit_stream_parser.rs @@ -106,6 +106,10 @@ const TEXT_SHIFT3_SET_CHARS: [char; 32] = [ 127 as char, ]; +const INSERT_STRING_CONST: &str = "\u{001E}\u{0004}"; +const VALUE_236: &str = "[)>\u{001E}05\u{001D}"; +const VALUE_237: &str = "[)>\u{001E}06\u{001D}"; + pub fn decode(bytes: &[u8]) -> Result { let mut bits = BitSource::new(bytes.to_vec()); let mut result = ECIStringBuilder::with_capacity(100); @@ -233,13 +237,13 @@ fn decodeAsciiSegment( 235=> // Upper Shift (shift to Extended ASCII) upperShift = true, 236=> {// 05 Macro - result.append_string("[)>\u{001E}05\u{001D}"); - resultTrailer.replace_range(0..0, "\u{001E}\u{0004}"); + result.append_string(VALUE_236); + resultTrailer.replace_range(0..0, INSERT_STRING_CONST); // resultTrailer.insert(0, "\u{001E}\u{0004}"); }, 237=>{ // 06 Macro - result.append_string("[)>\u{001E}06\u{001D}"); - resultTrailer.replace_range(0..0, "\u{001E}\u{0004}"); + result.append_string(VALUE_237); + resultTrailer.replace_range(0..0, INSERT_STRING_CONST); // resultTrailer.insert(0, "\u{001E}\u{0004}"); }, 238=> // Latch to ANSI X12 encodation diff --git a/src/datamatrix/decoder/decoder.rs b/src/datamatrix/decoder/decoder.rs index 92e89f6..7c3e5c0 100644 --- a/src/datamatrix/decoder/decoder.rs +++ b/src/datamatrix/decoder/decoder.rs @@ -75,10 +75,10 @@ impl Decoder { let dataBlocks = DataBlock::getDataBlocks(&codewords, version)?; // Count total number of data bytes - let mut totalBytes = 0; - for db in &dataBlocks { - totalBytes += db.getNumDataCodewords(); - } + let totalBytes = dataBlocks + .iter() + .fold(0, |acc, db| acc + db.getNumDataCodewords()); + let mut resultBytes = vec![0u8; totalBytes as usize]; let dataBlocksCount = dataBlocks.len(); diff --git a/src/datamatrix/decoder/version.rs b/src/datamatrix/decoder/version.rs index 695ab60..b6b920a 100644 --- a/src/datamatrix/decoder/version.rs +++ b/src/datamatrix/decoder/version.rs @@ -54,16 +54,23 @@ impl Version { dataRegionSizeRows, dataRegionSizeColumns, totalCodewords: { - // Calculate the total number of codewords - let mut total = 0; let ecCodewords = &ecBlocks.getECCodewords(); let ecbArray = ecBlocks.getECBlocks(); - for ecBlock in ecbArray { - total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); - } - - total + ecbArray.iter().fold(0, |acc, ecBlock| { + acc + ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords) + }) }, + // totalCodewords: { + // // Calculate the total number of codewords + // let mut total = 0; + // let ecCodewords = &ecBlocks.getECCodewords(); + // let ecbArray = ecBlocks.getECBlocks(); + // for ecBlock in ecbArray { + // total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords); + // } + + // total + // }, ecBlocks, } } diff --git a/src/datamatrix/detector/detector.rs b/src/datamatrix/detector/detector.rs index 6f4f946..251e294 100644 --- a/src/datamatrix/detector/detector.rs +++ b/src/datamatrix/detector/detector.rs @@ -29,7 +29,7 @@ use super::DatamatrixDetectorResult; */ pub struct Detector<'a> { image: &'a BitMatrix, - rectangleDetector: WhiteRectangleDetector, + rectangleDetector: WhiteRectangleDetector<'a>, } impl<'a> Detector<'_> { pub fn new(image: &'a BitMatrix) -> Result, Exceptions> { @@ -127,7 +127,7 @@ impl<'a> Detector<'_> { /** * Detect a solid side which has minimum transition. */ - fn detectSolid1(&self, cornerPoints: Vec) -> [RXingResultPoint; 4] { + fn detectSolid1(&self, cornerPoints: [RXingResultPoint; 4]) -> [RXingResultPoint; 4] { // 0 2 // 1 3 let pointA = cornerPoints[0]; diff --git a/src/qrcode/decoder/decoder.rs b/src/qrcode/decoder/decoder.rs index 7b22d02..d523fee 100644 --- a/src/qrcode/decoder/decoder.rs +++ b/src/qrcode/decoder/decoder.rs @@ -158,11 +158,10 @@ fn decode_bitmatrix_parser_with_hints( let dataBlocks = DataBlock::getDataBlocks(&codewords, version, ecLevel)?; // Count total number of data bytes - let mut totalBytes = 0usize; - for dataBlock in &dataBlocks { - // for (DataBlock dataBlock : dataBlocks) { - totalBytes += dataBlock.getNumDataCodewords() as usize; - } + let totalBytes = dataBlocks.iter().fold(0, |acc,dataBlock| { + acc + dataBlock.getNumDataCodewords() as usize + }); + let mut resultBytes = vec![0u8; totalBytes]; let mut resultOffset = 0; diff --git a/src/qrcode/detector/finder_pattern_finder.rs b/src/qrcode/detector/finder_pattern_finder.rs index ff5d5c8..31233fa 100755 --- a/src/qrcode/detector/finder_pattern_finder.rs +++ b/src/qrcode/detector/finder_pattern_finder.rs @@ -686,11 +686,10 @@ impl FinderPatternFinder { // vary too much. We arbitrarily say that when the total deviation from average exceeds // 5% of the total module size estimates, it's too much. let average = totalModuleSize / max as f32; - let mut totalDeviation = 0.0; - for pattern in &self.possibleCenters { - // for (FinderPattern pattern : possibleCenters) { - totalDeviation += (pattern.getEstimatedModuleSize() - average).abs(); - } + let totalDeviation = self.possibleCenters.iter().fold(0.0, |acc, pattern| { +acc + (pattern.getEstimatedModuleSize() - average).abs() + }); + totalDeviation <= 0.05 * totalModuleSize } diff --git a/src/qrcode/encoder/encoder.rs b/src/qrcode/encoder/encoder.rs index 5625ceb..95593a1 100644 --- a/src/qrcode/encoder/encoder.rs +++ b/src/qrcode/encoder/encoder.rs @@ -529,7 +529,7 @@ pub fn getNumDataBytesAndNumECBytesForBlockID( + ((num_data_bytes_in_group2 + numEcBytesInGroup2) * num_rs_blocks_in_group2) { return Err(Exceptions::WriterException(Some( - "Total bytes mismatch".to_owned(), + "total bytes mismatch".to_owned(), ))); // throw new WriterException("Total bytes mismatch"); diff --git a/src/rxing_result_point.rs b/src/rxing_result_point.rs index e1f1305..e4df79a 100644 --- a/src/rxing_result_point.rs +++ b/src/rxing_result_point.rs @@ -9,7 +9,7 @@ use std::hash::Hash; * * @author Sean Owen */ -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct RXingResultPoint { pub(crate) x: f32, pub(crate) y: f32,