This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
AztecLib is a pure Swift library for generating Aztec 2D barcodes per ISO/IEC 24778. It encodes strings, byte arrays, and Data objects into Aztec symbols with configurable error correction.
# Build
swift build
# Run all tests
swift test
# Run a single test file
swift test --filter AztecEncoderTests
# Run a specific test
swift test --filter AztecEncoderTests.encodes_hello_string
# Build and test via Xcode
xcodebuild -scheme AztecLib testThe library follows a 6-step pipeline (see AztecEncoder.swift:93-143):
- Data Encoding (
AztecDataEncoder) - Converts input to bits using modes (Upper, Lower, Digit, Punct, Mixed, Byte) - Configuration Selection (
pickConfiguration()inAztecConfiguration.swift) - Selects smallest symbol that fits payload + error correction - Codeword Packing (
BitBuffer.makeCodewords()) - Packs bits into codewords with "stuff bits" to avoid all-0 or all-1 patterns - Reed-Solomon Encoding (
ReedSolomonEncoder) - Adds parity codewords for error correction using Galois field arithmetic - Matrix Building (
AztecMatrixBuilder) - Assembles finder pattern, mode message, reference grid, and data layers - Export (
AztecSymbol) - Outputs packed bitmap with configurable bit ordering (LSB/MSB-first)
AztecEncoder- Public API entry point withencode()andencodeWithDetails()methodsAztecSymbol- Output container with size, rowStride, bytes, and subscript access to individual modulesAztecSymbolView- SwiftUI view for rendering symbols (iOS 15+, macOS 12+, tvOS 15+, watchOS 8+, visionOS 1+)AztecCodeView- Convenience SwiftUI view that encodes and renders in one stepAztecConfiguration- Symbol parameters (compact/full, layers, codeword sizes, parity counts)GaloisField- GF(2^m) arithmetic for m = 6, 8, 10, or 12 bitsReedSolomonEncoder- Generates parity codewords using generator polynomialsBitBuffer/CodewordBuffer- Bit-level packing utilities
- Compact symbols: 1-4 layers, 15x15 to 27x27 modules, 9x9 finder pattern
- Full symbols: 4-32 layers, 31x31 to 151x151 modules, 13x13 finder pattern
- Note:
fullSymbolSpecsarray starts at layer 4 (index 0), not layer 1
- Note:
These formulas must match ZXing's implementation for correct encoding:
// Symbol size for full symbols
let baseMatrixSize = 14 + 4 * layers
let refLines = (baseMatrixSize / 2 - 1) / 15
let symbolSize = baseMatrixSize + 1 + 2 * refLines
// Alignment map for data placement (full symbols)
// Maps logical data coordinates to physical matrix coordinates
// Skips center coordinate and reference grid lines
let origCenter = baseMatrixSize / 2
let center = symbolSize / 2
for i in 0..<origCenter {
let newOffset = i + i / 15 // Adds gap for ref grid lines
alignmentMap[origCenter - i - 1] = center - newOffset - 1
alignmentMap[origCenter + i] = center + newOffset + 1
}- GF(2^6): 0x43
- GF(2^8): 0x12D
- GF(2^10): 0x409
- GF(2^12): 0x1069
The library supports all Apple platforms:
- iOS 15.0+
- macOS 12.0+
- tvOS 15.0+
- watchOS 8.0+
- visionOS 1.0+
The SwiftUI views (AztecSymbolView, AztecCodeView) are available when SwiftUI is available.
Tests use Swift Testing framework (@Test macro). Test files mirror source structure in AztecLibTests/.
AztecComprehensiveTests.swift- Full coverage of encoding pipelineAztecDiagnosticTests.swift- Visual inspection helpers for debuggingAztecValidationTests.swift- Cross-validation against CIAztecCodeGenerator using Vision framework decoderAztecComparisonTests.swift- Module-level comparison between AztecLib and native encoders
The AztecValidationTests.swift file provides comprehensive validation by:
- Rendering AztecSymbol to CGImage with configurable module size and quiet zone
- Decoding using Apple's Vision framework (
VNDetectBarcodesRequest) - Comparing against CIAztecCodeGenerator reference implementation
- Testing scannability invariants (rotation, scaling)
# Run all validation tests
swift test --filter AztecValidationTests
# Run diagnostic comparison (prints decode results)
swift test --filter print_decode_comparison
# Save test images for manual inspection
swift test --filter save_test_images_for_manual_inspection
# Images saved to: /tmp/azteclib_test.png and /tmp/ciaztec_test.pngFor detailed error messages and cross-validation, use the zxing-cpp Python decoder.
Prerequisites:
- Python 3.9+ (included with macOS)
- pip (Python package manager)
Setup (one-time):
# Create a virtual environment (recommended location)
python3 -m venv ~/.venv/zxing
# Activate the virtual environment
source ~/.venv/zxing/bin/activate
# Install required packages
pip install zxing-cpp pillow
# Verify installation
python3 -c "import zxingcpp; print('zxing-cpp ready')"Alternative: Temporary virtual environment
# For quick testing without persistent venv
python3 -m venv /tmp/zxing-venv
source /tmp/zxing-venv/bin/activate
pip install zxing-cpp pillowUsage:
# Activate the virtual environment first
source ~/.venv/zxing/bin/activate # or /tmp/zxing-venv/bin/activate
# Decode an image (basic)
python3 Scripts/aztec_decode.py /tmp/azteclib_test.png
# Decode with verbose output (shows image info, format detected)
python3 Scripts/aztec_decode.py /tmp/azteclib_test.png --verbose
# Output as JSON (for scripting/automation)
python3 Scripts/aztec_decode.py /tmp/azteclib_test.png --json
# Show raw bytes as hex (for binary payloads)
python3 Scripts/aztec_decode.py /tmp/azteclib_test.png --rawComplete workflow example:
# 1. Generate test images from Swift tests
swift test --filter save_test_images_for_manual_inspection
# 2. Decode and compare
source ~/.venv/zxing/bin/activate
python3 Scripts/aztec_decode.py /tmp/azteclib_test.png --verbose
python3 Scripts/aztec_decode.py /tmp/ciaztec_test.png --verboseThe Scripts/aztec_decode.py helper provides:
- Detailed error messages when decoding fails
- Verbose mode showing image dimensions, format, and content type
- JSON output mode for automation (
--json) - Raw bytes output as hex (
--raw) - Exit code 0 on success, 1 on failure (for CI integration)
The test file provides these utility functions:
// Render AztecSymbol to CGImage with quiet zone
let image = renderAztecSymbol(symbol, moduleSize: 10, quietZoneModules: 4)
// Scale an image
let scaled = scaleImage(image, factor: 2.0)
// Rotate an image (90° increments)
let rotated = rotateImage(image, degrees: 90)
// Decode using Vision framework
let (data, error) = decodeAztecWithVision(image)
// Generate reference with CIAztecCodeGenerator
let ciImage = generateCIAztecCode(data: payload.data(using: .isoLatin1)!)// Random ASCII strings
let vectors = generateASCIITestVectors(count: 20, maxLength: 80)
// Random UTF-8 strings (various Unicode ranges)
let utf8Vectors = generateUTF8TestVectors(count: 20, maxLength: 50)
// Random binary data
let binaryVectors = generateBinaryTestVectors(count: 15, maxLength: 100)
// Edge cases (null bytes, repeated patterns, mode switching)
let edgeCases = generateEdgeCaseVectors()When debugging encoding issues, always compare against ZXing's reference implementation:
- Java: https://github.com/zxing/zxing/blob/master/core/src/main/java/com/google/zxing/aztec/encoder/
- Key files:
Encoder.java,HighLevelEncoder.java
-
Mode transitions: The latch/shift tables must exactly match ZXing's
LATCH_TABLEandSHIFT_TABLE. Pay special attention to multi-step transitions (e.g., Digit→Punct requires U/L→M/L→P/L, not a direct code). -
Alignment map: For full symbols, data placement coordinates must skip the center and reference grid lines. Use ZXing's formula with
i + i / 15offset. -
Symbol size: Reference grid line count is
(baseMatrixSize / 2 - 1) / 15, NOT(layers - 1) / 15. -
Array indexing:
fullSymbolSpecsstarts at layer 4 (index 0), so uselayers - 4notlayers - 1.
Apple's Vision framework cannot decode all Aztec symbols that ZXing can:
- Compact 23x23 (layer 3) often fails
- Larger full symbols (39x39+) often fail
- Use ZXing for authoritative decode verification