feat: ported qr-model1 support from zxing-cpp

This commit is contained in:
Henry Schimke
2024-01-11 12:53:04 -06:00
parent d2b3bf6c1e
commit eea448ae94
17 changed files with 485 additions and 41 deletions

View File

@@ -67,6 +67,8 @@ pub enum BarcodeFormat {
MICRO_QR_CODE,
RECTANGULAR_MICRO_QR_CODE,
/** RSS 14 */
RSS_14,
@@ -108,6 +110,7 @@ impl Display for BarcodeFormat {
BarcodeFormat::PDF_417 => "pdf 417",
BarcodeFormat::QR_CODE => "qrcode",
BarcodeFormat::MICRO_QR_CODE => "mqr",
BarcodeFormat::RECTANGULAR_MICRO_QR_CODE => "rmqr",
BarcodeFormat::RSS_14 => "rss 14",
BarcodeFormat::RSS_EXPANDED => "rss expanded",
BarcodeFormat::TELEPEN => "telepen",
@@ -150,6 +153,9 @@ impl From<&str> for BarcodeFormat {
"mqr" | "microqr" | "micro_qr" | "micro_qrcode" | "micro_qr_code" | "mqr_code" => {
BarcodeFormat::MICRO_QR_CODE
}
"rmqr" | "rectangular_mqr" | "rectangular_micro_qr" | "rmqr_code" => {
BarcodeFormat::RECTANGULAR_MICRO_QR_CODE
}
"rss 14" | "rss_14" | "rss14" | "gs1 databar" | "gs1 databar coupon"
| "gs1_databar_coupon" => BarcodeFormat::RSS_14,
"rss expanded" | "expanded rss" | "rss_expanded" => BarcodeFormat::RSS_EXPANDED,

View File

@@ -2,6 +2,8 @@ use crate::qrcode::decoder::{
ErrorCorrectionLevel, FormatInformation, FORMAT_INFO_DECODE_LOOKUP, FORMAT_INFO_MASK_QR,
};
pub const FORMAT_INFO_MASK_QR_MODEL1: u32 = 0x2825;
pub const FORMAT_INFO_DECODE_LOOKUP_MICRO: [[u32; 2]; 32] = [
[0x4445, 0x00],
[0x4172, 0x01],
@@ -50,7 +52,7 @@ impl FormatInformation {
let formatInfoBits2 =
((formatInfoBits2 >> 1) & 0b111111100000000) | (formatInfoBits2 & 0b11111111);
let mut fi = Self::FindBestFormatInfo(
FORMAT_INFO_MASK_QR,
&[0, FORMAT_INFO_MASK_QR],
FORMAT_INFO_DECODE_LOOKUP,
&[
formatInfoBits1,
@@ -60,6 +62,22 @@ impl FormatInformation {
],
);
let mut fi_model1 = Self::FindBestFormatInfo(
&[FORMAT_INFO_MASK_QR ^ FORMAT_INFO_MASK_QR_MODEL1],
FORMAT_INFO_DECODE_LOOKUP,
&[
formatInfoBits1,
formatInfoBits2,
Self::MirrorBits(formatInfoBits1),
mirroredFormatInfoBits2,
],
);
if fi_model1.hammingDistance < fi.hammingDistance {
fi_model1.isModel1 = true;
fi = fi_model1;
}
// Use bits 3/4 for error correction, and 0-2 for mask.
fi.error_correction_level =
ErrorCorrectionLevel::ECLevelFromBits((fi.index >> 3) & 0x03, false);
@@ -72,7 +90,7 @@ impl FormatInformation {
pub fn DecodeMQR(formatInfoBits: u32) -> Self {
// We don't use the additional masking (with 0x4445) to work around potentially non complying MicroQRCode encoders
let mut fi = Self::FindBestFormatInfo(
0,
&[0],
FORMAT_INFO_DECODE_LOOKUP_MICRO,
&[formatInfoBits, Self::MirrorBits(formatInfoBits)],
);
@@ -94,11 +112,11 @@ impl FormatInformation {
(bits.reverse_bits()) >> 17
}
pub fn FindBestFormatInfo(mask: u32, lookup: [[u32; 2]; 32], bits: &[u32]) -> Self {
pub fn FindBestFormatInfo(masks: &[u32], lookup: [[u32; 2]; 32], bits: &[u32]) -> Self {
let mut fi = FormatInformation::default();
// Some QR codes apparently do not apply the XOR mask. Try without and with additional masking.
for mask in [0, mask] {
for mask in masks {
// for (auto mask : {0, mask})
for (bitsIndex, bit_set) in bits.iter().enumerate() {
// for (int bitsIndex = 0; bitsIndex < Size(bits); ++bitsIndex)

View File

@@ -1,5 +1,7 @@
use crate::common::Result;
use crate::qrcode::decoder::{Version, VersionRef, MICRO_VERSIONS, VERSIONS, VERSION_DECODE_INFO};
use crate::qrcode::decoder::{
Version, VersionRef, MICRO_VERSIONS, MODEL1_VERSIONS, VERSIONS, VERSION_DECODE_INFO,
};
use crate::Exceptions;
// const Version* Version::AllMicroVersions()
@@ -16,7 +18,7 @@ use crate::Exceptions;
// }
impl Version {
pub fn FromDimension(dimension: u32) -> Result<VersionRef> {
pub fn FromDimension(dimension: u32, is_model1: bool) -> Result<VersionRef> {
let isMicro = dimension < 21;
if dimension % Self::DimensionStep(isMicro) != 1 {
//throw std::invalid_argument("Unexpected dimension");
@@ -25,17 +27,31 @@ impl Version {
Self::FromNumber(
(dimension - Self::DimensionOffset(isMicro)) / Self::DimensionStep(isMicro),
isMicro,
is_model1,
)
}
pub fn FromNumber(versionNumber: u32, is_micro: bool) -> Result<VersionRef> {
if versionNumber < 1 || versionNumber > (if is_micro { 4 } else { 40 }) {
pub fn FromNumber(versionNumber: u32, is_micro: bool, is_model1: bool) -> Result<VersionRef> {
if versionNumber < 1
|| versionNumber
> (if is_micro {
4
} else {
if is_model1 {
14
} else {
40
}
})
{
//throw std::invalid_argument("Version should be in range [1-40].");
return Err(Exceptions::ILLEGAL_ARGUMENT);
}
Ok(if is_micro {
&MICRO_VERSIONS[versionNumber as usize - 1]
} else if is_model1 {
&MODEL1_VERSIONS[versionNumber as usize - 1]
} else {
&VERSIONS[versionNumber as usize - 1]
})
@@ -92,4 +108,8 @@ impl Version {
pub const fn isMicroQRCode(&self) -> bool {
self.is_micro
}
pub const fn isQRCodeModel1(&self) -> bool {
self.is_model1
}
}

View File

@@ -157,6 +157,13 @@ where
self
}
pub fn withIsModel1(mut self, is_model_1: bool) -> DecoderResult<T> {
if is_model_1 {
self.content.symbology.modifier = 48
}
self
}
// pub fn build(self) -> DecoderResult<T> {
// }

View File

@@ -183,6 +183,9 @@ impl MultiFormatReader {
}
}
BarcodeFormat::MICRO_QR_CODE => QrReader.decode_with_hints(image, &self.hints),
BarcodeFormat::RECTANGULAR_MICRO_QR_CODE => {
QrReader.decode_with_hints(image, &self.hints)
}
BarcodeFormat::DATA_MATRIX => {
DataMatrixReader.decode_with_hints(image, &self.hints)
}

View File

@@ -33,7 +33,7 @@ pub fn hasValidDimension(bitMatrix: &BitMatrix, isMicro: bool) -> bool {
pub fn ReadVersion(bitMatrix: &BitMatrix) -> Result<VersionRef> {
let dimension = bitMatrix.height();
let mut version = Version::FromDimension(dimension)?;
let mut version = Version::FromDimension(dimension, false)?;
if version.getVersionNumber() < 7 {
return Ok(version);
@@ -235,6 +235,111 @@ pub fn ReadMQRCodewords(
Ok(result.iter().copied().map(|x| x as u8).collect())
}
pub fn ReadQRCodewordsModel1(
bitMatrix: &BitMatrix,
version: VersionRef,
formatInfo: &FormatInformation,
) -> Result<Vec<u8>> {
let mut result = Vec::with_capacity(version.getTotalCodewords() as usize);
let dimension = bitMatrix.height();
let columns = dimension / 4 + 1 + 2;
for j in 0..columns {
// for (int j = 0; j < columns; j++) {
if j <= 1 {
// vertical symbols on the right side
let rows = (dimension - 8) / 4;
for i in 0..rows {
// for (int i = 0; i < rows; i++) {
if j == 0 && i % 2 == 0 && i > 0 && i < rows - 1
// extension
{
continue;
}
let x = (dimension - 1) - (j * 2);
let y = (dimension - 1) - (i * 4);
let mut currentByte = 0;
for b in 0..8 {
// for (int b = 0; b < 8; b++) {
AppendBit(
&mut currentByte,
GetDataMaskBit(formatInfo.data_mask as u32, x - b % 2, y - (b / 2), None)?
!= getBit(
bitMatrix,
x - b % 2,
y - (b / 2),
Some(formatInfo.isMirrored),
),
);
}
result.push(currentByte);
}
} else if columns - j <= 4 {
// vertical symbols on the left side
let rows = (dimension - 16) / 4;
for i in 0..rows {
// for (int i = 0; i < rows; i++) {
let x = (columns - j - 1) * 2 + 1 + (if columns - j == 4 { 1 } else { 0 }); // timing
let y = (dimension - 1) - 8 - (i * 4);
let mut currentByte = 0;
for b in 0..8 {
// for (int b = 0; b < 8; b++) {
AppendBit(
&mut currentByte,
GetDataMaskBit(formatInfo.data_mask as u32, x - b % 2, y - (b / 2), None)?
!= getBit(
bitMatrix,
x - b % 2,
y - (b / 2),
Some(formatInfo.isMirrored),
),
);
}
result.push(currentByte);
}
} else {
// horizontal symbols
let rows = dimension / 2;
for i in 0..rows {
// for (int i = 0; i < rows; i++) {
if j == 2 && i >= rows - 4
// alignment & finder
{
continue;
}
if i == 0 && j % 2 == 1 && j + 1 != columns - 4
// extension
{
continue;
}
let x = (dimension - 1) - (2 * 2) - (j - 2) * 4;
let y = (dimension - 1) - (i * 2) - (if i >= rows - 3 { 1 } else { 0 }); // timing
let mut currentByte = 0;
for b in 0..8 {
// for (int b = 0; b < 8; b++) {
AppendBit(
&mut currentByte,
GetDataMaskBit(formatInfo.data_mask as u32, x - b % 4, y - (b / 4), None)?
!= getBit(
bitMatrix,
x - b % 4,
y - (b / 4),
Some(formatInfo.isMirrored),
),
);
}
result.push(currentByte);
}
}
}
result[0] &= 0xf; // ignore corner
if (result.len()) != version.getTotalCodewords() as usize {
return Err(Exceptions::FORMAT);
}
Ok(result.iter().copied().map(|x| x as u8).collect())
}
pub fn ReadCodewords(
bitMatrix: &BitMatrix,
version: VersionRef,
@@ -246,6 +351,8 @@ pub fn ReadCodewords(
if version.isMicroQRCode() {
ReadMQRCodewords(bitMatrix, version, formatInfo)
} else if formatInfo.isModel1 {
ReadQRCodewordsModel1(bitMatrix, version, formatInfo)
} else {
ReadQRCodewords(bitMatrix, version, formatInfo)
}

View File

@@ -299,6 +299,10 @@ pub fn DecodeBitStream(
let mut structuredAppend = StructuredAppendInfo::default();
let modeBitLength = Mode::get_codec_mode_bits_length(version);
if version.isQRCodeModel1() {
bits.readBits(4)?; /* Model 1 is leading with 4 0-bits -> drop them */
}
let res = (|| {
while !IsEndOfStream(&mut bits, version)? {
let mode: Mode = if modeBitLength == 0 {
@@ -387,11 +391,21 @@ pub fn DecodeBitStream(
.withError(res.err())
.withEcLevel(ecLevel.to_string())
.withVersionNumber(version.getVersionNumber())
.withStructuredAppend(structuredAppend))
.withStructuredAppend(structuredAppend)
.withIsModel1(version.isQRCodeModel1()))
}
pub fn Decode(bits: &BitMatrix) -> Result<DecoderResult<bool>> {
let Ok(pversion) = ReadVersion(bits) else {
let isMicroQRCode = bits.height() < 21;
let Ok(formatInfo) = ReadFormatInformation(bits, isMicroQRCode) else {
return Err(Exceptions::format_with("Invalid format information"));
};
let Ok(pversion) = (if formatInfo.isModel1 {
Version::FromDimension(bits.height(), true)
} else {
ReadVersion(bits)
}) else {
return Err(Exceptions::format_with("Invalid version"));
};
let version = pversion;

View File

@@ -42,7 +42,7 @@ fn SimpleByteMode() {
let bytes: Vec<u8> = ba.into();
let result = DecodeBitStream(
&bytes,
Version::FromNumber(1, false).expect("find_version"),
Version::FromNumber(1, false, false).expect("find_version"),
ErrorCorrectionLevel::M,
)
.expect("Decode")
@@ -64,7 +64,7 @@ fn SimpleSJIS() {
let bytes: Vec<u8> = ba.into();
let result = DecodeBitStream(
&bytes,
Version::FromNumber(1, false).unwrap(),
Version::FromNumber(1, false, false).unwrap(),
ErrorCorrectionLevel::M,
)
.unwrap()
@@ -86,7 +86,7 @@ fn ECI() {
let bytes: Vec<u8> = ba.into();
let result = DecodeBitStream(
&bytes,
Version::FromNumber(1, false).unwrap(),
Version::FromNumber(1, false, false).unwrap(),
ErrorCorrectionLevel::M,
)
.unwrap()
@@ -105,7 +105,7 @@ fn Hanzi() {
let bytes: Vec<u8> = ba.into();
let result = DecodeBitStream(
&bytes,
Version::FromNumber(1, false).unwrap(),
Version::FromNumber(1, false, false).unwrap(),
ErrorCorrectionLevel::M,
)
.unwrap()
@@ -127,7 +127,7 @@ fn HanziLevel1() {
let result = DecodeBitStream(
&bytes,
Version::FromNumber(1, false).unwrap(),
Version::FromNumber(1, false, false).unwrap(),
ErrorCorrectionLevel::M,
)
.unwrap()
@@ -138,7 +138,7 @@ fn HanziLevel1() {
#[test]
fn SymbologyIdentifier() {
let version = Version::FromNumber(1, false).unwrap();
let version = Version::FromNumber(1, false, false).unwrap();
let ecLevel = ErrorCorrectionLevel::M;
// Plain "ANUM(1) A"

View File

@@ -63,7 +63,7 @@ fn DecodeWithBitDifference() {
MASKED_TEST_FORMAT_INFO2 ^ 0x07,
),
);
assert!(!FormatInformation::DecodeQR(
assert!(FormatInformation::DecodeQR(
MASKED_TEST_FORMAT_INFO ^ 0x0F,
MASKED_TEST_FORMAT_INFO2 ^ 0x0F
)

View File

@@ -27,27 +27,39 @@ fn CharacterCount() {
// Spot check a few values
assert_eq!(
10,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(5, false).unwrap())
Mode::CharacterCountBits(
&Mode::NUMERIC,
Version::FromNumber(5, false, false).unwrap()
)
);
assert_eq!(
12,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(26, false).unwrap())
Mode::CharacterCountBits(
&Mode::NUMERIC,
Version::FromNumber(26, false, false).unwrap()
)
);
assert_eq!(
14,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(40, false).unwrap())
Mode::CharacterCountBits(
&Mode::NUMERIC,
Version::FromNumber(40, false, false).unwrap()
)
);
assert_eq!(
9,
Mode::CharacterCountBits(&Mode::ALPHANUMERIC, Version::FromNumber(6, false).unwrap())
Mode::CharacterCountBits(
&Mode::ALPHANUMERIC,
Version::FromNumber(6, false, false).unwrap()
)
);
assert_eq!(
8,
Mode::CharacterCountBits(&Mode::BYTE, Version::FromNumber(7, false).unwrap())
Mode::CharacterCountBits(&Mode::BYTE, Version::FromNumber(7, false, false).unwrap())
);
assert_eq!(
8,
Mode::CharacterCountBits(&Mode::KANJI, Version::FromNumber(8, false).unwrap())
Mode::CharacterCountBits(&Mode::KANJI, Version::FromNumber(8, false, false).unwrap())
);
}
@@ -110,26 +122,29 @@ fn MicroCharacterCount() {
// Spot check a few values
assert_eq!(
3,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(1, true).unwrap())
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(1, true, false).unwrap())
);
assert_eq!(
4,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(2, true).unwrap())
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(2, true, false).unwrap())
);
assert_eq!(
6,
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(4, true).unwrap())
Mode::CharacterCountBits(&Mode::NUMERIC, Version::FromNumber(4, true, false).unwrap())
);
assert_eq!(
3,
Mode::CharacterCountBits(&Mode::ALPHANUMERIC, Version::FromNumber(2, true).unwrap())
Mode::CharacterCountBits(
&Mode::ALPHANUMERIC,
Version::FromNumber(2, true, false).unwrap()
)
);
assert_eq!(
4,
Mode::CharacterCountBits(&Mode::BYTE, Version::FromNumber(3, true).unwrap())
Mode::CharacterCountBits(&Mode::BYTE, Version::FromNumber(3, true, false).unwrap())
);
assert_eq!(
4,
Mode::CharacterCountBits(&Mode::KANJI, Version::FromNumber(4, true).unwrap())
Mode::CharacterCountBits(&Mode::KANJI, Version::FromNumber(4, true, false).unwrap())
);
}

View File

@@ -26,13 +26,13 @@ fn DoTestVersion(expectedVersion: u32, mask: i32) {
#[test]
fn VersionForNumber() {
let version = Version::FromNumber(0, false);
let version = Version::FromNumber(0, false, false);
assert!(version.is_err(), "There is version with number 0");
for i in 1..=40 {
// for (int i = 1; i <= 40; i++) {
CheckVersion(
Version::FromNumber(i, false).expect("version number found"),
Version::FromNumber(i, false, false).expect("version number found"),
i,
4 * i + 17,
);
@@ -43,7 +43,7 @@ fn VersionForNumber() {
fn GetProvisionalVersionForDimension() {
for i in 1..=40 {
// for (int i = 1; i <= 40; i++) {
let prov = Version::FromDimension(4 * i + 17)
let prov = Version::FromDimension(4 * i + 17, false)
.unwrap_or_else(|_| panic!("version should exist for {i}"));
// assert_ne!(prov, nullptr);
assert_eq!(i, prov.getVersionNumber());
@@ -63,13 +63,14 @@ fn DecodeVersionInformation() {
#[test]
fn MicroVersionForNumber() {
let version = Version::FromNumber(0, true);
let version = Version::FromNumber(0, true, false);
assert!(version.is_err(), "There is version with number 0");
for i in 1..=4 {
// for (int i = 1; i <= 4; i++) {
CheckVersion(
Version::FromNumber(i, true).unwrap_or_else(|_| panic!("version for {i} should exist")),
Version::FromNumber(i, true, false)
.unwrap_or_else(|_| panic!("version for {i} should exist")),
i,
2 * i + 9,
);
@@ -80,7 +81,7 @@ fn MicroVersionForNumber() {
fn GetProvisionalMicroVersionForDimension() {
for i in 1..=4 {
// for (int i = 1; i <= 4; i++) {
let prov = Version::FromDimension(2 * i + 9)
let prov = Version::FromDimension(2 * i + 9, false)
.unwrap_or_else(|_| panic!("version for micro {i} should exist"));
// assert_ne!(prov, nullptr);
assert_eq!(i, prov.getVersionNumber());
@@ -100,7 +101,7 @@ fn FunctionPattern() {
};
for i in 1..=4 {
// for (int i = 1; i <= 4; i++) {
let version = Version::FromNumber(i, true).expect("version must be found");
let version = Version::FromNumber(i, true, false).expect("version must be found");
let functionPattern = version
.buildFunctionPattern()
.expect("function pattern must be found");

View File

@@ -73,6 +73,7 @@ pub struct FormatInformation {
pub data_mask: u8,
pub microVersion: u32,
pub isMirrored: bool,
pub isModel1: bool,
pub index: u8, // = 255;
pub bitsIndex: u8, // = 255;
@@ -86,6 +87,7 @@ impl Default for FormatInformation {
data_mask: Default::default(),
microVersion: 0,
isMirrored: false,
isModel1: false,
index: 255,
bitsIndex: 255,
}
@@ -104,6 +106,7 @@ impl FormatInformation {
error_correction_level: errorCorrectionLevel,
data_mask: dataMask,
isMirrored: false,
isModel1: false,
index: 255,
bitsIndex: 255,
})

View File

@@ -29,6 +29,7 @@ pub type VersionRef = &'static Version;
pub static VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::buildVersions);
pub static MICRO_VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::build_micro_versions);
pub static MODEL1_VERSIONS: Lazy<Vec<Version>> = Lazy::new(Version::build_model1_versions);
/**
* See ISO 18004:2006 Annex D.
@@ -55,6 +56,7 @@ pub struct Version {
ecBlocks: Vec<ECBlocks>,
totalCodewords: u32,
pub(crate) is_micro: bool,
pub(crate) is_model1: bool,
}
impl Version {
fn new(versionNumber: u32, alignmentPatternCenters: Vec<u32>, ecBlocks: [ECBlocks; 4]) -> Self {
@@ -73,6 +75,7 @@ impl Version {
ecBlocks: ecBlocks.to_vec(),
totalCodewords: total,
is_micro: false,
is_model1: false,
}
}
@@ -92,9 +95,35 @@ impl Version {
ecBlocks,
totalCodewords: total,
is_micro: true,
is_model1: false,
}
}
fn new_model1(versionNumber: u32, ecBlocks: Vec<ECBlocks>) -> Self {
let mut total = 0;
let ecCodewords = ecBlocks[0].getECCodewordsPerBlock();
let ecbArray = ecBlocks[0].getECBlocks();
let mut i = 0;
while i < ecbArray.len() {
total += ecbArray[i].getCount() * (ecbArray[i].getDataCodewords() + ecCodewords);
i += 1;
}
Self {
versionNumber,
alignmentPatternCenters: Vec::default(),
ecBlocks,
totalCodewords: total,
is_micro: false,
is_model1: true,
}
}
// #[inline(always)]
// pub(crate) const fn isMicro(ecBlocks: &[ECBlocks; 4]) -> bool {
// ecBlocks[0].ecCodewordsPerBlock < 7 || ecBlocks[0].ecCodewordsPerBlock == 8
// }
pub const fn getVersionNumber(&self) -> u32 {
self.versionNumber
}
@@ -970,6 +999,224 @@ impl Version {
new ECB::new(61, 16)))
]*/
}
/*
* {1, {
7 , 1, 19, 0, 0,
10, 1, 16, 0, 0,
13, 1, 13, 0, 0,
17, 1, 9 , 0, 0
}},
{2, {
10, 1, 36, 0, 0,
16, 1, 30, 0, 0,
22, 1, 24, 0, 0,
30, 1, 16, 0, 0,
}},
{3, {
15, 1, 57, 0, 0,
28, 1, 44, 0, 0,
36, 1, 36, 0, 0,
48, 1, 24, 0, 0,
}},
{4, {
20, 1, 80, 0, 0,
40, 1, 60, 0, 0,
50, 1, 50, 0, 0,
66, 1, 34, 0, 0,
}},
{5, {
26, 1, 108, 0, 0,
52, 1, 82 , 0, 0,
66, 1, 68 , 0, 0,
88, 2, 46 , 0, 0,
}},
{6, {
34 , 1, 136, 0, 0,
63 , 2, 106, 0, 0,
84 , 2, 86 , 0, 0,
112, 2, 58 , 0, 0,
}},
{7, {
42 , 1, 170, 0, 0,
80 , 2, 132, 0, 0,
104, 2, 108, 0, 0,
138, 3, 72 , 0, 0,
}},
{8, {
48 , 2, 208, 0, 0,
96 , 2, 160, 0, 0,
128, 2, 128, 0, 0,
168, 3, 87 , 0, 0,
}},
{9, {
60 , 2, 246, 0, 0,
120, 2, 186, 0, 0,
150, 3, 156, 0, 0,
204, 3, 102, 0, 0,
}},
{10, {
68 , 2, 290, 0, 0,
136, 2, 222, 0, 0,
174, 3, 183, 0, 0,
232, 4, 124, 0, 0,
}},
{11, {
80 , 2, 336, 0, 0,
160, 4, 256, 0, 0,
208, 4, 208, 0, 0,
270, 5, 145, 0, 0,
}},
{12, {
92 , 2, 384, 0, 0,
184, 4, 292, 0, 0,
232, 4, 244, 0, 0,
310, 5, 165, 0, 0,
}},
{13, {
108, 3, 432, 0, 0,
208, 4, 332, 0, 0,
264, 4, 276, 0, 0,
348, 6, 192, 0, 0,
}},
{14, {
120, 3, 489, 0, 0,
240, 4, 368, 0, 0,
300, 5, 310, 0, 0,
396, 6, 210, 0, 0,
}},
};
*/
pub fn build_model1_versions() -> Vec<Version> {
Vec::from([
Version::new_model1(
1,
vec![
ECBlocks::new(7, vec![ECB::new(1, 19)]),
ECBlocks::new(10, vec![ECB::new(1, 16)]),
ECBlocks::new(13, vec![ECB::new(1, 13)]),
ECBlocks::new(17, vec![ECB::new(1, 9)]),
],
),
Version::new_model1(
2,
vec![
ECBlocks::new(10, vec![ECB::new(1, 36)]),
ECBlocks::new(16, vec![ECB::new(1, 30)]),
ECBlocks::new(22, vec![ECB::new(1, 24)]),
ECBlocks::new(30, vec![ECB::new(1, 16)]),
],
),
Version::new_model1(
3,
vec![
ECBlocks::new(15, vec![ECB::new(1, 57)]),
ECBlocks::new(28, vec![ECB::new(1, 44)]),
ECBlocks::new(36, vec![ECB::new(1, 36)]),
ECBlocks::new(48, vec![ECB::new(1, 24)]),
],
),
Version::new_model1(
4,
vec![
ECBlocks::new(20, vec![ECB::new(1, 80)]),
ECBlocks::new(40, vec![ECB::new(1, 60)]),
ECBlocks::new(50, vec![ECB::new(1, 50)]),
ECBlocks::new(66, vec![ECB::new(1, 34)]),
],
),
Version::new_model1(
5,
vec![
ECBlocks::new(26, vec![ECB::new(1, 108)]),
ECBlocks::new(52, vec![ECB::new(1, 82)]),
ECBlocks::new(66, vec![ECB::new(1, 68)]),
ECBlocks::new(88, vec![ECB::new(2, 46)]),
],
),
Version::new_model1(
6,
vec![
ECBlocks::new(34, vec![ECB::new(1, 136)]),
ECBlocks::new(63, vec![ECB::new(2, 106)]),
ECBlocks::new(84, vec![ECB::new(2, 86)]),
ECBlocks::new(112, vec![ECB::new(2, 58)]),
],
),
Version::new_model1(
7,
vec![
ECBlocks::new(42, vec![ECB::new(1, 170)]),
ECBlocks::new(80, vec![ECB::new(2, 132)]),
ECBlocks::new(104, vec![ECB::new(2, 108)]),
ECBlocks::new(138, vec![ECB::new(3, 72)]),
],
),
Version::new_model1(
8,
vec![
ECBlocks::new(48, vec![ECB::new(2, 208)]),
ECBlocks::new(96, vec![ECB::new(2, 160)]),
ECBlocks::new(128, vec![ECB::new(2, 128)]),
ECBlocks::new(168, vec![ECB::new(3, 87)]),
],
),
Version::new_model1(
9,
vec![
ECBlocks::new(60, vec![ECB::new(2, 246)]),
ECBlocks::new(120, vec![ECB::new(2, 186)]),
ECBlocks::new(150, vec![ECB::new(3, 156)]),
ECBlocks::new(204, vec![ECB::new(3, 102)]),
],
),
Version::new_model1(
10,
vec![
ECBlocks::new(68, vec![ECB::new(2, 290)]),
ECBlocks::new(136, vec![ECB::new(2, 222)]),
ECBlocks::new(174, vec![ECB::new(3, 183)]),
ECBlocks::new(232, vec![ECB::new(4, 124)]),
],
),
Version::new_model1(
11,
vec![
ECBlocks::new(80, vec![ECB::new(2, 336)]),
ECBlocks::new(160, vec![ECB::new(4, 256)]),
ECBlocks::new(208, vec![ECB::new(4, 208)]),
ECBlocks::new(270, vec![ECB::new(5, 145)]),
],
),
Version::new_model1(
12,
vec![
ECBlocks::new(92, vec![ECB::new(2, 384)]),
ECBlocks::new(184, vec![ECB::new(4, 292)]),
ECBlocks::new(232, vec![ECB::new(4, 244)]),
ECBlocks::new(310, vec![ECB::new(5, 165)]),
],
),
Version::new_model1(
13,
vec![
ECBlocks::new(108, vec![ECB::new(3, 432)]),
ECBlocks::new(208, vec![ECB::new(4, 332)]),
ECBlocks::new(264, vec![ECB::new(4, 276)]),
ECBlocks::new(348, vec![ECB::new(6, 192)]),
],
),
Version::new_model1(
14,
vec![
ECBlocks::new(120, vec![ECB::new(3, 489)]),
ECBlocks::new(240, vec![ECB::new(4, 368)]),
ECBlocks::new(300, vec![ECB::new(5, 310)]),
ECBlocks::new(396, vec![ECB::new(6, 210)]),
],
),
])
}
}
impl fmt::Display for Version {