cargo fmt

This commit is contained in:
Henry Schimke
2022-10-17 10:51:08 -05:00
parent 111fe47566
commit ae11af8c5b
136 changed files with 2117 additions and 1776 deletions

View File

@@ -14,12 +14,9 @@
* limitations under the License.
*/
use std::{
collections::HashMap,
path::{ PathBuf},
};
use std::{collections::HashMap, path::PathBuf};
use image::{DynamicImage};
use image::DynamicImage;
use crate::{
common::BitMatrix, qrcode::QRCodeWriter, BarcodeFormat, EncodeHintType, EncodeHintValue, Writer,
@@ -85,7 +82,7 @@ fn testQRCodeWriter() {
// The QR should be multiplied up to fit, with extra padding if necessary
let bigEnough = 256;
let writer = QRCodeWriter {};
let matrix = writer.encode_with_hints(
let matrix = writer.encode_with_hints(
"http://www.google.com/",
&BarcodeFormat::QR_CODE,
bigEnough,

View File

@@ -28,21 +28,18 @@ type MaskCondition = fn(u32, u32) -> bool;
fn testMask0() {
testMaskAcrossDimensions(DataMask::DATA_MASK_000, |i, j| ((i + j) % 2 == 0));
testMaskAcrossDimensionsU8(0, |i, j| ((i + j) % 2 == 0));
}
#[test]
fn testMask1() {
testMaskAcrossDimensions(DataMask::DATA_MASK_001, |i, j| i % 2 == 0);
testMaskAcrossDimensionsU8(1, |i, j| i % 2 == 0);
}
#[test]
fn testMask2() {
testMaskAcrossDimensions(DataMask::DATA_MASK_010, |i, j| j % 3 == 0);
testMaskAcrossDimensionsU8(2, |i, j| j % 3 == 0);
}
#[test]
@@ -62,9 +59,7 @@ fn testMask5() {
testMaskAcrossDimensions(DataMask::DATA_MASK_101, |i, j| {
(i * j) % 2 + (i * j) % 3 == 0
});
testMaskAcrossDimensionsU8(5, |i, j| {
(i * j) % 2 + (i * j) % 3 == 0
});
testMaskAcrossDimensionsU8(5, |i, j| (i * j) % 2 + (i * j) % 3 == 0);
}
#[test]
@@ -72,9 +67,7 @@ fn testMask6() {
testMaskAcrossDimensions(DataMask::DATA_MASK_110, |i, j| {
((i * j) % 2 + (i * j) % 3) % 2 == 0
});
testMaskAcrossDimensionsU8(6, |i, j| {
((i * j) % 2 + (i * j) % 3) % 2 == 0
});
testMaskAcrossDimensionsU8(6, |i, j| ((i * j) % 2 + (i * j) % 3) % 2 == 0);
}
#[test]
@@ -82,9 +75,7 @@ fn testMask7() {
testMaskAcrossDimensions(DataMask::DATA_MASK_111, |i, j| {
((i + j) % 2 + (i * j) % 3) % 2 == 0
});
testMaskAcrossDimensionsU8(7, |i, j| {
((i + j) % 2 + (i * j) % 3) % 2 == 0
});
testMaskAcrossDimensionsU8(7, |i, j| ((i + j) % 2 + (i * j) % 3) % 2 == 0);
}
fn testMaskAcrossDimensionsU8(mask: u8, condition: MaskCondition) {

View File

@@ -14,57 +14,97 @@
* limitations under the License.
*/
use crate::qrcode::decoder::{FormatInformation, ErrorCorrectionLevel};
use crate::qrcode::decoder::{ErrorCorrectionLevel, FormatInformation};
/**
* @author Sean Owen
*/
const MASKED_TEST_FORMAT_INFO: u32 = 0x2BED;
const UNMASKED_TEST_FORMAT_INFO: u32 = MASKED_TEST_FORMAT_INFO ^ 0x5412;
const MASKED_TEST_FORMAT_INFO : u32 = 0x2BED;
const UNMASKED_TEST_FORMAT_INFO : u32= MASKED_TEST_FORMAT_INFO ^ 0x5412;
#[test]
fn testBitsDiffering() {
#[test]
fn testBitsDiffering() {
assert_eq!(0, FormatInformation::numBitsDiffering(1, 1));
assert_eq!(1, FormatInformation::numBitsDiffering(0, 2));
assert_eq!(2, FormatInformation::numBitsDiffering(1, 2));
assert_eq!(32, FormatInformation::numBitsDiffering(-1i32 as u32, 0));
}
}
#[test]
fn testDecode() {
#[test]
fn testDecode() {
// Normal case
let expected =
FormatInformation::decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
let expected = FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO,
MASKED_TEST_FORMAT_INFO,
);
assert!(expected.is_some());
let expected = expected.unwrap();
assert_eq!( 0x07, expected.getDataMask());
assert_eq!(0x07, expected.getDataMask());
assert_eq!(ErrorCorrectionLevel::Q, expected.getErrorCorrectionLevel());
// where the code forgot the mask!
assert_eq!(expected,
FormatInformation::decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO).expect("return"));
}
assert_eq!(
expected,
FormatInformation::decodeFormatInformation(
UNMASKED_TEST_FORMAT_INFO,
MASKED_TEST_FORMAT_INFO
)
.expect("return")
);
}
#[test]
fn testDecodeWithBitDifference() {
let expected =
FormatInformation::decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO).unwrap();
#[test]
fn testDecodeWithBitDifference() {
let expected = FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO,
MASKED_TEST_FORMAT_INFO,
)
.unwrap();
// 1,2,3,4 bits difference
assert_eq!(expected, FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x01, MASKED_TEST_FORMAT_INFO ^ 0x01).expect("return"));
assert_eq!(expected, FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x03).expect("return"));
assert_eq!(expected, FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x07, MASKED_TEST_FORMAT_INFO ^ 0x07).expect("return"));
assert_eq!(
expected,
FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x01,
MASKED_TEST_FORMAT_INFO ^ 0x01
)
.expect("return")
);
assert_eq!(
expected,
FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x03,
MASKED_TEST_FORMAT_INFO ^ 0x03
)
.expect("return")
);
assert_eq!(
expected,
FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x07,
MASKED_TEST_FORMAT_INFO ^ 0x07
)
.expect("return")
);
assert!(FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x0F, MASKED_TEST_FORMAT_INFO ^ 0x0F).is_none());
}
MASKED_TEST_FORMAT_INFO ^ 0x0F,
MASKED_TEST_FORMAT_INFO ^ 0x0F
)
.is_none());
}
#[test]
fn testDecodeWithMisread() {
let expected =
FormatInformation::decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO).unwrap();
assert_eq!(expected, FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x0F).unwrap());
}
#[test]
fn testDecodeWithMisread() {
let expected = FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO,
MASKED_TEST_FORMAT_INFO,
)
.unwrap();
assert_eq!(
expected,
FormatInformation::decodeFormatInformation(
MASKED_TEST_FORMAT_INFO ^ 0x03,
MASKED_TEST_FORMAT_INFO ^ 0x0F
)
.unwrap()
);
}

View File

