use std::io::Write; use std::mem; use g2p::{g2p, GaloisField}; use crate::{DeQRError, DeQRResult, BitGrid}; use crate::version_db::{RSParameters, VERSION_DATA_BASE}; g2p!(GF16, 4, modulus: 0b1_0011); g2p!(GF256, 8, modulus: 0b1_0001_1101); const MAX_PAYLOAD_SIZE: usize = 8896; /// Version of a QR Code which determines its size #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct Version(pub usize); impl Version { /// Given the grid size, determine the likely grid size pub fn from_size(b: usize) -> DeQRResult { let computed_version = b.saturating_sub(17) / 4; if computed_version > 0 && computed_version <= 40 { Ok(Version(computed_version)) } else { Err(DeQRError::InvalidVersion) } } /// Return the size of a grid of the given version pub fn to_size(&self) -> usize { self.0 as usize * 4 + 17 } } /// MetaData for a QR grid /// /// Stores information about the size/version of given grid. Also contains information about the /// error correction level and bit mask used. #[derive(Debug, Clone, Copy)] pub struct MetaData { /// The version/size of the grid pub version: Version, /// the error correction leven, between 0 and 3 pub ecc_level: u16, /// The mask that was used, value between 0 and 7 pub mask: u16, } #[derive(Clone)] pub struct RawData { data: [u8; MAX_PAYLOAD_SIZE], len: usize, } impl RawData { pub fn new() -> Self { RawData { data: [0; MAX_PAYLOAD_SIZE], len: 0, } } pub fn push(&mut self, bit: bool) { assert!((self.len >> 8) < MAX_PAYLOAD_SIZE); let bitpos = (self.len & 7) as u8; let bytepos = self.len >> 3; if bit { self.data[bytepos] |= 0x80_u8 >> bitpos; } self.len += 1; } } #[derive(Clone)] pub struct CorrectedDataStream { data: [u8; MAX_PAYLOAD_SIZE], ptr: usize, bit_len: usize, } impl CorrectedDataStream { pub fn bits_remaining(&self) -> usize { assert!(self.bit_len >= self.ptr); self.bit_len - self.ptr } pub fn take_bits(&mut self, nbits: usize) -> usize { let mut ret = 0; let max_len = ::std::cmp::min(self.bits_remaining(), nbits); assert!(max_len <= mem::size_of::() * 8); for _ in 0..max_len { let b = self.data[self.ptr >> 3]; let bitpos = self.ptr & 7; ret <<= 1; if 0 != (b << bitpos) & 0x80 { ret |= 1 } self.ptr += 1; } ret } } /* *********************************************************************** * Decoder algorithm */ #[derive(Copy, Clone)] pub struct DataStream { pub raw: [u8; MAX_PAYLOAD_SIZE], pub data_bits: usize, pub ptr: usize, pub data: [u8; MAX_PAYLOAD_SIZE], } /// Given a grid try to decode and write it to the output writer /// /// This tries to read the bit patterns from a [Grid](trait.Grid.html), correct errors /// and/or missing bits and write the result to the output. If successful also returns /// [MetaData](struct.MetaData.html) of the read grid. pub fn decode(code: &dyn BitGrid, writer: W) -> DeQRResult where W: Write { let meta = read_format(code)?; let raw = read_data(code, &meta); let stream = codestream_ecc(&meta, raw)?; decode_payload(&meta, stream, writer)?; Ok(meta) } fn decode_payload( meta: &MetaData, mut ds: CorrectedDataStream, mut writer: W, ) -> DeQRResult<()> where W: Write { while ds.bits_remaining() >= 4 { let ty = ds.take_bits(4); match ty { 0 => break, 1 => decode_numeric(meta, &mut ds, &mut writer), 2 => decode_alpha(meta, &mut ds, &mut writer), 4 => decode_byte(meta, &mut ds, &mut writer), 8 => decode_kanji(meta, &mut ds, &mut writer), 7 => decode_eci(meta, &mut ds, &mut writer), _ => { Err(DeQRError::UnknownDataType)? } }?; } Ok(()) } fn decode_eci( _meta: &MetaData, ds: &mut CorrectedDataStream, mut _writer: W, ) -> DeQRResult<()> where W: Write { if ds.bits_remaining() < 8 { Err(DeQRError::DataUnderflow)? } let mut _eci = ds.take_bits(8) as u32; if _eci & 0xc0 == 0x80 { if ds.bits_remaining() < 8 { Err(DeQRError::DataUnderflow)? } _eci = (_eci << 8) | (ds.take_bits(8) as u32) } else if _eci & 0xe0 == 0xc0 { if ds.bits_remaining() < 16 { Err(DeQRError::DataUnderflow)? } _eci = (_eci << 16) | (ds.take_bits(16) as u32) } Ok(()) } fn decode_kanji( meta: &MetaData, ds: &mut CorrectedDataStream, mut writer: W, ) -> DeQRResult<()> where W: Write { let nbits = match meta.version { Version(0..=9) => 8, Version(10..=26) => 10, _ => 12, }; let count = ds.take_bits(nbits); if ds.bits_remaining() < count * 13 { Err(DeQRError::DataUnderflow)? } for _ in 0..count { let d = ds.take_bits(13); let ms_b = d / 0xc0; let ls_b = d % 0xc0; let intermediate = ms_b << 8 | ls_b; let sjw = if intermediate + 0x8140 <= 0x9ffc { /* bytes are in the range 0x8140 to 0x9FFC */ (intermediate + 0x8140) as u16 } else { (intermediate + 0xc140) as u16 }; writer.write_all(&[(sjw >> 8) as u8, (sjw & 0xff) as u8]).map_err(|_| DeQRError::IoError)?; } Ok(()) } fn decode_byte( meta: &MetaData, ds: &mut CorrectedDataStream, mut writer: W, ) -> DeQRResult<()> where W: Write { let nbits = match meta.version { Version(0..=9) => 8, _ => 16 }; let count = ds.take_bits(nbits); if ds.bits_remaining() < count * 8 { return Err(DeQRError::DataUnderflow)?; } for _ in 0..count { let buf = &[ds.take_bits(8) as u8]; writer.write_all(buf) .map_err(|_| DeQRError::IoError)?; } Ok(()) } fn decode_alpha( meta: &MetaData, ds: &mut CorrectedDataStream, mut writer: W, ) -> DeQRResult<()> where W: Write { let nbits = match meta.version { Version(0..=9) => 9, Version(10..=26) => 11, _ => 13, }; let mut count = ds.take_bits(nbits); let mut buf = [0; 2]; while count >= 2 { alpha_tuple(&mut buf, ds, 11, 2)?; writer.write_all(&buf[..]) .map_err(|_| DeQRError::IoError)?; count -= 2; } if count == 1 { alpha_tuple(&mut buf, ds, 6, 1)?; writer.write_all(&buf[..1]) .map_err(|_| DeQRError::IoError)?; } Ok(()) } fn alpha_tuple( buf: &mut [u8; 2], ds: &mut CorrectedDataStream, nbits: usize, digits: usize, ) -> DeQRResult<()> { if ds.bits_remaining() < nbits { Err(DeQRError::DataUnderflow) } else { let mut tuple = ds.take_bits(nbits); for i in (0..digits).rev() { const ALPHA_MAP: &[u8; 46] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:\x00"; buf[i] = ALPHA_MAP[tuple % 45]; tuple /= 45; } Ok(()) } } fn decode_numeric( meta: &MetaData, ds: &mut CorrectedDataStream, mut writer: W, ) -> DeQRResult<()> where W: Write { let nbits = match meta.version { Version(0..=9) => 10, Version(10..=26) => 12, _ => 14, }; let mut count = ds.take_bits(nbits); let mut buf = [0; 3]; while count >= 3 { numeric_tuple(&mut buf, ds, 10, 3)?; writer.write_all(&buf[..]) .map_err(|_| DeQRError::IoError)?; count -= 3; } if count == 2 { numeric_tuple(&mut buf, ds, 7, 2)?; writer.write_all(&buf[..2]) .map_err(|_| DeQRError::IoError)?; count -= 2; } if count == 1 { numeric_tuple(&mut buf, ds, 4, 1)?; writer.write_all(&buf[..1]) .map_err(|_| DeQRError::IoError)?; } Ok(()) } fn numeric_tuple( buf: &mut [u8; 3], ds: &mut CorrectedDataStream, nbits: usize, digits: usize, ) -> DeQRResult<()> { if ds.bits_remaining() < nbits { Err(DeQRError::DataUnderflow) } else { let mut tuple = ds.take_bits(nbits); for i in (0..digits).rev() { buf[i] = (tuple % 10) as u8 + b'0'; tuple /= 10; } Ok(()) } } fn codestream_ecc( meta: &MetaData, ds: RawData, ) -> DeQRResult { let mut out = CorrectedDataStream { data: [0; MAX_PAYLOAD_SIZE], ptr: 0, bit_len: 0, }; let ver = &VERSION_DATA_BASE[meta.version.0 as usize]; let sb_ecc = &ver.ecc[meta.ecc_level as usize]; let lb_ecc = RSParameters { bs: sb_ecc.bs + 1, dw: sb_ecc.dw + 1, ns: sb_ecc.ns, }; 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; for i in 0..bc { let ecc = if i < sb_ecc.ns { sb_ecc } else { &lb_ecc }; let dst = &mut out.data[dst_offset..(dst_offset + ecc.bs)]; let num_ec = ecc.bs - ecc.dw; for j in 0..ecc.dw { dst[j] = ds.data[j * bc + i]; } for j in 0..num_ec { dst[ecc.dw + j] = ds.data[ecc_offset + j * bc + i]; } correct_block(dst, ecc)?; dst_offset += ecc.dw; } out.bit_len = dst_offset * 8; Ok(out) } fn correct_block( block: &mut [u8], ecc: &RSParameters, ) -> DeQRResult<()> { assert!(ecc.bs > ecc.dw); let npar = ecc.bs - ecc.dw; let mut sigma_deriv = [GF256::ZERO; 64]; // Calculate syndromes. If all 0 there is nothing to do. let s = match block_syndromes(&block[..ecc.bs], npar) { Ok(_) => return Ok(()), Err(s) => s, }; let sigma = berlekamp_massey(&s, npar); /* Compute derivative of sigma */ for i in (1..64).step_by(2) { sigma_deriv[i - 1] = sigma[i]; } /* Compute error evaluator polynomial */ let omega = eloc_poly( &s, &sigma, npar - 1, ); /* Find error locations and magnitudes */ for i in 0..ecc.bs { let xinv = GF256::GENERATOR.pow(255 - i); if poly_eval(&sigma, xinv) == GF256::ZERO { let sd_x = poly_eval(&sigma_deriv, xinv); let omega_x = poly_eval(&omega, xinv); let error = omega_x / sd_x; block[ecc.bs - i - 1] = (GF256(block[ecc.bs - i - 1]) + error).0; } } match block_syndromes(&block[..ecc.bs], npar) { Ok(_) => Ok(()), Err(_) => Err(DeQRError::DataEcc), } } /* *********************************************************************** * Code stream error correction * * Generator polynomial for GF(2^8) is x^8 + x^4 + x^3 + x^2 + 1 */ fn block_syndromes( block: &[u8], npar: usize, ) -> Result<[GF256; 64], [GF256; 64]> { let mut nonzero: bool = false; let mut s = [GF256::ZERO; 64]; for i in 0..npar { for j in 0..block.len() { let c = GF256(block[block.len() - 1 - j]); s[i] += c * GF256::GENERATOR.pow(i * j); } if s[i] != GF256::ZERO { nonzero = true; } } if nonzero { Err(s) } else { Ok(s) } } fn poly_eval( s: &[G; 64], x: G, ) -> G where G: GaloisField { let mut sum = G::ZERO; let mut x_pow = G::ONE; for i in 0..64 { sum += s[i] * x_pow; x_pow *= x; } sum } fn eloc_poly( s: &[GF256; 64], sigma: &[GF256; 64], npar: usize, ) -> [GF256; 64] { let mut omega = [GF256::ZERO; 64]; for i in 0..npar { let a = sigma[i]; for j in 0..(npar - i) { let b = s[j + 1]; omega[i + j] += a * b; } } omega } /* *********************************************************************** * Berlekamp-Massey algorithm for finding error locator polynomials. */ fn berlekamp_massey( s: &[G; 64], n: usize, ) -> [G; 64] where G: GaloisField { let mut ts: [G; 64] = [G::ZERO; 64]; let mut cs: [G; 64] = [G::ZERO; 64]; let mut bs: [G; 64] = [G::ZERO; 64]; let mut l: usize = 0; let mut m: usize = 1; let mut b = G::ONE; bs[0] = G::ONE; cs[0] = G::ONE; for n in 0..n { let mut d = s[n]; // Calculate in GF(p): // d = s[n] + \Sum_{i=1}^{l} c[i] * s[n - i] for i in 1..=l { d += cs[i] * s[n - i]; } // Pre-calculate d * b^-1 in GF(p) let mult = d / b; if d == G::ZERO { m += 1 } else if l * 2 <= n { ts.copy_from_slice(&cs); poly_add(&mut cs, &bs, mult, m); bs.copy_from_slice(&ts); l = n + 1 - l; b = d; m = 1 } else { poly_add(&mut cs, &bs, mult, m); m += 1 } } cs } /* *********************************************************************** * Polynomial operations */ fn poly_add( dst: &mut [G; 64], src: &[G; 64], c: G, shift: usize, ) -> () where G: GaloisField { if c == G::ZERO { return; } for i in 0..64 { let p = i + shift; if p >= 64 { break; } let v = src[i]; dst[p] += v * c; } } fn read_data( code: &dyn BitGrid, meta: &MetaData, ) -> RawData { let mut ds = RawData::new(); let mut y = code.size() - 1; let mut x = code.size() - 1; let mut neg_dir = true; while x > 0 { if x == 6 { x -= 1; } if !reserved_cell(meta.version, y, x) { ds.push(read_bit(code, meta, y, x)); } if !reserved_cell(meta.version, y, x - 1) { ds.push(read_bit(code, meta, y, x - 1)); } let (new_y, new_neg_dir) = match (y, neg_dir) { (0, true) => { x = x.saturating_sub(2); (0, false) } (y, false) if y == code.size() - 1 => { x = x.saturating_sub(2); (code.size() - 1, true) } (y, true) => (y - 1, true), (y, false) => (y + 1, false), }; y = new_y; neg_dir = new_neg_dir; } ds } fn read_bit( code: &dyn BitGrid, meta: &MetaData, y: usize, x: usize, ) -> bool { let mut v = code.bit(y, x) as u8; if mask_bit(meta.mask, y, x) { v ^= 1 } v != 0 } fn mask_bit( mask: u16, y: usize, x: usize, ) -> bool { match mask { 0 => 0 == (y + x) % 2, 1 => 0 == y % 2, 2 => 0 == x % 3, 3 => 0 == (y + x) % 3, 4 => 0 == ((y / 2) + (x / 3)) % 2, 5 => 0 == ((y * x) % 2 + (y * x) % 3), 6 => 0 == ((y * x) % 2 + (y * x) % 3) % 2, 7 => 0 == ((y * x) % 3 + (y + x) % 2) % 2, _ => panic!("Unknown mask value"), } } fn reserved_cell( version: Version, i: usize, j: usize, ) -> bool { let ver = &VERSION_DATA_BASE[version.0]; let size = version.0 * 4 + 17; /* Finder + format: top left */ if i < 9 && j < 9 { return true; } /* Finder + format: bottom left */ if i + 8 >= size && j < 9 { return true; } /* Finder + format: top right */ if i < 9 && j + 8 >= size { return true; } /* Exclude timing patterns */ if i == 6 || j == 6 { return true; } /* Exclude version info, if it exists. Version info sits adjacent to * the top-right and bottom-left finders in three rows, bounded by * the timing pattern. */ if version.0 >= 7 { if i < 6 && j + 11 >= size { return true; } else if i + 11 >= size && j < 6 { return true; } } /* Exclude alignment patterns */ let mut ai = None; let mut aj = None; fn abs_diff(x: usize, y: usize) -> usize { if x < y { y - x } else { x - y } } let mut len = 0; for (a, &pattern) in ver.apat.iter().take_while(|&&x| x != 0).enumerate() { len = a; if abs_diff(pattern, i) < 3 { ai = Some(a) } if abs_diff(pattern, j) < 3 { aj = Some(a) } } match (ai, aj) { (Some(x), Some(y)) if x == len && y == len => true, (Some(x), Some(_)) if 0 < x && x < len => true, (Some(_), Some(x)) if 0 < x && x < len => true, _ => false, } } fn correct_format(mut word: u16) -> DeQRResult { /* Evaluate U (received codeword) at each of alpha_1 .. alpha_6 * to get S_1 .. S_6 (but we index them from 0). */ if let Err(mut s) = format_syndromes(word) { let sigma = berlekamp_massey(&mut s, 6); /* Now, find the roots of the polynomial */ for i in 0..15 { if poly_eval(&sigma, GF16::GENERATOR.pow(15 - i)) == GF16::ZERO { word ^= 1 << i; } } // Double CHECK syndromes format_syndromes(word) .map_err(|_| DeQRError::FormatEcc)?; } Ok(word) } fn read_format(code: &dyn BitGrid) -> DeQRResult { let mut format = 0; // Try first location const XS: [usize; 15] = [ 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 4, 3, 2, 1, 0 ]; const YS: [usize; 15] = [ 0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8 ]; for i in (0..15).rev() { format = (format << 1) | code.bit(YS[i], XS[i]) as u16; } format ^= 0x5412; // Check format, try other location if needed let verified_format = correct_format(format).or_else(|_| { let mut format = 0; for i in 0..7 { format = (format << 1) | code.bit(code.size() - 1 - i, 8) as u16; } for i in 0..8 { format = (format << 1) | code.bit(8, code.size() - 8 + i) as u16; } format ^= 0x5412; correct_format(format) })?; let fdata = verified_format >> 10; let ecc_level = fdata >> 3; let mask = fdata & 7; let version = Version::from_size(code.size())?; Ok(MetaData { version, ecc_level, mask, }) } /* *********************************************************************** * Format value error correction * * Generator polynomial for GF(2^4) is x^4 + x + 1 */ fn format_syndromes(u: u16) -> Result<[GF16; 64], [GF16; 64]> { let mut result = [GF16(0); 64]; let mut nonzero = false; for i in 0..6 { for j in 0..15 { if u & (1 << j) != 0 { result[i] += GF16::GENERATOR.pow((i + 1) * j); } } if result[i].0 != 0 { nonzero = true; } } if nonzero { Err(result) } else { Ok(result) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_mask_0() { let test = [ [1, 0, 1, 0, 1, 0, 1, ], [0, 1, 0, 1, 0, 1, 0, ], [1, 0, 1, 0, 1, 0, 1, ], [0, 1, 0, 1, 0, 1, 0, ], [1, 0, 1, 0, 1, 0, 1, ], [0, 1, 0, 1, 0, 1, 0, ], [1, 0, 1, 0, 1, 0, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(0, y, x)); } } } #[test] fn test_mask_1() { let test = [ [1, 1, 1, 1, 1, 1, 1, ], [0, 0, 0, 0, 0, 0, 0, ], [1, 1, 1, 1, 1, 1, 1, ], [0, 0, 0, 0, 0, 0, 0, ], [1, 1, 1, 1, 1, 1, 1, ], [0, 0, 0, 0, 0, 0, 0, ], [1, 1, 1, 1, 1, 1, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(1, y, x)); } } } #[test] fn test_mask_2() { let test = [ [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(2, y, x)); } } } #[test] fn test_mask_3() { let test = [ [1, 0, 0, 1, 0, 0, 1, ], [0, 0, 1, 0, 0, 1, 0, ], [0, 1, 0, 0, 1, 0, 0, ], [1, 0, 0, 1, 0, 0, 1, ], [0, 0, 1, 0, 0, 1, 0, ], [0, 1, 0, 0, 1, 0, 0, ], [1, 0, 0, 1, 0, 0, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(3, y, x)); } } } #[test] fn test_mask_4() { let test = [ [1, 1, 1, 0, 0, 0, 1, ], [1, 1, 1, 0, 0, 0, 1, ], [0, 0, 0, 1, 1, 1, 0, ], [0, 0, 0, 1, 1, 1, 0, ], [1, 1, 1, 0, 0, 0, 1, ], [1, 1, 1, 0, 0, 0, 1, ], [0, 0, 0, 1, 1, 1, 0, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(4, y, x)); } } } #[test] fn test_mask_5() { let test = [ [1, 1, 1, 1, 1, 1, 1, ], [1, 0, 0, 0, 0, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 1, 0, 1, 0, 1, ], [1, 0, 0, 1, 0, 0, 1, ], [1, 0, 0, 0, 0, 0, 1, ], [1, 1, 1, 1, 1, 1, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(5, y, x)); } } } #[test] fn test_mask_6() { let test = [ [1, 1, 1, 1, 1, 1, 1, ], [1, 1, 1, 0, 0, 0, 1, ], [1, 1, 0, 1, 1, 0, 1, ], [1, 0, 1, 0, 1, 0, 1, ], [1, 0, 1, 1, 0, 1, 1, ], [1, 0, 0, 0, 1, 1, 1, ], [1, 1, 1, 1, 1, 1, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(6, y, x)); } } } #[test] fn test_mask_7() { let test = [ [1, 0, 1, 0, 1, 0, 1, ], [0, 0, 0, 1, 1, 1, 0, ], [1, 0, 0, 0, 1, 1, 1, ], [0, 1, 0, 1, 0, 1, 0, ], [1, 1, 1, 0, 0, 0, 1, ], [0, 1, 1, 1, 0, 0, 0, ], [1, 0, 1, 0, 1, 0, 1, ], ]; for x in 0..7 { for y in 0..7 { assert_eq!(test[y][x] != 0, mask_bit(7, y, x)); } } } }