#![allow(clippy::many_single_char_names)]
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
use crate::quirc::*;
use crate::version_db::*;
use crate::DecodeError;
#[derive(Copy, Clone)]
struct Datastream {
raw: [u8; 8896],
data_bits: i32,
ptr: i32,
data: [u8; 8896],
}
#[derive(Copy, Clone)]
struct GaloisField {
p: i32,
log: &'static [u8],
exp: &'static [u8],
}
static GF16_EXP: [u8; 16] = [
0x1, 0x2, 0x4, 0x8, 0x3, 0x6, 0xc, 0xb, 0x5, 0xa, 0x7, 0xe, 0xf, 0xd, 0x9, 0x1,
];
static GF16_LOG: [u8; 16] = [
0, 0xf, 0x1, 0x4, 0x2, 0x8, 0x5, 0xa, 0x3, 0xe, 0x9, 0x7, 0x6, 0xd, 0xb, 0xc,
];
static GF16: GaloisField = GaloisField {
p: 15,
log: &GF16_LOG,
exp: &GF16_EXP,
};
static GF256_EXP: [u8; 256] = [
0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x3, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x5, 0xa, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0xf, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0xd, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x9,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0xb, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x1,
];
static GF256_LOG: [u8; 256] = [
0, 0xff, 0x1, 0x19, 0x2, 0x32, 0x1a, 0xc6, 0x3, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x4,
0x64, 0xe0, 0xe, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x8, 0x4c, 0x71, 0x5,
0x8a, 0x65, 0x2f, 0xe1, 0x24, 0xf, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d,
0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x9, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 0x6,
0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 0x36,
0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e,
0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 0xca,
0x5e, 0x9b, 0x9f, 0xa, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x7,
0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0xd, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 0xe3,
0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 0x37,
0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2,
0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 0x1f,
0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0xc, 0x6f, 0xf6, 0x6c,
0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 0xcb,
0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0xb, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 0x4f,
0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,
];
static GF256: GaloisField = GaloisField {
p: 255,
log: &GF256_LOG,
exp: &GF256_EXP,
};
fn poly_add(dst: &mut [u8], src: &[u8], c: u8, shift: i32, gf: &GaloisField) {
if c == 0 {
return;
}
let log_c = gf.log[c as usize] as i32;
for (i, v) in src.iter().enumerate() {
let p = i + shift as usize;
if p >= 64 {
continue;
}
if *v == 0 {
continue;
}
dst[p] ^= (gf.exp[((gf.log[*v as usize] as i32 + log_c) % gf.p) as usize] as i32) as u8;
}
}
fn poly_eval(s: &[u8], x: u8, gf: &GaloisField) -> u8 {
if x == 0 {
return s[0];
}
let mut sum = 0;
let log_x = gf.log[x as usize];
for i in 0..64 {
let c = s[i as usize];
if c == 0 {
continue;
}
sum ^= gf.exp[((gf.log[c as usize] as i32 + log_x as i32 * i) % gf.p) as usize] as u8
}
sum
}
#[allow(non_snake_case)]
fn berlekamp_massey(s: &[u8], n: usize, gf: &GaloisField, sigma: &mut [u8]) {
let mut C: [u8; 64] = [0; 64];
let mut B: [u8; 64] = [0; 64];
let mut L = 0;
let mut m = 1;
let mut b = 1;
B[0] = 1;
C[0] = 1;
for n in 0..n {
let mut d = s[n];
let mult: u8;
for i in 1..=L {
if C[i] as i32 != 0 && s[n - i] as i32 != 0 {
let a = gf.log[C[i] as usize] as usize;
let b = gf.log[s[n - i] as usize] as usize;
let index = (a + b) % gf.p as usize;
d ^= gf.exp[index] as u8;
}
}
mult = gf.exp
[((gf.p - gf.log[b as usize] as i32 + gf.log[d as usize] as i32) % gf.p) as usize];
if d == 0 {
m += 1
} else if L * 2 <= n {
let T = C;
poly_add(&mut C, &B, mult, m, gf);
B.copy_from_slice(&T);
L = n + 1 - L;
b = d;
m = 1
} else {
poly_add(&mut C, &B, mult, m, gf);
m += 1
}
}
sigma[..64].copy_from_slice(&C);
}
fn block_syndromes(data: &[u8], bs: i32, npar: usize, s: &mut [u8]) -> i32 {
for val in s.iter_mut().take(64) {
*val = 0;
}
let mut nonzero = 0;
for i in 0..npar {
for j in 0..bs {
let c = data[(bs - j - 1) as usize];
if c == 0 {
continue;
}
s[i] ^= GF256_EXP[((GF256_LOG[c as usize] as i32 + i as i32 * j) % 255) as usize] as u8;
}
if s[i] != 0 {
nonzero = 1;
}
}
nonzero
}
fn eloc_poly(omega: &mut [u8], s: &[u8], sigma: &[u8], npar: usize) {
for val in omega.iter_mut().take(64) {
*val = 0;
}
for i in 0..npar {
let a = sigma[i];
let log_a = GF256_LOG[a as usize];
if a == 0 {
continue;
}
for j in 0..64 - 1 {
let b = s[j + 1];
if i + j >= npar {
break;
}
if b == 0 {
continue;
}
omega[i + j] ^=
GF256_EXP[((log_a as i32 + GF256_LOG[b as usize] as i32) % 255) as usize] as u8;
}
}
}
fn correct_block(data: &mut [u8], ecc: &RsParams) -> Result<(), DecodeError> {
let npar = ecc.bs as usize - ecc.dw as usize;
let mut s: [u8; 64] = [0; 64];
let mut sigma: [u8; 64] = [0; 64];
let mut sigma_deriv: [u8; 64] = [0; 64];
let mut omega: [u8; 64] = [0; 64];
if block_syndromes(data, ecc.bs, npar, &mut s) == 0 {
return Ok(());
}
berlekamp_massey(&s, npar, &GF256, &mut sigma);
let mut i = 0;
while i + 1 < 64 {
sigma_deriv[i as usize] = sigma[(i + 1) as usize];
i += 2
}
eloc_poly(&mut omega, &s, &sigma, npar - 1);
i = 0;
while i < ecc.bs {
let xinv = GF256_EXP[(255 - i) as usize];
if poly_eval(&sigma, xinv, &GF256) == 0 {
let sd_x = poly_eval(&sigma_deriv, xinv, &GF256);
let omega_x = poly_eval(&omega, xinv, &GF256);
let error = GF256_EXP[((255 - GF256_LOG[sd_x as usize] as i32
+ GF256_LOG[omega_x as usize] as i32)
% 255) as usize];
let index = (ecc.bs - i - 1) as usize;
data[index] ^= error as u8;
}
i += 1
}
if block_syndromes(data, ecc.bs, npar, &mut s) != 0 {
return Err(DecodeError::DataEcc);
}
Ok(())
}
fn format_syndromes(u: u16, s: &mut [u8]) -> i32 {
let mut nonzero = 0;
for val in s.iter_mut().take(64) {
*val = 0;
}
let mut i = 0;
while i < 3 * 2 {
s[i] = 0;
for j in 0..15 {
if u as i32 & 1 << j != 0 {
s[i] ^= GF16_EXP[((i + 1) * j % 15) as usize] as u8;
}
}
if s[i] != 0 {
nonzero = 1;
}
i += 1
}
nonzero
}
fn correct_format(f_ret: &mut u16) -> Result<(), DecodeError> {
let mut u: u16 = *f_ret;
let mut s: [u8; 64] = [0; 64];
let mut sigma: [u8; 64] = [0; 64];
if format_syndromes(u, &mut s) == 0 {
return Ok(());
}
berlekamp_massey(&s, 3 * 2, &GF16, &mut sigma);
for i in 0..15 {
if poly_eval(&sigma, GF16_EXP[(15 - i) as usize], &GF16) == 0 {
u ^= (1 << i) as u16;
}
}
if format_syndromes(u, &mut s) != 0 {
return Err(DecodeError::FormatEcc);
}
*f_ret = u;
Ok(())
}
#[inline]
fn grid_bit(code: &Code, x: i32, y: i32) -> i32 {
let p: i32 = y * code.size + x;
code.cell_bitmap[(p >> 3) as usize] as i32 >> (p & 7) & 1
}
fn read_format(code: &Code, data: &mut Data, which: i32) -> Result<(), DecodeError> {
let mut format: u16 = 0 as u16;
if which != 0 {
for i in 0..7 {
format = ((format as i32) << 1 | grid_bit(code, 8, code.size - 1 - i)) as u16;
}
for i in 0..8 {
format = ((format as i32) << 1 | grid_bit(code, code.size - 8 + i, 8)) as u16;
}
} else {
static XS: [i32; 15] = [8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 4, 3, 2, 1, 0];
static YS: [i32; 15] = [0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8];
for i in (0..=14).rev() {
format = ((format as i32) << 1 | grid_bit(code, XS[i as usize], YS[i as usize])) as u16;
}
}
format ^= 0x5412;
correct_format(&mut format)?;
let fdata = (format as i32 >> 10) as u16;
data.ecc_level = EccLevel::from_i32(fdata as i32 >> 3).unwrap();
data.mask = fdata as i32 & 7;
Ok(())
}
fn mask_bit(mask: i32, i: i32, j: i32) -> i32 {
match mask {
0 => ((i + j) % 2 == 0) as i32,
1 => (i % 2 == 0) as i32,
2 => (j % 3 == 0) as i32,
3 => ((i + j) % 3 == 0) as i32,
4 => ((i / 2 + j / 3) % 2 == 0) as i32,
5 => (i * j % 2 + i * j % 3 == 0) as i32,
6 => ((i * j % 2 + i * j % 3) % 2 == 0) as i32,
7 => ((i * j % 3 + (i + j) % 2) % 2 == 0) as i32,
_ => 0,
}
}
fn reserved_cell(version: usize, i: i32, j: i32) -> i32 {
let ver = &VERSION_DB[version];
let size = version as i32 * 4 + 17;
let mut ai: i32 = -1;
let mut aj: i32 = -1;
if i < 9 && j < 9 {
return 1;
}
if i + 8 >= size && j < 9 {
return 1;
}
if i < 9 && j + 8 >= size {
return 1;
}
if i == 6 || j == 6 {
return 1;
}
if version >= 7 {
if i < 6 && j + 11 >= size {
return 1;
}
if i + 11 >= size && j < 6 {
return 1;
}
}
let mut a = 0;
while a < 7 && ver.apat[a as usize] != 0 {
let p: i32 = ver.apat[a as usize];
if (p - i).abs() < 3 {
ai = a
}
if (p - j).abs() < 3 {
aj = a
}
a += 1
}
if ai >= 0 && aj >= 0 {
a -= 1;
if ai > 0 && ai < a {
return 1;
}
if aj > 0 && aj < a {
return 1;
}
if aj == a && ai == a {
return 1;
}
}
0
}
fn read_bit(code: &Code, data: &mut Data, mut ds: &mut Datastream, i: i32, j: i32) {
let bitpos: i32 = ds.data_bits & 7;
let bytepos: i32 = ds.data_bits >> 3;
let mut v: i32 = grid_bit(code, j, i);
if mask_bit(data.mask, i, j) != 0 {
v ^= 1
}
if v != 0 {
ds.raw[bytepos as usize] = (ds.raw[bytepos as usize] as i32 | 0x80 >> bitpos) as u8;
}
ds.data_bits += 1;
}
fn read_data(code: &Code, data: &mut Data, ds: &mut Datastream) {
let mut y: i32 = code.size - 1;
let mut x: i32 = code.size - 1;
let mut dir: i32 = -1;
while x > 0 {
if x == 6 {
x -= 1
}
if reserved_cell(data.version, y, x) == 0 {
read_bit(code, data, ds, y, x);
}
if reserved_cell(data.version, y, x - 1) == 0 {
read_bit(code, data, ds, y, x - 1);
}
y += dir;
if y < 0 || y >= code.size {
dir = -dir;
x -= 2;
y += dir
}
}
}
fn codestream_ecc(data: &mut Data, mut ds: &mut Datastream) -> Result<(), DecodeError> {
let ver = &VERSION_DB[data.version as usize];
let sb_ecc = &ver.ecc[data.ecc_level as usize];
let lb_count = (ver.data_bytes - sb_ecc.bs * sb_ecc.ns) / (sb_ecc.bs + 1);
let bc = lb_count + sb_ecc.ns;
let ecc_offset = sb_ecc.dw * bc + lb_count;
let mut dst_offset = 0;
let mut lb_ecc = sb_ecc.clone();
lb_ecc.dw += 1;
lb_ecc.bs += 1;
for i in 0..bc {
let dst = &mut ds.data[dst_offset as usize..];
let ecc = if i < sb_ecc.ns { sb_ecc } else { &lb_ecc };
let num_ec = ecc.bs - ecc.dw;
for j in 0..ecc.dw {
dst[j as usize] = ds.raw[(j * bc + i) as usize];
}
for j in 0..num_ec {
dst[(ecc.dw + j) as usize] = ds.raw[(ecc_offset + j * bc + i) as usize];
}
correct_block(dst, ecc)?;
dst_offset += ecc.dw;
}
ds.data_bits = dst_offset * 8;
Ok(())
}
#[inline]
fn bits_remaining(ds: &Datastream) -> i32 {
ds.data_bits - ds.ptr
}
fn take_bits(mut ds: &mut Datastream, mut len: i32) -> i32 {
let mut ret: i32 = 0;
while len != 0 && ds.ptr < ds.data_bits {
let b: u8 = ds.data[(ds.ptr >> 3) as usize];
let bitpos: i32 = ds.ptr & 7;
ret <<= 1;
if (b as i32) << bitpos & 0x80 != 0 {
ret |= 1
}
ds.ptr += 1;
len -= 1
}
ret
}
fn numeric_tuple(data: &mut Data, ds: &mut Datastream, bits: i32, digits: usize) -> i32 {
if bits_remaining(ds) < bits {
return -1;
}
let mut tuple = take_bits(ds, bits);
let len = data.payload.len();
data.payload.resize(len + digits, 0);
for val in data.payload[len..].iter_mut().rev() {
*val = (tuple % 10 + '0' as i32) as u8;
tuple /= 10;
}
0
}
fn decode_numeric(data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
let mut bits: i32 = 14;
if data.version < 10 {
bits = 10;
} else if data.version < 27 {
bits = 12;
}
let mut count = take_bits(ds, bits);
if data.payload.len() + count as usize + 1 > 8896 {
return Err(DecodeError::DataOverflow);
}
while count >= 3 {
if numeric_tuple(data, ds, 10, 3) < 0 {
return Err(DecodeError::DataUnderflow);
}
count -= 3;
}
if count >= 2 {
if numeric_tuple(data, ds, 7, 2) < 0 {
return Err(DecodeError::DataUnderflow);
}
count -= 2;
}
if count != 0 && numeric_tuple(data, ds, 4, 1) < 0 {
return Err(DecodeError::DataUnderflow);
}
Ok(())
}
fn alpha_tuple(data: &mut Data, ds: &mut Datastream, bits: i32, digits: usize) -> i32 {
if bits_remaining(ds) < bits {
return -1;
}
let mut tuple = take_bits(ds, bits);
static ALPHA_MAP: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
let len = data.payload.len();
data.payload.resize(len + digits, 0);
for val in data.payload[len..].iter_mut().rev() {
*val = ALPHA_MAP[(tuple % 45) as usize] as u8;
tuple /= 45;
}
0
}
fn decode_alpha(data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
let mut bits: i32 = 13;
if data.version < 10 {
bits = 9
} else if data.version < 27 {
bits = 11
}
let mut count = take_bits(ds, bits);
if data.payload.len() + count as usize + 1 > 8896 {
return Err(DecodeError::DataOverflow);
}
while count >= 2 {
if alpha_tuple(data, ds, 11, 2) < 0 {
return Err(DecodeError::DataUnderflow);
}
count -= 2
}
if count != 0 && alpha_tuple(data, ds, 6, 1) < 0 {
return Err(DecodeError::DataUnderflow);
}
Ok(())
}
fn decode_byte(data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
let bits = if data.version < 10 { 8 } else { 16 };
let count = take_bits(ds, bits);
if data.payload.len() + count as usize + 1 > 8896 {
return Err(DecodeError::DataOverflow);
}
if bits_remaining(ds) < count * 8 {
return Err(DecodeError::DataUnderflow);
}
for _i in 0..count {
data.payload.push(take_bits(ds, 8) as u8);
}
Ok(())
}
fn decode_kanji(data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
let mut bits = 12;
if data.version < 10 {
bits = 8;
} else if data.version < 27 {
bits = 10;
}
let count = take_bits(ds, bits);
if data.payload.len() + count as usize * 2 + 1 > 8896 {
return Err(DecodeError::DataOverflow);
}
if bits_remaining(ds) < count * 13 {
return Err(DecodeError::DataUnderflow);
}
for _i in 0..count {
let d = take_bits(ds, 13);
let msb = d / 0xc0;
let lsb = d % 0xc0;
let intermediate = msb << 8 | lsb;
let sjw = if intermediate + 0x8140 <= 0x9ffc {
(intermediate + 0x8140) as u16
} else {
(intermediate + 0xc140) as u16
};
data.payload.push((sjw as i32 >> 8) as u8);
data.payload.push((sjw as i32 & 0xff) as u8);
}
Ok(())
}
fn decode_eci(mut data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
if bits_remaining(ds) < 8 {
return Err(DecodeError::DataUnderflow);
}
data.eci = Eci::from_u32(take_bits(ds, 8) as u32);
if data.eci.and_then(|e| e.to_u32()).unwrap_or_default() & 0xc0 as u32 == 0x80 as u32 {
if bits_remaining(ds) < 8 {
return Err(DecodeError::DataUnderflow);
}
data.eci = Eci::from_u32(
data.eci.and_then(|e| e.to_u32()).unwrap_or_default() << 8 | take_bits(ds, 8) as u32,
);
} else if data.eci.and_then(|e| e.to_u32()).unwrap_or_default() & 0xe0 as u32 == 0xc0 as u32 {
if bits_remaining(ds) < 16 {
return Err(DecodeError::DataUnderflow);
}
data.eci = Eci::from_u32(
data.eci.and_then(|e| e.to_u32()).unwrap_or_default() << 16 | take_bits(ds, 16) as u32,
);
}
Ok(())
}
fn decode_payload(mut data: &mut Data, ds: &mut Datastream) -> Result<(), DecodeError> {
while bits_remaining(ds) >= 4 {
let type_0 = DataType::from_i32(take_bits(ds, 4));
match type_0 {
Some(DataType::Numeric) => decode_numeric(data, ds)?,
Some(DataType::Alpha) => decode_alpha(data, ds)?,
Some(DataType::Byte) => decode_byte(data, ds)?,
Some(DataType::Kanji) => decode_kanji(data, ds)?,
Some(DataType::Eci) => decode_eci(data, ds)?,
_ => {
break;
}
}
let t = type_0.map(|t| t as i32).unwrap_or_default();
let d = data.data_type.map(|t| t as i32).unwrap_or_default();
if t & (t - 1) == 0 && t > d {
data.data_type = type_0;
}
}
Ok(())
}
impl Code {
pub fn decode(&self) -> Result<Data, DecodeError> {
let mut ds: Datastream = Datastream {
raw: [0; 8896],
data_bits: 0,
ptr: 0,
data: [0; 8896],
};
if (self.size - 17) % 4 != 0 {
return Err(DecodeError::InvalidGridSize);
}
let mut data = Data::default();
data.version =
usize::try_from((self.size - 17) / 4).map_err(|_| DecodeError::InvalidVersion)?;
if data.version < VERSION_MIN || data.version > VERSION_MAX {
return Err(DecodeError::InvalidVersion);
}
let mut res = read_format(self, &mut data, 0);
if res.is_err() {
res = read_format(self, &mut data, 1);
}
res?;
read_data(self, &mut data, &mut ds);
codestream_ecc(&mut data, &mut ds)?;
decode_payload(&mut data, &mut ds)?;
Ok(data)
}
}