@@ -18,34 +18,50 @@ use crate::qrcode::decoder::Version;
use super::Mode;
/**
* @author Sean Owen
*/
#[test]
fn testForBits() {
#[test]
fn testForBits() {
assert_eq!(Mode::TERMINATOR, Mode::forBits(0x00).unwrap());
assert_eq!(Mode::NUMERIC, Mode::forBits(0x01).unwrap());
assert_eq!(Mode::ALPHANUMERIC, Mode::forBits(0x02).unwrap());
assert_eq!(Mode::BYTE, Mode::forBits(0x04).unwrap());
assert_eq!(Mode::KANJI, Mode::forBits(0x08).unwrap());
}
}
#[test]
#[should_panic]
fn testBadMode() {
#[test]
#[should_panic]
fn testBadMode() {
assert!(Mode::forBits(0x10).is_ok());
}
}
#[test]
fn testCharacterCount() {
#[test]
fn testCharacterCount() {
// Spot check a few values
assert_eq!(10, Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(5).unwrap()));
assert_eq!(12, Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(26).unwrap()));
assert_eq!(14, Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(40).unwrap()));
assert_eq!(9, Mode::ALPHANUMERIC.getCharacterCountBits(Version::getVersionForNumber(6).unwrap()));
assert_eq!(8, Mode::BYTE.getCharacterCountBits(Version::getVersionForNumber(7).unwrap()));
assert_eq!(8, Mode::KANJI.getCharacterCountBits(Version::getVersionForNumber(8).unwrap()));
}
assert_eq!(
10,
Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(5).unwrap())
);
assert_eq!(
12,
Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(26).unwrap())
);
assert_eq!(
14,
Mode::NUMERIC.getCharacterCountBits(Version::getVersionForNumber(40).unwrap())
);
assert_eq!(
9,
Mode::ALPHANUMERIC.getCharacterCountBits(Version::getVersionForNumber(6).unwrap())
);
assert_eq!(
8,
Mode::BYTE.getCharacterCountBits(Version::getVersionForNumber(7).unwrap())
);
assert_eq!(
8,
Mode::KANJI.getCharacterCountBits(Version::getVersionForNumber(8).unwrap())
);
}

View File

@@ -14,35 +14,36 @@
* limitations under the License.
*/
use crate::{qrcode::decoder::{Version, ErrorCorrectionLevel}, Exceptions};
use crate::{
qrcode::decoder::{ErrorCorrectionLevel, Version},
Exceptions,
};
/**
* @author Sean Owen
*/
#[test]
#[should_panic]
fn testBadVersion() {
#[test]
#[should_panic]
fn testBadVersion() {
assert!(Version::getVersionForNumber(0).is_ok());
}
}
#[test]
fn testVersionForNumber() {
#[test]
fn testVersionForNumber() {
for i in 1..=40 {
// for (int i = 1; i <= 40; i++) {
checkVersion(Version::getVersionForNumber(i), i, 4 * i + 17);
// for (int i = 1; i <= 40; i++) {
checkVersion(Version::getVersionForNumber(i), i, 4 * i + 17);
}
}
}
fn checkVersion( version:Result<&Version,Exceptions>, number:u32, dimension:u32) {
fn checkVersion(version: Result<&Version, Exceptions>, number: u32, dimension: u32) {
assert!(version.is_ok());
let version = version.unwrap();
assert_eq!(number, version.getVersionNumber());
// assertNotNull(version.getAlignmentPatternCenters());
if number > 1 {
assert!(version.getAlignmentPatternCenters().len() > 0);
assert!(version.getAlignmentPatternCenters().len() > 0);
}
assert_eq!(dimension, version.getDimensionForVersion());
let _tmp = version.getECBlocksForLevel(ErrorCorrectionLevel::H);
@@ -56,18 +57,23 @@ use crate::{qrcode::decoder::{Version, ErrorCorrectionLevel}, Exceptions};
// assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel::M));
// assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel::Q));
// assertNotNull(version.buildFunctionPattern());
}
}
#[test]
fn testGetProvisionalVersionForDimension() {
#[test]
fn testGetProvisionalVersionForDimension() {
for i in 1..=40 {
// for (int i = 1; i <= 40; i++) {
assert_eq!(i, Version::getProvisionalVersionForDimension(4 * i + 17).expect("must exist for supplied values").getVersionNumber());
// for (int i = 1; i <= 40; i++) {
assert_eq!(
i,
Version::getProvisionalVersionForDimension(4 * i + 17)
.expect("must exist for supplied values")
.getVersionNumber()
);
}
}
}
#[test]
fn testDecodeVersionInformation() {
#[test]
fn testDecodeVersionInformation() {
// Spot check
doTestVersion(7, 0x07C94);
doTestVersion(12, 0x0C762);
@@ -75,11 +81,10 @@ use crate::{qrcode::decoder::{Version, ErrorCorrectionLevel}, Exceptions};
doTestVersion(22, 0x168C9);
doTestVersion(27, 0x1B08E);
doTestVersion(32, 0x209D5);
}
fn doTestVersion( expectedVersion:u32, mask:u32) {
}
fn doTestVersion(expectedVersion: u32, mask: u32) {
let version = Version::decodeVersionInformation(mask);
assert!(version.is_ok());
assert_eq!(expectedVersion, version.unwrap().getVersionNumber());
}
}

View File

