most of reedsolomon test done

This commit is contained in:
Henry Schimke
2022-08-23 14:43:11 -05:00
parent a47796c3b8
commit ce1574b83e
3 changed files with 166 additions and 126 deletions

View File

@@ -7,4 +7,5 @@ edition = "2021"
[dependencies] [dependencies]
regex = "1" regex = "1"
encoding = "0.2" encoding = "0.2"
rand = "0.8.5"

View File

@@ -1,5 +1,8 @@
use rand::Rng;
use super::{ReedSolomonEncoder, GenericGF, ReedSolomonDecoder};
/* /*
* Copyright 2013 ZXing authors * Copyrigh&t 2013 ZXing authors
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,74 +37,74 @@
#[test] #[test]
fn testDataMatrix() { fn testDataMatrix() {
// real life test cases // real life test cases
testEncodeDecode(GenericGF.DATA_MATRIX_FIELD_256, testEncodeDecode(super::DATA_MATRIX_FIELD_256,
new int[] { 142, 164, 186 }, new int[] { 114, 25, 5, 88, 102 }); vec![ 142, 164, 186] , vec![ 114, 25, 5, 88, 102] );
testEncodeDecode(GenericGF.DATA_MATRIX_FIELD_256, testEncodeDecode(super::DATA_MATRIX_FIELD_256,
new int[] { vec! [
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64,
0x70, 0x65, 0x66, 0x2F, 0x68, 0x70, 0x70, 0x68, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70, 0x70, 0x68,
0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71,
0x30, 0x7B, 0x79, 0x6A, 0x6F, 0x68, 0x30, 0x81, 0x30, 0x7B, 0x79, 0x6A, 0x6F, 0x68, 0x30, 0x81,
0xF0, 0x88, 0x1F, 0xB5 0xF0, 0x88, 0x1F, 0xB5
}, ],
new int[] { vec![
0x1C, 0x64, 0xEE, 0xEB, 0xD0, 0x1D, 0x00, 0x03, 0x1C, 0x64, 0xEE, 0xEB, 0xD0, 0x1D, 0x00, 0x03,
0xF0, 0x1C, 0xF1, 0xD0, 0x6D, 0x00, 0x98, 0xDA, 0xF0, 0x1C, 0xF1, 0xD0, 0x6D, 0x00, 0x98, 0xDA,
0x80, 0x88, 0xBE, 0xFF, 0xB7, 0xFA, 0xA9, 0x95 0x80, 0x88, 0xBE, 0xFF, 0xB7, 0xFA, 0xA9, 0x95
}); ]);
// synthetic test cases // synthetic test cases
testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 10, 240); testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 10, 240);
testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 128, 127); testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 128, 127);
testEncodeDecodeRandom(GenericGF.DATA_MATRIX_FIELD_256, 220, 35); testEncodeDecodeRandom(super::DATA_MATRIX_FIELD_256, 220, 35);
} }
#[test] #[test]
fn testQRCode() { fn testQRCode() {
// Test case from example given in ISO 18004, Annex I // Test case from example given in ISO 18004, Annex I
testEncodeDecode(GenericGF.QR_CODE_FIELD_256, testEncodeDecode(super::QR_CODE_FIELD_256,
new int[] { vec![
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11,
0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11
}, ],
new int[] { vec![
0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87,
0x2C, 0x55 0x2C, 0x55
}); ]);
testEncodeDecode(GenericGF.QR_CODE_FIELD_256, testEncodeDecode(super::QR_CODE_FIELD_256,
new int[] { vec![
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F,
0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50, 0x61, 0x67, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50, 0x61, 0x67,
0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11,
0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11
}, ],
new int[] { vec![
0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85, 0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85,
0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8, 0x8B, 0x2E, 0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8, 0x8B, 0x2E,
0x08, 0x62 0x08, 0x62
}); ]);
// real life test cases // real life test cases
// synthetic test cases // synthetic test cases
testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 10, 240); testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 10, 240);
testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 128, 127); testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 128, 127);
testEncodeDecodeRandom(GenericGF.QR_CODE_FIELD_256, 220, 35); testEncodeDecodeRandom(super::QR_CODE_FIELD_256, 220, 35);
} }
#[test] #[test]
fn testAztec() { fn testAztec() {
// real life test cases // real life test cases
testEncodeDecode(GenericGF.AZTEC_PARAM, testEncodeDecode(super::AZTEC_PARAM,
new int[] { 0x5, 0x6 }, new int[] { 0x3, 0x2, 0xB, 0xB, 0x7 }); vec![ 0x5, 0x6] , vec![ 0x3, 0x2, 0xB, 0xB, 0x7] );
testEncodeDecode(GenericGF.AZTEC_PARAM, testEncodeDecode(super::AZTEC_PARAM,
new int[] { 0x0, 0x0, 0x0, 0x9 }, new int[] { 0xA, 0xD, 0x8, 0x6, 0x5, 0x6 }); vec![ 0x0, 0x0, 0x0, 0x9] , vec![ 0xA, 0xD, 0x8, 0x6, 0x5, 0x6] );
testEncodeDecode(GenericGF.AZTEC_PARAM, testEncodeDecode(super::AZTEC_PARAM,
new int[] { 0x2, 0x8, 0x8, 0x7 }, new int[] { 0xE, 0xC, 0xA, 0x9, 0x6, 0x8 }); vec![ 0x2, 0x8, 0x8, 0x7] , vec![ 0xE, 0xC, 0xA, 0x9, 0x6, 0x8] );
testEncodeDecode(GenericGF.AZTEC_DATA_6, new int[] { testEncodeDecode(super::AZTEC_DATA_6, vec![
0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B }, 0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B] ,
new int[] { vec![
0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14 0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14
}); ]);
testEncodeDecode(GenericGF.AZTEC_DATA_8, testEncodeDecode(super::AZTEC_DATA_8,
new int[] { vec![
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6,
0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA, 0xF8, 0xCE, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA, 0xF8, 0xCE,
0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9,
@@ -111,8 +114,8 @@
0x5F, 0x19, 0xD6, 0xFB, 0xD1, 0x0C, 0x85, 0x31, 0x5F, 0x19, 0xD6, 0xFB, 0xD1, 0x0C, 0x85, 0x31,
0xD0, 0x95, 0x2D, 0x8D, 0x73, 0xE1, 0x19, 0x4E, 0xD0, 0x95, 0x2D, 0x8D, 0x73, 0xE1, 0x19, 0x4E,
0x95, 0xB5, 0xF1, 0x9D, 0x6F 0x95, 0xB5, 0xF1, 0x9D, 0x6F
}, ],
new int[] { vec![
0x31, 0xD7, 0x04, 0x46, 0xB2, 0xC1, 0x06, 0x94, 0x31, 0xD7, 0x04, 0x46, 0xB2, 0xC1, 0x06, 0x94,
0x17, 0xE5, 0x0C, 0x2B, 0xA3, 0x99, 0x15, 0x7F, 0x17, 0xE5, 0x0C, 0x2B, 0xA3, 0x99, 0x15, 0x7F,
0x16, 0x3C, 0x66, 0xBA, 0x33, 0xD9, 0xE8, 0x87, 0x16, 0x3C, 0x66, 0xBA, 0x33, 0xD9, 0xE8, 0x87,
@@ -120,9 +123,9 @@
0xED, 0xA1, 0xF8, 0x47, 0x2A, 0x50, 0xA6, 0xBC, 0xED, 0xA1, 0xF8, 0x47, 0x2A, 0x50, 0xA6, 0xBC,
0x53, 0x7D, 0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73, 0x53, 0x7D, 0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73,
0x9F, 0xC1, 0x75 0x9F, 0xC1, 0x75
}); ]);
testEncodeDecode(GenericGF.AZTEC_DATA_10, testEncodeDecode(super::AZTEC_DATA_10,
new int[] { vec![
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD,
0x02E, 0x056, 0x26A, 0x281, 0x1C2, 0x1A6, 0x296, 0x045, 0x02E, 0x056, 0x26A, 0x281, 0x1C2, 0x1A6, 0x296, 0x045,
0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2, 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2,
@@ -165,8 +168,8 @@
0x201, 0x0AA, 0x04E, 0x004, 0x1B0, 0x070, 0x275, 0x154, 0x201, 0x0AA, 0x04E, 0x004, 0x1B0, 0x070, 0x275, 0x154,
0x026, 0x2C1, 0x2B3, 0x154, 0x2AA, 0x256, 0x0C1, 0x044, 0x026, 0x2C1, 0x2B3, 0x154, 0x2AA, 0x256, 0x0C1, 0x044,
0x004, 0x23F 0x004, 0x23F
}, ],
new int[] { vec![
0x379, 0x099, 0x348, 0x010, 0x090, 0x196, 0x09C, 0x1FF, 0x379, 0x099, 0x348, 0x010, 0x090, 0x196, 0x09C, 0x1FF,
0x1B0, 0x32D, 0x244, 0x0DE, 0x201, 0x386, 0x163, 0x11F, 0x1B0, 0x32D, 0x244, 0x0DE, 0x201, 0x386, 0x163, 0x11F,
0x39B, 0x344, 0x3FE, 0x02F, 0x188, 0x113, 0x3D9, 0x102, 0x39B, 0x344, 0x3FE, 0x02F, 0x188, 0x113, 0x3D9, 0x102,
@@ -185,9 +188,9 @@
0x306, 0x3A5, 0x352, 0x351, 0x275, 0x0ED, 0x045, 0x229, 0x306, 0x3A5, 0x352, 0x351, 0x275, 0x0ED, 0x045, 0x229,
0x0BF, 0x05D, 0x253, 0x1BE, 0x02E, 0x35A, 0x0E4, 0x2E9, 0x0BF, 0x05D, 0x253, 0x1BE, 0x02E, 0x35A, 0x0E4, 0x2E9,
0x17A, 0x166, 0x03C, 0x007 0x17A, 0x166, 0x03C, 0x007
}); ]);
testEncodeDecode(GenericGF.AZTEC_DATA_12, testEncodeDecode(super::AZTEC_DATA_12,
new int[] { vec![
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85,
0x69A, 0xA81, 0x709, 0xA6A, 0x584, 0x510, 0x4AA, 0x256, 0x69A, 0xA81, 0x709, 0xA6A, 0x584, 0x510, 0x4AA, 0x256,
0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C,
@@ -342,8 +345,8 @@
0x69C, 0xC41, 0x34C, 0x550, 0x10C, 0x835, 0x429, 0x33C, 0x69C, 0xC41, 0x34C, 0x550, 0x10C, 0x835, 0x429, 0x33C,
0xB33, 0x4D5, 0x509, 0xCCD, 0x550, 0x35B, 0x4E2, 0xAA0, 0xB33, 0x4D5, 0x509, 0xCCD, 0x550, 0x35B, 0x4E2, 0xAA0,
0x5E6, 0x205, 0xB09, 0x99C, 0x09F 0x5E6, 0x205, 0xB09, 0x99C, 0x09F
}, ],
new int[] { vec![
0xD54, 0x221, 0x154, 0x7CD, 0xBF3, 0x112, 0x89B, 0xC5E, 0xD54, 0x221, 0x154, 0x7CD, 0xBF3, 0x112, 0x89B, 0xC5E,
0x9CD, 0x07E, 0xFB6, 0x78F, 0x7FA, 0x16F, 0x377, 0x4B4, 0x9CD, 0x07E, 0xFB6, 0x78F, 0x7FA, 0x16F, 0x377, 0x4B4,
0x62D, 0x475, 0xBC2, 0x861, 0xB72, 0x9D0, 0x76A, 0x5A1, 0x62D, 0x475, 0xBC2, 0x861, 0xB72, 0x9D0, 0x76A, 0x5A1,
@@ -399,100 +402,128 @@
0x36D, 0x08D, 0xC76, 0x1E1, 0x1EC, 0x8D7, 0x231, 0xB68, 0x36D, 0x08D, 0xC76, 0x1E1, 0x1EC, 0x8D7, 0x231, 0xB68,
0x03C, 0x1DE, 0x7DF, 0x2B1, 0x09D, 0xC81, 0xDA4, 0x8F7, 0x03C, 0x1DE, 0x7DF, 0x2B1, 0x09D, 0xC81, 0xDA4, 0x8F7,
0x6B9, 0x947, 0x9B0 0x6B9, 0x947, 0x9B0
}); ]);
// synthetic test cases // synthetic test cases
testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 2, 5); // compact mode message testEncodeDecodeRandom(super::AZTEC_PARAM, 2, 5); // compact mode message
testEncodeDecodeRandom(GenericGF.AZTEC_PARAM, 4, 6); // full mode message testEncodeDecodeRandom(super::AZTEC_PARAM, 4, 6); // full mode message
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 10, 7); testEncodeDecodeRandom(super::AZTEC_DATA_6, 10, 7);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_6, 20, 12); testEncodeDecodeRandom(super::AZTEC_DATA_6, 20, 12);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 20, 11); testEncodeDecodeRandom(super::AZTEC_DATA_8, 20, 11);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_8, 128, 127); testEncodeDecodeRandom(super::AZTEC_DATA_8, 128, 127);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 128, 128); testEncodeDecodeRandom(super::AZTEC_DATA_10, 128, 128);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_10, 768, 255); testEncodeDecodeRandom(super::AZTEC_DATA_10, 768, 255);
testEncodeDecodeRandom(GenericGF.AZTEC_DATA_12, 3072, 1023); testEncodeDecodeRandom(super::AZTEC_DATA_12, 3072, 1023);
} }
fn corrupt(int[] received, int howMany, Random random, int max) { fn corrupt(received : &mut Vec<i32>, howMany:i32, random: &rand::rngs::ThreadRng, max:i32) {
BitSet corrupted = new BitSet(received.length); let corrupted = vec![false;received.len()];
for (int j = 0; j < howMany; j++) { //BitSet corrupted = new BitSet(received.length);
int location = random.nextInt(received.length); let mut skip = false;
int value = random.nextInt(max); for j in 0..howMany{
if (corrupted.get(location) || received[location] == value) { //for (int j = 0; j < howMany; j++) {
j--; if skip {
skip = false;
continue;
}
let location :usize = random.gen_range(0..received.len());
let value = random.gen_range(0..max);
if (corrupted[location] || received[location] == value) {
skip = true;
} else { } else {
corrupted.set(location); corrupted[location] = true;
received[location] = value; received[location] = value;
} }
} }
} }
fn testEncodeDecodeRandom(GenericGF field, int dataSize, int ecSize) { fn testEncodeDecodeRandom( field:GenericGF, dataSize:usize, ecSize:usize) {
assertTrue("Invalid data size for " + field, dataSize > 0 && dataSize <= field.getSize() - 3); assert!(dataSize > 0 && dataSize <= field.getSize() - 3, "Invalid data size for {}" , field);
assertTrue("Invalid ECC size for " + field, ecSize > 0 && ecSize + dataSize <= field.getSize()); assert!(ecSize > 0 && ecSize + dataSize <= field.getSize(),"Invalid ECC size for {}" , field);
ReedSolomonEncoder encoder = new ReedSolomonEncoder(field); let encoder = ReedSolomonEncoder::new(Box::new(field));
int[] message = new int[dataSize + ecSize]; let message =Vec::with_capacity(dataSize + ecSize);
int[] dataWords = new int[dataSize]; let dataWords:Vec<i32> = Vec::with_capacity(dataSize);
int[] ecWords = new int[ecSize]; let ecWords = Vec::with_capacity(ecSize);
Random random = getPseudoRandom(); let random = getPseudoRandom();
int iterations = field.getSize() > 256 ? 1 : DECODER_RANDOM_TEST_ITERATIONS; let iterations = if field.getSize() > 256 { 1} else {DECODER_RANDOM_TEST_ITERATIONS};
for (int i = 0; i < iterations; i++) { for i in 0..iterations{
//for (int i = 0; i < iterations; i++) {
// generate random data // generate random data
for (int k = 0; k < dataSize; k++) { for k in 0..dataSize{
dataWords[k] = random.nextInt(field.getSize()); //for (int k = 0; k < dataSize; k++) {
dataWords[k] = random.gen_range(0..field.getSize().try_into().unwrap());
} }
// generate ECC words // generate ECC words
System.arraycopy(dataWords, 0, message, 0, dataWords.length); message[0..dataWords.len()].clone_from_slice(&dataWords[..]);
encoder.encode(message, ecWords.length); //System.arraycopy(dataWords, 0, message, 0, dataWords.len());
System.arraycopy(message, dataSize, ecWords, 0, ecSize); encoder.encode(&mut message, ecWords.len());
ecWords[0..ecSize].clone_from_slice(&message[dataSize..ecSize]);
//System.arraycopy(message, dataSize, ecWords, 0, ecSize);
// check to see if Decoder can fix up to ecWords/2 random errors // check to see if Decoder can fix up to ecWords/2 random errors
testDecoder(field, dataWords, ecWords); testDecoder(field, dataWords, ecWords);
} }
} }
fn testEncodeDecode(GenericGF field, int[] dataWords, int[] ecWords) { fn testEncodeDecode( field:GenericGF, dataWords:Vec<i32>, ecWords:Vec<i32>) {
testEncoder(field, dataWords, ecWords); testEncoder(field, dataWords, ecWords);
testDecoder(field, dataWords, ecWords); testDecoder(field, dataWords, ecWords);
} }
fn testEncoder(GenericGF field, int[] dataWords, int[] ecWords) { fn testEncoder( field:GenericGF, dataWords:Vec<i32>, ecWords:Vec<i32>) {
ReedSolomonEncoder encoder = new ReedSolomonEncoder(field); let encoder = ReedSolomonEncoder::new(Box::new(field));
int[] messageExpected = new int[dataWords.length + ecWords.length]; let messageExpected = Vec::with_capacity(dataWords.len() + ecWords.len());
int[] message = new int[dataWords.length + ecWords.length]; let message = Vec::with_capacity(dataWords.len() + ecWords.len());
System.arraycopy(dataWords, 0, messageExpected, 0, dataWords.length); System.arraycopy(dataWords, 0, messageExpected, 0, dataWords.len());
System.arraycopy(ecWords, 0, messageExpected, dataWords.length, ecWords.length); System.arraycopy(ecWords, 0, messageExpected, dataWords.len(), ecWords.len());
System.arraycopy(dataWords, 0, message, 0, dataWords.length); System.arraycopy(dataWords, 0, message, 0, dataWords.len());
encoder.encode(message, ecWords.length); encoder.encode(&mut message, ecWords.len());
assertDataEquals("Encode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed", assertDataEquals("Encode in " + field + " (" + dataWords.len() + ',' + ecWords.len() + ") failed",
messageExpected, message); messageExpected, message);
} }
fn testDecoder(GenericGF field, int[] dataWords, int[] ecWords) { fn testDecoder( field:GenericGF, dataWords:Vec<i32>, ecWords:Vec<i32>) {
ReedSolomonDecoder decoder = new ReedSolomonDecoder(field); let decoder = ReedSolomonDecoder::new(field);
int[] message = new int[dataWords.length + ecWords.length]; let message = Vec::with_capacity(dataWords.len() + ecWords.len());
int maxErrors = ecWords.length / 2; let maxErrors = ecWords.len() / 2;
Random random = getPseudoRandom(); let random = getPseudoRandom();
int iterations = field.getSize() > 256 ? 1 : DECODER_TEST_ITERATIONS; let iterations = if field.getSize() > 256 {1} else {DECODER_TEST_ITERATIONS};
for (int j = 0; j < iterations; j++) { for j in 0..iterations {
for (int i = 0; i < ecWords.length; i++) { //for (int j = 0; j < iterations; j++) {
if (i > 10 && i < ecWords.length / 2 - 10) { for i in 0..ecWords.len() {
//for (int i = 0; i < ecWords.length; i++) {
if (i > 10 && i < ecWords.len() / 2 - 10) {
// performance improvement - skip intermediate cases in long-running tests // performance improvement - skip intermediate cases in long-running tests
i += ecWords.length / 10; i += ecWords.len() / 10;
} }
System.arraycopy(dataWords, 0, message, 0, dataWords.length); message[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
System.arraycopy(ecWords, 0, message, dataWords.length, ecWords.length); //System.arraycopy(dataWords, 0, message, 0, dataWords.len());
corrupt(message, i, random, field.getSize()); message[dataWords.len()..ecWords.len()].clone_from_slice(&ecWords[0..dataWords.len()]);
try { //System.arraycopy(ecWords, 0, message, dataWords.len(), ecWords.len());
decoder.decode(message, ecWords.length); corrupt(&mut message, i.try_into().unwrap(), &random, field.getSize().try_into().unwrap());
} catch (ReedSolomonException e) {
match
decoder.decode(message, ecWords.len())
{
Err(e) => {
// fail only if maxErrors exceeded // fail only if maxErrors exceeded
assertTrue("Decode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed at " + assert!(i > maxErrors, "Decode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed at " +
i + " errors: " + e, i + " errors: " + e);
i > maxErrors);
// else stop // else stop
break; break;
} },
Ok(_) => () };
// try {
// decoder.decode(message, ecWords.length);
// } catch (ReedSolomonException e) {
// // fail only if maxErrors exceeded
// assertTrue("Decode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed at " +
// i + " errors: " + e,
// i > maxErrors);
// // else stop
// break;
// }
if (i < maxErrors) { if (i < maxErrors) {
assertDataEquals("Decode in " + field + " (" + dataWords.length + ',' + ecWords.length + ") failed at " + assertDataEquals("Decode in " + field + " (" + dataWords.len() + ',' + ecWords.len() + ") failed at " +
i + " errors", i + " errors",
dataWords, dataWords,
message); message);
@@ -501,25 +532,31 @@
} }
} }
fn assertDataEquals(String message, int[] expected, int[] received) { fn assertDataEquals( message:String, expected:Vec<i32>, received:Vec<i32>) {
for (int i = 0; i < expected.length; i++) { for i in 0..expected.len() {
//for (int i = 0; i < expected.length; i++) {
if (expected[i] != received[i]) { if (expected[i] != received[i]) {
fail(message + ". Mismatch at " + i + ". Expected " + arrayToString(expected) + ", got " + panic!("{}. Mismatch at {}. Expected {}, got {}",message,i,arrayToString(&expected),arrayToString(&received[0..expected.len()]));
arrayToString(Arrays.copyOf(received, expected.length))); //fail();
} }
} }
} }
fn String arrayToString(int[] data) { fn arrayToString( data:&[i32]) -> String{
StringBuilder sb = new StringBuilder("{"); let sb = String::from("{");
for (int i = 0; i < data.length; i++) { for i in 0..data.len() {
sb.append(String.format(i > 0 ? ",%X" : "%X", data[i])); //for (int i = 0; i < data.length; i++) {
//sb.append(String.format(i > 0 ? ",%X" : "%X", data[i]));
sb.push_str(&format!("{}", data[i]));
} }
return sb.append('}').toString(); sb.push_str("}");
sb
} }
fn Random getPseudoRandom() { fn getPseudoRandom() -> rand::rngs::ThreadRng{
return new Random(0xDEADBEEF); rand::thread_rng()
//return new Random(0xDEADBEEF);
} }
//} //}

View File

@@ -5,6 +5,8 @@ use std::hash::Hash;
#[cfg(test)] #[cfg(test)]
mod GenericGFPolyTestCase; mod GenericGFPolyTestCase;
#[cfg(test)]
mod ReedSolomonTestCase;
/* /*
* Copyrigh&t 2007 ZXing authors * Copyrigh&t 2007 ZXing authors
@@ -316,7 +318,7 @@ impl GenericGFPoly {
}) })
} }
pub fn getCoefficients(&self) -> Vec<usize> { pub fn getCoefficients(&self) -> Vec<i32> {
return self.coefficients; return self.coefficients;
} }
@@ -337,7 +339,7 @@ impl GenericGFPoly {
/** /**
* @return coefficient of x^degree term in this polynomial * @return coefficient of x^degree term in this polynomial
*/ */
pub fn getCoefficient(&self, degree: usize) -> usize { pub fn getCoefficient(&self, degree: usize) -> i32 {
return self.coefficients[self.coefficients.len() - 1 - degree]; return self.coefficients[self.coefficients.len() - 1 - degree];
} }