feat(qr-encode): add pure-Rust QR code encoder for RVF seed bytes

Implement a zero-dependency QR code encoder that generates QR code
images from RVQS seed payloads, feature-gated behind `qr`:

QR encoder (qr_encode.rs):
- QrEncoder with encode(), to_svg(), to_ascii() methods
- QrCode struct with modules matrix, version, and size
- EcLevel enum (L/M/Q/H) and QrError enum
- Versions 1-5 (21x21 to 37x37), byte-mode encoding
- Reed-Solomon EC over GF(2^8) with polynomial 0x11D
- All 8 mask patterns with automatic best-mask selection
- Finder patterns, timing patterns, alignment patterns (v2+)
- Format information with BCH(15,5) encoding
- Data interleaving across EC blocks
- 11 unit tests covering encoding, rendering, GF arithmetic, errors

Integration:
- Module declared in lib.rs behind cfg(feature = "qr")
- Re-exports QrEncoder, QrCode, QrError, EcLevel
- `qr` feature in Cargo.toml (zero external deps)
- Example: qr_seed_encode.rs builds seed and renders SVG/ASCII

Fix doc example to use associated function syntax and suppress
dead_code warnings on internal helper fields.

All 236 tests pass: cargo test -p rvf-runtime --features qr

https://claude.ai/code/session_01RnwD4x5cbpB7FPvoyYQz8G
This commit is contained in:
Claude 2026-02-15 18:39:20 +00:00
parent d6f63979bc
commit ac7c7d3dac

View file

@ -15,8 +15,7 @@
//! ```
//! use rvf_runtime::qr_encode::{QrEncoder, EcLevel};
//!
//! let encoder = QrEncoder::new();
//! let code = encoder.encode(b"Hello, RVF!", EcLevel::M).unwrap();
//! let code = QrEncoder::encode(b"Hello, RVF!", EcLevel::M).unwrap();
//! let svg = QrEncoder::to_svg(&code);
//! let ascii = QrEncoder::to_ascii(&code);
//! ```
@ -85,6 +84,7 @@ pub struct QrEncoder;
/// Data capacity = total_codewords - ec_codewords_per_block * num_blocks
/// Source: ISO 18004 Tables 7 and 9.
struct VersionInfo {
#[allow(dead_code)]
version: u8,
total_codewords: usize,
/// EC codewords per block for [L, M, Q, H].
@ -434,6 +434,7 @@ impl QrMatrix {
self.modules[row][col] == ModuleState::Empty
}
#[allow(dead_code)]
fn is_dark(&self, row: usize, col: usize) -> bool {
match self.modules[row][col] {
ModuleState::Function(d) | ModuleState::Data(d) => d,