Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1004,3 +1004,69 @@ fn bench_find_min_version(bencher: &mut test::Bencher) {

//}}}
//------------------------------------------------------------------------------
//{{{ Auto Micro QR code's version minimization

/// Automatically determines the minimum version to store the data, and encode
/// the result.
///
/// This method will not consider any QR code versions.
///
/// # Errors
///
/// Returns `Err(QrError::DataTooLong)` if the data is too long to fit even the
/// highest Micro QR code version.
pub fn encode_auto_micro(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> {
let segments = Parser::new(data).collect::<Vec<Segment>>();
let mut possible_versions = Vec::new();
for version in 1..=4 {
let version = Version::Micro(version);
let opt_segments = Optimizer::new(segments.iter().copied(), version).collect::<Vec<_>>();
let total_len = total_encoded_len(&opt_segments, version);
let data_capacity = version.fetch(ec_level, &DATA_LENGTHS);
if let Ok(capacity) = data_capacity {
if total_len <= capacity {
possible_versions.push(version);
break;
}
}
}

let min_version = possible_versions.iter().min_by_key(|v| v.width());

if let Some(version) = min_version {
let mut bits = Bits::new(*version);
let opt_segments = Optimizer::new(segments.iter().copied(), *version).collect::<Vec<_>>();
bits.reserve(total_encoded_len(&opt_segments, *version));
bits.push_segments(data, opt_segments.into_iter())?;
bits.push_terminator(ec_level)?;
return Ok(bits);
}
Err(QrError::DataTooLong)
}

#[cfg(test)]
mod encode_auto_micro_tests {
use crate::bits::encode_auto_micro;
use crate::types::{EcLevel, Version};

#[test]
fn test_alpha_l() {
let bits = encode_auto_micro(b"HELLO WORLD", EcLevel::L).unwrap();
assert_eq!(bits.version(), Version::Micro(3));
}

#[test]
fn test_alpha_q() {
let bits = encode_auto_micro(b"HELLO WORLD", EcLevel::Q).unwrap();
assert_eq!(bits.version(), Version::Micro(4));
}

#[test]
fn test_mixed() {
let bits = encode_auto_micro(b"Mixed. 1234567890", EcLevel::M).unwrap();
assert_eq!(bits.version(), Version::Micro(4));
}
}

//}}}
//------------------------------------------------------------------------------
40 changes: 40 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ impl QrCode {
Self::with_error_correction_level(data, EcLevel::M)
}

/// Constructs a new Micro QR code which automatically encodes the given
/// data.
///
/// This method uses the "medium" error correction level and automatically
/// chooses the smallest Micro QR code.
///
/// ```
/// use qrcode::QrCode;
///
/// let code = QrCode::new_micro(b"Some data").unwrap();
/// ```
///
/// # Errors
///
/// Returns error if the Micro QR code cannot be constructed, e.g. when the
/// data is too long.
pub fn new_micro<D: AsRef<[u8]>>(data: D) -> QrResult<Self> {
Self::micro_with_error_correction_level(data, EcLevel::M)
}

/// Constructs a new QR code which automatically encodes the given data at a
/// specific error correction level.
///
Expand All @@ -104,6 +124,26 @@ impl QrCode {
Self::with_bits(bits, ec_level)
}

/// Constructs a new Micro QR code which automatically encodes the given
/// data at a specific error correction level.
///
/// This method automatically chooses the smallest Micro QR code.
///
/// ```
/// use qrcode::{EcLevel, QrCode};
///
/// let code = QrCode::micro_with_error_correction_level(b"Some data", EcLevel::Q).unwrap();
/// ```
///
/// # Errors
///
/// Returns error if the Micro QR code cannot be constructed, e.g. when the
/// data is too long.
pub fn micro_with_error_correction_level<D: AsRef<[u8]>>(data: D, ec_level: EcLevel) -> QrResult<Self> {
let bits = bits::encode_auto_micro(data.as_ref(), ec_level)?;
Self::with_bits(bits, ec_level)
}

/// Constructs a new QR code for the given version and error correction
/// level.
///
Expand Down
Loading