use crate::types::{
Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QRErrorCorrection, QuickCodesError, Result,
};
use qrcode::{EcLevel, QrCode};
pub fn generate_qr(data: &str) -> Result<Barcode> {
generate_qr_with_config(data, &BarcodeConfig::default())
}
pub fn generate_qr_with_config(data: &str, config: &BarcodeConfig) -> Result<Barcode> {
let ec_level = match config.qr_config.error_correction {
QRErrorCorrection::Low => EcLevel::L,
QRErrorCorrection::Medium => EcLevel::M,
QRErrorCorrection::Quartile => EcLevel::Q,
QRErrorCorrection::High => EcLevel::H,
};
let qr_code = QrCode::with_error_correction_level(data, ec_level)
.map_err(|e| QuickCodesError::GenerationError(format!("QR generation failed: {}", e)))?;
let width = qr_code.width();
let mut matrix = Vec::with_capacity(width);
for y in 0..width {
let mut row = Vec::with_capacity(width);
for x in 0..width {
row.push(qr_code[(x, y)] == qrcode::Color::Dark);
}
matrix.push(row);
}
Ok(Barcode {
barcode_type: BarcodeType::QRCode,
data: data.to_string(),
modules: BarcodeModules::Matrix(matrix),
config: config.clone(),
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_qr_generation() {
let result = generate_qr("Hello, World!");
assert!(result.is_ok());
let barcode = result.unwrap();
assert_eq!(barcode.barcode_type, BarcodeType::QRCode);
assert_eq!(barcode.data, "Hello, World!");
match barcode.modules {
BarcodeModules::Matrix(matrix) => {
assert!(!matrix.is_empty());
assert!(!matrix[0].is_empty());
assert_eq!(matrix.len(), matrix[0].len());
}
_ => panic!("QR code should generate a matrix"),
}
}
#[test]
fn test_qr_different_error_corrections() {
let mut config = BarcodeConfig::default();
for ec_level in [
QRErrorCorrection::Low,
QRErrorCorrection::Medium,
QRErrorCorrection::Quartile,
QRErrorCorrection::High,
] {
config.qr_config.error_correction = ec_level;
let result = generate_qr_with_config("Test data", &config);
assert!(
result.is_ok(),
"Failed with error correction: {:?}",
ec_level
);
}
}
#[test]
fn test_qr_empty_data() {
let result = generate_qr("");
assert!(result.is_ok()); }
#[test]
fn test_qr_large_data() {
let large_data = "A".repeat(1000);
let result = generate_qr(&large_data);
match result {
Ok(_) => (), Err(QuickCodesError::GenerationError(_)) => (), Err(e) => panic!("Unexpected error type: {:?}", e),
}
}
}