Added documentation comments to all remaining Rust functions/methods/structs, and added some section heading comments too.
This commit is contained in:
parent
3d4d941da3
commit
fca2a8a27c
|
@ -24,6 +24,10 @@
|
||||||
|
|
||||||
/*---- QrCode functionality ----*/
|
/*---- QrCode functionality ----*/
|
||||||
|
|
||||||
|
// Represents an immutable square grid of black and white cells for a QR Code symbol, and
|
||||||
|
// provides static functions to create a QR Code from user-supplied textual or binary data.
|
||||||
|
// This struct covers the QR Code model 2 specification, supporting all versions (sizes)
|
||||||
|
// from 1 to 40, all 4 error correction levels, and only 3 character encoding modes.
|
||||||
pub struct QrCode {
|
pub struct QrCode {
|
||||||
|
|
||||||
// This QR Code symbol's version number, which is always between 1 and 40 (inclusive).
|
// This QR Code symbol's version number, which is always between 1 and 40 (inclusive).
|
||||||
|
@ -52,6 +56,14 @@ pub struct QrCode {
|
||||||
|
|
||||||
impl QrCode {
|
impl QrCode {
|
||||||
|
|
||||||
|
/*---- Public static factory functions ----*/
|
||||||
|
|
||||||
|
// Returns a QR Code symbol representing the given Unicode text string at the given error correction level.
|
||||||
|
// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
|
||||||
|
// code points (not UTF-8 code units) if the low error correction level is used. The smallest possible
|
||||||
|
// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
|
||||||
|
// the ecl argument if it can be done without increasing the version. Returns a wrapped QrCode if successful,
|
||||||
|
// or None if the data is too long to fit in any version at the given ECC level.
|
||||||
pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Option<QrCode> {
|
pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Option<QrCode> {
|
||||||
let chrs: Vec<char> = text.chars().collect();
|
let chrs: Vec<char> = text.chars().collect();
|
||||||
let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs);
|
let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs);
|
||||||
|
@ -59,17 +71,35 @@ impl QrCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a QR Code symbol representing the given binary data string at the given error correction level.
|
||||||
|
// This function always encodes using the binary segment mode, not any text mode. The maximum number of
|
||||||
|
// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
|
||||||
|
// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
|
||||||
|
// Returns a wrapped QrCode if successful, or None if the data is too long to fit in any version at the given ECC level.
|
||||||
pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Option<QrCode> {
|
pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Option<QrCode> {
|
||||||
let segs: Vec<QrSegment> = vec![QrSegment::make_bytes(data)];
|
let segs: Vec<QrSegment> = vec![QrSegment::make_bytes(data)];
|
||||||
QrCode::encode_segments(&segs, ecl)
|
QrCode::encode_segments(&segs, ecl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a QR Code symbol representing the given data segments at the given error correction
|
||||||
|
// level or higher. The smallest possible QR Code version is automatically chosen for the output.
|
||||||
|
// This function allows the user to create a custom sequence of segments that switches
|
||||||
|
// between modes (such as alphanumeric and binary) to encode text more efficiently.
|
||||||
|
// This function is considered to be lower level than simply encoding text or binary data.
|
||||||
|
// Returns a wrapped QrCode if successful, or None if the data is too long to fit in any version at the given ECC level.
|
||||||
pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Option<QrCode> {
|
pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Option<QrCode> {
|
||||||
QrCode::encode_segments_advanced(segs, ecl, 1, 40, -1, true)
|
QrCode::encode_segments_advanced(segs, ecl, 1, 40, -1, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a QR Code symbol representing the given data segments with the given encoding parameters.
|
||||||
|
// The smallest possible QR Code version within the given range is automatically chosen for the output.
|
||||||
|
// This function allows the user to create a custom sequence of segments that switches
|
||||||
|
// between modes (such as alphanumeric and binary) to encode text more efficiently.
|
||||||
|
// This function is considered to be lower level than simply encoding text or binary data.
|
||||||
|
// Returns a wrapped QrCode if successful, or None if the data is too long to fit
|
||||||
|
// in any version in the given range at the given ECC level.
|
||||||
pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
|
pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
|
||||||
minversion: u8, maxversion: u8, mask: i8, boostecl: bool) -> Option<QrCode> {
|
minversion: u8, maxversion: u8, mask: i8, boostecl: bool) -> Option<QrCode> {
|
||||||
assert!(1 <= minversion && minversion <= maxversion && maxversion <= 40
|
assert!(1 <= minversion && minversion <= maxversion && maxversion <= 40
|
||||||
|
@ -133,6 +163,11 @@ impl QrCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---- Constructors ----*/
|
||||||
|
|
||||||
|
// Creates a new QR Code symbol with the given version number, error correction level,
|
||||||
|
// binary data array, and mask number. This is a cumbersome low-level constructor that
|
||||||
|
// should not be invoked directly by the user. To go one level up, see the encode_segments() function.
|
||||||
pub fn encode_codewords(ver: u8, ecl: QrCodeEcc, datacodewords: &[u8], mask: i8) -> QrCode {
|
pub fn encode_codewords(ver: u8, ecl: QrCodeEcc, datacodewords: &[u8], mask: i8) -> QrCode {
|
||||||
// Check arguments
|
// Check arguments
|
||||||
assert!(1 <= ver && ver <= 40 && -1 <= mask && mask <= 7, "Value out of range");
|
assert!(1 <= ver && ver <= 40 && -1 <= mask && mask <= 7, "Value out of range");
|
||||||
|
@ -157,6 +192,9 @@ impl QrCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Creates a new QR Code symbol based on the given existing object, but with a potentially
|
||||||
|
// different mask pattern. The version, error correction level, codewords, etc. of the newly
|
||||||
|
// created object are all identical to the argument object; only the mask may differ.
|
||||||
pub fn remask(qr: &QrCode, mask: i8) -> QrCode {
|
pub fn remask(qr: &QrCode, mask: i8) -> QrCode {
|
||||||
// Check arguments
|
// Check arguments
|
||||||
assert!(-1 <= mask && mask <= 7, "Mask out of range");
|
assert!(-1 <= mask && mask <= 7, "Mask out of range");
|
||||||
|
@ -210,16 +248,21 @@ impl QrCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the color of the module at the given coordinates, which must be in bounds.
|
||||||
fn module(&self, x: i32, y: i32) -> bool {
|
fn module(&self, x: i32, y: i32) -> bool {
|
||||||
self.modules[(y * self.size + x) as usize]
|
self.modules[(y * self.size + x) as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a mutable reference to the module's color at the given coordinates, which must be in bounds.
|
||||||
fn module_mut(&mut self, x: i32, y: i32) -> &mut bool {
|
fn module_mut(&mut self, x: i32, y: i32) -> &mut bool {
|
||||||
&mut self.modules[(y * self.size + x) as usize]
|
&mut self.modules[(y * self.size + x) as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Based on the given number of border modules to add as padding, this returns a
|
||||||
|
// string whose contents represents an SVG XML file that depicts this QR Code symbol.
|
||||||
|
// Note that Unix newlines (\n) are always used, regardless of the platform.
|
||||||
pub fn to_svg_string(&self, border: i32) -> String {
|
pub fn to_svg_string(&self, border: i32) -> String {
|
||||||
assert!(border >= 0, "Border must be non-negative");
|
assert!(border >= 0, "Border must be non-negative");
|
||||||
let mut result: String = String::new();
|
let mut result: String = String::new();
|
||||||
|
@ -651,7 +694,9 @@ impl QrCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns an entry from the given table based on the given values.
|
||||||
fn table_get(table: &'static [[i8; 41]; 4], ver: u8, ecl: QrCodeEcc) -> usize {
|
fn table_get(table: &'static [[i8; 41]; 4], ver: u8, ecl: QrCodeEcc) -> usize {
|
||||||
|
assert!(1 <= ver && ver <= 40, "Version number out of range");
|
||||||
table[ecl.ordinal()][ver as usize] as usize
|
table[ecl.ordinal()][ver as usize] as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,6 +734,7 @@ static NUM_ERROR_CORRECTION_BLOCKS: [[i8; 41]; 4] = [
|
||||||
|
|
||||||
/*---- QrCodeEcc functionality ----*/
|
/*---- QrCodeEcc functionality ----*/
|
||||||
|
|
||||||
|
// Represents the error correction level used in a QR Code symbol. Immutable.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum QrCodeEcc {
|
pub enum QrCodeEcc {
|
||||||
Low,
|
Low,
|
||||||
|
@ -727,6 +773,9 @@ impl QrCodeEcc {
|
||||||
|
|
||||||
/*---- ReedSolomonGenerator functionality ----*/
|
/*---- ReedSolomonGenerator functionality ----*/
|
||||||
|
|
||||||
|
// Computes the Reed-Solomon error correction codewords for a sequence of data codewords
|
||||||
|
// at a given degree. Objects are immutable, and the state only depends on the degree.
|
||||||
|
// This class exists because each data block in a QR Code shares the same the divisor polynomial.
|
||||||
struct ReedSolomonGenerator {
|
struct ReedSolomonGenerator {
|
||||||
|
|
||||||
// Coefficients of the divisor polynomial, stored from highest to lowest power, excluding the leading term which
|
// Coefficients of the divisor polynomial, stored from highest to lowest power, excluding the leading term which
|
||||||
|
@ -738,6 +787,8 @@ struct ReedSolomonGenerator {
|
||||||
|
|
||||||
impl ReedSolomonGenerator {
|
impl ReedSolomonGenerator {
|
||||||
|
|
||||||
|
// Creates a Reed-Solomon ECC generator for the given degree. This could be implemented
|
||||||
|
// as a lookup table over all possible parameter values, instead of as an algorithm.
|
||||||
fn new(degree: usize) -> ReedSolomonGenerator {
|
fn new(degree: usize) -> ReedSolomonGenerator {
|
||||||
assert!(1 <= degree && degree <= 255, "Degree out of range");
|
assert!(1 <= degree && degree <= 255, "Degree out of range");
|
||||||
// Start with the monomial x^0
|
// Start with the monomial x^0
|
||||||
|
@ -764,6 +815,7 @@ impl ReedSolomonGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Computes and returns the Reed-Solomon error correction codewords for the given sequence of data codewords.
|
||||||
fn get_remainder(&self, data: &[u8]) -> Vec<u8> {
|
fn get_remainder(&self, data: &[u8]) -> Vec<u8> {
|
||||||
// Compute the remainder by performing polynomial division
|
// Compute the remainder by performing polynomial division
|
||||||
let mut result: Vec<u8> = vec![0; self.coefficients.len()];
|
let mut result: Vec<u8> = vec![0; self.coefficients.len()];
|
||||||
|
@ -796,6 +848,9 @@ impl ReedSolomonGenerator {
|
||||||
|
|
||||||
/*---- QrSegment functionality ----*/
|
/*---- QrSegment functionality ----*/
|
||||||
|
|
||||||
|
// Represents a character string to be encoded in a QR Code symbol.
|
||||||
|
// Each segment has a mode, and a sequence of characters that is already
|
||||||
|
// encoded as a sequence of bits. Instances of this struct are immutable.
|
||||||
pub struct QrSegment {
|
pub struct QrSegment {
|
||||||
|
|
||||||
// The mode indicator for this segment.
|
// The mode indicator for this segment.
|
||||||
|
@ -814,6 +869,7 @@ impl QrSegment {
|
||||||
|
|
||||||
/*---- Static factory functions ----*/
|
/*---- Static factory functions ----*/
|
||||||
|
|
||||||
|
// Returns a segment representing the given binary data encoded in byte mode.
|
||||||
pub fn make_bytes(data: &[u8]) -> QrSegment {
|
pub fn make_bytes(data: &[u8]) -> QrSegment {
|
||||||
let mut bb: Vec<bool> = Vec::with_capacity(data.len() * 8);
|
let mut bb: Vec<bool> = Vec::with_capacity(data.len() * 8);
|
||||||
for b in data {
|
for b in data {
|
||||||
|
@ -825,6 +881,8 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a segment representing the given string of decimal digits encoded in numeric mode.
|
||||||
|
// Panics if the string contains non-digit characters.
|
||||||
pub fn make_numeric(text: &[char]) -> QrSegment {
|
pub fn make_numeric(text: &[char]) -> QrSegment {
|
||||||
let mut bb: Vec<bool> = Vec::with_capacity(text.len() * 3 + (text.len() + 2) / 3);
|
let mut bb: Vec<bool> = Vec::with_capacity(text.len() * 3 + (text.len() + 2) / 3);
|
||||||
let mut accumdata: u32 = 0;
|
let mut accumdata: u32 = 0;
|
||||||
|
@ -846,6 +904,9 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a segment representing the given text string encoded in alphanumeric mode.
|
||||||
|
// The characters allowed are: 0 to 9, A to Z (uppercase only), space, dollar, percent, asterisk,
|
||||||
|
// plus, hyphen, period, slash, colon. Panics if the string contains non-encodable characters.
|
||||||
pub fn make_alphanumeric(text: &[char]) -> QrSegment {
|
pub fn make_alphanumeric(text: &[char]) -> QrSegment {
|
||||||
let mut bb: Vec<bool> = Vec::with_capacity(text.len() * 5 + (text.len() + 1) / 2);
|
let mut bb: Vec<bool> = Vec::with_capacity(text.len() * 5 + (text.len() + 1) / 2);
|
||||||
let mut accumdata: u32 = 0;
|
let mut accumdata: u32 = 0;
|
||||||
|
@ -870,6 +931,8 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a new mutable list of zero or more segments to represent the given Unicode text string.
|
||||||
|
// The result may use various segment modes and switch modes to optimize the length of the bit stream.
|
||||||
pub fn make_segments(text: &[char]) -> Vec<QrSegment> {
|
pub fn make_segments(text: &[char]) -> Vec<QrSegment> {
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
vec![]
|
vec![]
|
||||||
|
@ -884,6 +947,8 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a segment representing an Extended Channel Interpretation
|
||||||
|
// (ECI) designator with the given assignment value.
|
||||||
pub fn make_eci(assignval: u32) -> QrSegment {
|
pub fn make_eci(assignval: u32) -> QrSegment {
|
||||||
let mut bb: Vec<bool> = Vec::with_capacity(24);
|
let mut bb: Vec<bool> = Vec::with_capacity(24);
|
||||||
if assignval < (1 << 7) {
|
if assignval < (1 << 7) {
|
||||||
|
@ -901,6 +966,7 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Creates a new QR Code data segment with the given parameters and data.
|
||||||
pub fn new(mode: QrSegmentMode, numchars: usize, data: Vec<bool>) -> QrSegment {
|
pub fn new(mode: QrSegmentMode, numchars: usize, data: Vec<bool>) -> QrSegment {
|
||||||
QrSegment {
|
QrSegment {
|
||||||
mode: mode,
|
mode: mode,
|
||||||
|
@ -910,21 +976,29 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---- Instance field getters ----*/
|
||||||
|
|
||||||
|
// Returns the mode indicator for this segment.
|
||||||
pub fn mode(&self) -> QrSegmentMode {
|
pub fn mode(&self) -> QrSegmentMode {
|
||||||
self.mode
|
self.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the length of this segment's unencoded data, measured in characters.
|
||||||
pub fn num_chars(&self) -> usize {
|
pub fn num_chars(&self) -> usize {
|
||||||
self.numchars
|
self.numchars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a view of the bits of this segment.
|
||||||
pub fn data(&self) -> &Vec<bool> {
|
pub fn data(&self) -> &Vec<bool> {
|
||||||
&self.data
|
&self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---- Other static functions ----*/
|
||||||
|
|
||||||
|
// Package-private helper function.
|
||||||
fn get_total_bits(segs: &[QrSegment], version: u8) -> Option<usize> {
|
fn get_total_bits(segs: &[QrSegment], version: u8) -> Option<usize> {
|
||||||
assert!(1 <= version && version <= 40, "Version number out of range");
|
assert!(1 <= version && version <= 40, "Version number out of range");
|
||||||
let mut result: usize = 0;
|
let mut result: usize = 0;
|
||||||
|
@ -942,11 +1016,13 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tests whether the given string can be encoded as a segment in alphanumeric mode.
|
||||||
fn is_alphanumeric(text: &[char]) -> bool {
|
fn is_alphanumeric(text: &[char]) -> bool {
|
||||||
text.iter().all(|c| ALPHANUMERIC_CHARSET.contains(c))
|
text.iter().all(|c| ALPHANUMERIC_CHARSET.contains(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Tests whether the given string can be encoded as a segment in numeric mode.
|
||||||
fn is_numeric(text: &[char]) -> bool {
|
fn is_numeric(text: &[char]) -> bool {
|
||||||
text.iter().all(|c| '0' <= *c && *c <= '9')
|
text.iter().all(|c| '0' <= *c && *c <= '9')
|
||||||
}
|
}
|
||||||
|
@ -954,6 +1030,8 @@ impl QrSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The set of all legal characters in alphanumeric mode,
|
||||||
|
// where each character value maps to the index in the string.
|
||||||
static ALPHANUMERIC_CHARSET: [char; 45] = ['0','1','2','3','4','5','6','7','8','9',
|
static ALPHANUMERIC_CHARSET: [char; 45] = ['0','1','2','3','4','5','6','7','8','9',
|
||||||
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
||||||
' ','$','%','*','+','-','.','/',':'];
|
' ','$','%','*','+','-','.','/',':'];
|
||||||
|
@ -962,6 +1040,7 @@ static ALPHANUMERIC_CHARSET: [char; 45] = ['0','1','2','3','4','5','6','7','8','
|
||||||
|
|
||||||
/*---- QrSegmentMode functionality ----*/
|
/*---- QrSegmentMode functionality ----*/
|
||||||
|
|
||||||
|
// The mode field of a segment. Immutable.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum QrSegmentMode {
|
pub enum QrSegmentMode {
|
||||||
Numeric,
|
Numeric,
|
||||||
|
@ -987,6 +1066,8 @@ impl QrSegmentMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the bit width of the segment character count field
|
||||||
|
// for this mode object at the given version number.
|
||||||
pub fn num_char_count_bits(&self, ver: u8) -> u8 {
|
pub fn num_char_count_bits(&self, ver: u8) -> u8 {
|
||||||
let array: [u8; 3] = match *self {
|
let array: [u8; 3] = match *self {
|
||||||
QrSegmentMode::Numeric => [10, 12, 14],
|
QrSegmentMode::Numeric => [10, 12, 14],
|
||||||
|
|
Loading…
Reference in New Issue