use super::{EcLevel, Version};
use crate::segment::Mode;
#[derive(Debug, Clone, Copy)]
pub struct EcBlocks {
pub ec_per_block: usize,
pub group1_blocks: usize,
pub group1_data: usize,
pub group2_blocks: usize,
pub group2_data: usize,
}
impl EcBlocks {
pub fn total_blocks(&self) -> usize {
self.group1_blocks + self.group2_blocks
}
pub fn total_data(&self) -> usize {
self.group1_blocks * self.group1_data + self.group2_blocks * self.group2_data
}
pub fn total_codewords(&self) -> usize {
self.total_data() + self.total_blocks() * self.ec_per_block
}
}
fn level_index(level: EcLevel) -> usize {
match level {
EcLevel::L => 0,
EcLevel::M => 1,
EcLevel::Q => 2,
EcLevel::H => 3,
}
}
pub fn ec_blocks(version: Version, level: EcLevel) -> EcBlocks {
let r = EC_BLOCK_TABLE[version.number() as usize - 1][level_index(level)];
EcBlocks {
ec_per_block: r[0] as usize,
group1_blocks: r[1] as usize,
group1_data: r[2] as usize,
group2_blocks: r[3] as usize,
group2_data: r[4] as usize,
}
}
pub fn alignment_positions(version: Version) -> &'static [u8] {
ALIGNMENT_POSITIONS[version.number() as usize - 1]
}
pub fn remainder_bits(version: Version) -> usize {
REMAINDER_BITS[version.number() as usize - 1] as usize
}
pub fn char_count_bits(version: Version, mode: &Mode) -> usize {
let v = version.number();
let group = if v <= 9 {
0
} else if v <= 26 {
1
} else {
2
};
match mode {
Mode::Numeric => [10, 12, 14][group],
Mode::Alphanumeric => [9, 11, 13][group],
Mode::Byte => [8, 16, 16][group],
Mode::Kanji => [8, 10, 12][group],
Mode::Eci(_) => 0,
}
}
pub fn mode_indicator(mode: &Mode) -> u8 {
match mode {
Mode::Numeric => 0b0001,
Mode::Alphanumeric => 0b0010,
Mode::Byte => 0b0100,
Mode::Kanji => 0b1000,
Mode::Eci(_) => 0b0111,
}
}
pub fn mode_from_indicator(indicator: u8) -> Option<Mode> {
match indicator {
0b0001 => Some(Mode::Numeric),
0b0010 => Some(Mode::Alphanumeric),
0b0100 => Some(Mode::Byte),
0b1000 => Some(Mode::Kanji),
0b0111 => Some(Mode::Eci(0)),
_ => None,
}
}
#[rustfmt::skip]
const EC_BLOCK_TABLE: [[[u16; 5]; 4]; 40] = [
[[7,1,19,0,0],[10,1,16,0,0],[13,1,13,0,0],[17,1,9,0,0]],
[[10,1,34,0,0],[16,1,28,0,0],[22,1,22,0,0],[28,1,16,0,0]],
[[15,1,55,0,0],[26,1,44,0,0],[18,2,17,0,0],[22,2,13,0,0]],
[[20,1,80,0,0],[18,2,32,0,0],[26,2,24,0,0],[16,4,9,0,0]],
[[26,1,108,0,0],[24,2,43,0,0],[18,2,15,2,16],[22,2,11,2,12]],
[[18,2,68,0,0],[16,4,27,0,0],[24,4,19,0,0],[28,4,15,0,0]],
[[20,2,78,0,0],[18,4,31,0,0],[18,2,14,4,15],[26,4,13,1,14]],
[[24,2,97,0,0],[22,2,38,2,39],[22,4,18,2,19],[26,4,14,2,15]],
[[30,2,116,0,0],[22,3,36,2,37],[20,4,16,4,17],[24,4,12,4,13]],
[[18,2,68,2,69],[26,4,43,1,44],[24,6,19,2,20],[28,6,15,2,16]],
[[20,4,81,0,0],[30,1,50,4,51],[28,4,22,4,23],[24,3,12,8,13]],
[[24,2,92,2,93],[22,6,36,2,37],[26,4,20,6,21],[28,7,14,4,15]],
[[26,4,107,0,0],[22,8,37,1,38],[24,8,20,4,21],[22,12,11,4,12]],
[[30,3,115,1,116],[24,4,40,5,41],[20,11,16,5,17],[24,11,12,5,13]],
[[22,5,87,1,88],[24,5,41,5,42],[30,5,24,7,25],[24,11,12,7,13]],
[[24,5,98,1,99],[28,7,45,3,46],[24,15,19,2,20],[30,3,15,13,16]],
[[28,1,107,5,108],[28,10,46,1,47],[28,1,22,15,23],[28,2,14,17,15]],
[[30,5,120,1,121],[26,9,43,4,44],[28,17,22,1,23],[28,2,14,19,15]],
[[28,3,113,4,114],[26,3,44,11,45],[26,17,21,4,22],[26,9,13,16,14]],
[[28,3,107,5,108],[26,3,41,13,42],[30,15,24,5,25],[28,15,15,10,16]],
[[28,4,116,4,117],[26,17,42,0,0],[28,17,22,6,23],[30,19,16,6,17]],
[[28,2,111,7,112],[28,17,46,0,0],[30,7,24,16,25],[24,34,13,0,0]],
[[30,4,121,5,122],[28,4,47,14,48],[30,11,24,14,25],[30,16,15,14,16]],
[[30,6,117,4,118],[28,6,45,14,46],[30,11,24,16,25],[30,30,16,2,17]],
[[26,8,106,4,107],[28,8,47,13,48],[30,7,24,22,25],[30,22,15,13,16]],
[[28,10,114,2,115],[28,19,46,4,47],[28,28,22,6,23],[30,33,16,4,17]],
[[30,8,122,4,123],[28,22,45,3,46],[30,8,23,26,24],[30,12,15,28,16]],
[[30,3,117,10,118],[28,3,45,23,46],[30,4,24,31,25],[30,11,15,31,16]],
[[30,7,116,7,117],[28,21,45,7,46],[30,1,23,37,24],[30,19,15,26,16]],
[[30,5,115,10,116],[28,19,47,10,48],[30,15,24,25,25],[30,23,15,25,16]],
[[30,13,115,3,116],[28,2,46,29,47],[30,42,24,1,25],[30,23,15,28,16]],
[[30,17,115,0,0],[28,10,46,23,47],[30,10,24,35,25],[30,19,15,35,16]],
[[30,17,115,1,116],[28,14,46,21,47],[30,29,24,19,25],[30,11,15,46,16]],
[[30,13,115,6,116],[28,14,46,23,47],[30,44,24,7,25],[30,59,16,1,17]],
[[30,12,121,7,122],[28,12,47,26,48],[30,39,24,14,25],[30,22,15,41,16]],
[[30,6,121,14,122],[28,6,47,34,48],[30,46,24,10,25],[30,2,15,64,16]],
[[30,17,122,4,123],[28,29,46,14,47],[30,49,24,10,25],[30,24,15,46,16]],
[[30,4,122,18,123],[28,13,46,32,47],[30,48,24,14,25],[30,42,15,32,16]],
[[30,20,117,4,118],[28,40,47,7,48],[30,43,24,22,25],[30,10,15,67,16]],
[[30,19,118,6,119],[28,18,47,31,48],[30,34,24,34,25],[30,20,15,61,16]],
];
#[rustfmt::skip]
const ALIGNMENT_POSITIONS: [&[u8]; 40] = [
&[],
&[6,18], &[6,22], &[6,26], &[6,30], &[6,34],
&[6,22,38], &[6,24,42], &[6,26,46], &[6,28,50], &[6,30,54],
&[6,32,58], &[6,34,62], &[6,26,46,66], &[6,26,48,70], &[6,26,50,74],
&[6,30,54,78], &[6,30,56,82], &[6,30,58,86], &[6,34,62,90], &[6,28,50,72,94],
&[6,26,50,74,98], &[6,30,54,78,102], &[6,28,54,80,106], &[6,32,58,84,110],
&[6,30,58,86,114], &[6,34,62,90,118], &[6,26,50,74,98,122], &[6,30,54,78,102,126],
&[6,26,52,78,104,130], &[6,30,56,82,108,134], &[6,34,60,86,112,138],
&[6,30,58,86,114,142], &[6,34,62,90,118,146], &[6,30,54,78,102,126,150],
&[6,24,50,76,102,128,154], &[6,28,54,80,106,132,158], &[6,32,58,84,110,136,162],
&[6,26,54,82,110,138,166], &[6,30,58,86,114,142,170],
];
#[rustfmt::skip]
const REMAINDER_BITS: [u8; 40] = [
0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0,
];