Skip to main content

forme/
qrcode.rs

1//! # QR Code Generation
2//!
3//! Converts data strings into QR code matrices for vector rendering in PDF.
4//! Uses the `qrcode` crate for encoding and error correction.
5
6use qrcode::types::QrError;
7use qrcode::QrCode;
8
9/// A QR code represented as a grid of boolean modules.
10#[derive(Debug, Clone)]
11pub struct QrMatrix {
12    /// true = dark module, false = light module.
13    pub modules: Vec<Vec<bool>>,
14    /// Number of modules per side (QR codes are always square).
15    pub size: usize,
16}
17
18/// Generate a QR code matrix from the given data string.
19pub fn generate_qr(data: &str) -> Result<QrMatrix, QrError> {
20    let code = QrCode::new(data.as_bytes())?;
21    let size = code.width();
22    let modules = (0..size)
23        .map(|y| {
24            (0..size)
25                .map(|x| code[(x, y)] == qrcode::Color::Dark)
26                .collect()
27        })
28        .collect();
29    Ok(QrMatrix { modules, size })
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn test_generate_qr_valid() {
38        let matrix = generate_qr("https://formepdf.com").unwrap();
39        assert!(matrix.size > 0, "QR matrix should have positive size");
40        assert_eq!(matrix.modules.len(), matrix.size, "Rows should match size");
41        assert_eq!(
42            matrix.modules[0].len(),
43            matrix.size,
44            "Columns should match size"
45        );
46    }
47
48    #[test]
49    fn test_generate_qr_square() {
50        let matrix = generate_qr("test data").unwrap();
51        for (i, row) in matrix.modules.iter().enumerate() {
52            assert_eq!(row.len(), matrix.size, "Row {i} length should equal size");
53        }
54    }
55
56    #[test]
57    fn test_generate_qr_has_dark_modules() {
58        let matrix = generate_qr("hello").unwrap();
59        let has_dark = matrix.modules.iter().any(|row| row.iter().any(|&m| m));
60        assert!(has_dark, "QR code should have at least some dark modules");
61    }
62}