High-performance SIMD-optimized Luhn algorithm validator for payment card numbers with zero-allocation design.
Luhn Ultra is a blazingly fast, memory-efficient Rust library for validating payment card numbers using the Luhn algorithm (Mod-10). Built for production systems requiring PCI DSS compliance and high-throughput payment processing.
- β‘ Zero Allocations: No heap allocations in validation hot paths
- π§ͺ Battle Tested: Comprehensive test suite including fuzzing and property-based tests
- π§ Flexible API: Both fast boolean paths and detailed error reporting
- π¦ Batch Processing: Efficient batch validation with optional parallelization
- π‘οΈ Memory Safe: Unsafe code limited to documented SIMD kernels only
- SSE2: β₯1.5 GB/s throughput
- Latency: p50 β€200ns per validation
- Scaling: β₯85% linear scaling with parallelization
Add to your Cargo.toml
:
[dependencies]
luhn_ultra = "0.1"
# Optional: Enable parallel batch processing
luhn_ultra = { version = "0.1", features = ["parallel"] }
use luhn_ultra::Validator;
let validator = Validator::new();
// Fast path: boolean result for 16-digit ASCII PANs
let pan16: [u8; 16] = *b"4111111111111116";
let is_valid = validator.validate_pan16_ascii(&pan16);
println!("Valid: {}", is_valid); // Valid: true
// Relaxed validation: handles spaces, dashes, variable length
let is_valid = validator.validate_pan_relaxed("4111-1111-1111-1116");
println!("Valid: {}", is_valid); // Valid: true
use luhn_ultra::{Validator, ValidationError};
let validator = Validator::new();
match validator.validate_pan_strict("4111-1111-1111-1117") {
Ok(valid) => println!("Valid: {}", valid),
Err(ValidationError::InvalidChecksum) => println!("Invalid checksum"),
Err(ValidationError::InvalidLength { length }) => {
println!("Invalid length: {}", length);
}
Err(ValidationError::InvalidCharacter { position, character }) => {
println!("Invalid character '{}' at position {}", character as char, position);
}
}
use luhn_ultra::Validator;
let validator = Validator::new();
// Batch validation for 16-digit PANs
let pans = vec![
*b"4111111111111116",
*b"5555555555554444",
*b"4000000000000002",
];
let results = validator.validate_pan16_batch(&pans);
println!("Results: {:?}", results); // [true, true, true]
// Batch validation with error details
let pan_strings = vec![
"4111-1111-1111-1116",
"5555-5555-5555-4444",
"invalid-pan-number",
];
let results = validator.validate_pan_batch_strict(&pan_strings);
for (i, result) in results.iter().enumerate() {
match result {
Ok(valid) => println!("PAN {}: Valid = {}", i, valid),
Err(e) => println!("PAN {}: Error = {}", i, e),
}
}
use luhn_ultra::{check_digit_ascii, complete_ascii};
// Compute check digit for a PAN body
let body = b"411111111111111";
if let Some(check_digit) = check_digit_ascii(body) {
println!("Check digit: {}", check_digit as char); // Check digit: 6
}
// Complete a PAN with computed check digit
let body = b"411111111111111";
if let Some(completed) = complete_ascii(body) {
let pan_str = std::str::from_utf8(&completed[..16]).unwrap();
println!("Completed PAN: {}", pan_str); // Completed PAN: 4111111111111116
}
Enable the parallel
feature and use batch operations:
use luhn_ultra::Validator;
let validator = Validator::new();
// Large batch processing automatically uses parallel workers
let pans: Vec<[u8; 16]> = (0..10000)
.map(|_| *b"4111111111111116")
.collect();
let results = validator.validate_pan16_batch(&pans);
println!("Processed {} PANs", results.len());
Validator
: Main validation engine (zero-sized, cheap to create)ValidationError
: Detailed error information for strict validation
validate_pan16_ascii(&[u8; 16]) -> bool
: Fastest path for 16-digit ASCII PANsvalidate_pan_relaxed(&str) -> bool
: Flexible validation with separator handlingvalidate_pan_strict(&str) -> Result<bool, ValidationError>
: Detailed error reportingvalidate_pan16_batch(&[[u8; 16]]) -> Vec<bool>
: Batch validation for 16-digit PANsvalidate_pan_batch_strict(&[&str]) -> Vec<Result<bool, ValidationError>>
: Batch with errors
check_digit_ascii(&[u8]) -> Option<u8>
: Compute Luhn check digitcomplete_ascii(&[u8]) -> Option<[u8; 32]>
: Complete PAN with check digit
The library supports Payment Card Numbers with lengths from 13 to 19 digits, covering:
- 13 digits: Some Visa cards
- 14 digits: Diners Club
- 15 digits: American Express
- 16 digits: Visa, Mastercard, Discover (most common)
- 17-19 digits: Some specialized cards
- Runtime Detection: Automatically uses best available SIMD instructions
- SSE2 Baseline: Optimized for x86/x86_64 with SSE2 support
- Scalar Fallback: Pure Rust implementation for other architectures
- Future Ready: Designed for easy AVX2/AVX-512 extensions
- Minimal Unsafe: Unsafe code limited to SIMD intrinsics only
- Documented Safety: All unsafe blocks have detailed SAFETY comments
- Extensive Testing: Fuzzing and property-based tests ensure correctness
Run the comprehensive test suite:
# Unit and integration tests
cargo test
# Property-based tests
cargo test --test property_tests
# Benchmarks
cargo bench
# Fuzzing (requires nightly)
cargo +nightly fuzz run validate_pan16_ascii
For maximum performance:
- Use the fast path:
validate_pan16_ascii()
for 16-digit ASCII PANs - Enable parallelization: Add
features = ["parallel"]
for large batches - Batch processing: Use batch methods for multiple validations
- Avoid allocations: Prefer byte slices over String conversions
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contributions are welcome! Please ensure:
- All tests pass:
cargo test
- Code is formatted:
cargo fmt
- No clippy warnings:
cargo clippy
- Benchmarks don't regress:
cargo bench
This library is designed with PCI DSS compliance in mind. For security issues, please contact the maintainers directly rather than opening public issues.