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