@@ -82,7 +82,7 @@ impl BitMatrixParser {
let dimension = self.bitMatrix.getHeight();
let mut formatInfoBits2 = 0;
let jMin = dimension - 7;
for j in (jMin..=dimension-1).rev() {
for j in (jMin..=dimension - 1).rev() {
// for (int j = dimension - 1; j >= jMin; j--) {
formatInfoBits2 = self.copyBit(8, j, formatInfoBits2);
}

View File

@@ -16,7 +16,7 @@
use crate::Exceptions;
use super::{VersionRef, ErrorCorrectionLevel};
use super::{ErrorCorrectionLevel, VersionRef};
/**
* <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into
@@ -26,118 +26,120 @@ use super::{VersionRef, ErrorCorrectionLevel};
* @author Sean Owen
*/
pub struct DataBlock {
numDataCodewords:u32,
codewords:Vec<u8>,
numDataCodewords: u32,
codewords: Vec<u8>,
}
impl DataBlock {
fn new( numDataCodewords:u32, codewords:Vec<u8>) -> Self{
Self{
numDataCodewords,
codewords,
}
}
/**
* <p>When QR Codes use multiple data blocks, they are actually interleaved.
* That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
* method will separate the data into original blocks.</p>
*
* @param rawCodewords bytes as read directly from the QR Code
* @param version version of the QR Code
* @param ecLevel error-correction level of the QR Code
* @return DataBlocks containing original bytes, "de-interleaved" from representation in the
* QR Code
*/
pub fn getDataBlocks( rawCodewords:&[u8],
version:VersionRef,
ecLevel:ErrorCorrectionLevel) -> Result<Vec<Self>,Exceptions> {
if rawCodewords.len() as u32 != version.getTotalCodewords() {
return Err(Exceptions::IllegalArgumentException("".to_owned()))
fn new(numDataCodewords: u32, codewords: Vec<u8>) -> Self {
Self {
numDataCodewords,
codewords,
}
}
// Figure out the number and size of data blocks used by this version and
// error correction level
let ecBlocks = version.getECBlocksForLevel(ecLevel);
/**
* <p>When QR Codes use multiple data blocks, they are actually interleaved.
* That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
* method will separate the data into original blocks.</p>
*
* @param rawCodewords bytes as read directly from the QR Code
* @param version version of the QR Code
* @param ecLevel error-correction level of the QR Code
* @return DataBlocks containing original bytes, "de-interleaved" from representation in the
* QR Code
*/
pub fn getDataBlocks(
rawCodewords: &[u8],
version: VersionRef,
ecLevel: ErrorCorrectionLevel,
) -> Result<Vec<Self>, Exceptions> {
if rawCodewords.len() as u32 != version.getTotalCodewords() {
return Err(Exceptions::IllegalArgumentException("".to_owned()));
}
// First count the total number of data blocks
let mut _totalBlocks = 0;
let ecBlockArray = ecBlocks.getECBlocks();
for ecBlock in ecBlockArray {
// for (Version.ECB ecBlock : ecBlockArray) {
_totalBlocks += ecBlock.getCount();
// Figure out the number and size of data blocks used by this version and
// error correction level
let ecBlocks = version.getECBlocksForLevel(ecLevel);
// First count the total number of data blocks
let mut _totalBlocks = 0;
let ecBlockArray = ecBlocks.getECBlocks();
for ecBlock in ecBlockArray {
// for (Version.ECB ecBlock : ecBlockArray) {
_totalBlocks += ecBlock.getCount();
}
// Now establish DataBlocks of the appropriate size and number of data codewords
let mut result = Vec::new();
let mut numRXingResultBlocks = 0;
for ecBlock in ecBlockArray {
// for (Version.ECB ecBlock : ecBlockArray) {
for _i in 0..ecBlock.getCount() {
// for (int i = 0; i < ecBlock.getCount(); i++) {
let numDataCodewords = ecBlock.getDataCodewords();
let numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;
// result[numRXingResultBlocks] = DataBlock::new(numDataCodewords, vec![0u8;numBlockCodewords as usize]);
result.push(DataBlock::new(
numDataCodewords,
vec![0u8; numBlockCodewords as usize],
));
numRXingResultBlocks += 1;
}
}
// All blocks have the same amount of data, except that the last n
// (where n may be 0) have 1 more byte. Figure out where these start.
let shorterBlocksTotalCodewords = result[0].codewords.len();
let mut longerBlocksStartAt = result.len() - 1;
loop {
//while longerBlocksStartAt >= 0 {
let numCodewords = result[longerBlocksStartAt].codewords.len();
if numCodewords == shorterBlocksTotalCodewords {
break;
}
longerBlocksStartAt -= 1;
}
longerBlocksStartAt += 1;
let shorterBlocksNumDataCodewords =
shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock() as usize;
// The last elements of result may be 1 element longer;
// first fill out as many elements as all of them have
let mut rawCodewordsOffset = 0;
for i in 0..shorterBlocksNumDataCodewords {
// for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
for j in 0..numRXingResultBlocks {
// for (int j = 0; j < numRXingResultBlocks; j++) {
result[j].codewords[i] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
}
// Fill out the last data block in the longer ones
for j in longerBlocksStartAt..numRXingResultBlocks {
// for (int j = longerBlocksStartAt; j < numRXingResultBlocks; j++) {
result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
// Now add in error correction blocks
let max = result[0].codewords.len();
for i in shorterBlocksNumDataCodewords..max {
// for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
for j in 0..numRXingResultBlocks {
// for (int j = 0; j < numRXingResultBlocks; j++) {
let iOffset = if j < longerBlocksStartAt { i } else { i + 1 };
result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
}
Ok(result)
}
// Now establish DataBlocks of the appropriate size and number of data codewords
let mut result = Vec::new();
let mut numRXingResultBlocks = 0;
for ecBlock in ecBlockArray {
// for (Version.ECB ecBlock : ecBlockArray) {
for _i in 0..ecBlock.getCount() {
// for (int i = 0; i < ecBlock.getCount(); i++) {
let numDataCodewords = ecBlock.getDataCodewords();
let numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;
// result[numRXingResultBlocks] = DataBlock::new(numDataCodewords, vec![0u8;numBlockCodewords as usize]);
result.push( DataBlock::new(numDataCodewords, vec![0u8;numBlockCodewords as usize]));
numRXingResultBlocks += 1;
}
pub fn getNumDataCodewords(&self) -> u32 {
self.numDataCodewords
}
// All blocks have the same amount of data, except that the last n
// (where n may be 0) have 1 more byte. Figure out where these start.
let shorterBlocksTotalCodewords = result[0].codewords.len();
let mut longerBlocksStartAt = result.len() - 1;
loop {
//while longerBlocksStartAt >= 0 {
let numCodewords = result[longerBlocksStartAt].codewords.len();
if numCodewords == shorterBlocksTotalCodewords {
break;
}
longerBlocksStartAt-=1;
pub fn getCodewords(&self) -> &[u8] {
&self.codewords
}
longerBlocksStartAt+=1;
let shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock() as usize;
// The last elements of result may be 1 element longer;
// first fill out as many elements as all of them have
let mut rawCodewordsOffset = 0;
for i in 0..shorterBlocksNumDataCodewords {
// for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
for j in 0..numRXingResultBlocks {
// for (int j = 0; j < numRXingResultBlocks; j++) {
result[j].codewords[i] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
}
// Fill out the last data block in the longer ones
for j in longerBlocksStartAt..numRXingResultBlocks{
// for (int j = longerBlocksStartAt; j < numRXingResultBlocks; j++) {
result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
// Now add in error correction blocks
let max = result[0].codewords.len();
for i in shorterBlocksNumDataCodewords..max {
// for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
for j in 0..numRXingResultBlocks {
// for (int j = 0; j < numRXingResultBlocks; j++) {
let iOffset = if j < longerBlocksStartAt {i} else {i + 1};
result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset];
rawCodewordsOffset += 1;
}
}
Ok(result)
}
pub fn getNumDataCodewords(&self) -> u32{
self. numDataCodewords
}
pub fn getCodewords(&self) -> &[u8] {
&self.codewords
}
}

View File

@@ -27,7 +27,7 @@ use crate::{common::BitMatrix, Exceptions};
*
* @author Sean Owen
*/
#[derive(Copy,Clone,Eq, PartialEq)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum DataMask {
// See ISO 18004:2006 6.8.1
/**
@@ -222,15 +222,18 @@ impl TryFrom<u8> for DataMask {
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0=>Ok(DataMask::DATA_MASK_000),
1=>Ok(DataMask::DATA_MASK_001),
2=>Ok(DataMask::DATA_MASK_010),
3=>Ok(DataMask::DATA_MASK_011),
4=>Ok(DataMask::DATA_MASK_100),
5=>Ok(DataMask::DATA_MASK_101),
6=>Ok(DataMask::DATA_MASK_110),
7=>Ok(DataMask::DATA_MASK_111),
_=>Err(Exceptions::IllegalArgumentException(format!("{} is not between 0 and 7",value))),
0 => Ok(DataMask::DATA_MASK_000),
1 => Ok(DataMask::DATA_MASK_001),
2 => Ok(DataMask::DATA_MASK_010),
3 => Ok(DataMask::DATA_MASK_011),
4 => Ok(DataMask::DATA_MASK_100),
5 => Ok(DataMask::DATA_MASK_101),
6 => Ok(DataMask::DATA_MASK_110),
7 => Ok(DataMask::DATA_MASK_111),
_ => Err(Exceptions::IllegalArgumentException(format!(
"{} is not between 0 and 7",
value
))),
}
}
}
}

View File

@@ -286,17 +286,19 @@ fn decodeByteSegment(
encoding = CharacterSetECI::getCharset(currentCharacterSetECI.as_ref().unwrap());
}
let encode_string = if currentCharacterSetECI.is_some() && currentCharacterSetECI.as_ref().unwrap() == &CharacterSetECI::Cp437 {
{
use codepage_437::BorrowFromCp437;
use codepage_437::CP437_CONTROL;
let encode_string = if currentCharacterSetECI.is_some()
&& currentCharacterSetECI.as_ref().unwrap() == &CharacterSetECI::Cp437
{
{
use codepage_437::BorrowFromCp437;
use codepage_437::CP437_CONTROL;
String::borrow_from_cp437(&readBytes, &CP437_CONTROL)
}
}else {
encoding
.decode(&readBytes, encoding::DecoderTrap::Strict)
.unwrap()
String::borrow_from_cp437(&readBytes, &CP437_CONTROL)
}
} else {
encoding
.decode(&readBytes, encoding::DecoderTrap::Strict)
.unwrap()
};
// let encode_string = encoding

View File

@@ -198,7 +198,7 @@ fn correctErrors(codewordBytes: &mut [u8], numDataCodewords: usize) -> Result<()
codewordsInts[i] = codewordBytes[i]; // & 0xFF;
}
let mut sending_code_words : Vec<i32> = codewordsInts.iter().map(|x| *x as i32).collect();
let mut sending_code_words: Vec<i32> = codewordsInts.iter().map(|x| *x as i32).collect();
if let Err(e) = RS_DECODER.decode(
&mut sending_code_words,

View File

@@ -88,15 +88,15 @@ impl From<ErrorCorrectionLevel> for u8 {
}
impl FromStr for ErrorCorrectionLevel {
type Err=Exceptions;
type Err = Exceptions;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// First try to see if the string is just the name of the value
let as_str = match s.to_uppercase().as_str() {
"L" => Some(ErrorCorrectionLevel::L),
"M" => Some(ErrorCorrectionLevel::M),
"Q" =>Some(ErrorCorrectionLevel::Q),
"H" =>Some(ErrorCorrectionLevel::H),
"Q" => Some(ErrorCorrectionLevel::Q),
"H" => Some(ErrorCorrectionLevel::H),
_ => None,
};
@@ -110,7 +110,10 @@ impl FromStr for ErrorCorrectionLevel {
return number_possible.unwrap().try_into();
}
return Err(Exceptions::IllegalArgumentException(format!("could not parse {} into an ec level", s)))
return Err(Exceptions::IllegalArgumentException(format!(
"could not parse {} into an ec level",
s
)));
}
}

View File

@@ -101,12 +101,12 @@ impl FormatInformation {
) -> Option<FormatInformation> {
let formatInfo = Self::doDecodeFormatInformation(masked_format_info1, masked_format_info2);
if formatInfo.is_some() {
return formatInfo
return formatInfo;
}
// Should return null, but, some QR codes apparently
// do not mask this info. Try again by actually masking the pattern
// first
Self::doDecodeFormatInformation(
Self::doDecodeFormatInformation(
masked_format_info1 ^ FORMAT_INFO_MASK_QR,
masked_format_info2 ^ FORMAT_INFO_MASK_QR,
)

View File

@@ -1,32 +1,32 @@
mod version;
mod mode;
mod error_correction_level;
mod format_information;
mod data_block;
mod qr_code_decoder_meta_data;
mod data_mask;
mod bit_matrix_parser;
mod data_block;
mod data_mask;
pub mod decoded_bit_stream_parser;
pub mod decoder;
mod error_correction_level;
mod format_information;
mod mode;
mod qr_code_decoder_meta_data;
mod version;
#[cfg(test)]
mod ErrorCorrectionLevelTestCase;
#[cfg(test)]
mod ModeTestCase;
#[cfg(test)]
mod VersionTestCase;
#[cfg(test)]
mod FormatInformationTestCase;
#[cfg(test)]
mod DataMaskTestCase;
#[cfg(test)]
mod DecodedBitStreamParserTestCase;
#[cfg(test)]
mod ErrorCorrectionLevelTestCase;
#[cfg(test)]
mod FormatInformationTestCase;
#[cfg(test)]
mod ModeTestCase;
#[cfg(test)]
mod VersionTestCase;
pub use version::*;
pub use mode::*;
pub use bit_matrix_parser::*;
pub use data_block::*;
pub use data_mask::*;
pub use error_correction_level::*;
pub use format_information::*;
pub use data_block::*;
pub use mode::*;
pub use qr_code_decoder_meta_data::*;
pub use data_mask::*;
pub use bit_matrix_parser::*;
pub use version::*;

View File

@@ -24,31 +24,30 @@ use crate::RXingResultPoint;
*/
pub struct QRCodeDecoderMetaData(bool);
impl QRCodeDecoderMetaData {
pub fn new( mirrored:bool) -> Self {
Self(mirrored)
}
/**
* @return true if the QR Code was mirrored.
*/
pub fn isMirrored(&self) -> bool{
self.0
}
/**
* Apply the result points' order correction due to mirroring.
*
* @param points Array of points to apply mirror correction to.
*/
pub fn applyMirroredCorrection(&self, points : &mut [RXingResultPoint]) {
if !self.0 || points.is_empty() || points.len() < 3 {
return
impl QRCodeDecoderMetaData {
pub fn new(mirrored: bool) -> Self {
Self(mirrored)
}
let bottom_left = points[0];
points[0] = points[2];
points[2] = bottom_left;
// No need to 'fix' top-left and alignment pattern.
}
/**
* @return true if the QR Code was mirrored.
*/
pub fn isMirrored(&self) -> bool {
self.0
}
/**
* Apply the result points' order correction due to mirroring.
*
* @param points Array of points to apply mirror correction to.
*/
pub fn applyMirroredCorrection(&self, points: &mut [RXingResultPoint]) {
if !self.0 || points.is_empty() || points.len() < 3 {
return;
}
let bottom_left = points[0];
points[0] = points[2];
points[2] = bottom_left;
// No need to 'fix' top-left and alignment pattern.
}
}

View File

@@ -156,7 +156,7 @@ impl Version {
/**
* See ISO 18004:2006 Annex E
*/
pub fn buildFunctionPattern(&self) -> Result<BitMatrix,Exceptions> {
pub fn buildFunctionPattern(&self) -> Result<BitMatrix, Exceptions> {
let dimension = self.getDimensionForVersion();
let mut bitMatrix = BitMatrix::with_single_dimension(dimension);
@@ -932,7 +932,7 @@ impl fmt::Display for Version {
* will be the same across all blocks within one version.</p>
*/
#[derive(Debug)]
pub struct ECBlocks {
pub struct ECBlocks {
ecCodewordsPerBlock: u32,
ecBlocks: Vec<ECB>,
}

View File

@@ -24,7 +24,7 @@ use crate::{RXingResultPoint, ResultPoint};
*
* @author Sean Owen
*/
#[derive(Debug,Clone, Copy,PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AlignmentPattern {
estimatedModuleSize: f32,
point: (f32, f32),
@@ -40,7 +40,10 @@ impl ResultPoint for AlignmentPattern {
}
fn into_rxing_result_point(self) -> RXingResultPoint {
RXingResultPoint { x: self.point.0, y: self.point.1 }
RXingResultPoint {
x: self.point.0,
y: self.point.1,
}
}
}

View File

@@ -97,7 +97,7 @@ impl AlignmentPatternFinder {
// Search from middle outwards
let i = (middleI as i32
+ (if (iGen & 0x01) == 0 {
(iGen as i32 + 1) / 2
(iGen as i32 + 1) / 2
} else {
-((iGen as i32 + 1) / 2)
})) as u32;
@@ -172,7 +172,7 @@ impl AlignmentPatternFinder {
* figures the location of the center of this black/white/black run.
*/
fn centerFromEnd(stateCount: &[u32], end: u32) -> f32 {
(end as f32 - stateCount[2] as f32) - stateCount[1] as f32 / 2.0
(end as f32 - stateCount[2] as f32) - stateCount[1] as f32 / 2.0
}
/**
@@ -237,15 +237,21 @@ impl AlignmentPatternFinder {
}
// Now also count down from center
i = startI as i32+ 1;
while i < maxI as i32 && image.get(centerJ, i as u32) && self.crossCheckStateCount[1] <= maxCount {
i = startI as i32 + 1;
while i < maxI as i32
&& image.get(centerJ, i as u32)
&& self.crossCheckStateCount[1] <= maxCount
{
self.crossCheckStateCount[1] += 1;
i += 1;
}
if i == maxI as i32 || self.crossCheckStateCount[1] > maxCount {
return f32::NAN;
}
while i < maxI as i32 && !image.get(centerJ, i as u32) && self.crossCheckStateCount[2] <= maxCount {
while i < maxI as i32
&& !image.get(centerJ, i as u32)
&& self.crossCheckStateCount[2] <= maxCount
{
self.crossCheckStateCount[2] += 1;
i += 1;
}
@@ -288,7 +294,7 @@ impl AlignmentPatternFinder {
) -> Option<AlignmentPattern> {
let stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
let centerJ = Self::centerFromEnd(stateCount, j);
let centerI = self.crossCheckVertical(
let centerI = self.crossCheckVertical(
i,
centerJ.floor() as u32,
2 * stateCount[1],

View File

@@ -18,8 +18,7 @@ use std::collections::HashMap;
use crate::{
common::{
detector::MathUtils, BitMatrix, DefaultGridSampler, GridSampler,
PerspectiveTransform,
detector::MathUtils, BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform,
},
qrcode::decoder::Version,
result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
@@ -338,10 +337,11 @@ impl Detector {
let mut scale = 1.0;
let mut otherToX = fromX as i32 - (toX as i32 - fromX as i32);
if otherToX < 0 {
scale = fromX as f32 / (fromX as i32- otherToX) as f32;
scale = fromX as f32 / (fromX as i32 - otherToX) as f32;
otherToX = 0;
} else if otherToX as u32 >= self.image.getWidth() {
scale = (self.image.getWidth() as i32 - 1 - fromX as i32) as f32 / (otherToX - fromX as i32) as f32;
scale = (self.image.getWidth() as i32 - 1 - fromX as i32) as f32
/ (otherToX - fromX as i32) as f32;
otherToX = self.image.getWidth() as i32 - 1;
}
let mut otherToY = (fromY as f32 - (toY as f32 - fromY as f32) * scale).floor() as i32;
@@ -351,12 +351,18 @@ impl Detector {
scale = fromY as f32 / (fromY as i32 - otherToY) as f32;
otherToY = 0;
} else if otherToY as u32 >= self.image.getHeight() {
scale = (self.image.getHeight() as i32 - 1 - fromY as i32) as f32 / (otherToY - fromY as i32) as f32;
scale = (self.image.getHeight() as i32 - 1 - fromY as i32) as f32
/ (otherToY - fromY as i32) as f32;
otherToY = self.image.getHeight() as i32 - 1;
}
otherToX = (fromX as f32+ (otherToX as f32 - fromX as f32) * scale).floor() as i32;
otherToX = (fromX as f32 + (otherToX as f32 - fromX as f32) * scale).floor() as i32;
result += self.sizeOfBlackWhiteBlackRun(fromX as u32, fromY as u32, otherToX as u32, otherToY as u32);
result += self.sizeOfBlackWhiteBlackRun(
fromX as u32,
fromY as u32,
otherToX as u32,
otherToY as u32,
);
// Middle pixel is double-counted this way; subtract 1
return result - 1.0;
@@ -462,7 +468,7 @@ impl Detector {
// Look for an alignment pattern (3 modules in size) around where it
// should be
let allowance = (allowanceFactor * overallEstModuleSize) as u32;
let alignmentAreaLeftX = 0.max(estAlignmentX as i32- allowance as i32) as u32;
let alignmentAreaLeftX = 0.max(estAlignmentX as i32 - allowance as i32) as u32;
let alignmentAreaRightX = (self.image.getWidth() - 1).min(estAlignmentX + allowance);
if ((alignmentAreaRightX - alignmentAreaLeftX) as f32) < overallEstModuleSize * 3.0 {
return Err(Exceptions::NotFoundException("not found".to_owned()));

View File

@@ -40,7 +40,10 @@ impl ResultPoint for FinderPattern {
}
fn into_rxing_result_point(self) -> RXingResultPoint {
RXingResultPoint { x: self.point.0, y: self.point.1 }
RXingResultPoint {
x: self.point.0,
y: self.point.1,
}
}
}

View File

@@ -16,7 +16,7 @@
use crate::{
common::BitMatrix, result_point_utils, DecodeHintType, DecodingHintDictionary, Exceptions,
RXingResultPointCallback, ResultPoint,
RXingResultPointCallback, ResultPoint,
};
use super::{FinderPattern, FinderPatternInfo};
@@ -76,7 +76,6 @@ impl FinderPatternFinder {
&mut self,
hints: &DecodingHintDictionary,
) -> Result<FinderPatternInfo, Exceptions> {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
let maxI = self.image.getHeight();
let maxJ = self.image.getWidth();
@@ -136,7 +135,9 @@ impl FinderPatternFinder {
// Skip by rowSkip, but back off by stateCount[2] (size of last center
// of pattern we saw) to be conservative, and also back off by iSkip which
// is about to be re-added
i += rowSkip as i32 - stateCount[2] as i32 - iSkip as i32;
i += rowSkip as i32
- stateCount[2] as i32
- iSkip as i32;
// i += rowSkip - stateCount[2] - iSkip ;
j = maxJ - 1;
}
@@ -144,7 +145,7 @@ impl FinderPatternFinder {
} else {
FinderPatternFinder::doShiftCounts2(&mut stateCount);
currentState = 3;
j+=1;
j += 1;
continue;
}
// Clear state to start looking again
@@ -164,7 +165,7 @@ impl FinderPatternFinder {
stateCount[currentState] += 1;
}
}
j+=1;
j += 1;
}
if FinderPatternFinder::foundPatternCross(&stateCount) {
let confirmed = self.handlePossibleCenter(&stateCount, i as u32, maxJ);
@@ -379,7 +380,10 @@ impl FinderPatternFinder {
if i < 0 {
return f32::NAN;
}
while i >= 0 && !self.image.get(centerJ, i as u32) && self.crossCheckStateCount[1] <= maxCount {
while i >= 0
&& !self.image.get(centerJ, i as u32)
&& self.crossCheckStateCount[1] <= maxCount
{
self.crossCheckStateCount[1] += 1;
i -= 1;
}
@@ -387,7 +391,10 @@ impl FinderPatternFinder {
if i < 0 || self.crossCheckStateCount[1] > maxCount {
return f32::NAN;
}
while i >= 0 && self.image.get(centerJ, i as u32) && self.crossCheckStateCount[0] <= maxCount {
while i >= 0
&& self.image.get(centerJ, i as u32)
&& self.crossCheckStateCount[0] <= maxCount
{
self.crossCheckStateCount[0] += 1;
i -= 1;
}
@@ -404,14 +411,20 @@ impl FinderPatternFinder {
if i == maxI {
return f32::NAN;
}
while i < maxI && !self.image.get(centerJ, i as u32) && self.crossCheckStateCount[3] < maxCount {
while i < maxI
&& !self.image.get(centerJ, i as u32)
&& self.crossCheckStateCount[3] < maxCount
{
self.crossCheckStateCount[3] += 1;
i += 1;
}
if i == maxI || self.crossCheckStateCount[3] >= maxCount {
return f32::NAN;
}
while i < maxI && self.image.get(centerJ, i as u32) && self.crossCheckStateCount[4] < maxCount {
while i < maxI
&& self.image.get(centerJ, i as u32)
&& self.crossCheckStateCount[4] < maxCount
{
self.crossCheckStateCount[4] += 1;
i += 1;
}
@@ -426,7 +439,9 @@ impl FinderPatternFinder {
+ self.crossCheckStateCount[2]
+ self.crossCheckStateCount[3]
+ self.crossCheckStateCount[4];
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64) >= 2 * originalStateCountTotal as i64 {
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64)
>= 2 * originalStateCountTotal as i64
{
return f32::NAN;
}
@@ -462,14 +477,20 @@ impl FinderPatternFinder {
if j < 0 {
return f32::NAN;
}
while j >= 0 && !self.image.get(j as u32, centerI) && self.crossCheckStateCount[1] <= maxCount {
while j >= 0
&& !self.image.get(j as u32, centerI)
&& self.crossCheckStateCount[1] <= maxCount
{
self.crossCheckStateCount[1] += 1;
j -= 1;
}
if j < 0 || self.crossCheckStateCount[1] > maxCount {
return f32::NAN;
}
while j >= 0 && self.image.get(j as u32 as u32, centerI) && self.crossCheckStateCount[0] <= maxCount {
while j >= 0
&& self.image.get(j as u32 as u32, centerI)
&& self.crossCheckStateCount[0] <= maxCount
{
self.crossCheckStateCount[0] += 1;
j -= 1;
}
@@ -485,14 +506,20 @@ impl FinderPatternFinder {
if j == maxJ as i32 {
return f32::NAN;
}
while j < maxJ as i32 && !self.image.get(j as u32, centerI) && self.crossCheckStateCount[3] < maxCount {
while j < maxJ as i32
&& !self.image.get(j as u32, centerI)
&& self.crossCheckStateCount[3] < maxCount
{
self.crossCheckStateCount[3] += 1;
j += 1;
}
if j == (maxJ as i32) || self.crossCheckStateCount[3] >= maxCount {
return f32::NAN;
}
while j < (maxJ as i32) && self.image.get(j as u32, centerI) && self.crossCheckStateCount[4] < maxCount {
while j < (maxJ as i32)
&& self.image.get(j as u32, centerI)
&& self.crossCheckStateCount[4] < maxCount
{
self.crossCheckStateCount[4] += 1;
j += 1;
}
@@ -507,7 +534,9 @@ impl FinderPatternFinder {
+ self.crossCheckStateCount[2]
+ self.crossCheckStateCount[3]
+ self.crossCheckStateCount[4];
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64) >= originalStateCountTotal as i64 {
if 5 * (stateCountTotal as i64 - originalStateCountTotal as i64)
>= originalStateCountTotal as i64
{
return f32::NAN;
}
@@ -559,7 +588,8 @@ impl FinderPatternFinder {
let stateCountTotal =
stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
let mut centerJ = Self::centerFromEnd(stateCount, j);
let centerI = self.crossCheckVertical(i, centerJ.floor() as u32, stateCount[2], stateCountTotal);
let centerI =
self.crossCheckVertical(i, centerJ.floor() as u32, stateCount[2], stateCountTotal);
if !centerI.is_nan() {
// Re-cross check
centerJ = self.crossCheckHorizontal(
@@ -568,7 +598,9 @@ impl FinderPatternFinder {
stateCount[2],
stateCountTotal,
);
if !centerJ.is_nan() && self.crossCheckDiagonal(centerI.floor() as u32, centerJ.floor() as u32) {
if !centerJ.is_nan()
&& self.crossCheckDiagonal(centerI.floor() as u32, centerJ.floor() as u32)
{
let estimatedModuleSize = stateCountTotal as f32 / 7.0;
let mut found = false;
for index in 0..self.possibleCenters.len() {

View File

@@ -1,18 +1,18 @@
mod finder_pattern_info;
mod finder_pattern;
mod alignment_pattern;
mod alignment_pattern_finder;
mod finder_pattern_finder;
mod detector;
mod finder_pattern;
mod finder_pattern_finder;
mod finder_pattern_info;
mod qrcode_detector_result;
pub use finder_pattern_info::*;
pub use finder_pattern::*;
pub use alignment_pattern::*;
pub use alignment_pattern_finder::*;
pub use finder_pattern_finder::*;
pub use detector::*;
pub use finder_pattern::*;
pub use finder_pattern_finder::*;
pub use finder_pattern_info::*;
pub use qrcode_detector_result::*;
#[cfg(test)]
mod DetectorTest;
mod DetectorTest;

View File

@@ -1,6 +1,6 @@
use crate::{
common::{BitMatrix, DetectorRXingResult},
RXingResultPoint,
RXingResultPoint,
};
pub struct QRCodeDetectorResult {

View File

@@ -415,7 +415,8 @@ fn testAppendLengthInfo() {
Version::getVersionForNumber(1).unwrap(),
Mode::NUMERIC,
&mut bits,
).expect("ok");
)
.expect("ok");
assert_eq!(" ........ .X", bits.to_string()); // 10 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(
@@ -423,7 +424,8 @@ fn testAppendLengthInfo() {
Version::getVersionForNumber(10).unwrap(),
Mode::ALPHANUMERIC,
&mut bits,
).expect("ok");
)
.expect("ok");
assert_eq!(" ........ .X.", bits.to_string()); // 11 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(
@@ -431,7 +433,8 @@ fn testAppendLengthInfo() {
Version::getVersionForNumber(27).unwrap(),
Mode::BYTE,
&mut bits,
).expect("ok");
)
.expect("ok");
assert_eq!(" ........ XXXXXXXX", bits.to_string()); // 16 bits.
let mut bits = BitArray::new();
encoder::appendLengthInfo(
@@ -439,7 +442,8 @@ fn testAppendLengthInfo() {
Version::getVersionForNumber(40).unwrap(),
Mode::KANJI,
&mut bits,
).expect("ok");
)
.expect("ok");
assert_eq!(" ..X..... ....", bits.to_string()); // 12 bits.
}
@@ -453,7 +457,8 @@ fn testAppendBytes() {
Mode::NUMERIC,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
).expect("ok");
)
.expect("ok");
assert_eq!(" ...X", bits.to_string());
// Should use appendAlphanumericBytes.
// A = 10 = 0xa = 001010 in 6 bits
@@ -463,7 +468,8 @@ fn testAppendBytes() {
Mode::ALPHANUMERIC,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
).expect("ok");
)
.expect("ok");
assert_eq!(" ..X.X.", bits.to_string());
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
//try {
@@ -488,7 +494,8 @@ fn testAppendBytes() {
Mode::BYTE,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
).expect("ok");
)
.expect("ok");
assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string());
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
encoder::appendBytes(
@@ -496,7 +503,8 @@ fn testAppendBytes() {
Mode::BYTE,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
).expect("ok");
)
.expect("ok");
// Should use appendKanjiBytes.
// 0x93, 0x5f
let mut bits = BitArray::new();
@@ -505,7 +513,8 @@ fn testAppendBytes() {
Mode::KANJI,
&mut bits,
encoder::DEFAULT_BYTE_MODE_ENCODING,
).expect("ok");
)
.expect("ok");
assert_eq!(" .XX.XX.. XXXXX", bits.to_string());
}
@@ -540,80 +549,45 @@ fn testTerminateBits() {
#[test]
fn testGetNumDataBytesAndNumECBytesForBlockID() {
// Version 1-H.
let (numDataBytes,numEcBytes) = encoder::getNumDataBytesAndNumECBytesForBlockID(
26,
9,
1,
0,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0).expect("ok");
assert_eq!(9, numDataBytes);
assert_eq!(17, numEcBytes);
// Version 3-H. 2 blocks.
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
70,
26,
2,
0,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0).expect("ok");
assert_eq!(13, numDataBytes);
assert_eq!(22, numEcBytes);
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
70,
26,
2,
1,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1).expect("ok");
assert_eq!(13, numDataBytes);
assert_eq!(22, numEcBytes);
// Version 7-H. (4 + 1) blocks.
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
196,
66,
5,
0,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0).expect("ok");
assert_eq!(13, numDataBytes);
assert_eq!(26, numEcBytes);
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
196,
66,
5,
4,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4).expect("ok");
assert_eq!(14, numDataBytes);
assert_eq!(26, numEcBytes);
// Version 40-H. (20 + 61) blocks.
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
3706,
1276,
81,
0,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0).expect("ok");
assert_eq!(15, numDataBytes);
assert_eq!(30, numEcBytes);
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
3706,
1276,
81,
20,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20).expect("ok");
assert_eq!(16, numDataBytes);
assert_eq!(30, numEcBytes);
let (numDataBytes,numEcBytes) =encoder::getNumDataBytesAndNumECBytesForBlockID(
3706,
1276,
81,
80,
).expect("ok");
let (numDataBytes, numEcBytes) =
encoder::getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80).expect("ok");
assert_eq!(16, numDataBytes);
assert_eq!(30, numEcBytes);
}
@@ -738,7 +712,8 @@ fn testAppendAlphanumericBytes() {
fn testAppend8BitBytes() {
// 0x61, 0x62, 0x63
let mut bits = BitArray::new();
encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).expect("append");
encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING)
.expect("append");
assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string());
// Empty.
let mut bits = BitArray::new();

View File

@@ -254,7 +254,8 @@ fn testBuildMatrix() {
Version::getVersionForNumber(1).expect("version"), // Version 1
3, // Mask pattern 3
&mut matrix,
).expect("append");
)
.expect("append");
let expected = r" 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1

View File

@@ -14,20 +14,21 @@
* limitations under the License.
*/
use crate::qrcode::{decoder::{Mode, ErrorCorrectionLevel, Version}, encoder::ByteMatrix};
use crate::qrcode::{
decoder::{ErrorCorrectionLevel, Mode, Version},
encoder::ByteMatrix,
};
use super::QRCode;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author mysen@google.com (Chris Mysen) - ported from C++
*/
#[test]
fn test() {
let mut qrCode = QRCode::new();
fn test() {
let mut qrCode = QRCode::new();
// First, test simple setters and getters.
// We use numbers of version 7-H.
@@ -42,43 +43,43 @@ use super::QRCode;
assert_eq!(3, qrCode.getMaskPattern());
// Prepare the matrix.
let mut matrix = ByteMatrix::new(45, 45);
let mut matrix = ByteMatrix::new(45, 45);
// Just set bogus zero/one values.
for y in 0..45 {
// for (int y = 0; y < 45; ++y) {
for x in 0..45 {
// for (int x = 0; x < 45; ++x) {
matrix.set(x, y, ((y + x) % 2) as u8);
}
// for (int y = 0; y < 45; ++y) {
for x in 0..45 {
// for (int x = 0; x < 45; ++x) {
matrix.set(x, y, ((y + x) % 2) as u8);
}
}
// Set the matrix.
qrCode.setMatrix(matrix.clone());
assert_eq!(&matrix, qrCode.getMatrix().as_ref().unwrap());
}
}
#[test]
fn testToString1() {
let qrCode = QRCode::new();
#[test]
fn testToString1() {
let qrCode = QRCode::new();
let expected =
"<<\n mode: null\n ecLevel: null\n version: null\n maskPattern: -1\n matrix: null\n>>\n";
assert_eq!(expected, qrCode.to_string());
}
assert_eq!(expected, qrCode.to_string());
}
#[test]
fn testToString2() {
let mut qrCode = QRCode::new();
#[test]
fn testToString2() {
let mut qrCode = QRCode::new();
qrCode.setMode(Mode::BYTE);
qrCode.setECLevel(ErrorCorrectionLevel::H);
qrCode.setVersion(Version::getVersionForNumber(1).expect("predefined value must exist"));
qrCode.setMaskPattern(3);
let mut matrix = ByteMatrix::new(21, 21);
let mut matrix = ByteMatrix::new(21, 21);
for y in 0..21 {
// for (int y = 0; y < 21; ++y) {
for x in 0..21 {
// for (int x = 0; x < 21; ++x) {
matrix.set(x, y, ((y + x) % 2) as u8);
}
// for (int y = 0; y < 21; ++y) {
for x in 0..21 {
// for (int x = 0; x < 21; ++x) {
matrix.set(x, y, ((y + x) % 2) as u8);
}
}
qrCode.setMatrix(matrix);
let expected = "<<\n \
@@ -110,13 +111,12 @@ use super::QRCode;
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n\
>>\n";
assert_eq!(expected, qrCode.to_string());
}
}
#[test]
fn testIsValidMaskPattern() {
#[test]
fn testIsValidMaskPattern() {
assert!(!QRCode::isValidMaskPattern(-1));
assert!(QRCode::isValidMaskPattern(0));
assert!(QRCode::isValidMaskPattern(7));
assert!(!QRCode::isValidMaskPattern(8));
}
}

View File

@@ -43,7 +43,7 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::{
common::{
reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder},
BitArray, CharacterSetECI,
BitArray, CharacterSetECI,
},
qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef},
EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions,
@@ -155,9 +155,11 @@ pub fn encode_with_hints(
let encoding = if encoding.is_some() {
encoding.unwrap()
} else {
if let Ok(_encs) = DEFAULT_BYTE_MODE_ENCODING.encode(content, encoding::EncoderTrap::Strict){
if let Ok(_encs) =
DEFAULT_BYTE_MODE_ENCODING.encode(content, encoding::EncoderTrap::Strict)
{
DEFAULT_BYTE_MODE_ENCODING
}else {
} else {
has_encoding_hint = true;
encoding::all::UTF_8
}
@@ -302,8 +304,12 @@ fn recommendVersion(
// Hard part: need to know version to know how many bits length takes. But need to know how many
// bits it takes to know version. First we take a guess at version by assuming version will be
// the minimum, 1:
let provisional_bits_needed =
calculateBitsNeeded(mode, header_bits, data_bits, Version::getVersionForNumber(1)?);
let provisional_bits_needed = calculateBitsNeeded(
mode,
header_bits,
data_bits,
Version::getVersionForNumber(1)?,
);
let provisional_version = chooseVersion(provisional_bits_needed, ec_level)?;
// Use that guess to calculate the right version. I am still not sure this works in 100% of cases.

View File

@@ -48,10 +48,10 @@ pub fn applyMaskPenaltyRule2(matrix: &ByteMatrix) -> u32 {
let array = matrix.getArray();
let width = matrix.getWidth();
let height = matrix.getHeight();
for y in 0..(height -1) as usize {
for y in 0..(height - 1) as usize {
// for (int y = 0; y < height - 1; y++) {
let arrayY = &array[y];
for x in 0..(width -1) as usize {
for x in 0..(width - 1) as usize {
// for (int x = 0; x < width - 1; x++) {
let value = arrayY[x];
if value == arrayY[x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1] {
@@ -154,7 +154,8 @@ pub fn applyMaskPenaltyRule4(matrix: &ByteMatrix) -> u32 {
}
}
let numTotalCells = matrix.getHeight() * matrix.getWidth();
let fivePercentVariances = (numDarkCells as i64 * 2 - numTotalCells as i64).abs() as u32 * 10 / numTotalCells;
let fivePercentVariances =
(numDarkCells as i64 * 2 - numTotalCells as i64).abs() as u32 * 10 / numTotalCells;
return fivePercentVariances * N4;
}

View File

@@ -24,7 +24,7 @@ use crate::{
Exceptions,
};
use unicode_segmentation::{ UnicodeSegmentation};
use unicode_segmentation::UnicodeSegmentation;
use super::encoder;
@@ -834,14 +834,15 @@ impl RXingResultList {
}
let first = list.get(0);
// prepend or insert a FNC1_FIRST_POSITION after the ECI (if any)
if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI {//&& containsECI {
if first.is_some() && first.as_ref().unwrap().mode != Mode::ECI {
//&& containsECI {
list.insert(
if first.as_ref().unwrap().mode != Mode::ECI {
//first
list.len()
} else {
//second
list.len()-1
list.len() - 1
},
RXingResultNode::new(
Mode::FNC1_FIRST_POSITION,

View File

@@ -1,23 +1,23 @@
mod qr_code;
mod byte_matrix;
mod block_pair;
mod byte_matrix;
pub mod encoder;
pub mod mask_util;
pub mod matrix_util;
mod minimal_encoder;
pub mod encoder;
mod qr_code;
pub use qr_code::*;
pub use byte_matrix::*;
pub use block_pair::*;
pub use byte_matrix::*;
pub use minimal_encoder::*;
pub use qr_code::*;
#[cfg(test)]
mod QRCodeTestCase;
#[cfg(test)]
mod BitVectorTestCase;
#[cfg(test)]
mod EncoderTestCase;
#[cfg(test)]
mod MaskUtilTestCase;
#[cfg(test)]
mod MatrixUtilTestCase;
#[cfg(test)]
mod EncoderTestCase;
mod QRCodeTestCase;

View File

@@ -16,131 +16,124 @@
use std::fmt;
use crate::qrcode::decoder::{Mode, ErrorCorrectionLevel, Version, VersionRef};
use crate::qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef};
use super::ByteMatrix;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author dswitkin@google.com (Daniel Switkin) - ported from C++
*/
#[derive(Debug, Clone)]
pub struct QRCode {
// public static final int NUM_MASK_PATTERNS = 8;
mode:Option<Mode>,
ecLevel:Option<ErrorCorrectionLevel>,
version:Option<VersionRef>,
maskPattern:i32,
matrix:Option<ByteMatrix>,
// public static final int NUM_MASK_PATTERNS = 8;
mode: Option<Mode>,
ecLevel: Option<ErrorCorrectionLevel>,
version: Option<VersionRef>,
maskPattern: i32,
matrix: Option<ByteMatrix>,
}
impl QRCode {
pub const NUM_MASK_PATTERNS : i32 = 8;
pub const NUM_MASK_PATTERNS: i32 = 8;
pub fn new()->Self {
Self {
mode: None,
ecLevel: None,
version: None,
maskPattern: -1,
matrix: None,
pub fn new() -> Self {
Self {
mode: None,
ecLevel: None,
version: None,
maskPattern: -1,
matrix: None,
}
}
}
/**
* @return the mode. Not relevant if {@link com.google.zxing.EncodeHintType#QR_COMPACT} is selected.
*/
pub fn getMode(&self) -> &Option<Mode>{
&self.mode
}
/**
* @return the mode. Not relevant if {@link com.google.zxing.EncodeHintType#QR_COMPACT} is selected.
*/
pub fn getMode(&self) -> &Option<Mode> {
&self.mode
}
pub fn getECLevel(&self) -> &Option<ErrorCorrectionLevel>{
&self.ecLevel
}
pub fn getECLevel(&self) -> &Option<ErrorCorrectionLevel> {
&self.ecLevel
}
pub fn getVersion(&self) -> &Option<&'static Version>{
&self.version
}
pub fn getVersion(&self) -> &Option<&'static Version> {
&self.version
}
pub fn getMaskPattern(&self) -> i32{
self.maskPattern
}
pub fn getMaskPattern(&self) -> i32 {
self.maskPattern
}
pub fn getMatrix(&self) ->&Option<ByteMatrix>{
&self.matrix
}
pub fn getMatrix(&self) -> &Option<ByteMatrix> {
&self.matrix
}
pub fn setMode(&mut self, value: Mode) {
self.mode = Some(value);
}
pub fn setMode(&mut self, value:Mode) {
self.mode = Some(value);
}
pub fn setECLevel(&mut self, value: ErrorCorrectionLevel) {
self.ecLevel = Some(value);
}
pub fn setECLevel(&mut self, value:ErrorCorrectionLevel) {
self.ecLevel = Some(value);
}
pub fn setVersion(&mut self, version: &'static Version) {
self.version = Some(version);
}
pub fn setVersion(&mut self, version:&'static Version) {
self.version = Some(version);
}
pub fn setMaskPattern(&mut self, value: i32) {
self.maskPattern = value;
}
pub fn setMaskPattern(&mut self, value:i32) {
self.maskPattern = value;
}
pub fn setMatrix(&mut self, value:ByteMatrix) {
self.matrix = Some(value);
}
// Check if "mask_pattern" is valid.
pub fn isValidMaskPattern( maskPattern:i32) -> bool{
maskPattern >= 0 && maskPattern < Self::NUM_MASK_PATTERNS
}
pub fn setMatrix(&mut self, value: ByteMatrix) {
self.matrix = Some(value);
}
// Check if "mask_pattern" is valid.
pub fn isValidMaskPattern(maskPattern: i32) -> bool {
maskPattern >= 0 && maskPattern < Self::NUM_MASK_PATTERNS
}
}
impl fmt::Display for QRCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut result = String::with_capacity(200);
result.push_str("<<\n");
result.push_str(" mode: ");
if self.mode.is_some() {
result.push_str(&format!("{:?}",self.mode.as_ref().unwrap()));
}else {
result.push_str("null");
}
// result.push_str(&format!("{:?}", self.mode));
result.push_str("\n ecLevel: ");
if self.ecLevel.is_some() {
result.push_str(&format!("{:?}",self.ecLevel.as_ref().unwrap()));
}else {
result.push_str("null");
}
// result.push_str(&format!("{:?}", self.ecLevel));
result.push_str("\n version: ");
if self.version.is_some() {
result.push_str(&format!("{}",self.version.as_ref().unwrap()));
}else {
result.push_str("null");
}
result.push_str("\n maskPattern: ");
result.push_str(&format!("{}",self.maskPattern));
if self.matrix.is_none() {
result.push_str("\n matrix: null\n");
} else {
result.push_str("\n matrix:\n");
if self.matrix.is_some() {
result.push_str(&format!("{}",self.matrix.as_ref().unwrap()));
}else {
result.push_str("null");
let mut result = String::with_capacity(200);
result.push_str("<<\n");
result.push_str(" mode: ");
if self.mode.is_some() {
result.push_str(&format!("{:?}", self.mode.as_ref().unwrap()));
} else {
result.push_str("null");
}
}
result.push_str(">>\n");
write!(f, "{}", result)
// result.push_str(&format!("{:?}", self.mode));
result.push_str("\n ecLevel: ");
if self.ecLevel.is_some() {
result.push_str(&format!("{:?}", self.ecLevel.as_ref().unwrap()));
} else {
result.push_str("null");
}
// result.push_str(&format!("{:?}", self.ecLevel));
result.push_str("\n version: ");
if self.version.is_some() {
result.push_str(&format!("{}", self.version.as_ref().unwrap()));
} else {
result.push_str("null");
}
result.push_str("\n maskPattern: ");
result.push_str(&format!("{}", self.maskPattern));
if self.matrix.is_none() {
result.push_str("\n matrix: null\n");
} else {
result.push_str("\n matrix:\n");
if self.matrix.is_some() {
result.push_str(&format!("{}", self.matrix.as_ref().unwrap()));
} else {
result.push_str("null");
}
}
result.push_str(">>\n");
write!(f, "{}", result)
}
}
}

View File

@@ -1,5 +1,5 @@
pub mod detector;
pub mod decoder;
pub mod detector;
pub mod encoder;
mod qr_code_reader;
@@ -9,4 +9,4 @@ mod qr_code_writer;
pub use qr_code_writer::*;
#[cfg(test)]
mod QRCodeWriterTestCase;
mod QRCodeWriterTestCase;

View File

@@ -19,7 +19,7 @@ use std::collections::HashMap;
use crate::{
common::{BitMatrix, DecoderRXingResult, DetectorRXingResult},
BarcodeFormat, DecodeHintType, Exceptions, RXingResult, RXingResultMetadataType,
RXingResultMetadataValue, RXingResultPoint, Reader,
RXingResultMetadataValue, RXingResultPoint, Reader,
};
use super::{
@@ -155,7 +155,7 @@ impl QRCodeReader {
let moduleSize = Self::moduleSize(&leftTopBlack, image)?;
let mut top = leftTopBlack[1] as i32;
let bottom = rightBottomBlack[1] as i32;
let bottom = rightBottomBlack[1] as i32;
let mut left = leftTopBlack[0] as i32;
let mut right = rightBottomBlack[0] as i32;
@@ -193,7 +193,9 @@ impl QRCodeReader {
// But careful that this does not sample off the edge
// "right" is the farthest-right valid pixel location -- right+1 is not necessarily
// This is positive by how much the inner x loop below would be too large
let nudgedTooFarRight = left as i32 + ((matrixWidth as i32 - 1) as f32 * moduleSize as f32) as i32 - right as i32;
let nudgedTooFarRight = left as i32
+ ((matrixWidth as i32 - 1) as f32 * moduleSize as f32) as i32
- right as i32;
if nudgedTooFarRight > 0 {
if nudgedTooFarRight > nudge as i32 {
// Neither way fits; abort