Skip to main content

anyd/codes/qr/
mod.rs

1//! QR Code (ISO/IEC 18004) encoder and structural decoder.
2//!
3//! Layout:
4//! - [`gf`]      — GF(256) arithmetic and Reed–Solomon encode/decode.
5//! - `tables`    — the spec's per-version capacity, EC-block and alignment tables.
6//! - `matrix`    — module placement, masking and format/version information.
7//! - `encode`    — [`Symbol`] → [`BitMatrix`].
8//! - `decode`    — [`BitMatrix`] → [`Symbol`].
9//!
10//! [`Symbol`]: crate::Symbol
11//! [`BitMatrix`]: crate::output::BitMatrix
12
13mod decode;
14mod encode;
15pub mod gf;
16mod matrix;
17mod sample;
18mod tables;
19
20pub use decode::QrDecoder;
21pub use encode::QrEncoder;
22pub use sample::{QrScanner, sample_grid, scan};
23
24/// QR error-correction level, in ascending order of recovery capacity.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
26pub enum EcLevel {
27    /// ~7% recovery.
28    L,
29    /// ~15% recovery.
30    M,
31    /// ~25% recovery.
32    Q,
33    /// ~30% recovery.
34    H,
35}
36
37impl EcLevel {
38    /// The 2-bit field value used in the format information.
39    pub fn format_bits(self) -> u8 {
40        match self {
41            EcLevel::L => 0b01,
42            EcLevel::M => 0b00,
43            EcLevel::Q => 0b11,
44            EcLevel::H => 0b10,
45        }
46    }
47
48    /// Recover an EC level from its 2-bit format field.
49    pub fn from_format_bits(bits: u8) -> Self {
50        match bits & 0b11 {
51            0b01 => EcLevel::L,
52            0b00 => EcLevel::M,
53            0b11 => EcLevel::Q,
54            _ => EcLevel::H,
55        }
56    }
57}
58
59/// A QR symbol version, 1–40. The module grid is `21 + 4 * (version - 1)` on a side.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
61pub struct Version(u8);
62
63impl Version {
64    /// Construct a version, validating the `1..=40` range.
65    pub fn new(v: u8) -> Option<Self> {
66        (1..=40).contains(&v).then_some(Version(v))
67    }
68
69    /// The version number, 1–40.
70    pub fn number(self) -> u8 {
71        self.0
72    }
73
74    /// Side length of the module grid.
75    pub fn size(self) -> usize {
76        21 + 4 * (self.0 as usize - 1)
77    }
78}
79
80/// The data mask pattern applied to the encoding region, 0–7.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82pub struct Mask(u8);
83
84impl Mask {
85    /// Construct a mask, validating the `0..=7` range.
86    pub fn new(m: u8) -> Option<Self> {
87        (m <= 7).then_some(Mask(m))
88    }
89
90    /// The mask pattern index, 0–7.
91    pub fn index(self) -> u8 {
92        self.0
93    }
94}
95
96/// QR-specific parameters needed to re-encode a symbol identically.
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct QrMeta {
99    /// Symbol version (size).
100    pub version: Version,
101    /// Error-correction level.
102    pub ec_level: EcLevel,
103    /// Applied data mask pattern.
104    pub mask: Mask,
105}