Changed Rust QrCodeEcc struct into enum, changed fields to methods, made the type copyable, got rid of static lifetimes and references in favor of passing by value, updated programs to work with this altered API.

pull/16/head
Project Nayuki 7 years ago
parent b6e0f4f8ee
commit b7817ab944

@ -27,10 +27,6 @@
extern crate qrcodegen;
use qrcodegen::QrCode;
use qrcodegen::QrCodeEcc;
use qrcodegen::QrCodeEcc_LOW;
use qrcodegen::QrCodeEcc_MEDIUM;
use qrcodegen::QrCodeEcc_QUARTILE;
use qrcodegen::QrCodeEcc_HIGH;
use qrcodegen::QrSegment;
@ -45,7 +41,7 @@ fn main() {
// Creates a single QR Code, then prints it to the console.
fn do_basic_demo() {
let text: &'static str = "Hello, world!"; // User-supplied Unicode text
let errcorlvl: &'static QrCodeEcc = &QrCodeEcc_LOW; // Error correction level
let errcorlvl: QrCodeEcc = QrCodeEcc::Low; // Error correction level
// Make and print the QR Code symbol
let qr: QrCode = QrCode::encode_text(text, errcorlvl).unwrap();
@ -57,20 +53,20 @@ fn do_basic_demo() {
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
fn do_variety_demo() {
// Project Nayuki URL
let qr = QrCode::encode_text("https://www.nayuki.io/", &QrCodeEcc_HIGH).unwrap();
let qr = QrCode::encode_text("https://www.nayuki.io/", QrCodeEcc::High).unwrap();
let qr = QrCode::remask(&qr, 3); // Change mask, forcing to mask #3
print_qr(&qr);
// Numeric mode encoding (3.33 bits per digit)
let qr = QrCode::encode_text("314159265358979323846264338327950288419716939937510", &QrCodeEcc_MEDIUM).unwrap();
let qr = QrCode::encode_text("314159265358979323846264338327950288419716939937510", QrCodeEcc::Medium).unwrap();
print_qr(&qr);
// Alphanumeric mode encoding (5.5 bits per character)
let qr = QrCode::encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", &QrCodeEcc_HIGH).unwrap();
let qr = QrCode::encode_text("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCodeEcc::High).unwrap();
print_qr(&qr);
// Unicode text as UTF-8, and different masks
let qr = QrCode::encode_text("こんにちwa、世界 αβγδ", &QrCodeEcc_QUARTILE).unwrap();
let qr = QrCode::encode_text("こんにちwa、世界 αβγδ", QrCodeEcc::Quartile).unwrap();
print_qr(&QrCode::remask(&qr, 0));
print_qr(&QrCode::remask(&qr, 1));
print_qr(&QrCode::remask(&qr, 5));
@ -84,7 +80,7 @@ fn do_variety_demo() {
"'without pictures or conversations?' So she was considering in her own mind (as well as she could, ",
"for the hot day made her feel very sleepy and stupid), whether the pleasure of making a ",
"daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly ",
"a White Rabbit with pink eyes ran close by her."), &QrCodeEcc_HIGH).unwrap();
"a White Rabbit with pink eyes ran close by her."), QrCodeEcc::High).unwrap();
print_qr(&qr);
}
@ -94,21 +90,21 @@ fn do_segment_demo() {
// Illustration "silver"
let silver0 = "THE SQUARE ROOT OF 2 IS 1.";
let silver1 = "41421356237309504880168872420969807856967187537694807317667973799";
let qr = QrCode::encode_text(&[silver0, silver1].concat(), &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_text(&[silver0, silver1].concat(), QrCodeEcc::Low).unwrap();
print_qr(&qr);
let segs = vec![
QrSegment::make_alphanumeric(&to_chars(silver0)),
QrSegment::make_numeric(&to_chars(silver1)),
];
let qr = QrCode::encode_segments(&segs, &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_segments(&segs, QrCodeEcc::Low).unwrap();
print_qr(&qr);
// Illustration "golden"
let golden0 = "Golden ratio φ = 1.";
let golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374";
let golden2 = "......";
let qr = QrCode::encode_text(&[golden0, golden1, golden2].concat(), &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_text(&[golden0, golden1, golden2].concat(), QrCodeEcc::Low).unwrap();
print_qr(&qr);
let segs = vec![
@ -116,12 +112,12 @@ fn do_segment_demo() {
QrSegment::make_numeric(&to_chars(golden1)),
QrSegment::make_alphanumeric(&to_chars(golden2)),
];
let qr = QrCode::encode_segments(&segs, &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_segments(&segs, QrCodeEcc::Low).unwrap();
print_qr(&qr);
// Illustration "Madoka": kanji, kana, Greek, Cyrillic, full-width Latin characters
let madoka = "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?";
let qr = QrCode::encode_text(madoka, &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_text(madoka, QrCodeEcc::Low).unwrap();
print_qr(&qr);
let kanjichars: Vec<u32> = vec![ // Kanji mode encoding (13 bits per character)
@ -139,7 +135,7 @@ fn do_segment_demo() {
let segs = vec![
QrSegment::new(&qrcodegen::QrSegmentMode_KANJI, kanjichars.len(), bb),
];
let qr = QrCode::encode_segments(&segs, &QrCodeEcc_LOW).unwrap();
let qr = QrCode::encode_segments(&segs, QrCodeEcc::Low).unwrap();
print_qr(&qr);
}

@ -28,6 +28,7 @@
extern crate qrcodegen;
use qrcodegen::QrCode;
use qrcodegen::QrCodeEcc;
use qrcodegen::QrSegment;
@ -70,7 +71,7 @@ fn main() {
}
// Try to make QR Code symbol
match QrCode::encode_segments_advanced(&segs, &ECC_LEVELS[errcorlvl as usize],
match QrCode::encode_segments_advanced(&segs, ECC_LEVELS[errcorlvl as usize],
minversion as u8, maxversion as u8, mask as i8, boostecl != 0) {
Some(qr) => {
@ -103,9 +104,9 @@ fn read_int() -> i16 {
}
static ECC_LEVELS: [&'static qrcodegen::QrCodeEcc; 4] = [
&qrcodegen::QrCodeEcc_LOW,
&qrcodegen::QrCodeEcc_MEDIUM,
&qrcodegen::QrCodeEcc_QUARTILE,
&qrcodegen::QrCodeEcc_HIGH,
static ECC_LEVELS: [QrCodeEcc; 4] = [
QrCodeEcc::Low,
QrCodeEcc::Medium,
QrCodeEcc::Quartile,
QrCodeEcc::High,
];

@ -34,7 +34,7 @@ pub struct QrCode {
size: i32,
// The error correction level used in this QR Code symbol.
errorcorrectionlevel: &'static QrCodeEcc,
errorcorrectionlevel: QrCodeEcc,
// The mask pattern used in this QR Code symbol, in the range 0 to 7 (i.e. unsigned 3-bit integer).
// Note that even if a constructor was called with automatic masking requested
@ -52,25 +52,25 @@ pub struct QrCode {
impl QrCode {
pub fn encode_text(text: &str, ecl: &'static QrCodeEcc) -> Option<QrCode> {
pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Option<QrCode> {
let chrs: Vec<char> = text.chars().collect();
let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs);
QrCode::encode_segments(&segs, ecl)
}
pub fn encode_binary(data: &[u8], ecl: &'static QrCodeEcc) -> Option<QrCode> {
pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Option<QrCode> {
let segs: Vec<QrSegment> = vec![QrSegment::make_bytes(data)];
QrCode::encode_segments(&segs, ecl)
}
pub fn encode_segments(segs: &[QrSegment], ecl: &'static QrCodeEcc) -> Option<QrCode> {
pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Option<QrCode> {
QrCode::encode_segments_advanced(segs, ecl, 1, 40, -1, true)
}
pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: &'static QrCodeEcc,
pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
minversion: u8, maxversion: u8, mask: i8, boostecl: bool) -> Option<QrCode> {
assert!(1 <= minversion && minversion <= maxversion && maxversion <= 40 && -1 <= mask && mask <= 7, "Invalid value");
@ -92,9 +92,9 @@ impl QrCode {
}
// Increase the error correction level while the data still fits in the current version number
for newecl in &[&QrCodeEcc_MEDIUM, &QrCodeEcc_QUARTILE, &QrCodeEcc_HIGH] {
if boostecl && datausedbits <= QrCode::get_num_data_codewords(version, newecl) * 8 {
ecl = newecl;
for newecl in &[QrCodeEcc::Medium, QrCodeEcc::Quartile, QrCodeEcc::High] {
if boostecl && datausedbits <= QrCode::get_num_data_codewords(version, *newecl) * 8 {
ecl = *newecl;
}
}
@ -131,7 +131,7 @@ impl QrCode {
}
pub fn encode_codewords(ver: u8, ecl: &'static QrCodeEcc, datacodewords: &[u8], mask: i8) -> QrCode {
pub fn encode_codewords(ver: u8, ecl: QrCodeEcc, datacodewords: &[u8], mask: i8) -> QrCode {
// Check arguments
assert!(1 <= ver && ver <= 40 && -1 <= mask && mask <= 7, "Value out of range");
@ -189,7 +189,7 @@ impl QrCode {
// Returns this QR Code's error correction level.
pub fn error_correction_level(&self) -> &'static QrCodeEcc {
pub fn error_correction_level(&self) -> QrCodeEcc {
self.errorcorrectionlevel
}
@ -283,7 +283,7 @@ impl QrCode {
fn draw_format_bits(&mut self, mask: u8) {
// Calculate error correction code and pack bits
let size: i32 = self.size;
let mut data: u32 = (self.errorcorrectionlevel.formatbits << 3 | mask) as u32; // errcorrlvl is uint2, mask is uint3
let mut data: u32 = self.errorcorrectionlevel.format_bits() << 3 | (mask as u32); // errcorrlvl is uint2, mask is uint3
let mut rem: u32 = data;
for _ in 0 .. 10 {
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
@ -637,7 +637,7 @@ impl QrCode {
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
// QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
fn get_num_data_codewords(ver: u8, ecl: &QrCodeEcc) -> usize {
fn get_num_data_codewords(ver: u8, ecl: QrCodeEcc) -> usize {
assert!(1 <= ver && ver <= 40, "Version number out of range");
QrCode::get_num_raw_data_modules(ver) / 8
- QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK, ver, ecl)
@ -645,8 +645,8 @@ impl QrCode {
}
fn table_get(table: &'static [[i8; 41]; 4], ver: u8, ecl: &QrCodeEcc) -> usize {
table[ecl.ordinal as usize][ver as usize] as usize
fn table_get(table: &'static [[i8; 41]; 4], ver: u8, ecl: QrCodeEcc) -> usize {
table[ecl.ordinal()][ver as usize] as usize
}
}
@ -683,23 +683,41 @@ static NUM_ERROR_CORRECTION_BLOCKS: [[i8; 41]; 4] = [
/*---- QrCodeEcc functionality ----*/
pub struct QrCodeEcc {
#[derive(Clone, Copy)]
pub enum QrCodeEcc {
Low,
Medium,
Quartile,
High,
}
impl QrCodeEcc {
// Returns an unsigned 2-bit integer (in the range 0 to 3).
fn ordinal(&self) -> usize {
match *self {
QrCodeEcc::Low => 0,
QrCodeEcc::Medium => 1,
QrCodeEcc::Quartile => 2,
QrCodeEcc::High => 3,
}
}
// In the range 0 to 3 (unsigned 2-bit integer).
pub ordinal: u8,
// In the range 0 to 3 (unsigned 2-bit integer).
formatbits: u8,
// Returns an unsigned 2-bit integer (in the range 0 to 3).
fn format_bits(&self) -> u32 {
match *self {
QrCodeEcc::Low => 1,
QrCodeEcc::Medium => 0,
QrCodeEcc::Quartile => 3,
QrCodeEcc::High => 2,
}
}
}
pub static QrCodeEcc_LOW : QrCodeEcc = QrCodeEcc { ordinal: 0, formatbits: 1 };
pub static QrCodeEcc_MEDIUM : QrCodeEcc = QrCodeEcc { ordinal: 1, formatbits: 0 };
pub static QrCodeEcc_QUARTILE: QrCodeEcc = QrCodeEcc { ordinal: 2, formatbits: 3 };
pub static QrCodeEcc_HIGH : QrCodeEcc = QrCodeEcc { ordinal: 3, formatbits: 2 };
/*---- ReedSolomonGenerator functionality ----*/

Loading…
Cancel
Save