#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SquareSpec {
pub symbol_size: usize,
pub region_size: usize,
pub regions_per_axis: usize,
pub data_cw: usize,
pub ec_cw: usize,
pub blocks: usize,
}
impl SquareSpec {
pub fn total_cw(&self) -> usize {
self.data_cw + self.ec_cw
}
pub fn ec_per_block(&self) -> usize {
self.ec_cw / self.blocks
}
pub fn mapping_size(&self) -> usize {
self.region_size * self.regions_per_axis
}
}
#[rustfmt::skip]
const SQUARE: &[SquareSpec] = &[
SquareSpec { symbol_size: 10, region_size: 8, regions_per_axis: 1, data_cw: 3, ec_cw: 5, blocks: 1 },
SquareSpec { symbol_size: 12, region_size: 10, regions_per_axis: 1, data_cw: 5, ec_cw: 7, blocks: 1 },
SquareSpec { symbol_size: 14, region_size: 12, regions_per_axis: 1, data_cw: 8, ec_cw: 10, blocks: 1 },
SquareSpec { symbol_size: 16, region_size: 14, regions_per_axis: 1, data_cw: 12, ec_cw: 12, blocks: 1 },
SquareSpec { symbol_size: 18, region_size: 16, regions_per_axis: 1, data_cw: 18, ec_cw: 14, blocks: 1 },
SquareSpec { symbol_size: 20, region_size: 18, regions_per_axis: 1, data_cw: 22, ec_cw: 18, blocks: 1 },
SquareSpec { symbol_size: 22, region_size: 20, regions_per_axis: 1, data_cw: 30, ec_cw: 20, blocks: 1 },
SquareSpec { symbol_size: 24, region_size: 22, regions_per_axis: 1, data_cw: 36, ec_cw: 24, blocks: 1 },
SquareSpec { symbol_size: 26, region_size: 24, regions_per_axis: 1, data_cw: 44, ec_cw: 28, blocks: 1 },
SquareSpec { symbol_size: 32, region_size: 14, regions_per_axis: 2, data_cw: 62, ec_cw: 36, blocks: 1 },
SquareSpec { symbol_size: 36, region_size: 16, regions_per_axis: 2, data_cw: 86, ec_cw: 42, blocks: 1 },
SquareSpec { symbol_size: 40, region_size: 18, regions_per_axis: 2, data_cw: 114, ec_cw: 48, blocks: 1 },
SquareSpec { symbol_size: 44, region_size: 20, regions_per_axis: 2, data_cw: 144, ec_cw: 56, blocks: 1 },
SquareSpec { symbol_size: 48, region_size: 22, regions_per_axis: 2, data_cw: 174, ec_cw: 68, blocks: 1 },
SquareSpec { symbol_size: 52, region_size: 24, regions_per_axis: 2, data_cw: 204, ec_cw: 84, blocks: 2 },
SquareSpec { symbol_size: 64, region_size: 14, regions_per_axis: 4, data_cw: 280, ec_cw: 112, blocks: 2 },
SquareSpec { symbol_size: 72, region_size: 16, regions_per_axis: 4, data_cw: 368, ec_cw: 144, blocks: 4 },
SquareSpec { symbol_size: 80, region_size: 18, regions_per_axis: 4, data_cw: 456, ec_cw: 192, blocks: 4 },
SquareSpec { symbol_size: 88, region_size: 20, regions_per_axis: 4, data_cw: 576, ec_cw: 224, blocks: 4 },
SquareSpec { symbol_size: 96, region_size: 22, regions_per_axis: 4, data_cw: 696, ec_cw: 272, blocks: 4 },
SquareSpec { symbol_size: 104, region_size: 24, regions_per_axis: 4, data_cw: 816, ec_cw: 336, blocks: 6 },
SquareSpec { symbol_size: 120, region_size: 18, regions_per_axis: 6, data_cw: 1050, ec_cw: 408, blocks: 6 },
SquareSpec { symbol_size: 132, region_size: 20, regions_per_axis: 6, data_cw: 1304, ec_cw: 496, blocks: 8 },
SquareSpec { symbol_size: 144, region_size: 22, regions_per_axis: 6, data_cw: 1558, ec_cw: 620, blocks: 10 },
];
pub fn all_squares() -> &'static [SquareSpec] {
SQUARE
}
pub fn smallest_square_for(data_cw: usize) -> Option<SquareSpec> {
all_squares().iter().copied().find(|s| s.data_cw >= data_cw)
}
pub fn square_by_size(symbol_size: usize) -> Option<SquareSpec> {
all_squares()
.iter()
.copied()
.find(|s| s.symbol_size == symbol_size)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn geometry_is_consistent() {
for s in all_squares() {
assert_eq!(
s.symbol_size,
s.mapping_size() + 2 * s.regions_per_axis,
"symbol {} border geometry",
s.symbol_size
);
let modules = s.mapping_size() * s.mapping_size();
let slack = modules - s.total_cw() * 8;
assert!(
slack == 0 || slack == 4,
"symbol {} slack {slack}",
s.symbol_size
);
assert_eq!(s.ec_cw % s.blocks, 0, "symbol {} ec split", s.symbol_size);
}
}
}