1 /*
2 * QR Code generator library (Rust)
3 *
4 * Copyright (c) Project Nayuki. (MIT License)
5 * https://www.nayuki.io/page/qr-code-generator-library
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 * - The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 * - The Software is provided "as is", without warranty of any kind, express or
16 * implied, including but not limited to the warranties of merchantability,
17 * fitness for a particular purpose and noninfringement. In no event shall the
18 * authors or copyright holders be liable for any claim, damages or other
19 * liability, whether in an action of contract, tort or otherwise, arising from,
20 * out of or in connection with the Software or the use or other dealings in the
21 * Software.
22 */
23
24
25 //! Generates QR Codes from text strings and byte arrays.
26 //!
27 //! This project aims to be the best, clearest QR Code generator library.
28 //! The primary goals are flexible options and absolute correctness.
29 //! Secondary goals are compact implementation size and good documentation comments.
30 //!
31 //! Home page with live JavaScript demo, extensive descriptions, and competitor comparisons:
32 //! [https://www.nayuki.io/page/qr-code-generator-library](https://www.nayuki.io/page/qr-code-generator-library)
33 //!
34 //! # Features
35 //!
36 //! Core features:
37 //!
38 //! - Available in 6 programming languages, all with nearly equal functionality: Java, TypeScript/JavaScript, Python, Rust, C++, C
39 //! - Significantly shorter code but more documentation comments compared to competing libraries
40 //! - Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard
41 //! - Output format: Raw modules/pixels of the QR symbol
42 //! - Detects finder-like penalty patterns more accurately than other implementations
43 //! - Encodes numeric and special-alphanumeric text in less space than general text
44 //! - Open source code under the permissive MIT License
45 //!
46 //! Manual parameters:
47 //!
48 //! - User can specify minimum and maximum version numbers allowed, then library will automatically choose smallest version in the range that fits the data
49 //! - User can specify mask pattern manually, otherwise library will automatically evaluate all 8 masks and select the optimal one
50 //! - User can specify absolute error correction level, or allow the library to boost it if it doesn't increase the version number
51 //! - User can create a list of data segments manually and add ECI segments
52 //!
53 //! # Examples
54 //!
55 //! ```
56 //! extern crate qrcodegen;
57 //! use qrcodegen::Mask;
58 //! use qrcodegen::QrCode;
59 //! use qrcodegen::QrCodeEcc;
60 //! use qrcodegen::QrSegment;
61 //! use qrcodegen::Version;
62 //! ```
63 //!
64 //! Simple operation:
65 //!
66 //! ```
67 //! let qr = QrCode::encode_text("Hello, world!",
68 //! QrCodeEcc::Medium).unwrap();
69 //! let svg = to_svg_string(&qr, 4); // See qrcodegen-demo
70 //! ```
71 //!
72 //! Manual operation:
73 //!
74 //! ```
75 //! let chrs: Vec<char> = "3141592653589793238462643383".chars().collect();
76 //! let segs = QrSegment::make_segments(&chrs);
77 //! let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::High,
78 //! Version::new(5), Version::new(5), Some(Mask::new(2)), false).unwrap();
79 //! for y in 0 .. qr.size() {
80 //! for x in 0 .. qr.size() {
81 //! (... paint qr.get_module(x, y) ...)
82 //! }
83 //! }
84 //! ```
85
86
87 /*---- QrCode functionality ----*/
88
89 /// A QR Code symbol, which is a type of two-dimension barcode.
90 ///
91 /// Invented by Denso Wave and described in the ISO/IEC 18004 standard.
92 ///
93 /// Instances of this struct represent an immutable square grid of dark and light cells.
94 /// The impl provides static factory functions to create a QR Code from text or binary data.
95 /// The struct and impl cover the QR Code Model 2 specification, supporting all versions
96 /// (sizes) from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
97 ///
98 /// Ways to create a QR Code object:
99 ///
100 /// - High level: Take the payload data and call `QrCode::encode_text()` or `QrCode::encode_binary()`.
101 /// - Mid level: Custom-make the list of segments and call
102 /// `QrCode::encode_segments()` or `QrCode::encode_segments_advanced()`.
103 /// - Low level: Custom-make the array of data codeword bytes (including segment
104 /// headers and final padding, excluding error correction codewords), supply the
105 /// appropriate version number, and call the `QrCode::encode_codewords()` constructor.
106 ///
107 /// (Note that all ways require supplying the desired error correction level.)
108 #[derive(Clone, PartialEq, Eq)]
109 pub struct QrCode {
110
111 // Scalar parameters:
112
113 // The version number of this QR Code, which is between 1 and 40 (inclusive).
114 // This determines the size of this barcode.
115 version: Version,
116
117 // The width and height of this QR Code, measured in modules, between
118 // 21 and 177 (inclusive). This is equal to version * 4 + 17.
119 size: i32,
120
121 // The error correction level used in this QR Code.
122 errorcorrectionlevel: QrCodeEcc,
123
124 // The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
125 // Even if a QR Code is created with automatic masking requested (mask = None),
126 // the resulting object still has a mask value between 0 and 7.
127 mask: Mask,
128
129 // Grids of modules/pixels, with dimensions of size*size:
130
131 // The modules of this QR Code (false = light, true = dark).
132 // Immutable after constructor finishes. Accessed through get_module().
133 modules: Vec<bool>,
134
135 // Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
136 isfunction: Vec<bool>,
137
138 }
139
140
141 impl QrCode {
142
143 /*---- Static factory functions (high level) ----*/
144
145 /// Returns a QR Code representing the given Unicode text string at the given error correction level.
146 ///
147 /// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
148 /// code points (not UTF-8 code units) if the low error correction level is used. The smallest possible
149 /// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
150 /// the ecl argument if it can be done without increasing the version.
151 ///
152 /// Returns a wrapped `QrCode` if successful, or `Err` if the
153 /// data is too long to fit in any version at the given ECC level.
encode_text(text: &str, ecl: QrCodeEcc) -> Result<Self,DataTooLong>154 pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
155 let chrs: Vec<char> = text.chars().collect();
156 let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs);
157 QrCode::encode_segments(&segs, ecl)
158 }
159
160
161 /// Returns a QR Code representing the given binary data at the given error correction level.
162 ///
163 /// This function always encodes using the binary segment mode, not any text mode. The maximum number of
164 /// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
165 /// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
166 ///
167 /// Returns a wrapped `QrCode` if successful, or `Err` if the
168 /// data is too long to fit in any version at the given ECC level.
encode_binary(data: &[u8], ecl: QrCodeEcc) -> Result<Self,DataTooLong>169 pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
170 let segs: [QrSegment; 1] = [QrSegment::make_bytes(data)];
171 QrCode::encode_segments(&segs, ecl)
172 }
173
174
175 /*---- Static factory functions (mid level) ----*/
176
177 /// Returns a QR Code representing the given segments at the given error correction level.
178 ///
179 /// The smallest possible QR Code version is automatically chosen for the output. The ECC level
180 /// of the result may be higher than the ecl argument if it can be done without increasing the version.
181 ///
182 /// This function allows the user to create a custom sequence of segments that switches
183 /// between modes (such as alphanumeric and byte) to encode text in less space.
184 /// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
185 ///
186 /// Returns a wrapped `QrCode` if successful, or `Err` if the
187 /// data is too long to fit in any version at the given ECC level.
encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Result<Self,DataTooLong>188 pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
189 QrCode::encode_segments_advanced(segs, ecl, Version::MIN, Version::MAX, None, true)
190 }
191
192
193 /// Returns a QR Code representing the given segments with the given encoding parameters.
194 ///
195 /// The smallest possible QR Code version within the given range is automatically
196 /// chosen for the output. Iff boostecl is `true`, then the ECC level of the result
197 /// may be higher than the ecl argument if it can be done without increasing the
198 /// version. The mask number is either between 0 to 7 (inclusive) to force that
199 /// mask, or `None` to automatically choose an appropriate mask (which may be slow).
200 ///
201 /// This function allows the user to create a custom sequence of segments that switches
202 /// between modes (such as alphanumeric and byte) to encode text in less space.
203 /// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
204 ///
205 /// Returns a wrapped `QrCode` if successful, or `Err` if the data is too
206 /// long to fit in any version in the given range at the given ECC level.
encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc, minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<Self,DataTooLong>207 pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
208 minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<Self,DataTooLong> {
209 assert!(minversion.value() <= maxversion.value(), "Invalid value");
210
211 // Find the minimal version number to use
212 let mut version: Version = minversion;
213 let datausedbits: usize = loop {
214 // Number of data bits available
215 let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;
216 let dataused: Option<usize> = QrSegment::get_total_bits(segs, version);
217 if dataused.map_or(false, |n| n <= datacapacitybits) {
218 break dataused.unwrap(); // This version number is found to be suitable
219 } else if version.value() >= maxversion.value() { // All versions in the range could not fit the given data
220 let msg: String = match dataused {
221 None => String::from("Segment too long"),
222 Some(n) => format!("Data length = {} bits, Max capacity = {} bits",
223 n, datacapacitybits),
224 };
225 return Err(DataTooLong(msg));
226 } else {
227 version = Version::new(version.value() + 1);
228 }
229 };
230
231 // Increase the error correction level while the data still fits in the current version number
232 for &newecl in &[QrCodeEcc::Medium, QrCodeEcc::Quartile, QrCodeEcc::High] { // From low to high
233 if boostecl && datausedbits <= QrCode::get_num_data_codewords(version, newecl) * 8 {
234 ecl = newecl;
235 }
236 }
237
238 // Concatenate all segments to create the data bit string
239 let mut bb = BitBuffer(Vec::new());
240 for seg in segs {
241 bb.append_bits(seg.mode.mode_bits(), 4);
242 bb.append_bits(seg.numchars as u32, seg.mode.num_char_count_bits(version));
243 bb.0.extend_from_slice(&seg.data);
244 }
245 assert_eq!(bb.0.len(), datausedbits);
246
247 // Add terminator and pad up to a byte if applicable
248 let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;
249 assert!(bb.0.len() <= datacapacitybits);
250 let numzerobits: usize = std::cmp::min(4, datacapacitybits - bb.0.len());
251 bb.append_bits(0, numzerobits as u8);
252 let numzerobits: usize = bb.0.len().wrapping_neg() & 7;
253 bb.append_bits(0, numzerobits as u8);
254 assert_eq!(bb.0.len() % 8, 0, "Assertion error");
255
256 // Pad with alternating bytes until data capacity is reached
257 for &padbyte in [0xEC, 0x11].iter().cycle() {
258 if bb.0.len() >= datacapacitybits {
259 break;
260 }
261 bb.append_bits(padbyte, 8);
262 }
263
264 // Pack bits into bytes in big endian
265 let mut datacodewords = vec![0u8; bb.0.len() / 8];
266 for (i, &bit) in bb.0.iter().enumerate() {
267 datacodewords[i >> 3] |= u8::from(bit) << (7 - (i & 7));
268 }
269
270 // Create the QR Code object
271 Ok(QrCode::encode_codewords(version, ecl, &datacodewords, mask))
272 }
273
274
275 /*---- Constructor (low level) ----*/
276
277 /// Creates a new QR Code with the given version number,
278 /// error correction level, data codeword bytes, and mask number.
279 ///
280 /// This is a low-level API that most users should not use directly.
281 /// A mid-level API is the `encode_segments()` function.
encode_codewords(ver: Version, ecl: QrCodeEcc, datacodewords: &[u8], mut mask: Option<Mask>) -> Self282 pub fn encode_codewords(ver: Version, ecl: QrCodeEcc, datacodewords: &[u8], mut mask: Option<Mask>) -> Self {
283 // Initialize fields
284 let size = usize::from(ver.value()) * 4 + 17;
285 let mut result = Self {
286 version: ver,
287 size: size as i32,
288 mask: Mask::new(0), // Dummy value
289 errorcorrectionlevel: ecl,
290 modules : vec![false; size * size], // Initially all light
291 isfunction: vec![false; size * size],
292 };
293
294 // Compute ECC, draw modules
295 result.draw_function_patterns();
296 let allcodewords: Vec<u8> = result.add_ecc_and_interleave(datacodewords);
297 result.draw_codewords(&allcodewords);
298
299 // Do masking
300 if mask.is_none() { // Automatically choose best mask
301 let mut minpenalty = std::i32::MAX;
302 for i in 0u8 .. 8 {
303 let newmask = Mask::new(i);
304 result.apply_mask(newmask);
305 result.draw_format_bits(newmask);
306 let penalty: i32 = result.get_penalty_score();
307 if penalty < minpenalty {
308 mask = Some(newmask);
309 minpenalty = penalty;
310 }
311 result.apply_mask(newmask); // Undoes the mask due to XOR
312 }
313 }
314 let mask: Mask = mask.unwrap();
315 result.mask = mask;
316 result.apply_mask(mask); // Apply the final choice of mask
317 result.draw_format_bits(mask); // Overwrite old format bits
318
319 result.isfunction.clear();
320 result.isfunction.shrink_to_fit();
321 result
322 }
323
324
325 /*---- Public methods ----*/
326
327 /// Returns this QR Code's version, in the range [1, 40].
version(&self) -> Version328 pub fn version(&self) -> Version {
329 self.version
330 }
331
332
333 /// Returns this QR Code's size, in the range [21, 177].
size(&self) -> i32334 pub fn size(&self) -> i32 {
335 self.size
336 }
337
338
339 /// Returns this QR Code's error correction level.
error_correction_level(&self) -> QrCodeEcc340 pub fn error_correction_level(&self) -> QrCodeEcc {
341 self.errorcorrectionlevel
342 }
343
344
345 /// Returns this QR Code's mask, in the range [0, 7].
mask(&self) -> Mask346 pub fn mask(&self) -> Mask {
347 self.mask
348 }
349
350
351 /// Returns the color of the module (pixel) at the given coordinates,
352 /// which is `false` for light or `true` for dark.
353 ///
354 /// The top left corner has the coordinates (x=0, y=0). If the given
355 /// coordinates are out of bounds, then `false` (light) is returned.
get_module(&self, x: i32, y: i32) -> bool356 pub fn get_module(&self, x: i32, y: i32) -> bool {
357 0 <= x && x < self.size && 0 <= y && y < self.size && self.module(x, y)
358 }
359
360
361 // Returns the color of the module at the given coordinates, which must be in bounds.
module(&self, x: i32, y: i32) -> bool362 fn module(&self, x: i32, y: i32) -> bool {
363 self.modules[(y * self.size + x) as usize]
364 }
365
366
367 // Returns a mutable reference to the module's color at the given coordinates, which must be in bounds.
module_mut(&mut self, x: i32, y: i32) -> &mut bool368 fn module_mut(&mut self, x: i32, y: i32) -> &mut bool {
369 &mut self.modules[(y * self.size + x) as usize]
370 }
371
372
373 /*---- Private helper methods for constructor: Drawing function modules ----*/
374
375 // Reads this object's version field, and draws and marks all function modules.
draw_function_patterns(&mut self)376 fn draw_function_patterns(&mut self) {
377 // Draw horizontal and vertical timing patterns
378 let size: i32 = self.size;
379 for i in 0 .. size {
380 self.set_function_module(6, i, i % 2 == 0);
381 self.set_function_module(i, 6, i % 2 == 0);
382 }
383
384 // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
385 self.draw_finder_pattern(3, 3);
386 self.draw_finder_pattern(size - 4, 3);
387 self.draw_finder_pattern(3, size - 4);
388
389 // Draw numerous alignment patterns
390 let alignpatpos: Vec<i32> = self.get_alignment_pattern_positions();
391 let numalign: usize = alignpatpos.len();
392 for i in 0 .. numalign {
393 for j in 0 .. numalign {
394 // Don't draw on the three finder corners
395 if !(i == 0 && j == 0 || i == 0 && j == numalign - 1 || i == numalign - 1 && j == 0) {
396 self.draw_alignment_pattern(alignpatpos[i], alignpatpos[j]);
397 }
398 }
399 }
400
401 // Draw configuration data
402 self.draw_format_bits(Mask::new(0)); // Dummy mask value; overwritten later in the constructor
403 self.draw_version();
404 }
405
406
407 // Draws two copies of the format bits (with its own error correction code)
408 // based on the given mask and this object's error correction level field.
draw_format_bits(&mut self, mask: Mask)409 fn draw_format_bits(&mut self, mask: Mask) {
410 // Calculate error correction code and pack bits
411 let bits: u32 = {
412 // errcorrlvl is uint2, mask is uint3
413 let data: u32 = u32::from(self.errorcorrectionlevel.format_bits() << 3 | mask.value());
414 let mut rem: u32 = data;
415 for _ in 0 .. 10 {
416 rem = (rem << 1) ^ ((rem >> 9) * 0x537);
417 }
418 (data << 10 | rem) ^ 0x5412 // uint15
419 };
420 assert_eq!(bits >> 15, 0, "Assertion error");
421
422 // Draw first copy
423 for i in 0 .. 6 {
424 self.set_function_module(8, i, get_bit(bits, i));
425 }
426 self.set_function_module(8, 7, get_bit(bits, 6));
427 self.set_function_module(8, 8, get_bit(bits, 7));
428 self.set_function_module(7, 8, get_bit(bits, 8));
429 for i in 9 .. 15 {
430 self.set_function_module(14 - i, 8, get_bit(bits, i));
431 }
432
433 // Draw second copy
434 let size: i32 = self.size;
435 for i in 0 .. 8 {
436 self.set_function_module(size - 1 - i, 8, get_bit(bits, i));
437 }
438 for i in 8 .. 15 {
439 self.set_function_module(8, size - 15 + i, get_bit(bits, i));
440 }
441 self.set_function_module(8, size - 8, true); // Always dark
442 }
443
444
445 // Draws two copies of the version bits (with its own error correction code),
446 // based on this object's version field, iff 7 <= version <= 40.
draw_version(&mut self)447 fn draw_version(&mut self) {
448 if self.version.value() < 7 {
449 return;
450 }
451
452 // Calculate error correction code and pack bits
453 let bits: u32 = {
454 let data = u32::from(self.version.value()); // uint6, in the range [7, 40]
455 let mut rem: u32 = data;
456 for _ in 0 .. 12 {
457 rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
458 }
459 data << 12 | rem // uint18
460 };
461 assert!(bits >> 18 == 0, "Assertion error");
462
463 // Draw two copies
464 for i in 0 .. 18 {
465 let bit: bool = get_bit(bits, i);
466 let a: i32 = self.size - 11 + i % 3;
467 let b: i32 = i / 3;
468 self.set_function_module(a, b, bit);
469 self.set_function_module(b, a, bit);
470 }
471 }
472
473
474 // Draws a 9*9 finder pattern including the border separator,
475 // with the center module at (x, y). Modules can be out of bounds.
draw_finder_pattern(&mut self, x: i32, y: i32)476 fn draw_finder_pattern(&mut self, x: i32, y: i32) {
477 for dy in -4 ..= 4 {
478 for dx in -4 ..= 4 {
479 let xx: i32 = x + dx;
480 let yy: i32 = y + dy;
481 if 0 <= xx && xx < self.size && 0 <= yy && yy < self.size {
482 let dist: i32 = std::cmp::max(dx.abs(), dy.abs()); // Chebyshev/infinity norm
483 self.set_function_module(xx, yy, dist != 2 && dist != 4);
484 }
485 }
486 }
487 }
488
489
490 // Draws a 5*5 alignment pattern, with the center module
491 // at (x, y). All modules must be in bounds.
draw_alignment_pattern(&mut self, x: i32, y: i32)492 fn draw_alignment_pattern(&mut self, x: i32, y: i32) {
493 for dy in -2 ..= 2 {
494 for dx in -2 ..= 2 {
495 self.set_function_module(x + dx, y + dy, std::cmp::max(dx.abs(), dy.abs()) != 1);
496 }
497 }
498 }
499
500
501 // Sets the color of a module and marks it as a function module.
502 // Only used by the constructor. Coordinates must be in bounds.
set_function_module(&mut self, x: i32, y: i32, isdark: bool)503 fn set_function_module(&mut self, x: i32, y: i32, isdark: bool) {
504 *self.module_mut(x, y) = isdark;
505 self.isfunction[(y * self.size + x) as usize] = true;
506 }
507
508
509 /*---- Private helper methods for constructor: Codewords and masking ----*/
510
511 // Returns a new byte string representing the given data with the appropriate error correction
512 // codewords appended to it, based on this object's version and error correction level.
add_ecc_and_interleave(&self, data: &[u8]) -> Vec<u8>513 fn add_ecc_and_interleave(&self, data: &[u8]) -> Vec<u8> {
514 let ver: Version = self.version;
515 let ecl: QrCodeEcc = self.errorcorrectionlevel;
516 assert_eq!(data.len(), QrCode::get_num_data_codewords(ver, ecl), "Illegal argument");
517
518 // Calculate parameter numbers
519 let numblocks: usize = QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl);
520 let blockecclen: usize = QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK , ver, ecl);
521 let rawcodewords: usize = QrCode::get_num_raw_data_modules(ver) / 8;
522 let numshortblocks: usize = numblocks - rawcodewords % numblocks;
523 let shortblocklen: usize = rawcodewords / numblocks;
524
525 // Split data into blocks and append ECC to each block
526 let mut blocks = Vec::<Vec<u8>>::with_capacity(numblocks);
527 let rsdiv: Vec<u8> = QrCode::reed_solomon_compute_divisor(blockecclen);
528 let mut k: usize = 0;
529 for i in 0 .. numblocks {
530 let datlen: usize = shortblocklen - blockecclen + usize::from(i >= numshortblocks);
531 let mut dat = data[k .. k + datlen].to_vec();
532 k += datlen;
533 let ecc: Vec<u8> = QrCode::reed_solomon_compute_remainder(&dat, &rsdiv);
534 if i < numshortblocks {
535 dat.push(0);
536 }
537 dat.extend_from_slice(&ecc);
538 blocks.push(dat);
539 }
540
541 // Interleave (not concatenate) the bytes from every block into a single sequence
542 let mut result = Vec::<u8>::with_capacity(rawcodewords);
543 for i in 0 ..= shortblocklen {
544 for (j, block) in blocks.iter().enumerate() {
545 // Skip the padding byte in short blocks
546 if i != shortblocklen - blockecclen || j >= numshortblocks {
547 result.push(block[i]);
548 }
549 }
550 }
551 result
552 }
553
554
555 // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
556 // data area of this QR Code. Function modules need to be marked off before this is called.
draw_codewords(&mut self, data: &[u8])557 fn draw_codewords(&mut self, data: &[u8]) {
558 assert_eq!(data.len(), QrCode::get_num_raw_data_modules(self.version) / 8, "Illegal argument");
559
560 let mut i: usize = 0; // Bit index into the data
561 // Do the funny zigzag scan
562 let mut right: i32 = self.size - 1;
563 while right >= 1 { // Index of right column in each column pair
564 if right == 6 {
565 right = 5;
566 }
567 for vert in 0 .. self.size { // Vertical counter
568 for j in 0 .. 2 {
569 let x: i32 = right - j; // Actual x coordinate
570 let upward: bool = (right + 1) & 2 == 0;
571 let y: i32 = if upward { self.size - 1 - vert } else { vert }; // Actual y coordinate
572 if !self.isfunction[(y * self.size + x) as usize] && i < data.len() * 8 {
573 *self.module_mut(x, y) = get_bit(u32::from(data[i >> 3]), 7 - ((i & 7) as i32));
574 i += 1;
575 }
576 // If this QR Code has any remainder bits (0 to 7), they were assigned as
577 // 0/false/light by the constructor and are left unchanged by this method
578 }
579 }
580 right -= 2;
581 }
582 assert_eq!(i, data.len() * 8, "Assertion error");
583 }
584
585
586 // XORs the codeword modules in this QR Code with the given mask pattern.
587 // The function modules must be marked and the codeword bits must be drawn
588 // before masking. Due to the arithmetic of XOR, calling apply_mask() with
589 // the same mask value a second time will undo the mask. A final well-formed
590 // QR Code needs exactly one (not zero, two, etc.) mask applied.
apply_mask(&mut self, mask: Mask)591 fn apply_mask(&mut self, mask: Mask) {
592 for y in 0 .. self.size {
593 for x in 0 .. self.size {
594 let invert: bool = match mask.value() {
595 0 => (x + y) % 2 == 0,
596 1 => y % 2 == 0,
597 2 => x % 3 == 0,
598 3 => (x + y) % 3 == 0,
599 4 => (x / 3 + y / 2) % 2 == 0,
600 5 => x * y % 2 + x * y % 3 == 0,
601 6 => (x * y % 2 + x * y % 3) % 2 == 0,
602 7 => ((x + y) % 2 + x * y % 3) % 2 == 0,
603 _ => unreachable!(),
604 };
605 *self.module_mut(x, y) ^= invert & !self.isfunction[(y * self.size + x) as usize];
606 }
607 }
608 }
609
610
611 // Calculates and returns the penalty score based on state of this QR Code's current modules.
612 // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
get_penalty_score(&self) -> i32613 fn get_penalty_score(&self) -> i32 {
614 let mut result: i32 = 0;
615 let size: i32 = self.size;
616
617 // Adjacent modules in row having same color, and finder-like patterns
618 for y in 0 .. size {
619 let mut runcolor = false;
620 let mut runx: i32 = 0;
621 let mut runhistory = FinderPenalty::new(size);
622 for x in 0 .. size {
623 if self.module(x, y) == runcolor {
624 runx += 1;
625 if runx == 5 {
626 result += PENALTY_N1;
627 } else if runx > 5 {
628 result += 1;
629 }
630 } else {
631 runhistory.add_history(runx);
632 if !runcolor {
633 result += runhistory.count_patterns() * PENALTY_N3;
634 }
635 runcolor = self.module(x, y);
636 runx = 1;
637 }
638 }
639 result += runhistory.terminate_and_count(runcolor, runx) * PENALTY_N3;
640 }
641 // Adjacent modules in column having same color, and finder-like patterns
642 for x in 0 .. size {
643 let mut runcolor = false;
644 let mut runy: i32 = 0;
645 let mut runhistory = FinderPenalty::new(size);
646 for y in 0 .. size {
647 if self.module(x, y) == runcolor {
648 runy += 1;
649 if runy == 5 {
650 result += PENALTY_N1;
651 } else if runy > 5 {
652 result += 1;
653 }
654 } else {
655 runhistory.add_history(runy);
656 if !runcolor {
657 result += runhistory.count_patterns() * PENALTY_N3;
658 }
659 runcolor = self.module(x, y);
660 runy = 1;
661 }
662 }
663 result += runhistory.terminate_and_count(runcolor, runy) * PENALTY_N3;
664 }
665
666 // 2*2 blocks of modules having same color
667 for y in 0 .. size - 1 {
668 for x in 0 .. size - 1 {
669 let color: bool = self.module(x, y);
670 if color == self.module(x + 1, y) &&
671 color == self.module(x, y + 1) &&
672 color == self.module(x + 1, y + 1) {
673 result += PENALTY_N2;
674 }
675 }
676 }
677
678 // Balance of dark and light modules
679 let dark: i32 = self.modules.iter().copied().map(i32::from).sum();
680 let total: i32 = size * size; // Note that size is odd, so dark/total != 1/2
681 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
682 let k: i32 = ((dark * 20 - total * 10).abs() + total - 1) / total - 1;
683 result += k * PENALTY_N4;
684 result
685 }
686
687
688 /*---- Private helper functions ----*/
689
690 // Returns an ascending list of positions of alignment patterns for this version number.
691 // Each position is in the range [0,177), and are used on both the x and y axes.
692 // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
get_alignment_pattern_positions(&self) -> Vec<i32>693 fn get_alignment_pattern_positions(&self) -> Vec<i32> {
694 let ver: u8 = self.version.value();
695 if ver == 1 {
696 vec![]
697 } else {
698 let numalign = i32::from(ver) / 7 + 2;
699 let step: i32 = if ver == 32 { 26 } else
700 {(i32::from(ver) * 4 + numalign * 2 + 1) / (numalign * 2 - 2) * 2};
701 let mut result: Vec<i32> = (0 .. numalign - 1).map(
702 |i| self.size - 7 - i * step).collect();
703 result.push(6);
704 result.reverse();
705 result
706 }
707 }
708
709
710 // Returns the number of data bits that can be stored in a QR Code of the given version number, after
711 // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
712 // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
get_num_raw_data_modules(ver: Version) -> usize713 fn get_num_raw_data_modules(ver: Version) -> usize {
714 let ver = usize::from(ver.value());
715 let mut result: usize = (16 * ver + 128) * ver + 64;
716 if ver >= 2 {
717 let numalign: usize = ver / 7 + 2;
718 result -= (25 * numalign - 10) * numalign - 55;
719 if ver >= 7 {
720 result -= 36;
721 }
722 }
723 assert!(208 <= result && result <= 29648);
724 result
725 }
726
727
728 // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
729 // QR Code of the given version number and error correction level, with remainder bits discarded.
730 // This stateless pure function could be implemented as a (40*4)-cell lookup table.
get_num_data_codewords(ver: Version, ecl: QrCodeEcc) -> usize731 fn get_num_data_codewords(ver: Version, ecl: QrCodeEcc) -> usize {
732 QrCode::get_num_raw_data_modules(ver) / 8
733 - QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK , ver, ecl)
734 * QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl)
735 }
736
737
738 // Returns an entry from the given table based on the given values.
table_get(table: &'static [[i8; 41]; 4], ver: Version, ecl: QrCodeEcc) -> usize739 fn table_get(table: &'static [[i8; 41]; 4], ver: Version, ecl: QrCodeEcc) -> usize {
740 table[ecl.ordinal()][usize::from(ver.value())] as usize
741 }
742
743
744 // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
745 // implemented as a lookup table over all possible parameter values, instead of as an algorithm.
reed_solomon_compute_divisor(degree: usize) -> Vec<u8>746 fn reed_solomon_compute_divisor(degree: usize) -> Vec<u8> {
747 assert!(1 <= degree && degree <= 255, "Degree out of range");
748 // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
749 // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
750 let mut result = vec![0u8; degree - 1];
751 result.push(1); // Start off with the monomial x^0
752
753 // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
754 // and drop the highest monomial term which is always 1x^degree.
755 // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
756 let mut root: u8 = 1;
757 for _ in 0 .. degree { // Unused variable i
758 // Multiply the current product by (x - r^i)
759 for j in 0 .. degree {
760 result[j] = QrCode::reed_solomon_multiply(result[j], root);
761 if j + 1 < result.len() {
762 result[j] ^= result[j + 1];
763 }
764 }
765 root = QrCode::reed_solomon_multiply(root, 0x02);
766 }
767 result
768 }
769
770
771 // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
reed_solomon_compute_remainder(data: &[u8], divisor: &[u8]) -> Vec<u8>772 fn reed_solomon_compute_remainder(data: &[u8], divisor: &[u8]) -> Vec<u8> {
773 let mut result = vec![0u8; divisor.len()];
774 for b in data { // Polynomial division
775 let factor: u8 = b ^ result.remove(0);
776 result.push(0);
777 for (x, &y) in result.iter_mut().zip(divisor.iter()) {
778 *x ^= QrCode::reed_solomon_multiply(y, factor);
779 }
780 }
781 result
782 }
783
784
785 // Returns the product of the two given field elements modulo GF(2^8/0x11D).
786 // All inputs are valid. This could be implemented as a 256*256 lookup table.
reed_solomon_multiply(x: u8, y: u8) -> u8787 fn reed_solomon_multiply(x: u8, y: u8) -> u8 {
788 // Russian peasant multiplication
789 let mut z: u8 = 0;
790 for i in (0 .. 8).rev() {
791 z = (z << 1) ^ ((z >> 7) * 0x1D);
792 z ^= ((y >> i) & 1) * x;
793 }
794 z
795 }
796
797 }
798
799
800 /*---- Helper struct for get_penalty_score() ----*/
801
802 struct FinderPenalty {
803 qr_size: i32,
804 run_history: [i32; 7],
805 }
806
807
808 impl FinderPenalty {
809
new(size: i32) -> Self810 pub fn new(size: i32) -> Self {
811 Self {
812 qr_size: size,
813 run_history: [0i32; 7],
814 }
815 }
816
817
818 // Pushes the given value to the front and drops the last value.
add_history(&mut self, mut currentrunlength: i32)819 pub fn add_history(&mut self, mut currentrunlength: i32) {
820 if self.run_history[0] == 0 {
821 currentrunlength += self.qr_size; // Add light border to initial run
822 }
823 let rh = &mut self.run_history;
824 for i in (0 .. rh.len()-1).rev() {
825 rh[i + 1] = rh[i];
826 }
827 rh[0] = currentrunlength;
828 }
829
830
831 // Can only be called immediately after a light run is added, and returns either 0, 1, or 2.
count_patterns(&self) -> i32832 pub fn count_patterns(&self) -> i32 {
833 let rh = &self.run_history;
834 let n = rh[1];
835 assert!(n <= self.qr_size * 3);
836 let core = n > 0 && rh[2] == n && rh[3] == n * 3 && rh[4] == n && rh[5] == n;
837 ( i32::from(core && rh[0] >= n * 4 && rh[6] >= n)
838 + i32::from(core && rh[6] >= n * 4 && rh[0] >= n))
839 }
840
841
842 // Must be called at the end of a line (row or column) of modules.
terminate_and_count(mut self, currentruncolor: bool, mut currentrunlength: i32) -> i32843 pub fn terminate_and_count(mut self, currentruncolor: bool, mut currentrunlength: i32) -> i32 {
844 if currentruncolor { // Terminate dark run
845 self.add_history(currentrunlength);
846 currentrunlength = 0;
847 }
848 currentrunlength += self.qr_size; // Add light border to final run
849 self.add_history(currentrunlength);
850 self.count_patterns()
851 }
852
853 }
854
855
856 /*---- Constants and tables ----*/
857
858 // For use in get_penalty_score(), when evaluating which mask is best.
859 const PENALTY_N1: i32 = 3;
860 const PENALTY_N2: i32 = 3;
861 const PENALTY_N3: i32 = 40;
862 const PENALTY_N4: i32 = 10;
863
864
865 static ECC_CODEWORDS_PER_BLOCK: [[i8; 41]; 4] = [
866 // Version: (note that index 0 is for padding, and is set to an illegal value)
867 //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
868 [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], // Low
869 [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28], // Medium
870 [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], // Quartile
871 [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], // High
872 ];
873
874 static NUM_ERROR_CORRECTION_BLOCKS: [[i8; 41]; 4] = [
875 // Version: (note that index 0 is for padding, and is set to an illegal value)
876 //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
877 [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25], // Low
878 [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49], // Medium
879 [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68], // Quartile
880 [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81], // High
881 ];
882
883
884
885 /*---- QrCodeEcc functionality ----*/
886
887 /// The error correction level in a QR Code symbol.
888 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
889 pub enum QrCodeEcc {
890 /// The QR Code can tolerate about 7% erroneous codewords.
891 Low ,
892 /// The QR Code can tolerate about 15% erroneous codewords.
893 Medium ,
894 /// The QR Code can tolerate about 25% erroneous codewords.
895 Quartile,
896 /// The QR Code can tolerate about 30% erroneous codewords.
897 High ,
898 }
899
900
901 impl QrCodeEcc {
902
903 // Returns an unsigned 2-bit integer (in the range 0 to 3).
ordinal(self) -> usize904 fn ordinal(self) -> usize {
905 use QrCodeEcc::*;
906 match self {
907 Low => 0,
908 Medium => 1,
909 Quartile => 2,
910 High => 3,
911 }
912 }
913
914
915 // Returns an unsigned 2-bit integer (in the range 0 to 3).
format_bits(self) -> u8916 fn format_bits(self) -> u8 {
917 use QrCodeEcc::*;
918 match self {
919 Low => 1,
920 Medium => 0,
921 Quartile => 3,
922 High => 2,
923 }
924 }
925
926 }
927
928
929
930 /*---- QrSegment functionality ----*/
931
932 /// A segment of character/binary/control data in a QR Code symbol.
933 ///
934 /// Instances of this struct are immutable.
935 ///
936 /// The mid-level way to create a segment is to take the payload data
937 /// and call a static factory function such as `QrSegment::make_numeric()`.
938 /// The low-level way to create a segment is to custom-make the bit buffer
939 /// and call the `QrSegment::new()` constructor with appropriate values.
940 ///
941 /// This segment struct imposes no length restrictions, but QR Codes have restrictions.
942 /// Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
943 /// Any segment longer than this is meaningless for the purpose of generating QR Codes.
944 #[derive(Clone, PartialEq, Eq)]
945 pub struct QrSegment {
946
947 // The mode indicator of this segment. Accessed through mode().
948 mode: QrSegmentMode,
949
950 // The length of this segment's unencoded data. Measured in characters for
951 // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
952 // Not the same as the data's bit length. Accessed through num_chars().
953 numchars: usize,
954
955 // The data bits of this segment. Accessed through data().
956 data: Vec<bool>,
957
958 }
959
960
961 impl QrSegment {
962
963 /*---- Static factory functions (mid level) ----*/
964
965 /// Returns a segment representing the given binary data encoded in byte mode.
966 ///
967 /// All input byte slices are acceptable.
968 ///
969 /// Any text string can be converted to UTF-8 bytes and encoded as a byte mode segment.
make_bytes(data: &[u8]) -> Self970 pub fn make_bytes(data: &[u8]) -> Self {
971 let mut bb = BitBuffer(Vec::with_capacity(data.len() * 8));
972 for &b in data {
973 bb.append_bits(u32::from(b), 8);
974 }
975 QrSegment::new(QrSegmentMode::Byte, data.len(), bb.0)
976 }
977
978
979 /// Returns a segment representing the given string of decimal digits encoded in numeric mode.
980 ///
981 /// Panics if the string contains non-digit characters.
make_numeric(text: &[char]) -> Self982 pub fn make_numeric(text: &[char]) -> Self {
983 let mut bb = BitBuffer(Vec::with_capacity(text.len() * 3 + (text.len() + 2) / 3));
984 let mut accumdata: u32 = 0;
985 let mut accumcount: u8 = 0;
986 for &c in text {
987 assert!('0' <= c && c <= '9', "String contains non-numeric characters");
988 accumdata = accumdata * 10 + (u32::from(c) - u32::from('0'));
989 accumcount += 1;
990 if accumcount == 3 {
991 bb.append_bits(accumdata, 10);
992 accumdata = 0;
993 accumcount = 0;
994 }
995 }
996 if accumcount > 0 { // 1 or 2 digits remaining
997 bb.append_bits(accumdata, accumcount * 3 + 1);
998 }
999 QrSegment::new(QrSegmentMode::Numeric, text.len(), bb.0)
1000 }
1001
1002
1003 /// Returns a segment representing the given text string encoded in alphanumeric mode.
1004 ///
1005 /// The characters allowed are: 0 to 9, A to Z (uppercase only), space,
1006 /// dollar, percent, asterisk, plus, hyphen, period, slash, colon.
1007 ///
1008 /// Panics if the string contains non-encodable characters.
make_alphanumeric(text: &[char]) -> Self1009 pub fn make_alphanumeric(text: &[char]) -> Self {
1010 let mut bb = BitBuffer(Vec::with_capacity(text.len() * 5 + (text.len() + 1) / 2));
1011 let mut accumdata: u32 = 0;
1012 let mut accumcount: u32 = 0;
1013 for &c in text {
1014 let i: usize = ALPHANUMERIC_CHARSET.iter().position(|&x| x == c)
1015 .expect("String contains unencodable characters in alphanumeric mode");
1016 accumdata = accumdata * 45 + (i as u32);
1017 accumcount += 1;
1018 if accumcount == 2 {
1019 bb.append_bits(accumdata, 11);
1020 accumdata = 0;
1021 accumcount = 0;
1022 }
1023 }
1024 if accumcount > 0 { // 1 character remaining
1025 bb.append_bits(accumdata, 6);
1026 }
1027 QrSegment::new(QrSegmentMode::Alphanumeric, text.len(), bb.0)
1028 }
1029
1030
1031 /// Returns a list of zero or more segments to represent the given Unicode text string.
1032 ///
1033 /// The result may use various segment modes and switch
1034 /// modes to optimize the length of the bit stream.
make_segments(text: &[char]) -> Vec<Self>1035 pub fn make_segments(text: &[char]) -> Vec<Self> {
1036 if text.is_empty() {
1037 vec![]
1038 } else if QrSegment::is_numeric(text) {
1039 vec![QrSegment::make_numeric(text)]
1040 } else if QrSegment::is_alphanumeric(text) {
1041 vec![QrSegment::make_alphanumeric(text)]
1042 } else {
1043 let s: String = text.iter().cloned().collect();
1044 vec![QrSegment::make_bytes(s.as_bytes())]
1045 }
1046 }
1047
1048
1049 /// Returns a segment representing an Extended Channel Interpretation
1050 /// (ECI) designator with the given assignment value.
make_eci(assignval: u32) -> Self1051 pub fn make_eci(assignval: u32) -> Self {
1052 let mut bb = BitBuffer(Vec::with_capacity(24));
1053 if assignval < (1 << 7) {
1054 bb.append_bits(assignval, 8);
1055 } else if assignval < (1 << 14) {
1056 bb.append_bits(2, 2);
1057 bb.append_bits(assignval, 14);
1058 } else if assignval < 1_000_000 {
1059 bb.append_bits(6, 3);
1060 bb.append_bits(assignval, 21);
1061 } else {
1062 panic!("ECI assignment value out of range");
1063 }
1064 QrSegment::new(QrSegmentMode::Eci, 0, bb.0)
1065 }
1066
1067
1068 /*---- Constructor (low level) ----*/
1069
1070 /// Creates a new QR Code segment with the given attributes and data.
1071 ///
1072 /// The character count (numchars) must agree with the mode and
1073 /// the bit buffer length, but the constraint isn't checked.
new(mode: QrSegmentMode, numchars: usize, data: Vec<bool>) -> Self1074 pub fn new(mode: QrSegmentMode, numchars: usize, data: Vec<bool>) -> Self {
1075 Self { mode, numchars, data }
1076 }
1077
1078
1079 /*---- Instance field getters ----*/
1080
1081 /// Returns the mode indicator of this segment.
mode(&self) -> QrSegmentMode1082 pub fn mode(&self) -> QrSegmentMode {
1083 self.mode
1084 }
1085
1086
1087 /// Returns the character count field of this segment.
num_chars(&self) -> usize1088 pub fn num_chars(&self) -> usize {
1089 self.numchars
1090 }
1091
1092
1093 /// Returns the data bits of this segment.
data(&self) -> &Vec<bool>1094 pub fn data(&self) -> &Vec<bool> {
1095 &self.data
1096 }
1097
1098
1099 /*---- Other static functions ----*/
1100
1101 // Calculates and returns the number of bits needed to encode the given
1102 // segments at the given version. The result is None if a segment has too many
1103 // characters to fit its length field, or the total bits exceeds usize::MAX.
get_total_bits(segs: &[Self], version: Version) -> Option<usize>1104 fn get_total_bits(segs: &[Self], version: Version) -> Option<usize> {
1105 let mut result: usize = 0;
1106 for seg in segs {
1107 let ccbits: u8 = seg.mode.num_char_count_bits(version);
1108 // ccbits can be as large as 16, but usize can be as small as 16
1109 if let Some(limit) = 1usize.checked_shl(u32::from(ccbits)) {
1110 if seg.numchars >= limit {
1111 return None; // The segment's length doesn't fit the field's bit width
1112 }
1113 }
1114 result = result.checked_add(4 + usize::from(ccbits))?;
1115 result = result.checked_add(seg.data.len())?;
1116 }
1117 Some(result)
1118 }
1119
1120
1121 /// Tests whether the given string can be encoded as a segment in numeric mode.
1122 ///
1123 /// A string is encodable iff each character is in the range 0 to 9.
is_numeric(text: &[char]) -> bool1124 pub fn is_numeric(text: &[char]) -> bool {
1125 text.iter().all(|&c| '0' <= c && c <= '9')
1126 }
1127
1128
1129 /// Tests whether the given string can be encoded as a segment in alphanumeric mode.
1130 ///
1131 /// A string is encodable iff each character is in the following set: 0 to 9, A to Z
1132 /// (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
is_alphanumeric(text: &[char]) -> bool1133 pub fn is_alphanumeric(text: &[char]) -> bool {
1134 text.iter().all(|c| ALPHANUMERIC_CHARSET.contains(c))
1135 }
1136
1137 }
1138
1139
1140 // The set of all legal characters in alphanumeric mode,
1141 // where each character value maps to the index in the string.
1142 static ALPHANUMERIC_CHARSET: [char; 45] = ['0','1','2','3','4','5','6','7','8','9',
1143 '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',
1144 ' ','$','%','*','+','-','.','/',':'];
1145
1146
1147
1148 /*---- QrSegmentMode functionality ----*/
1149
1150 /// Describes how a segment's data bits are interpreted.
1151 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
1152 pub enum QrSegmentMode {
1153 Numeric,
1154 Alphanumeric,
1155 Byte,
1156 Kanji,
1157 Eci,
1158 }
1159
1160
1161 impl QrSegmentMode {
1162
1163 // Returns an unsigned 4-bit integer value (range 0 to 15)
1164 // representing the mode indicator bits for this mode object.
mode_bits(self) -> u321165 fn mode_bits(self) -> u32 {
1166 use QrSegmentMode::*;
1167 match self {
1168 Numeric => 0x1,
1169 Alphanumeric => 0x2,
1170 Byte => 0x4,
1171 Kanji => 0x8,
1172 Eci => 0x7,
1173 }
1174 }
1175
1176
1177 // Returns the bit width of the character count field for a segment in this mode
1178 // in a QR Code at the given version number. The result is in the range [0, 16].
num_char_count_bits(self, ver: Version) -> u81179 fn num_char_count_bits(self, ver: Version) -> u8 {
1180 use QrSegmentMode::*;
1181 (match self {
1182 Numeric => [10, 12, 14],
1183 Alphanumeric => [ 9, 11, 13],
1184 Byte => [ 8, 16, 16],
1185 Kanji => [ 8, 10, 12],
1186 Eci => [ 0, 0, 0],
1187 })[usize::from((ver.value() + 7) / 17)]
1188 }
1189
1190 }
1191
1192
1193
1194 /*---- Bit buffer functionality ----*/
1195
1196 /// An appendable sequence of bits (0s and 1s).
1197 ///
1198 /// Mainly used by QrSegment.
1199 pub struct BitBuffer(pub Vec<bool>);
1200
1201
1202 impl BitBuffer {
1203 /// Appends the given number of low-order bits of the given value to this buffer.
1204 ///
1205 /// Requires len ≤ 31 and val < 2<sup>len</sup>.
append_bits(&mut self, val: u32, len: u8)1206 pub fn append_bits(&mut self, val: u32, len: u8) {
1207 assert!(len <= 31 && (val >> len) == 0, "Value out of range");
1208 self.0.extend((0 .. i32::from(len)).rev().map(|i| get_bit(val, i))); // Append bit by bit
1209 }
1210 }
1211
1212
1213
1214 /*---- Miscellaneous values ----*/
1215
1216 /// The error type when the supplied data does not fit any QR Code version.
1217 ///
1218 /// Ways to handle this exception include:
1219 ///
1220 /// - Decrease the error correction level if it was greater than `QrCodeEcc::Low`.
1221 /// - If the `encode_segments_advanced()` function was called, then increase the maxversion
1222 /// argument if it was less than `Version::MAX`. (This advice does not apply to the
1223 /// other factory functions because they search all versions up to `Version::MAX`.)
1224 /// - Split the text data into better or optimal segments in order to reduce the number of bits required.
1225 /// - Change the text or binary data to be shorter.
1226 /// - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric).
1227 /// - Propagate the error upward to the caller/user.
1228 #[derive(Debug, Clone)]
1229 pub struct DataTooLong(String);
1230
1231 impl std::error::Error for DataTooLong {
description(&self) -> &str1232 fn description(&self) -> &str {
1233 &self.0
1234 }
1235 }
1236
1237 impl std::fmt::Display for DataTooLong {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result1238 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1239 f.write_str(&self.0)
1240 }
1241 }
1242
1243
1244 /// A number between 1 and 40 (inclusive).
1245 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1246 pub struct Version(u8);
1247
1248 impl Version {
1249 /// The minimum version number supported in the QR Code Model 2 standard.
1250 pub const MIN: Version = Version( 1);
1251
1252 /// The maximum version number supported in the QR Code Model 2 standard.
1253 pub const MAX: Version = Version(40);
1254
1255 /// Creates a version object from the given number.
1256 ///
1257 /// Panics if the number is outside the range [1, 40].
new(ver: u8) -> Self1258 pub fn new(ver: u8) -> Self {
1259 assert!(Version::MIN.value() <= ver && ver <= Version::MAX.value(), "Version number out of range");
1260 Self(ver)
1261 }
1262
1263 /// Returns the value, which is in the range [1, 40].
value(self) -> u81264 pub fn value(self) -> u8 {
1265 self.0
1266 }
1267 }
1268
1269
1270 /// A number between 0 and 7 (inclusive).
1271 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1272 pub struct Mask(u8);
1273
1274 impl Mask {
1275 /// Creates a mask object from the given number.
1276 ///
1277 /// Panics if the number is outside the range [0, 7].
new(mask: u8) -> Self1278 pub fn new(mask: u8) -> Self {
1279 assert!(mask <= 7, "Mask value out of range");
1280 Self(mask)
1281 }
1282
1283 /// Returns the value, which is in the range [0, 7].
value(self) -> u81284 pub fn value(self) -> u8 {
1285 self.0
1286 }
1287 }
1288
1289
1290 // Returns true iff the i'th bit of x is set to 1.
get_bit(x: u32, i: i32) -> bool1291 fn get_bit(x: u32, i: i32) -> bool {
1292 (x >> i) & 1 != 0
1293 }
1294