1 /*
2 * QR Code generator library (Rust, no heap)
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::Version;
62 //! ```
63 //!
64 //! Text data:
65 //!
66 //! ```
67 //! let mut outbuffer = vec![0u8; Version::MAX.buffer_len()];
68 //! let mut tempbuffer = vec![0u8; Version::MAX.buffer_len()];
69 //! let qr = QrCode::encode_text("Hello, world!", &mut tempbuffer, &mut outbuffer,
70 //! QrCodeEcc::Medium, Version::MIN, Version:MAX, None, true).unwrap();
71 //! let svg = to_svg_string(&qr, 4); // See qrcodegen-demo
72 //! ```
73 //!
74 //! Binary data:
75 //!
76 //! ```
77 //! let mut outbuffer = vec![0u8; Version::MAX.buffer_len()];
78 //! let mut dataandtemp = vec![0u8; Version::MAX.buffer_len()];
79 //! dataandtemp[0] = 0xE3;
80 //! dataandtemp[1] = 0x81;
81 //! dataandtemp[2] = 0x82;
82 //! let qr = QrCode::encode_binary(&mut dataandtemp, 3, &mut outbuffer, QrCodeEcc::High,
83 //! Version::new(2), Version::new(7), Some(Mask::new(4)), false).unwrap();
84 //! for y in 0 .. qr.size() {
85 //! for x in 0 .. qr.size() {
86 //! (... paint qr.get_module(x, y) ...)
87 //! }
88 //! }
89 //! ```
90
91
92 #![no_std]
93 #![forbid(unsafe_code)]
94 use core::convert::TryFrom;
95
96
97 /*---- QrCode functionality ----*/
98
99 /// A QR Code symbol, which is a type of two-dimension barcode.
100 ///
101 /// Invented by Denso Wave and described in the ISO/IEC 18004 standard.
102 ///
103 /// Instances of this struct represent an immutable square grid of dark and light cells.
104 /// The impl provides static factory functions to create a QR Code from text or binary data.
105 /// The struct and impl cover the QR Code Model 2 specification, supporting all versions
106 /// (sizes) from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
107 ///
108 /// Ways to create a QR Code object:
109 ///
110 /// - High level: Take the payload data and call `QrCode::encode_text()` or `QrCode::encode_binary()`.
111 /// - Mid level: Custom-make the list of segments and call
112 /// `QrCode::encode_segments_to_codewords()` and then `QrCode::encode_codewords()`.
113 /// - Low level: Custom-make the array of data codeword bytes (including segment
114 /// headers and final padding, excluding error correction codewords), supply the
115 /// appropriate version number, and call the `QrCode::encode_codewords()` constructor.
116 ///
117 /// (Note that all ways require supplying the desired error correction level and various byte buffers.)
118 pub struct QrCode<'a> {
119
120 // The width and height of this QR Code, measured in modules, between
121 // 21 and 177 (inclusive). This is equal to version * 4 + 17.
122 size: &'a mut u8,
123
124 // The modules of this QR Code (0 = light, 1 = dark), packed bitwise into bytes.
125 // Immutable after constructor finishes. Accessed through get_module().
126 modules: &'a mut [u8],
127
128 }
129
130
131 impl<'a> QrCode<'a> {
132
133 /*---- Static factory functions (high level) ----*/
134
135 /// Encodes the given text string to a QR Code, returning a wrapped `QrCode` if successful.
136 /// If the data is too long to fit in any version in the given range
137 /// at the given ECC level, then `Err` is returned.
138 ///
139 /// The smallest possible QR Code version within the given range is automatically
140 /// chosen for the output. Iff boostecl is `true`, then the ECC level of the result
141 /// may be higher than the ecl argument if it can be done without increasing the
142 /// version. The mask number is either between 0 to 7 (inclusive) to force that
143 /// mask, or `None` to automatically choose an appropriate mask (which may be slow).
144 ///
145 /// About the slices, letting len = maxversion.buffer_len():
146 /// - Before calling the function:
147 /// - The slices tempbuffer and outbuffer each must have a length of at least len.
148 /// - If a slice is longer than len, then the function will not
149 /// read from or write to the suffix array[len .. array.len()].
150 /// - The initial values of both slices can be arbitrary
151 /// because the function always writes before reading.
152 /// - After the function returns, both slices have no guarantee on what values are stored.
153 ///
154 /// If successful, the resulting QR Code may use numeric,
155 /// alphanumeric, or byte mode to encode the text.
156 ///
157 /// In the most optimistic case, a QR Code at version 40 with low ECC
158 /// can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string
159 /// up to 4296 characters, or any digit string up to 7089 characters.
160 /// These numbers represent the hard upper limit of the QR Code standard.
161 ///
162 /// Please consult the QR Code specification for information on
163 /// data capacities per version, ECC level, and text encoding mode.
encode_text<'b>(text: &str, tempbuffer: &'b mut [u8], mut outbuffer: &'a mut [u8], ecl: QrCodeEcc, minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<QrCode<'a>,DataTooLong>164 pub fn encode_text<'b>(text: &str, tempbuffer: &'b mut [u8], mut outbuffer: &'a mut [u8], ecl: QrCodeEcc,
165 minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<QrCode<'a>,DataTooLong> {
166
167 let minlen: usize = outbuffer.len().min(tempbuffer.len());
168 outbuffer = &mut outbuffer[ .. minlen];
169
170 let textlen: usize = text.len(); // In bytes
171 if textlen == 0 {
172 let (datacodewordslen, ecl, version) = QrCode::encode_segments_to_codewords(&[], outbuffer, ecl, minversion, maxversion, boostecl)?;
173 return Ok(Self::encode_codewords(outbuffer, datacodewordslen, tempbuffer, ecl, version, mask));
174 }
175
176 use QrSegmentMode::*;
177 let buflen: usize = outbuffer.len();
178 let seg: QrSegment = if QrSegment::is_numeric(text) && QrSegment::calc_buffer_size(Numeric, textlen).map_or(false, |x| x <= buflen) {
179 QrSegment::make_numeric(text, tempbuffer)
180 } else if QrSegment::is_alphanumeric(text) && QrSegment::calc_buffer_size(Alphanumeric, textlen).map_or(false, |x| x <= buflen) {
181 QrSegment::make_alphanumeric(text, tempbuffer)
182 } else if QrSegment::calc_buffer_size(Byte, textlen).map_or(false, |x| x <= buflen) {
183 QrSegment::make_bytes(text.as_bytes())
184 } else {
185 return Err(DataTooLong::SegmentTooLong);
186 };
187 let (datacodewordslen, ecl, version) = QrCode::encode_segments_to_codewords(&[seg], outbuffer, ecl, minversion, maxversion, boostecl)?;
188 Ok(Self::encode_codewords(outbuffer, datacodewordslen, tempbuffer, ecl, version, mask))
189 }
190
191
192 /// Encodes the given binary data to a QR Code, returning a wrapped `QrCode` if successful.
193 /// If the data is too long to fit in any version in the given range
194 /// at the given ECC level, then `Err` is returned.
195 ///
196 /// The smallest possible QR Code version within the given range is automatically
197 /// chosen for the output. Iff boostecl is `true`, then the ECC level of the result
198 /// may be higher than the ecl argument if it can be done without increasing the
199 /// version. The mask number is either between 0 to 7 (inclusive) to force that
200 /// mask, or `None` to automatically choose an appropriate mask (which may be slow).
201 ///
202 /// About the slices, letting len = maxversion.buffer_len():
203 /// - Before calling the function:
204 /// - The slices dataandtempbuffer and outbuffer each must have a length of at least len.
205 /// - If a slice is longer than len, then the function will not
206 /// read from or write to the suffix array[len .. array.len()].
207 /// - The input slice range dataandtempbuffer[0 .. datalen] should normally be
208 /// valid UTF-8 text, but is not required by the QR Code standard.
209 /// - The initial values of dataandtempbuffer[datalen .. len] and outbuffer[0 .. len]
210 /// can be arbitrary because the function always writes before reading.
211 /// - After the function returns, both slices have no guarantee on what values are stored.
212 ///
213 /// If successful, the resulting QR Code will use byte mode to encode the data.
214 ///
215 /// In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte
216 /// sequence up to length 2953. This is the hard upper limit of the QR Code standard.
217 ///
218 /// Please consult the QR Code specification for information on
219 /// data capacities per version, ECC level, and text encoding mode.
encode_binary<'b>(dataandtempbuffer: &'b mut [u8], datalen: usize, mut outbuffer: &'a mut [u8], ecl: QrCodeEcc, minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<QrCode<'a>,DataTooLong>220 pub fn encode_binary<'b>(dataandtempbuffer: &'b mut [u8], datalen: usize, mut outbuffer: &'a mut [u8], ecl: QrCodeEcc,
221 minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<QrCode<'a>,DataTooLong> {
222
223 assert!(datalen <= dataandtempbuffer.len(), "Invalid data length");
224 let minlen: usize = outbuffer.len().min(dataandtempbuffer.len());
225 outbuffer = &mut outbuffer[ .. minlen];
226
227 if QrSegment::calc_buffer_size(QrSegmentMode::Byte, datalen).map_or(true, |x| x > outbuffer.len()) {
228 return Err(DataTooLong::SegmentTooLong);
229 }
230 let seg: QrSegment = QrSegment::make_bytes(&dataandtempbuffer[ .. datalen]);
231 let (datacodewordslen, ecl, version) = QrCode::encode_segments_to_codewords(&[seg], outbuffer, ecl, minversion, maxversion, boostecl)?;
232 Ok(Self::encode_codewords(outbuffer, datacodewordslen, dataandtempbuffer, ecl, version, mask))
233 }
234
235
236 /*---- Static factory functions (mid level) ----*/
237
238 /// Returns an intermediate state representing the given segments
239 /// with the given encoding parameters being encoded into codewords.
240 ///
241 /// The smallest possible QR Code version within the given range is automatically
242 /// chosen for the output. Iff boostecl is `true`, then the ECC level of the result
243 /// may be higher than the ecl argument if it can be done without increasing the
244 /// version. The mask number is either between 0 to 7 (inclusive) to force that
245 /// mask, or `None` to automatically choose an appropriate mask (which may be slow).
246 ///
247 /// This function exists to allow segments to use parts of a temporary buffer,
248 /// then have the segments be encoded to an output buffer, then invalidate all the segments,
249 /// and finally have the output buffer and temporary buffer be encoded to a QR Code.
encode_segments_to_codewords(segs: &[QrSegment], outbuffer: &'a mut [u8], mut ecl: QrCodeEcc, minversion: Version, maxversion: Version, boostecl: bool) -> Result<(usize,QrCodeEcc,Version),DataTooLong>250 pub fn encode_segments_to_codewords(segs: &[QrSegment], outbuffer: &'a mut [u8],
251 mut ecl: QrCodeEcc, minversion: Version, maxversion: Version, boostecl: bool)
252 -> Result<(usize,QrCodeEcc,Version),DataTooLong> {
253
254 assert!(minversion <= maxversion, "Invalid value");
255 assert!(outbuffer.len() >= QrCode::get_num_data_codewords(maxversion, ecl), "Invalid buffer length");
256
257 // Find the minimal version number to use
258 let mut version: Version = minversion;
259 let datausedbits: usize = loop {
260 let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8; // Number of data bits available
261 let dataused: Option<usize> = QrSegment::get_total_bits(segs, version);
262 if dataused.map_or(false, |n| n <= datacapacitybits) {
263 break dataused.unwrap(); // This version number is found to be suitable
264 } else if version >= maxversion { // All versions in the range could not fit the given data
265 return Err(match dataused {
266 None => DataTooLong::SegmentTooLong,
267 Some(n) => DataTooLong::DataOverCapacity(n, datacapacitybits),
268 });
269 } else {
270 version = Version::new(version.value() + 1);
271 }
272 };
273
274 // Increase the error correction level while the data still fits in the current version number
275 for &newecl in &[QrCodeEcc::Medium, QrCodeEcc::Quartile, QrCodeEcc::High] { // From low to high
276 if boostecl && datausedbits <= QrCode::get_num_data_codewords(version, newecl) * 8 {
277 ecl = newecl;
278 }
279 }
280
281 // Concatenate all segments to create the data bit string
282 let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;
283 let mut bb = BitBuffer::new(&mut outbuffer[ .. datacapacitybits/8]);
284 for seg in segs {
285 bb.append_bits(seg.mode.mode_bits(), 4);
286 bb.append_bits(u32::try_from(seg.numchars).unwrap(), seg.mode.num_char_count_bits(version));
287 for i in 0 .. seg.bitlength {
288 let bit: u8 = (seg.data[i >> 3] >> (7 - (i & 7))) & 1;
289 bb.append_bits(bit.into(), 1);
290 }
291 }
292 debug_assert_eq!(bb.length, datausedbits);
293
294 // Add terminator and pad up to a byte if applicable
295 let numzerobits: usize = core::cmp::min(4, datacapacitybits - bb.length);
296 bb.append_bits(0, u8::try_from(numzerobits).unwrap());
297 let numzerobits: usize = bb.length.wrapping_neg() & 7;
298 bb.append_bits(0, u8::try_from(numzerobits).unwrap());
299 debug_assert_eq!(bb.length % 8, 0);
300
301 // Pad with alternating bytes until data capacity is reached
302 for &padbyte in [0xEC, 0x11].iter().cycle() {
303 if bb.length >= datacapacitybits {
304 break;
305 }
306 bb.append_bits(padbyte, 8);
307 }
308 Ok((bb.length / 8, ecl, version))
309 }
310
311
312 /*---- Constructor (low level) ----*/
313
314 /// Creates a new QR Code with the given version number,
315 /// error correction level, data codeword bytes, and mask number.
316 ///
317 /// This is a low-level API that most users should not use directly.
318 /// A mid-level API is the `encode_segments_to_codewords()` function.
encode_codewords<'b>(mut datacodewordsandoutbuffer: &'a mut [u8], datacodewordslen: usize, mut tempbuffer: &'b mut [u8], ecl: QrCodeEcc, version: Version, mut msk: Option<Mask>) -> QrCode<'a>319 pub fn encode_codewords<'b>(mut datacodewordsandoutbuffer: &'a mut [u8], datacodewordslen: usize, mut tempbuffer: &'b mut [u8],
320 ecl: QrCodeEcc, version: Version, mut msk: Option<Mask>) -> QrCode<'a> {
321
322 datacodewordsandoutbuffer = &mut datacodewordsandoutbuffer[ .. version.buffer_len()];
323 tempbuffer = &mut tempbuffer [ .. version.buffer_len()];
324
325 // Compute ECC
326 let rawcodewords: usize = QrCode::get_num_raw_data_modules(version) / 8;
327 assert!(datacodewordslen <= rawcodewords);
328 let (data, temp) = datacodewordsandoutbuffer.split_at_mut(datacodewordslen);
329 let allcodewords = Self::add_ecc_and_interleave(data, version, ecl, temp, tempbuffer);
330
331 // Draw modules
332 let mut result: QrCode = QrCode::<'a>::function_modules_marked(datacodewordsandoutbuffer, version);
333 result.draw_codewords(allcodewords);
334 result.draw_light_function_modules();
335 let funcmods: QrCode = QrCode::<'b>::function_modules_marked(tempbuffer, version); // Just a grid, not a real QR Code
336
337 // Do masking
338 if msk.is_none() { // Automatically choose best mask
339 let mut minpenalty = core::i32::MAX;
340 for i in 0u8 .. 8 {
341 let i = Mask::new(i);
342 result.apply_mask(&funcmods, i);
343 result.draw_format_bits(ecl, i);
344 let penalty: i32 = result.get_penalty_score();
345 if penalty < minpenalty {
346 msk = Some(i);
347 minpenalty = penalty;
348 }
349 result.apply_mask(&funcmods, i); // Undoes the mask due to XOR
350 }
351 }
352 let msk: Mask = msk.unwrap();
353 result.apply_mask(&funcmods, msk); // Apply the final choice of mask
354 result.draw_format_bits(ecl, msk); // Overwrite old format bits
355 result
356 }
357
358
359 /*---- Public methods ----*/
360
361 /// Returns this QR Code's version, in the range [1, 40].
version(&self) -> Version362 pub fn version(&self) -> Version {
363 Version::new((*self.size - 17) / 4)
364 }
365
366
367 /// Returns this QR Code's size, in the range [21, 177].
size(&self) -> i32368 pub fn size(&self) -> i32 {
369 i32::from(*self.size)
370 }
371
372
373 /// Returns this QR Code's error correction level.
error_correction_level(&self) -> QrCodeEcc374 pub fn error_correction_level(&self) -> QrCodeEcc {
375 let index =
376 usize::from(self.get_module_bounded(0, 8)) << 1 |
377 usize::from(self.get_module_bounded(1, 8)) << 0;
378 use QrCodeEcc::*;
379 [Medium, Low, High, Quartile][index]
380 }
381
382
383 /// Returns this QR Code's mask, in the range [0, 7].
mask(&self) -> Mask384 pub fn mask(&self) -> Mask {
385 Mask::new(
386 u8::from(self.get_module_bounded(2, 8)) << 2 |
387 u8::from(self.get_module_bounded(3, 8)) << 1 |
388 u8::from(self.get_module_bounded(4, 8)) << 0)
389 }
390
391
392 /// Returns the color of the module (pixel) at the given coordinates,
393 /// which is `false` for light or `true` for dark.
394 ///
395 /// The top left corner has the coordinates (x=0, y=0). If the given
396 /// coordinates are out of bounds, then `false` (light) is returned.
get_module(&self, x: i32, y: i32) -> bool397 pub fn get_module(&self, x: i32, y: i32) -> bool {
398 let range = 0 .. self.size();
399 range.contains(&x) && range.contains(&y) && self.get_module_bounded(x as u8, y as u8)
400 }
401
402
403 // Returns the color of the module at the given coordinates, which must be in bounds.
get_module_bounded(&self, x: u8, y: u8) -> bool404 fn get_module_bounded(&self, x: u8, y: u8) -> bool {
405 let range = 0 .. *self.size;
406 assert!(range.contains(&x) && range.contains(&y));
407 let index = usize::from(y) * usize::from(*self.size) + usize::from(x);
408 let byteindex: usize = index >> 3;
409 let bitindex: usize = index & 7;
410 get_bit(self.modules[byteindex].into(), bitindex as u8)
411 }
412
413
414 // Sets the color of the module at the given coordinates, doing nothing if out of bounds.
set_module_unbounded(&mut self, x: i32, y: i32, isdark: bool)415 fn set_module_unbounded(&mut self, x: i32, y: i32, isdark: bool) {
416 let range = 0 .. self.size();
417 if range.contains(&x) && range.contains(&y) {
418 self.set_module_bounded(x as u8, y as u8, isdark);
419 }
420 }
421
422
423 // Sets the color of the module at the given coordinates, which must be in bounds.
set_module_bounded(&mut self, x: u8, y: u8, isdark: bool)424 fn set_module_bounded(&mut self, x: u8, y: u8, isdark: bool) {
425 let range = 0 .. *self.size;
426 assert!(range.contains(&x) && range.contains(&y));
427 let index = usize::from(y) * usize::from(*self.size) + usize::from(x);
428 let byteindex: usize = index >> 3;
429 let bitindex: usize = index & 7;
430 if isdark {
431 self.modules[byteindex] |= 1u8 << bitindex;
432 } else {
433 self.modules[byteindex] &= !(1u8 << bitindex);
434 }
435 }
436
437
438 /*---- Error correction code generation ----*/
439
440 // Appends error correction bytes to each block of the given data array, then interleaves
441 // bytes from the blocks, stores them in the output array, and returns a slice of resultbuf.
442 // temp is used as a temporary work area and will be clobbered by this function.
add_ecc_and_interleave<'b>(data: &[u8], ver: Version, ecl: QrCodeEcc, temp: &mut [u8], resultbuf: &'b mut [u8]) -> &'b [u8]443 fn add_ecc_and_interleave<'b>(data: &[u8], ver: Version, ecl: QrCodeEcc, temp: &mut [u8], resultbuf: &'b mut [u8]) -> &'b [u8] {
444 assert_eq!(data.len(), QrCode::get_num_data_codewords(ver, ecl));
445
446 // Calculate parameter numbers
447 let numblocks: usize = QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl);
448 let blockecclen: usize = QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK , ver, ecl);
449 let rawcodewords: usize = QrCode::get_num_raw_data_modules(ver) / 8;
450 let numshortblocks: usize = numblocks - rawcodewords % numblocks;
451 let shortblockdatalen: usize = rawcodewords / numblocks - blockecclen;
452 let result = &mut resultbuf[ .. rawcodewords];
453
454 // Split data into blocks, calculate ECC, and interleave
455 // (not concatenate) the bytes into a single sequence
456 let rs = ReedSolomonGenerator::new(blockecclen);
457 let mut dat: &[u8] = data;
458 let ecc: &mut [u8] = &mut temp[ .. blockecclen]; // Temporary storage
459 for i in 0 .. numblocks {
460 let datlen: usize = shortblockdatalen + usize::from(i >= numshortblocks);
461 rs.compute_remainder(&dat[ .. datlen], ecc);
462 let mut k: usize = i;
463 for j in 0 .. datlen { // Copy data
464 if j == shortblockdatalen {
465 k -= numshortblocks;
466 }
467 result[k] = dat[j];
468 k += numblocks;
469 }
470 let mut k: usize = data.len() + i;
471 for j in 0 .. blockecclen { // Copy ECC
472 result[k] = ecc[j];
473 k += numblocks;
474 }
475 dat = &dat[datlen .. ];
476 }
477 debug_assert_eq!(dat.len(), 0);
478 result
479 }
480
481
482 /*---- Drawing function modules ----*/
483
484 // Creates a QR Code grid with light modules for the given
485 // version's size, then marks every function module as dark.
function_modules_marked(outbuffer: &'a mut [u8], ver: Version) -> Self486 fn function_modules_marked(outbuffer: &'a mut [u8], ver: Version) -> Self {
487 assert_eq!(outbuffer.len(), ver.buffer_len());
488 let parts: (&mut u8, &mut [u8]) = outbuffer.split_first_mut().unwrap();
489 let mut result = Self {
490 size: parts.0,
491 modules: parts.1,
492 };
493 let size: u8 = ver.value() * 4 + 17;
494 *result.size = size;
495 result.modules.fill(0);
496
497 // Fill horizontal and vertical timing patterns
498 result.fill_rectangle(6, 0, 1, size);
499 result.fill_rectangle(0, 6, size, 1);
500
501 // Fill 3 finder patterns (all corners except bottom right) and format bits
502 result.fill_rectangle(0, 0, 9, 9);
503 result.fill_rectangle(size - 8, 0, 8, 9);
504 result.fill_rectangle(0, size - 8, 9, 8);
505
506 // Fill numerous alignment patterns
507 let mut alignpatposbuf = [0u8; 7];
508 let alignpatpos: &[u8] = result.get_alignment_pattern_positions(&mut alignpatposbuf);
509 for (i, pos0) in alignpatpos.iter().enumerate() {
510 for (j, pos1) in alignpatpos.iter().enumerate() {
511 // Don't draw on the three finder corners
512 if !((i == 0 && j == 0) || (i == 0 && j == alignpatpos.len() - 1) || (i == alignpatpos.len() - 1 && j == 0)) {
513 result.fill_rectangle(pos0 - 2, pos1 - 2, 5, 5);
514 }
515 }
516 }
517
518 // Fill version blocks
519 if ver.value() >= 7 {
520 result.fill_rectangle(size - 11, 0, 3, 6);
521 result.fill_rectangle(0, size - 11, 6, 3);
522 }
523
524 result
525 }
526
527
528 // Draws light function modules and possibly some dark modules onto this QR Code, without changing
529 // non-function modules. This does not draw the format bits. This requires all function modules to be previously
530 // marked dark (namely by function_modules_marked()), because this may skip redrawing dark function modules.
draw_light_function_modules(&mut self)531 fn draw_light_function_modules(&mut self) {
532 // Draw horizontal and vertical timing patterns
533 let size: u8 = *self.size;
534 for i in (7 .. size-7).step_by(2) {
535 self.set_module_bounded(6, i, false);
536 self.set_module_bounded(i, 6, false);
537 }
538
539 // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
540 for dy in -4i32 ..= 4 {
541 for dx in -4i32 ..= 4 {
542 let dist: i32 = dx.abs().max(dy.abs());
543 if dist == 2 || dist == 4 {
544 self.set_module_unbounded(3 + dx, 3 + dy, false);
545 self.set_module_unbounded(i32::from(size) - 4 + dx, 3 + dy, false);
546 self.set_module_unbounded(3 + dx, i32::from(size) - 4 + dy, false);
547 }
548 }
549 }
550
551 // Draw numerous alignment patterns
552 let mut alignpatposbuf = [0u8; 7];
553 let alignpatpos: &[u8] = self.get_alignment_pattern_positions(&mut alignpatposbuf);
554 for (i, &pos0) in alignpatpos.iter().enumerate() {
555 for (j, &pos1) in alignpatpos.iter().enumerate() {
556 if (i == 0 && j == 0) || (i == 0 && j == alignpatpos.len() - 1) || (i == alignpatpos.len() - 1 && j == 0) {
557 continue; // Don't draw on the three finder corners
558 }
559 for dy in -1 ..= 1 {
560 for dx in -1 ..= 1 {
561 self.set_module_bounded((i32::from(pos0) + dx) as u8, (i32::from(pos1) + dy) as u8, dx == 0 && dy == 0);
562 }
563 }
564 }
565 }
566
567 // Draw version blocks
568 let ver = u32::from(self.version().value()); // uint6, in the range [7, 40]
569 if ver >= 7 {
570 // Calculate error correction code and pack bits
571 let bits: u32 = {
572 let mut rem: u32 = ver;
573 for _ in 0 .. 12 {
574 rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
575 }
576 ver << 12 | rem // uint18
577 };
578 debug_assert_eq!(bits >> 18, 0);
579
580 // Draw two copies
581 for i in 0u8 .. 18 {
582 let bit: bool = get_bit(bits, i);
583 let a: u8 = size - 11 + i % 3;
584 let b: u8 = i / 3;
585 self.set_module_bounded(a, b, bit);
586 self.set_module_bounded(b, a, bit);
587 }
588 }
589 }
590
591
592 // Draws two copies of the format bits (with its own error correction code) based
593 // on the given mask and error correction level. This always draws all modules of
594 // the format bits, unlike draw_light_function_modules() which might skip dark modules.
draw_format_bits(&mut self, ecl: QrCodeEcc, mask: Mask)595 fn draw_format_bits(&mut self, ecl: QrCodeEcc, mask: Mask) {
596 // Calculate error correction code and pack bits
597 let bits: u32 = {
598 // errcorrlvl is uint2, mask is uint3
599 let data = u32::from(ecl.format_bits() << 3 | mask.value());
600 let mut rem: u32 = data;
601 for _ in 0 .. 10 {
602 rem = (rem << 1) ^ ((rem >> 9) * 0x537);
603 }
604 (data << 10 | rem) ^ 0x5412 // uint15
605 };
606 debug_assert_eq!(bits >> 15, 0);
607
608 // Draw first copy
609 for i in 0 .. 6 {
610 self.set_module_bounded(8, i, get_bit(bits, i));
611 }
612 self.set_module_bounded(8, 7, get_bit(bits, 6));
613 self.set_module_bounded(8, 8, get_bit(bits, 7));
614 self.set_module_bounded(7, 8, get_bit(bits, 8));
615 for i in 9 .. 15 {
616 self.set_module_bounded(14 - i, 8, get_bit(bits, i));
617 }
618
619 // Draw second copy
620 let size: u8 = *self.size;
621 for i in 0 .. 8 {
622 self.set_module_bounded(size - 1 - i, 8, get_bit(bits, i));
623 }
624 for i in 8 .. 15 {
625 self.set_module_bounded(8, size - 15 + i, get_bit(bits, i));
626 }
627 self.set_module_bounded(8, size - 8, true); // Always dark
628 }
629
630
631 // Sets every module in the range [left : left + width] * [top : top + height] to dark.
fill_rectangle(&mut self, left: u8, top: u8, width: u8, height: u8)632 fn fill_rectangle(&mut self, left: u8, top: u8, width: u8, height: u8) {
633 for dy in 0 .. height {
634 for dx in 0 .. width {
635 self.set_module_bounded(left + dx, top + dy, true);
636 }
637 }
638 }
639
640
641 /*---- Drawing data modules and masking ----*/
642
643 // Draws the raw codewords (including data and ECC) onto this QR Code. This requires the initial state of
644 // the QR Code to be dark at function modules and light at codeword modules (including unused remainder bits).
draw_codewords(&mut self, data: &[u8])645 fn draw_codewords(&mut self, data: &[u8]) {
646 assert_eq!(data.len(), QrCode::get_num_raw_data_modules(self.version()) / 8, "Illegal argument");
647
648 let size: i32 = self.size();
649 let mut i: usize = 0; // Bit index into the data
650 // Do the funny zigzag scan
651 let mut right: i32 = size - 1;
652 while right >= 1 { // Index of right column in each column pair
653 if right == 6 {
654 right = 5;
655 }
656 for vert in 0 .. size { // Vertical counter
657 for j in 0 .. 2 {
658 let x = (right - j) as u8; // Actual x coordinate
659 let upward: bool = (right + 1) & 2 == 0;
660 let y = (if upward { size - 1 - vert } else { vert }) as u8; // Actual y coordinate
661 if !self.get_module_bounded(x, y) && i < data.len() * 8 {
662 self.set_module_bounded(x, y, get_bit(data[i >> 3].into(), 7 - ((i as u8) & 7)));
663 i += 1;
664 }
665 // If this QR Code has any remainder bits (0 to 7), they were assigned as
666 // 0/false/light by the constructor and are left unchanged by this method
667 }
668 }
669 right -= 2;
670 }
671 debug_assert_eq!(i, data.len() * 8);
672 }
673
674
675 // XORs the codeword modules in this QR Code with the given mask pattern
676 // and given pattern of function modules. The codeword bits must be drawn
677 // before masking. Due to the arithmetic of XOR, calling apply_mask() with
678 // the same mask value a second time will undo the mask. A final well-formed
679 // QR Code needs exactly one (not zero, two, etc.) mask applied.
apply_mask(&mut self, functionmodules: &QrCode, mask: Mask)680 fn apply_mask(&mut self, functionmodules: &QrCode, mask: Mask) {
681 for y in 0 .. *self.size {
682 for x in 0 .. *self.size {
683 if functionmodules.get_module_bounded(x, y) {
684 continue;
685 }
686 let invert: bool = {
687 let x = i32::from(x);
688 let y = i32::from(y);
689 match mask.value() {
690 0 => (x + y) % 2 == 0,
691 1 => y % 2 == 0,
692 2 => x % 3 == 0,
693 3 => (x + y) % 3 == 0,
694 4 => (x / 3 + y / 2) % 2 == 0,
695 5 => x * y % 2 + x * y % 3 == 0,
696 6 => (x * y % 2 + x * y % 3) % 2 == 0,
697 7 => ((x + y) % 2 + x * y % 3) % 2 == 0,
698 _ => unreachable!(),
699 }
700 };
701 self.set_module_bounded(x, y,
702 self.get_module_bounded(x, y) ^ invert);
703 }
704 }
705 }
706
707
708 // Calculates and returns the penalty score based on state of this QR Code's current modules.
709 // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
get_penalty_score(&self) -> i32710 fn get_penalty_score(&self) -> i32 {
711 let mut result: i32 = 0;
712 let size: u8 = *self.size;
713
714 // Adjacent modules in row having same color, and finder-like patterns
715 for y in 0 .. size {
716 let mut runcolor = false;
717 let mut runx: i32 = 0;
718 let mut runhistory = FinderPenalty::new(size);
719 for x in 0 .. size {
720 if self.get_module_bounded(x, y) == runcolor {
721 runx += 1;
722 if runx == 5 {
723 result += PENALTY_N1;
724 } else if runx > 5 {
725 result += 1;
726 }
727 } else {
728 runhistory.add_history(runx);
729 if !runcolor {
730 result += runhistory.count_patterns() * PENALTY_N3;
731 }
732 runcolor = self.get_module_bounded(x, y);
733 runx = 1;
734 }
735 }
736 result += runhistory.terminate_and_count(runcolor, runx) * PENALTY_N3;
737 }
738 // Adjacent modules in column having same color, and finder-like patterns
739 for x in 0 .. size {
740 let mut runcolor = false;
741 let mut runy: i32 = 0;
742 let mut runhistory = FinderPenalty::new(size);
743 for y in 0 .. size {
744 if self.get_module_bounded(x, y) == runcolor {
745 runy += 1;
746 if runy == 5 {
747 result += PENALTY_N1;
748 } else if runy > 5 {
749 result += 1;
750 }
751 } else {
752 runhistory.add_history(runy);
753 if !runcolor {
754 result += runhistory.count_patterns() * PENALTY_N3;
755 }
756 runcolor = self.get_module_bounded(x, y);
757 runy = 1;
758 }
759 }
760 result += runhistory.terminate_and_count(runcolor, runy) * PENALTY_N3;
761 }
762
763 // 2*2 blocks of modules having same color
764 for y in 0 .. size-1 {
765 for x in 0 .. size-1 {
766 let color: bool = self.get_module_bounded(x, y);
767 if color == self.get_module_bounded(x + 1, y) &&
768 color == self.get_module_bounded(x, y + 1) &&
769 color == self.get_module_bounded(x + 1, y + 1) {
770 result += PENALTY_N2;
771 }
772 }
773 }
774
775 // Balance of dark and light modules
776 let dark = self.modules.iter().map(|x| x.count_ones()).sum::<u32>() as i32;
777 let total = i32::from(size) * i32::from(size); // Note that size is odd, so dark/total != 1/2
778 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
779 let k: i32 = ((dark * 20 - total * 10).abs() + total - 1) / total - 1;
780 debug_assert!(0 <= k && k <= 9);
781 result += k * PENALTY_N4;
782 debug_assert!(0 <= result && result <= 2568888); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
783 result
784 }
785
786
787 /*---- Private helper functions ----*/
788
789 // Calculates and stores an ascending list of positions of alignment patterns
790 // for this version number, returning a slice of resultbuf.
791 // Each position is in the range [0,177), and are used on both the x and y axes.
792 // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
get_alignment_pattern_positions<'b>(&self, resultbuf: &'b mut [u8; 7]) -> &'b [u8]793 fn get_alignment_pattern_positions<'b>(&self, resultbuf: &'b mut [u8; 7]) -> &'b [u8] {
794 let ver: u8 = self.version().value();
795 if ver == 1 {
796 &resultbuf[ .. 0]
797 } else {
798 let numalign: u8 = ver / 7 + 2;
799 let step: u8 = if ver == 32 { 26 } else
800 {(ver * 4 + numalign * 2 + 1) / (numalign * 2 - 2) * 2};
801 let result = &mut resultbuf[ .. usize::from(numalign)];
802 for i in 0 .. numalign-1 {
803 result[usize::from(i)] = *self.size - 7 - i * step;
804 }
805 *result.last_mut().unwrap() = 6;
806 result.reverse();
807 result
808 }
809 }
810
811
812 // Returns the number of data bits that can be stored in a QR Code of the given version number, after
813 // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
814 // 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) -> usize815 fn get_num_raw_data_modules(ver: Version) -> usize {
816 let ver = usize::from(ver.value());
817 let mut result: usize = (16 * ver + 128) * ver + 64;
818 if ver >= 2 {
819 let numalign: usize = ver / 7 + 2;
820 result -= (25 * numalign - 10) * numalign - 55;
821 if ver >= 7 {
822 result -= 36;
823 }
824 }
825 debug_assert!((208 ..= 29648).contains(&result));
826 result
827 }
828
829
830 // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
831 // QR Code of the given version number and error correction level, with remainder bits discarded.
832 // This stateless pure function could be implemented as a (40*4)-cell lookup table.
get_num_data_codewords(ver: Version, ecl: QrCodeEcc) -> usize833 fn get_num_data_codewords(ver: Version, ecl: QrCodeEcc) -> usize {
834 QrCode::get_num_raw_data_modules(ver) / 8
835 - QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK , ver, ecl)
836 * QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl)
837 }
838
839
840 // Returns an entry from the given table based on the given values.
table_get(table: &'static [[i8; 41]; 4], ver: Version, ecl: QrCodeEcc) -> usize841 fn table_get(table: &'static [[i8; 41]; 4], ver: Version, ecl: QrCodeEcc) -> usize {
842 table[ecl.ordinal()][usize::from(ver.value())] as usize
843 }
844
845 }
846
847
848 impl PartialEq for QrCode<'_> {
eq(&self, other: &QrCode<'_>) -> bool849 fn eq(&self, other: &QrCode<'_>) -> bool{
850 *self.size == *other.size &&
851 *self.modules == *other.modules
852 }
853 }
854
855 impl Eq for QrCode<'_> {}
856
857
858 /*---- Helper struct for add_ecc_and_interleave() ----*/
859
860 struct ReedSolomonGenerator {
861
862 // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
863 // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
864 divisor: [u8; 30],
865
866 // The degree of the divisor polynomial, in the range [1, 30].
867 degree: usize,
868
869 }
870
871
872 impl ReedSolomonGenerator {
873
874 // Creates a Reed-Solomon ECC generator polynomial for the given degree. This could be
875 // implemented as a lookup table over all possible parameter values, instead of as an algorithm.
new(degree: usize) -> Self876 fn new(degree: usize) -> Self {
877 let mut result = Self {
878 divisor: [0u8; 30],
879 degree: degree,
880 };
881 assert!((1 ..= result.divisor.len()).contains(°ree), "Degree out of range");
882 let divisor: &mut [u8] = &mut result.divisor[ .. degree];
883 divisor[degree - 1] = 1; // Start off with the monomial x^0
884
885 // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
886 // and drop the highest monomial term which is always 1x^degree.
887 // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
888 let mut root: u8 = 1;
889 for _ in 0 .. degree { // Unused variable i
890 // Multiply the current product by (x - r^i)
891 for j in 0 .. degree {
892 divisor[j] = Self::multiply(divisor[j], root);
893 if j + 1 < divisor.len() {
894 divisor[j] ^= divisor[j + 1];
895 }
896 }
897 root = Self::multiply(root, 0x02);
898 }
899 result
900 }
901
902
903 // Returns the Reed-Solomon error correction codeword for the given data polynomial and this divisor polynomial.
compute_remainder(&self, data: &[u8], result: &mut [u8])904 fn compute_remainder(&self, data: &[u8], result: &mut [u8]) {
905 assert_eq!(result.len(), self.degree);
906 result.fill(0);
907 for b in data { // Polynomial division
908 let factor: u8 = b ^ result[0];
909 result.copy_within(1 .. , 0);
910 result[result.len() - 1] = 0;
911 for (x, &y) in result.iter_mut().zip(self.divisor.iter()) {
912 *x ^= Self::multiply(y, factor);
913 }
914 }
915 }
916
917
918 // Returns the product of the two given field elements modulo GF(2^8/0x11D).
919 // All inputs are valid. This could be implemented as a 256*256 lookup table.
multiply(x: u8, y: u8) -> u8920 fn multiply(x: u8, y: u8) -> u8 {
921 // Russian peasant multiplication
922 let mut z: u8 = 0;
923 for i in (0 .. 8).rev() {
924 z = (z << 1) ^ ((z >> 7) * 0x1D);
925 z ^= ((y >> i) & 1) * x;
926 }
927 z
928 }
929
930 }
931
932
933 /*---- Helper struct for get_penalty_score() ----*/
934
935 struct FinderPenalty {
936 qr_size: i32,
937 run_history: [i32; 7],
938 }
939
940
941 impl FinderPenalty {
942
new(size: u8) -> Self943 pub fn new(size: u8) -> Self {
944 Self {
945 qr_size: i32::from(size),
946 run_history: [0; 7],
947 }
948 }
949
950
951 // Pushes the given value to the front and drops the last value.
add_history(&mut self, mut currentrunlength: i32)952 pub fn add_history(&mut self, mut currentrunlength: i32) {
953 if self.run_history[0] == 0 {
954 currentrunlength += self.qr_size; // Add light border to initial run
955 }
956 let len: usize = self.run_history.len();
957 self.run_history.copy_within(0 .. len-1, 1);
958 self.run_history[0] = currentrunlength;
959 }
960
961
962 // Can only be called immediately after a light run is added, and returns either 0, 1, or 2.
count_patterns(&self) -> i32963 pub fn count_patterns(&self) -> i32 {
964 let rh = &self.run_history;
965 let n = rh[1];
966 debug_assert!(n <= self.qr_size * 3);
967 let core = n > 0 && rh[2] == n && rh[3] == n * 3 && rh[4] == n && rh[5] == n;
968 ( i32::from(core && rh[0] >= n * 4 && rh[6] >= n)
969 + i32::from(core && rh[6] >= n * 4 && rh[0] >= n))
970 }
971
972
973 // Must be called at the end of a line (row or column) of modules.
terminate_and_count(mut self, currentruncolor: bool, mut currentrunlength: i32) -> i32974 pub fn terminate_and_count(mut self, currentruncolor: bool, mut currentrunlength: i32) -> i32 {
975 if currentruncolor { // Terminate dark run
976 self.add_history(currentrunlength);
977 currentrunlength = 0;
978 }
979 currentrunlength += self.qr_size; // Add light border to final run
980 self.add_history(currentrunlength);
981 self.count_patterns()
982 }
983
984 }
985
986
987 /*---- Constants and tables ----*/
988
989 // For use in get_penalty_score(), when evaluating which mask is best.
990 const PENALTY_N1: i32 = 3;
991 const PENALTY_N2: i32 = 3;
992 const PENALTY_N3: i32 = 40;
993 const PENALTY_N4: i32 = 10;
994
995
996 static ECC_CODEWORDS_PER_BLOCK: [[i8; 41]; 4] = [
997 // Version: (note that index 0 is for padding, and is set to an illegal value)
998 //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
999 [-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
1000 [-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
1001 [-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
1002 [-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
1003 ];
1004
1005 static NUM_ERROR_CORRECTION_BLOCKS: [[i8; 41]; 4] = [
1006 // Version: (note that index 0 is for padding, and is set to an illegal value)
1007 //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
1008 [-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
1009 [-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
1010 [-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
1011 [-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
1012 ];
1013
1014
1015
1016 /*---- QrCodeEcc functionality ----*/
1017
1018 /// The error correction level in a QR Code symbol.
1019 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
1020 pub enum QrCodeEcc {
1021 /// The QR Code can tolerate about 7% erroneous codewords.
1022 Low ,
1023 /// The QR Code can tolerate about 15% erroneous codewords.
1024 Medium ,
1025 /// The QR Code can tolerate about 25% erroneous codewords.
1026 Quartile,
1027 /// The QR Code can tolerate about 30% erroneous codewords.
1028 High ,
1029 }
1030
1031
1032 impl QrCodeEcc {
1033
1034 // Returns an unsigned 2-bit integer (in the range 0 to 3).
ordinal(self) -> usize1035 fn ordinal(self) -> usize {
1036 use QrCodeEcc::*;
1037 match self {
1038 Low => 0,
1039 Medium => 1,
1040 Quartile => 2,
1041 High => 3,
1042 }
1043 }
1044
1045
1046 // Returns an unsigned 2-bit integer (in the range 0 to 3).
format_bits(self) -> u81047 fn format_bits(self) -> u8 {
1048 use QrCodeEcc::*;
1049 match self {
1050 Low => 1,
1051 Medium => 0,
1052 Quartile => 3,
1053 High => 2,
1054 }
1055 }
1056
1057 }
1058
1059
1060
1061 /*---- QrSegment functionality ----*/
1062
1063 /// A segment of character/binary/control data in a QR Code symbol.
1064 ///
1065 /// Instances of this struct are immutable.
1066 ///
1067 /// The mid-level way to create a segment is to take the payload data
1068 /// and call a static factory function such as `QrSegment::make_numeric()`.
1069 /// The low-level way to create a segment is to custom-make the bit buffer
1070 /// and call the `QrSegment::new()` constructor with appropriate values.
1071 ///
1072 /// This segment struct imposes no length restrictions, but QR Codes have restrictions.
1073 /// Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
1074 /// Any segment longer than this is meaningless for the purpose of generating QR Codes.
1075 pub struct QrSegment<'a> {
1076
1077 // The mode indicator of this segment. Accessed through mode().
1078 mode: QrSegmentMode,
1079
1080 // The length of this segment's unencoded data. Measured in characters for
1081 // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
1082 // Not the same as the data's bit length. Accessed through num_chars().
1083 numchars: usize,
1084
1085 // The data bits of this segment, packed in bitwise big endian.
1086 data: &'a [u8],
1087
1088 // The number of valid data bits used in the buffer. Requires bitlength <= data.len() * 8.
1089 // The character count (numchars) must agree with the mode and the bit buffer length.
1090 bitlength: usize,
1091
1092 }
1093
1094
1095 impl<'a> QrSegment<'a> {
1096
1097 /*---- Static factory functions (mid level) ----*/
1098
1099 /// Returns a segment representing the given binary data encoded in byte mode.
1100 ///
1101 /// All input byte slices are acceptable.
1102 ///
1103 /// Any text string can be converted to UTF-8 bytes and encoded as a byte mode segment.
make_bytes(data: &'a [u8]) -> Self1104 pub fn make_bytes(data: &'a [u8]) -> Self {
1105 QrSegment::new(QrSegmentMode::Byte, data.len(), data, data.len().checked_mul(8).unwrap())
1106 }
1107
1108
1109 /// Returns a segment representing the given string of decimal digits encoded in numeric mode.
1110 ///
1111 /// Panics if the string contains non-digit characters.
make_numeric(text: &str, buf: &'a mut [u8]) -> Self1112 pub fn make_numeric(text: &str, buf: &'a mut [u8]) -> Self {
1113 let mut bb = BitBuffer::new(buf);
1114 let mut accumdata: u32 = 0;
1115 let mut accumcount: u8 = 0;
1116 for b in text.bytes() {
1117 assert!((b'0' ..= b'9').contains(&b), "String contains non-numeric characters");
1118 accumdata = accumdata * 10 + u32::from(b - b'0');
1119 accumcount += 1;
1120 if accumcount == 3 {
1121 bb.append_bits(accumdata, 10);
1122 accumdata = 0;
1123 accumcount = 0;
1124 }
1125 }
1126 if accumcount > 0 { // 1 or 2 digits remaining
1127 bb.append_bits(accumdata, accumcount * 3 + 1);
1128 }
1129 QrSegment::new(QrSegmentMode::Numeric, text.len(), bb.data, bb.length)
1130 }
1131
1132
1133 /// Returns a segment representing the given text string encoded in alphanumeric mode.
1134 ///
1135 /// The characters allowed are: 0 to 9, A to Z (uppercase only), space,
1136 /// dollar, percent, asterisk, plus, hyphen, period, slash, colon.
1137 ///
1138 /// Panics if the string contains non-encodable characters.
make_alphanumeric(text: &str, buf: &'a mut [u8]) -> Self1139 pub fn make_alphanumeric(text: &str, buf: &'a mut [u8]) -> Self {
1140 let mut bb = BitBuffer::new(buf);
1141 let mut accumdata: u32 = 0;
1142 let mut accumcount: u8 = 0;
1143 for c in text.chars() {
1144 let i: usize = ALPHANUMERIC_CHARSET.find(c)
1145 .expect("String contains unencodable characters in alphanumeric mode");
1146 accumdata = accumdata * 45 + u32::try_from(i).unwrap();
1147 accumcount += 1;
1148 if accumcount == 2 {
1149 bb.append_bits(accumdata, 11);
1150 accumdata = 0;
1151 accumcount = 0;
1152 }
1153 }
1154 if accumcount > 0 { // 1 character remaining
1155 bb.append_bits(accumdata, 6);
1156 }
1157 QrSegment::new(QrSegmentMode::Alphanumeric, text.len(), bb.data, bb.length)
1158 }
1159
1160
1161 /// Returns a segment representing an Extended Channel Interpretation
1162 /// (ECI) designator with the given assignment value.
make_eci(assignval: u32, buf: &'a mut [u8]) -> Self1163 pub fn make_eci(assignval: u32, buf: &'a mut [u8]) -> Self {
1164 let mut bb = BitBuffer::new(buf);
1165 if assignval < (1 << 7) {
1166 bb.append_bits(assignval, 8);
1167 } else if assignval < (1 << 14) {
1168 bb.append_bits(0b10, 2);
1169 bb.append_bits(assignval, 14);
1170 } else if assignval < 1_000_000 {
1171 bb.append_bits(0b110, 3);
1172 bb.append_bits(assignval, 21);
1173 } else {
1174 panic!("ECI assignment value out of range");
1175 }
1176 QrSegment::new(QrSegmentMode::Eci, 0, bb.data, bb.length)
1177 }
1178
1179
1180 /*---- Constructor (low level) ----*/
1181
1182 /// Creates a new QR Code segment with the given attributes and data.
1183 ///
1184 /// The character count (numchars) must agree with the mode and
1185 /// the bit buffer length, but the constraint isn't checked.
new(mode: QrSegmentMode, numchars: usize, data: &'a [u8], bitlength: usize) -> Self1186 pub fn new(mode: QrSegmentMode, numchars: usize, data: &'a [u8], bitlength: usize) -> Self {
1187 assert!(bitlength == 0 || (bitlength - 1) / 8 < data.len());
1188 Self { mode, numchars, data, bitlength }
1189 }
1190
1191
1192 /*---- Instance field getters ----*/
1193
1194 /// Returns the mode indicator of this segment.
mode(&self) -> QrSegmentMode1195 pub fn mode(&self) -> QrSegmentMode {
1196 self.mode
1197 }
1198
1199
1200 /// Returns the character count field of this segment.
num_chars(&self) -> usize1201 pub fn num_chars(&self) -> usize {
1202 self.numchars
1203 }
1204
1205
1206 /*---- Other static functions ----*/
1207
1208 /// Returns the number of bytes needed for the data buffer of a segment
1209 /// containing the given number of characters using the given mode, or None if the
1210 /// internal calculation of the number of needed bits exceeds usize::MAX. Notes:
1211 ///
1212 /// - It is okay for the user to allocate more bytes for the buffer than needed.
1213 /// - For byte mode, numchars measures the number of bytes, not Unicode code points.
1214 /// - For ECI mode, numchars must be 0, and the worst-case number of bytes is returned.
1215 /// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
calc_buffer_size(mode: QrSegmentMode, numchars: usize) -> Option<usize>1216 pub fn calc_buffer_size(mode: QrSegmentMode, numchars: usize) -> Option<usize> {
1217 let temp = Self::calc_bit_length(mode, numchars)?;
1218 Some(temp / 8 + usize::from(temp % 8 != 0)) // ceil(temp / 8)
1219 }
1220
1221
1222 // Returns the number of data bits needed to represent a segment
1223 // containing the given number of characters using the given mode,
1224 // or None if the the number of needed bits exceeds usize::MAX. Notes:
1225 // - For byte mode, numchars measures the number of bytes, not Unicode code points.
1226 // - For ECI mode, numchars must be 0, and the worst-case number of bits is returned.
1227 // An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
calc_bit_length(mode: QrSegmentMode, numchars: usize) -> Option<usize>1228 fn calc_bit_length(mode: QrSegmentMode, numchars: usize) -> Option<usize> {
1229 // Returns ceil((numer / denom) * numchars)
1230 let mul_frac_ceil = |numer: usize, denom: usize|
1231 Some(numchars)
1232 .and_then(|x| x.checked_mul(numer))
1233 .and_then(|x| x.checked_add(denom - 1))
1234 .map(|x| x / denom);
1235
1236 use QrSegmentMode::*;
1237 match mode {
1238 Numeric => mul_frac_ceil(10, 3),
1239 Alphanumeric => mul_frac_ceil(11, 2),
1240 Byte => mul_frac_ceil( 8, 1),
1241 Kanji => mul_frac_ceil(13, 1),
1242 Eci => {
1243 assert_eq!(numchars, 0);
1244 Some(3 * 8)
1245 },
1246 }
1247 }
1248
1249
1250 // Calculates and returns the number of bits needed to encode the given
1251 // segments at the given version. The result is None if a segment has too many
1252 // characters to fit its length field, or the total bits exceeds usize::MAX.
get_total_bits(segs: &[Self], version: Version) -> Option<usize>1253 fn get_total_bits(segs: &[Self], version: Version) -> Option<usize> {
1254 let mut result: usize = 0;
1255 for seg in segs {
1256 let ccbits: u8 = seg.mode.num_char_count_bits(version);
1257 // ccbits can be as large as 16, but usize can be as small as 16
1258 if let Some(limit) = 1usize.checked_shl(ccbits.into()) {
1259 if seg.numchars >= limit {
1260 return None; // The segment's length doesn't fit the field's bit width
1261 }
1262 }
1263 result = result.checked_add(4 + usize::from(ccbits))?;
1264 result = result.checked_add(seg.bitlength)?;
1265 }
1266 Some(result)
1267 }
1268
1269
1270 /// Tests whether the given string can be encoded as a segment in numeric mode.
1271 /// A string is encodable iff each character is in the range 0 to 9.
is_numeric(text: &str) -> bool1272 pub fn is_numeric(text: &str) -> bool {
1273 text.chars().all(|c| ('0' ..= '9').contains(&c))
1274 }
1275
1276
1277 /// Tests whether the given string can be encoded as a segment in alphanumeric mode.
1278 /// A string is encodable iff each character is in the following set: 0 to 9, A to Z
1279 /// (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
is_alphanumeric(text: &str) -> bool1280 pub fn is_alphanumeric(text: &str) -> bool {
1281 text.chars().all(|c| ALPHANUMERIC_CHARSET.contains(c))
1282 }
1283
1284 }
1285
1286
1287 // The set of all legal characters in alphanumeric mode,
1288 // where each character value maps to the index in the string.
1289 static ALPHANUMERIC_CHARSET: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
1290
1291
1292
1293 /*---- QrSegmentMode functionality ----*/
1294
1295 /// Describes how a segment's data bits are interpreted.
1296 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
1297 pub enum QrSegmentMode {
1298 Numeric,
1299 Alphanumeric,
1300 Byte,
1301 Kanji,
1302 Eci,
1303 }
1304
1305
1306 impl QrSegmentMode {
1307
1308 // Returns an unsigned 4-bit integer value (range 0 to 15)
1309 // representing the mode indicator bits for this mode object.
mode_bits(self) -> u321310 fn mode_bits(self) -> u32 {
1311 use QrSegmentMode::*;
1312 match self {
1313 Numeric => 0x1,
1314 Alphanumeric => 0x2,
1315 Byte => 0x4,
1316 Kanji => 0x8,
1317 Eci => 0x7,
1318 }
1319 }
1320
1321
1322 // Returns the bit width of the character count field for a segment in this mode
1323 // in a QR Code at the given version number. The result is in the range [0, 16].
num_char_count_bits(self, ver: Version) -> u81324 fn num_char_count_bits(self, ver: Version) -> u8 {
1325 use QrSegmentMode::*;
1326 (match self {
1327 Numeric => [10, 12, 14],
1328 Alphanumeric => [ 9, 11, 13],
1329 Byte => [ 8, 16, 16],
1330 Kanji => [ 8, 10, 12],
1331 Eci => [ 0, 0, 0],
1332 })[usize::from((ver.value() + 7) / 17)]
1333 }
1334
1335 }
1336
1337
1338 /*---- BitBuffer functionality ----*/
1339
1340 /// An appendable sequence of bits (0s and 1s).
1341 ///
1342 /// Mainly used by QrSegment.
1343 pub struct BitBuffer<'a> {
1344
1345 data: &'a mut [u8],
1346
1347 length: usize,
1348
1349 }
1350
1351
1352 impl<'a> BitBuffer<'a> {
1353
1354 // Creates a bit buffer based on the given byte array.
new(buffer: &'a mut [u8]) -> Self1355 pub fn new(buffer: &'a mut [u8]) -> Self {
1356 Self {
1357 data: buffer,
1358 length: 0,
1359 }
1360 }
1361
1362
1363 // Returns the length of this bit buffer, in bits.
len(&self) -> usize1364 pub fn len(&self) -> usize {
1365 self.length
1366 }
1367
1368
1369 // Appends the given number of low-order bits of the given value to this byte-based
1370 // bit buffer, increasing the bit length. Requires 0 <= numBits <= 31 and val < 2^numBits.
append_bits(&mut self, val: u32, len: u8)1371 pub fn append_bits(&mut self, val: u32, len: u8) {
1372 assert!(len <= 31 && val >> len == 0);
1373 assert!(usize::from(len) <= usize::MAX - self.length);
1374 for i in (0 .. len).rev() {
1375 let index: usize = self.length >> 3;
1376 let shift: u8 = 7 - ((self.length as u8) & 7);
1377 let bit: u8 = ((val >> i) as u8) & 1;
1378 if shift == 7 {
1379 self.data[index] = bit << shift;
1380 } else {
1381 self.data[index] |= bit << shift;
1382 }
1383 self.length += 1;
1384 }
1385 }
1386
1387 }
1388
1389
1390
1391 /*---- Miscellaneous values ----*/
1392
1393 /// The error type when the supplied data does not fit any QR Code version.
1394 ///
1395 /// Ways to handle this exception include:
1396 ///
1397 /// - Decrease the error correction level if it was greater than `QrCodeEcc::Low`.
1398 /// - Increase the maxversion argument if it was less than `Version::MAX`.
1399 /// - Split the text data into better or optimal segments in order to reduce the number of bits required.
1400 /// - Change the text or binary data to be shorter.
1401 /// - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric).
1402 /// - Propagate the error upward to the caller/user.
1403 #[derive(Debug, Clone)]
1404 pub enum DataTooLong {
1405 SegmentTooLong,
1406 DataOverCapacity(usize, usize),
1407 }
1408
1409 impl core::fmt::Display for DataTooLong {
fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result1410 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1411 match *self {
1412 Self::SegmentTooLong => write!(f, "Segment too long"),
1413 Self::DataOverCapacity(datalen, maxcapacity) =>
1414 write!(f, "Data length = {} bits, Max capacity = {} bits", datalen, maxcapacity),
1415 }
1416 }
1417 }
1418
1419
1420 /// A number between 1 and 40 (inclusive).
1421 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1422 pub struct Version(u8);
1423
1424 impl Version {
1425 /// The minimum version number supported in the QR Code Model 2 standard.
1426 pub const MIN: Version = Version( 1);
1427
1428 /// The maximum version number supported in the QR Code Model 2 standard.
1429 pub const MAX: Version = Version(40);
1430
1431 /// Creates a version object from the given number.
1432 ///
1433 /// Panics if the number is outside the range [1, 40].
new(ver: u8) -> Self1434 pub fn new(ver: u8) -> Self {
1435 assert!((Version::MIN.value() ..= Version::MAX.value()).contains(&ver), "Version number out of range");
1436 Self(ver)
1437 }
1438
1439 /// Returns the value, which is in the range [1, 40].
value(self) -> u81440 pub fn value(self) -> u8 {
1441 self.0
1442 }
1443
1444 /// Returns the minimum length required for the output and temporary
1445 /// buffers when creating a QR Code of this version number.
buffer_len(self) -> usize1446 pub const fn buffer_len(self) -> usize {
1447 let sidelen = (self.0 as usize) * 4 + 17;
1448 (sidelen * sidelen + 7) / 8 + 1
1449 }
1450 }
1451
1452
1453 /// A number between 0 and 7 (inclusive).
1454 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1455 pub struct Mask(u8);
1456
1457 impl Mask {
1458 /// Creates a mask object from the given number.
1459 ///
1460 /// Panics if the number is outside the range [0, 7].
new(mask: u8) -> Self1461 pub fn new(mask: u8) -> Self {
1462 assert!(mask <= 7, "Mask value out of range");
1463 Self(mask)
1464 }
1465
1466 /// Returns the value, which is in the range [0, 7].
value(self) -> u81467 pub fn value(self) -> u8 {
1468 self.0
1469 }
1470 }
1471
1472
1473 // Returns true iff the i'th bit of x is set to 1.
get_bit(x: u32, i: u8) -> bool1474 fn get_bit(x: u32, i: u8) -> bool {
1475 (x >> i) & 1 != 0
1476 }
1477