diff --git a/src/aztec/decoder.rs b/src/aztec/decoder.rs index 5185fed..fb49080 100644 --- a/src/aztec/decoder.rs +++ b/src/aztec/decoder.rs @@ -19,7 +19,7 @@ use encoding::Encoding; use crate::{ common::{ reedsolomon::{ - get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonDecoder, + get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonDecoder, GenericGFRef, }, BitMatrix, CharacterSetECI, DecoderRXingResult, DetectorRXingResult, }, @@ -327,7 +327,7 @@ fn correct_bits( ddata: &AztecDetectorRXingResult, rawbits: &[bool], ) -> Result { - let gf: GenericGF; + let gf: GenericGFRef; let codeword_size; if ddata.getNbLayers() <= 2 { diff --git a/src/aztec/encoder/encoder.rs b/src/aztec/encoder/encoder.rs index c6d3ff9..07689bc 100644 --- a/src/aztec/encoder/encoder.rs +++ b/src/aztec/encoder/encoder.rs @@ -19,7 +19,7 @@ use encoding::Encoding; use crate::{ common::{ reedsolomon::{ - get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonEncoder, + get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonEncoder, GenericGFRef, }, BitArray, BitMatrix, }, @@ -484,7 +484,7 @@ fn bitsToWords(stuffedBits: &BitArray, wordSize: usize, totalWords: usize) -> Ve return message; } -fn getGF(wordSize: usize) -> Result { +fn getGF(wordSize: usize) -> Result { match wordSize { 4 => Ok(get_predefined_genericgf(PredefinedGenericGF::AztecParam)), 6 => Ok(get_predefined_genericgf(PredefinedGenericGF::AztecData6)), diff --git a/src/common/reedsolomon/GenericGFPolyTestCase.rs b/src/common/reedsolomon/GenericGFPolyTestCase.rs index c36c712..29341ac 100644 --- a/src/common/reedsolomon/GenericGFPolyTestCase.rs +++ b/src/common/reedsolomon/GenericGFPolyTestCase.rs @@ -31,33 +31,33 @@ use super::{GenericGF, GenericGFPoly}; #[test] fn testPolynomialString() { - let FIELD = Rc::new(super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256)); - let fz = super::GenericGFPoly::new(FIELD.clone(), &vec![0; 1]).unwrap(); + let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256); + let fz = super::GenericGFPoly::new(FIELD, &vec![0; 1]).unwrap(); assert_eq!("0", fz.getZero().to_string()); - let n1mono = GenericGF::buildMonomial(FIELD.clone(), 0, -1); + let n1mono = GenericGF::buildMonomial(FIELD, 0, -1); assert_eq!("-1", n1mono.to_string()); - let p = GenericGFPoly::new(FIELD.clone(), &vec![3, 0, -2, 1, 1]).unwrap(); + let p = GenericGFPoly::new(FIELD, &vec![3, 0, -2, 1, 1]).unwrap(); assert_eq!("a^25x^4 - ax^2 + x + 1", p.to_string()); - let p = GenericGFPoly::new(FIELD.clone(), &vec![3]).unwrap(); + let p = GenericGFPoly::new(FIELD, &vec![3]).unwrap(); assert_eq!("a^25", p.to_string()); } #[test] fn testZero() { - let FIELD = Rc::new(super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256)); - let fz = super::GenericGFPoly::new(FIELD.clone(), &vec![0; 1]).unwrap(); + let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256); + let fz = super::GenericGFPoly::new(FIELD, &vec![0; 1]).unwrap(); - assert_eq!(fz.getZero(), GenericGF::buildMonomial(FIELD.clone(), 1, 0)); + assert_eq!(fz.getZero(), GenericGF::buildMonomial(FIELD, 1, 0)); assert_eq!( fz.getZero(), - GenericGF::buildMonomial(FIELD.clone(), 1, 2).multiply_with_scalar(0) + GenericGF::buildMonomial(FIELD, 1, 2).multiply_with_scalar(0) ); } #[test] fn testEvaluate() { - let FIELD = Rc::new(super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256)); + let FIELD = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256); - assert_eq!(3, GenericGF::buildMonomial(FIELD.clone(), 0, 3).evaluateAt(0)); + assert_eq!(3, GenericGF::buildMonomial(FIELD, 0, 3).evaluateAt(0)); } diff --git a/src/common/reedsolomon/ReedSolomonTestCase.rs b/src/common/reedsolomon/ReedSolomonTestCase.rs index 7a24f19..ff63b95 100644 --- a/src/common/reedsolomon/ReedSolomonTestCase.rs +++ b/src/common/reedsolomon/ReedSolomonTestCase.rs @@ -1,6 +1,6 @@ use rand::Rng; -use super::{GenericGF, ReedSolomonDecoder, ReedSolomonEncoder}; +use super::{GenericGF, ReedSolomonDecoder, ReedSolomonEncoder, GenericGFRef}; /* * Copyrigh&t 2013 ZXing authors * @@ -52,9 +52,9 @@ fn test_data_matrix() { ], ); // synthetic test cases - test_encode_decode_random(dm256.clone(), 220, 35); - test_encode_decode_random(dm256.clone(), 10, 240); - test_encode_decode_random(dm256.clone(), 128, 127); + test_encode_decode_random(dm256, 220, 35); + test_encode_decode_random(dm256, 10, 240); + test_encode_decode_random(dm256, 128, 127); } #[test] @@ -83,9 +83,9 @@ fn test_qr_code() { ); // real life test cases // synthetic test cases - test_encode_decode_random(qrcf256.clone(), 10, 240); - test_encode_decode_random(qrcf256.clone(), 128, 127); - test_encode_decode_random(qrcf256.clone(), 220, 35); + test_encode_decode_random(qrcf256, 10, 240); + test_encode_decode_random(qrcf256, 128, 127); + test_encode_decode_random(qrcf256, 220, 35); } #[test] @@ -329,15 +329,15 @@ fn test_aztec() { let azd10 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10); let azd12 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12); - test_encode_decode_random(azp.clone(), 2, 5); // compact mode message - test_encode_decode_random(azp.clone(), 4, 6); // full mode message - test_encode_decode_random(azd6.clone(), 10, 7); - test_encode_decode_random(azd6.clone(), 20, 12); - test_encode_decode_random(azd8.clone(), 20, 11); - test_encode_decode_random(azd8.clone(), 128, 127); - test_encode_decode_random(azd10.clone(), 128, 128); - test_encode_decode_random(azd10.clone(), 768, 255); - test_encode_decode_random(azd12.clone(), 3072, 1023); + test_encode_decode_random(azp, 2, 5); // compact mode message + test_encode_decode_random(azp, 4, 6); // full mode message + test_encode_decode_random(azd6, 10, 7); + test_encode_decode_random(azd6, 20, 12); + test_encode_decode_random(azd8, 20, 11); + test_encode_decode_random(azd8, 128, 127); + test_encode_decode_random(azd10, 128, 128); + test_encode_decode_random(azd10, 768, 255); + test_encode_decode_random(azd12, 3072, 1023); } fn corrupt(received: &mut Vec, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) { @@ -361,7 +361,7 @@ fn corrupt(received: &mut Vec, howMany: i32, random: &mut rand::rngs::Threa } } -fn test_encode_decode_random(field: GenericGF, dataSize: usize, ecSize: usize) { +fn test_encode_decode_random(field: GenericGFRef, dataSize: usize, ecSize: usize) { assert!( dataSize > 0 && dataSize <= field.getSize() - 3, "Invalid data size for {}", @@ -372,7 +372,7 @@ fn test_encode_decode_random(field: GenericGF, dataSize: usize, ecSize: usize) { "Invalid ECC size for {}", field ); - let mut encoder = ReedSolomonEncoder::new(field.clone()); + let mut encoder = ReedSolomonEncoder::new(field); let mut message = vec![0; dataSize + ecSize]; let mut dataWords: Vec = vec![0; dataSize]; let mut ecWords = vec![0; ecSize]; @@ -402,13 +402,13 @@ fn test_encode_decode_random(field: GenericGF, dataSize: usize, ecSize: usize) { } } -fn test_encode_decode(field: &GenericGF, dataWords: &Vec, ecWords: &Vec) { +fn test_encode_decode(field: GenericGFRef, dataWords: &Vec, ecWords: &Vec) { test_encoder(field, dataWords, ecWords); test_decoder(field, dataWords, ecWords); } -fn test_encoder(field: &GenericGF, dataWords: &Vec, ecWords: &Vec) { - let mut encoder = ReedSolomonEncoder::new(field.clone()); +fn test_encoder(field: GenericGFRef, dataWords: &Vec, ecWords: &Vec) { + let mut encoder = ReedSolomonEncoder::new(field); let mut messageExpected = vec![0; dataWords.len() + ecWords.len()]; let mut message = vec![0; dataWords.len() + ecWords.len()]; messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]); @@ -431,8 +431,8 @@ fn test_encoder(field: &GenericGF, dataWords: &Vec, ecWords: &Vec) { ); } -fn test_decoder(field: &GenericGF, dataWords: &Vec, ecWords: &Vec) { - let decoder = ReedSolomonDecoder::new(field.clone()); +fn test_decoder(field: GenericGFRef, dataWords: &Vec, ecWords: &Vec) { + let decoder = ReedSolomonDecoder::new(field); let mut message = vec![0; dataWords.len() + ecWords.len()]; let maxErrors = ecWords.len() / 2; let mut random = get_pseudo_random(); diff --git a/src/common/reedsolomon/mod.rs b/src/common/reedsolomon/mod.rs index d0d30dd..309323e 100644 --- a/src/common/reedsolomon/mod.rs +++ b/src/common/reedsolomon/mod.rs @@ -1,4 +1,4 @@ -use std::{fmt, rc::Rc}; +use std::{fmt}; use crate::Exceptions; use std::hash::Hash; @@ -26,6 +26,19 @@ mod ReedSolomonTestCase; //package com.google.zxing.common.reedsolomon; +pub type GenericGFRef = &'static GenericGF; + +use lazy_static::lazy_static; + +lazy_static! { + static ref AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 + static ref AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1); // x^10 + x^3 + 1 + static ref AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1); // x^6 + x + 1 + static ref AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1); // x^4 + x + 1 + static ref QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + static ref DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 +} + // pub const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 // pub const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1); // x^10 + x^3 + 1 // pub const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1); // x^6 + x + 1 @@ -47,17 +60,17 @@ pub enum PredefinedGenericGF { } /// Replacement for old const options, has the downside of generating new versions whenever one is requested. -pub fn get_predefined_genericgf(request: PredefinedGenericGF) -> GenericGF { +pub fn get_predefined_genericgf(request: PredefinedGenericGF) -> GenericGFRef { match request { - PredefinedGenericGF::AztecData12 => GenericGF::new(0x1069, 4096, 1), // x^12 + x^6 + x^5 + x^3 + 1, - PredefinedGenericGF::AztecData10 => GenericGF::new(0x409, 1024, 1), // x^10 + x^3 + 1 + PredefinedGenericGF::AztecData12 => &AZTEC_DATA_12, // x^12 + x^6 + x^5 + x^3 + 1, + PredefinedGenericGF::AztecData10 => &AZTEC_DATA_10, // x^10 + x^3 + 1 PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => { - GenericGF::new(0x43, 64, 1) + &AZTEC_DATA_6 } // x^6 + x + 1 - PredefinedGenericGF::AztecParam => GenericGF::new(0x13, 16, 1), // x^4 + x + 1 - PredefinedGenericGF::QrCodeField256 => GenericGF::new(0x011D, 256, 0), // x^8 + x^4 + x^3 + x^2 + 1 + PredefinedGenericGF::AztecParam => &AZTEC_PARAM, // x^4 + x + 1 + PredefinedGenericGF::QrCodeField256 => &QR_CODE_FIELD_256, // x^8 + x^4 + x^3 + x^2 + 1 PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => { - GenericGF::new(0x012D, 256, 1) + &DATA_MATRIX_FIELD_256 } // x^8 + x^5 + x^3 + x^2 + 1 } } @@ -172,13 +185,13 @@ impl GenericGF { /** * @return the monomial representing coefficient * x^degree */ - pub fn buildMonomial(source: Rc, degree: usize, coefficient: i32) -> GenericGFPoly { + pub fn buildMonomial(source: GenericGFRef, degree: usize, coefficient: i32) -> GenericGFPoly { if coefficient == 0 { - return GenericGFPoly::new(source.clone(), &vec![0]).unwrap(); + return GenericGFPoly::new(source, &vec![0]).unwrap(); } let mut coefficients = vec![0; degree + 1]; coefficients[0] = coefficient; - return GenericGFPoly::new(source.clone(), &coefficients).unwrap(); + return GenericGFPoly::new(source, &coefficients).unwrap(); } /** @@ -282,7 +295,7 @@ impl fmt::Display for GenericGF { */ #[derive(Debug, Clone)] pub struct GenericGFPoly { - field: Rc, + field: GenericGFRef, coefficients: Vec, } @@ -303,7 +316,7 @@ impl GenericGFPoly { * or if leading coefficient is 0 and this is not a * constant polynomial (that is, it is not the monomial "0") */ - pub fn new(field: Rc, coefficients: &Vec) -> Result { + pub fn new(field: GenericGFRef, coefficients: &Vec) -> Result { if coefficients.len() == 0 { return Err(Exceptions::IllegalArgumentException( "coefficients.len()".to_owned(), @@ -431,7 +444,7 @@ impl GenericGFPoly { ); } - return Ok(GenericGFPoly::new(self.field.clone(), &sumDiff)?); + return Ok(GenericGFPoly::new(self.field, &sumDiff)?); } pub fn multiply(&self, other: &GenericGFPoly) -> Result { @@ -466,7 +479,7 @@ impl GenericGFPoly { ); } } - return Ok(GenericGFPoly::new(self.field.clone(), &product)?); + return Ok(GenericGFPoly::new(self.field, &product)?); } pub fn multiply_with_scalar(&self, scalar: i32) -> GenericGFPoly { @@ -485,15 +498,15 @@ impl GenericGFPoly { .field .multiply(self.coefficients[i], scalar.try_into().unwrap()); } - return GenericGFPoly::new(self.field.clone(), &product).unwrap(); + return GenericGFPoly::new(self.field, &product).unwrap(); } pub fn getZero(&self) -> Self { - GenericGFPoly::new(self.field.clone(), &vec![0]).unwrap() + GenericGFPoly::new(self.field, &vec![0]).unwrap() } pub fn getOne(&self) -> Self { - GenericGFPoly::new(self.field.clone(), &vec![1]).unwrap() + GenericGFPoly::new(self.field, &vec![1]).unwrap() } pub fn multiply_by_monomial( @@ -513,7 +526,7 @@ impl GenericGFPoly { //for (int i = 0; i < size; i++) { product[i] = self.field.multiply(self.coefficients[i], coefficient); } - return Ok(GenericGFPoly::new(self.field.clone(), &product)?); + return Ok(GenericGFPoly::new(self.field, &product)?); } pub fn divide( @@ -551,7 +564,7 @@ impl GenericGFPoly { inverse_denominator_leading_term, ); let term = other.multiply_by_monomial(degree_difference, scale)?; - let iteration_quotient = GenericGF::buildMonomial(self.field.clone(), degree_difference, scale); + let iteration_quotient = GenericGF::buildMonomial(self.field, degree_difference, scale); quotient = quotient.addOrSubtract(&iteration_quotient)?; remainder = remainder.addOrSubtract(&term)?; } @@ -648,12 +661,12 @@ impl fmt::Display for GenericGFPoly { * @author sanfordsquires */ pub struct ReedSolomonDecoder { - field: Rc, + field: GenericGFRef, } impl ReedSolomonDecoder { - pub fn new(field: GenericGF) -> Self { - Self { field: Rc::new(field) } + pub fn new(field: GenericGFRef) -> Self { + Self { field: field } } /** @@ -666,7 +679,7 @@ impl ReedSolomonDecoder { * @throws ReedSolomonException if decoding fails for any reason */ pub fn decode(&self, received: &mut Vec, twoS: i32) -> Result<(), Exceptions> { - let poly = GenericGFPoly::new(self.field.clone(), received).unwrap(); + let poly = GenericGFPoly::new(self.field, received).unwrap(); let mut syndromeCoefficients = vec![0; twoS.try_into().unwrap()]; let mut noError = true; for i in 0..twoS { @@ -686,7 +699,7 @@ impl ReedSolomonDecoder { if noError { return Ok(()); } - let syndrome = match GenericGFPoly::new(self.field.clone(), &syndromeCoefficients) { + let syndrome = match GenericGFPoly::new(self.field, &syndromeCoefficients) { Ok(res) => res, Err(fail) => { return Err(Exceptions::ReedSolomonException( @@ -695,7 +708,7 @@ impl ReedSolomonDecoder { } }; let sigmaOmega = self.runEuclideanAlgorithm( - &GenericGF::buildMonomial(self.field.clone(), twoS.try_into().unwrap(), 1), + &GenericGF::buildMonomial(self.field, twoS.try_into().unwrap(), 1), &syndrome, twoS.try_into().unwrap(), )?; @@ -772,7 +785,7 @@ impl ReedSolomonDecoder { let scale = self .field .multiply(r.getCoefficient(r.getDegree()), dltInverse); - q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field.clone(), degreeDiff, scale)) { + q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale)) { Ok(res) => res, Err(err) => { return Err(Exceptions::ReedSolomonException( @@ -951,15 +964,15 @@ impl ReedSolomonDecoder { * @author William Rucklidge */ pub struct ReedSolomonEncoder { - field: Rc, + field: GenericGFRef, cachedGenerators: Vec, } impl ReedSolomonEncoder { - pub fn new(field: GenericGF) -> Self { - let n = Rc::new(field); + pub fn new(field: GenericGFRef) -> Self { + let n = field; Self { - cachedGenerators: vec![GenericGFPoly::new(n.clone(), &vec![1]).unwrap()], + cachedGenerators: vec![GenericGFPoly::new(n, &vec![1]).unwrap()], field: n, } } @@ -977,7 +990,7 @@ impl ReedSolomonEncoder { nextGenerator = lastGenerator .multiply( &GenericGFPoly::new( - self.field.clone(), + self.field, &vec![ 1, self.field.exp(d as i32 - 1 + self.field.getGeneratorBase()), @@ -1007,7 +1020,7 @@ impl ReedSolomonEncoder { "No data bytes provided".to_owned(), )); } - let fld = self.field.clone(); + let fld = self.field; let generator = self.buildGenerator(ec_bytes); let mut info_coefficients: Vec = vec![0; data_bytes]; info_coefficients[0..data_bytes].clone_from_slice(&to_encode[0..data_bytes]);