From 8ef73d23250768273e1e7816fa83e1771b620199 Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Wed, 6 Sep 2017 16:20:09 +0000 Subject: [PATCH] Changed Rust API to take Option instead of i8 for automatic masking, updated related code and assertions. --- Readme.markdown | 2 +- rust/Cargo.toml | 2 +- rust/examples/qrcodegen-demo.rs | 10 +++++----- rust/examples/qrcodegen-worker.rs | 3 ++- rust/src/lib.rs | 32 ++++++++++++++++--------------- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Readme.markdown b/Readme.markdown index 13d1a1c..0d215a2 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -160,7 +160,7 @@ Rust language: let chrs: Vec = "3141592653589793238462643383".chars().collect(); let segs = QrSegment::make_segments(&chrs); let qr1 = QrCode::encode_segments_advanced( - &segs, QrCodeEcc::High, 5, 5, 2, false).unwrap(); + &segs, QrCodeEcc::High, 5, 5, Some(2), false).unwrap(); for y in 0 .. qr1.size() { for x in 0 .. qr1.size() { (... paint qr1.get_module(x, y) ...) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d497eb7..6f9a3ce 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "qrcodegen" -version = "1.2.0" +version = "1.2.1" authors = ["Project Nayuki"] diff --git a/rust/examples/qrcodegen-demo.rs b/rust/examples/qrcodegen-demo.rs index 6b6c2a2..069d491 100644 --- a/rust/examples/qrcodegen-demo.rs +++ b/rust/examples/qrcodegen-demo.rs @@ -54,7 +54,7 @@ fn do_basic_demo() { fn do_variety_demo() { // Project Nayuki URL let qr = QrCode::encode_text("https://www.nayuki.io/", QrCodeEcc::High).unwrap(); - let qr = QrCode::remask(&qr, 3); // Change mask, forcing to mask #3 + let qr = QrCode::remask(&qr, Some(3)); // Change mask, forcing to mask #3 print_qr(&qr); // Numeric mode encoding (3.33 bits per digit) @@ -67,10 +67,10 @@ fn do_variety_demo() { // Unicode text as UTF-8, and different masks 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)); - print_qr(&QrCode::remask(&qr, 7)); + print_qr(&QrCode::remask(&qr, Some(0))); + print_qr(&QrCode::remask(&qr, Some(1))); + print_qr(&QrCode::remask(&qr, Some(5))); + print_qr(&QrCode::remask(&qr, Some(7))); // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland) let qr = QrCode::encode_text(concat!( diff --git a/rust/examples/qrcodegen-worker.rs b/rust/examples/qrcodegen-worker.rs index 5325098..3ba8575 100644 --- a/rust/examples/qrcodegen-worker.rs +++ b/rust/examples/qrcodegen-worker.rs @@ -71,8 +71,9 @@ fn main() { } // Try to make QR Code symbol + let msk: Option = if mask == -1 { None } else { Some(mask as u8) }; match QrCode::encode_segments_advanced(&segs, ECC_LEVELS[errcorlvl as usize], - minversion as u8, maxversion as u8, mask as i8, boostecl != 0) { + minversion as u8, maxversion as u8, msk, boostecl != 0) { Some(qr) => { // Print grid of modules diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 1940e52..1a6696d 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -89,7 +89,7 @@ impl QrCode { // 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::encode_segments_advanced(segs, ecl, 1, 40, -1, true) + QrCode::encode_segments_advanced(segs, ecl, 1, 40, None, true) } @@ -101,9 +101,9 @@ impl QrCode { // 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, - minversion: u8, maxversion: u8, mask: i8, boostecl: bool) -> Option { - assert!(1 <= minversion && minversion <= maxversion && maxversion <= 40 - && -1 <= mask && mask <= 7, "Invalid value"); + minversion: u8, maxversion: u8, mask: Option, boostecl: bool) -> Option { + assert!(1 <= minversion && minversion <= maxversion && maxversion <= 40, "Invalid value"); + assert!(mask == None || mask.unwrap() <= 7, "Invalid value"); // Find the minimal version number to use let mut version: u8 = minversion; @@ -168,9 +168,10 @@ impl QrCode { // 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: Option) -> QrCode { // Check arguments - assert!(1 <= ver && ver <= 40 && -1 <= mask && mask <= 7, "Value out of range"); + assert!(1 <= ver && ver <= 40, "Value out of range"); + assert!(mask == None || mask.unwrap() <= 7, "Value out of range"); // Initialize fields let size: usize = (ver as usize) * 4 + 17; @@ -195,9 +196,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: Option) -> QrCode { // Check arguments - assert!(-1 <= mask && mask <= 7, "Mask out of range"); + assert!(mask == None || mask.unwrap() <= 7, "Mask out of range"); // Copy fields let mut result = QrCode { @@ -525,24 +526,25 @@ impl QrCode { // A messy helper function for the constructors. This QR Code must be in an unmasked state when this // method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed. // This method applies and returns the actual mask chosen, from 0 to 7. - fn handle_constructor_masking(&mut self, mut mask: i8) { - if mask == -1 { // Automatically choose best mask + fn handle_constructor_masking(&mut self, mut mask: Option) { + if mask == None { // Automatically choose best mask let mut minpenalty: i32 = std::i32::MAX; for i in 0u8 .. 8 { self.draw_format_bits(i); self.apply_mask(i); let penalty: i32 = self.get_penalty_score(); if penalty < minpenalty { - mask = i as i8; + mask = Some(i); minpenalty = penalty; } self.apply_mask(i); // Undoes the mask due to XOR } } - assert!(0 <= mask && mask <= 7, "Assertion error"); - self.draw_format_bits(mask as u8); // Overwrite old format bits - self.apply_mask(mask as u8); // Apply the final choice of mask - self.mask = mask as u8; + let msk: u8 = mask.unwrap(); + assert!(msk <= 7, "Assertion error"); + self.draw_format_bits(msk); // Overwrite old format bits + self.apply_mask(msk); // Apply the final choice of mask + self.mask = msk; }