15317bbafSopenharmony_ci/*
25317bbafSopenharmony_ci * QR Code generator library (Rust)
35317bbafSopenharmony_ci *
45317bbafSopenharmony_ci * Copyright (c) Project Nayuki. (MIT License)
55317bbafSopenharmony_ci * https://www.nayuki.io/page/qr-code-generator-library
65317bbafSopenharmony_ci *
75317bbafSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy of
85317bbafSopenharmony_ci * this software and associated documentation files (the "Software"), to deal in
95317bbafSopenharmony_ci * the Software without restriction, including without limitation the rights to
105317bbafSopenharmony_ci * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
115317bbafSopenharmony_ci * the Software, and to permit persons to whom the Software is furnished to do so,
125317bbafSopenharmony_ci * subject to the following conditions:
135317bbafSopenharmony_ci * - The above copyright notice and this permission notice shall be included in
145317bbafSopenharmony_ci *   all copies or substantial portions of the Software.
155317bbafSopenharmony_ci * - The Software is provided "as is", without warranty of any kind, express or
165317bbafSopenharmony_ci *   implied, including but not limited to the warranties of merchantability,
175317bbafSopenharmony_ci *   fitness for a particular purpose and noninfringement. In no event shall the
185317bbafSopenharmony_ci *   authors or copyright holders be liable for any claim, damages or other
195317bbafSopenharmony_ci *   liability, whether in an action of contract, tort or otherwise, arising from,
205317bbafSopenharmony_ci *   out of or in connection with the Software or the use or other dealings in the
215317bbafSopenharmony_ci *   Software.
225317bbafSopenharmony_ci */
235317bbafSopenharmony_ci
245317bbafSopenharmony_ci
255317bbafSopenharmony_ci//! Generates QR Codes from text strings and byte arrays.
265317bbafSopenharmony_ci//!
275317bbafSopenharmony_ci//! This project aims to be the best, clearest QR Code generator library.
285317bbafSopenharmony_ci//! The primary goals are flexible options and absolute correctness.
295317bbafSopenharmony_ci//! Secondary goals are compact implementation size and good documentation comments.
305317bbafSopenharmony_ci//!
315317bbafSopenharmony_ci//! Home page with live JavaScript demo, extensive descriptions, and competitor comparisons:
325317bbafSopenharmony_ci//! [https://www.nayuki.io/page/qr-code-generator-library](https://www.nayuki.io/page/qr-code-generator-library)
335317bbafSopenharmony_ci//!
345317bbafSopenharmony_ci//! # Features
355317bbafSopenharmony_ci//!
365317bbafSopenharmony_ci//! Core features:
375317bbafSopenharmony_ci//!
385317bbafSopenharmony_ci//! - Significantly shorter code but more documentation comments compared to competing libraries
395317bbafSopenharmony_ci//! - Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard
405317bbafSopenharmony_ci//! - Output format: Raw modules/pixels of the QR symbol
415317bbafSopenharmony_ci//! - Detects finder-like penalty patterns more accurately than other implementations
425317bbafSopenharmony_ci//! - Encodes numeric and special-alphanumeric text in less space than general text
435317bbafSopenharmony_ci//! - Open-source code under the permissive MIT License
445317bbafSopenharmony_ci//!
455317bbafSopenharmony_ci//! Manual parameters:
465317bbafSopenharmony_ci//!
475317bbafSopenharmony_ci//! - User can specify minimum and maximum version numbers allowed, then library will automatically choose smallest version in the range that fits the data
485317bbafSopenharmony_ci//! - User can specify mask pattern manually, otherwise library will automatically evaluate all 8 masks and select the optimal one
495317bbafSopenharmony_ci//! - User can specify absolute error correction level, or allow the library to boost it if it doesn't increase the version number
505317bbafSopenharmony_ci//! - User can create a list of data segments manually and add ECI segments
515317bbafSopenharmony_ci//!
525317bbafSopenharmony_ci//! More information about QR Code technology and this library's design can be found on the project home page.
535317bbafSopenharmony_ci//!
545317bbafSopenharmony_ci//! # Examples
555317bbafSopenharmony_ci//!
565317bbafSopenharmony_ci//! ```
575317bbafSopenharmony_ci//! extern crate qrcodegen;
585317bbafSopenharmony_ci//! use qrcodegen::Mask;
595317bbafSopenharmony_ci//! use qrcodegen::QrCode;
605317bbafSopenharmony_ci//! use qrcodegen::QrCodeEcc;
615317bbafSopenharmony_ci//! use qrcodegen::QrSegment;
625317bbafSopenharmony_ci//! use qrcodegen::Version;
635317bbafSopenharmony_ci//! ```
645317bbafSopenharmony_ci//!
655317bbafSopenharmony_ci//! Simple operation:
665317bbafSopenharmony_ci//!
675317bbafSopenharmony_ci//! ```
685317bbafSopenharmony_ci//! let qr = QrCode::encode_text("Hello, world!",
695317bbafSopenharmony_ci//!     QrCodeEcc::Medium).unwrap();
705317bbafSopenharmony_ci//! let svg = to_svg_string(&qr, 4);  // See qrcodegen-demo
715317bbafSopenharmony_ci//! ```
725317bbafSopenharmony_ci//!
735317bbafSopenharmony_ci//! Manual operation:
745317bbafSopenharmony_ci//!
755317bbafSopenharmony_ci//! ```
765317bbafSopenharmony_ci//! let text: &str = "3141592653589793238462643383";
775317bbafSopenharmony_ci//! let segs = QrSegment::make_segments(text);
785317bbafSopenharmony_ci//! let qr = QrCode::encode_segments_advanced(&segs, QrCodeEcc::High,
795317bbafSopenharmony_ci//!     Version::new(5), Version::new(5), Some(Mask::new(2)), false).unwrap();
805317bbafSopenharmony_ci//! for y in 0 .. qr.size() {
815317bbafSopenharmony_ci//!     for x in 0 .. qr.size() {
825317bbafSopenharmony_ci//!         (... paint qr.get_module(x, y) ...)
835317bbafSopenharmony_ci//!     }
845317bbafSopenharmony_ci//! }
855317bbafSopenharmony_ci//! ```
865317bbafSopenharmony_ci
875317bbafSopenharmony_ci
885317bbafSopenharmony_ci#![forbid(unsafe_code)]
895317bbafSopenharmony_ciuse std::convert::TryFrom;
905317bbafSopenharmony_ci
915317bbafSopenharmony_ci
925317bbafSopenharmony_ci/*---- QrCode functionality ----*/
935317bbafSopenharmony_ci
945317bbafSopenharmony_ci/// A QR Code symbol, which is a type of two-dimension barcode.
955317bbafSopenharmony_ci///
965317bbafSopenharmony_ci/// Invented by Denso Wave and described in the ISO/IEC 18004 standard.
975317bbafSopenharmony_ci///
985317bbafSopenharmony_ci/// Instances of this struct represent an immutable square grid of dark and light cells.
995317bbafSopenharmony_ci/// The impl provides static factory functions to create a QR Code from text or binary data.
1005317bbafSopenharmony_ci/// The struct and impl cover the QR Code Model 2 specification, supporting all versions
1015317bbafSopenharmony_ci/// (sizes) from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
1025317bbafSopenharmony_ci///
1035317bbafSopenharmony_ci/// Ways to create a QR Code object:
1045317bbafSopenharmony_ci///
1055317bbafSopenharmony_ci/// - High level: Take the payload data and call `QrCode::encode_text()` or `QrCode::encode_binary()`.
1065317bbafSopenharmony_ci/// - Mid level: Custom-make the list of segments and call
1075317bbafSopenharmony_ci///   `QrCode::encode_segments()` or `QrCode::encode_segments_advanced()`.
1085317bbafSopenharmony_ci/// - Low level: Custom-make the array of data codeword bytes (including segment
1095317bbafSopenharmony_ci///   headers and final padding, excluding error correction codewords), supply the
1105317bbafSopenharmony_ci///   appropriate version number, and call the `QrCode::encode_codewords()` constructor.
1115317bbafSopenharmony_ci///
1125317bbafSopenharmony_ci/// (Note that all ways require supplying the desired error correction level.)
1135317bbafSopenharmony_ci#[derive(Clone, PartialEq, Eq)]
1145317bbafSopenharmony_cipub struct QrCode {
1155317bbafSopenharmony_ci
1165317bbafSopenharmony_ci	// Scalar parameters:
1175317bbafSopenharmony_ci
1185317bbafSopenharmony_ci	// The version number of this QR Code, which is between 1 and 40 (inclusive).
1195317bbafSopenharmony_ci	// This determines the size of this barcode.
1205317bbafSopenharmony_ci	version: Version,
1215317bbafSopenharmony_ci
1225317bbafSopenharmony_ci	// The width and height of this QR Code, measured in modules, between
1235317bbafSopenharmony_ci	// 21 and 177 (inclusive). This is equal to version * 4 + 17.
1245317bbafSopenharmony_ci	size: i32,
1255317bbafSopenharmony_ci
1265317bbafSopenharmony_ci	// The error correction level used in this QR Code.
1275317bbafSopenharmony_ci	errorcorrectionlevel: QrCodeEcc,
1285317bbafSopenharmony_ci
1295317bbafSopenharmony_ci	// The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
1305317bbafSopenharmony_ci	// Even if a QR Code is created with automatic masking requested (mask = None),
1315317bbafSopenharmony_ci	// the resulting object still has a mask value between 0 and 7.
1325317bbafSopenharmony_ci	mask: Mask,
1335317bbafSopenharmony_ci
1345317bbafSopenharmony_ci	// Grids of modules/pixels, with dimensions of size*size:
1355317bbafSopenharmony_ci
1365317bbafSopenharmony_ci	// The modules of this QR Code (false = light, true = dark).
1375317bbafSopenharmony_ci	// Immutable after constructor finishes. Accessed through get_module().
1385317bbafSopenharmony_ci	modules: Vec<bool>,
1395317bbafSopenharmony_ci
1405317bbafSopenharmony_ci	// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
1415317bbafSopenharmony_ci	isfunction: Vec<bool>,
1425317bbafSopenharmony_ci
1435317bbafSopenharmony_ci}
1445317bbafSopenharmony_ci
1455317bbafSopenharmony_ci
1465317bbafSopenharmony_ciimpl QrCode {
1475317bbafSopenharmony_ci
1485317bbafSopenharmony_ci	/*---- Static factory functions (high level) ----*/
1495317bbafSopenharmony_ci
1505317bbafSopenharmony_ci	/// Returns a QR Code representing the given Unicode text string at the given error correction level.
1515317bbafSopenharmony_ci	///
1525317bbafSopenharmony_ci	/// As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer Unicode
1535317bbafSopenharmony_ci	/// code points (not UTF-8 code units) if the low error correction level is used. The smallest possible
1545317bbafSopenharmony_ci	/// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
1555317bbafSopenharmony_ci	/// the ecl argument if it can be done without increasing the version.
1565317bbafSopenharmony_ci	///
1575317bbafSopenharmony_ci	/// Returns a wrapped `QrCode` if successful, or `Err` if the
1585317bbafSopenharmony_ci	/// data is too long to fit in any version at the given ECC level.
1595317bbafSopenharmony_ci	pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
1605317bbafSopenharmony_ci		let segs: Vec<QrSegment> = QrSegment::make_segments(text);
1615317bbafSopenharmony_ci		QrCode::encode_segments(&segs, ecl)
1625317bbafSopenharmony_ci	}
1635317bbafSopenharmony_ci
1645317bbafSopenharmony_ci
1655317bbafSopenharmony_ci	/// Returns a QR Code representing the given binary data at the given error correction level.
1665317bbafSopenharmony_ci	///
1675317bbafSopenharmony_ci	/// This function always encodes using the binary segment mode, not any text mode. The maximum number of
1685317bbafSopenharmony_ci	/// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
1695317bbafSopenharmony_ci	/// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
1705317bbafSopenharmony_ci	///
1715317bbafSopenharmony_ci	/// Returns a wrapped `QrCode` if successful, or `Err` if the
1725317bbafSopenharmony_ci	/// data is too long to fit in any version at the given ECC level.
1735317bbafSopenharmony_ci	pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
1745317bbafSopenharmony_ci		let segs: [QrSegment; 1] = [QrSegment::make_bytes(data)];
1755317bbafSopenharmony_ci		QrCode::encode_segments(&segs, ecl)
1765317bbafSopenharmony_ci	}
1775317bbafSopenharmony_ci
1785317bbafSopenharmony_ci
1795317bbafSopenharmony_ci	/*---- Static factory functions (mid level) ----*/
1805317bbafSopenharmony_ci
1815317bbafSopenharmony_ci	/// Returns a QR Code representing the given segments at the given error correction level.
1825317bbafSopenharmony_ci	///
1835317bbafSopenharmony_ci	/// The smallest possible QR Code version is automatically chosen for the output. The ECC level
1845317bbafSopenharmony_ci	/// of the result may be higher than the ecl argument if it can be done without increasing the version.
1855317bbafSopenharmony_ci	///
1865317bbafSopenharmony_ci	/// This function allows the user to create a custom sequence of segments that switches
1875317bbafSopenharmony_ci	/// between modes (such as alphanumeric and byte) to encode text in less space.
1885317bbafSopenharmony_ci	/// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
1895317bbafSopenharmony_ci	///
1905317bbafSopenharmony_ci	/// Returns a wrapped `QrCode` if successful, or `Err` if the
1915317bbafSopenharmony_ci	/// data is too long to fit in any version at the given ECC level.
1925317bbafSopenharmony_ci	pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
1935317bbafSopenharmony_ci		QrCode::encode_segments_advanced(segs, ecl, Version::MIN, Version::MAX, None, true)
1945317bbafSopenharmony_ci	}
1955317bbafSopenharmony_ci
1965317bbafSopenharmony_ci
1975317bbafSopenharmony_ci	/// Returns a QR Code representing the given segments with the given encoding parameters.
1985317bbafSopenharmony_ci	///
1995317bbafSopenharmony_ci	/// The smallest possible QR Code version within the given range is automatically
2005317bbafSopenharmony_ci	/// chosen for the output. Iff boostecl is `true`, then the ECC level of the result
2015317bbafSopenharmony_ci	/// may be higher than the ecl argument if it can be done without increasing the
2025317bbafSopenharmony_ci	/// version. The mask number is either between 0 to 7 (inclusive) to force that
2035317bbafSopenharmony_ci	/// mask, or `None` to automatically choose an appropriate mask (which may be slow).
2045317bbafSopenharmony_ci	///
2055317bbafSopenharmony_ci	/// This function allows the user to create a custom sequence of segments that switches
2065317bbafSopenharmony_ci	/// between modes (such as alphanumeric and byte) to encode text in less space.
2075317bbafSopenharmony_ci	/// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
2085317bbafSopenharmony_ci	///
2095317bbafSopenharmony_ci	/// Returns a wrapped `QrCode` if successful, or `Err` if the data is too
2105317bbafSopenharmony_ci	/// long to fit in any version in the given range at the given ECC level.
2115317bbafSopenharmony_ci	pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
2125317bbafSopenharmony_ci			minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool)
2135317bbafSopenharmony_ci			-> Result<Self,DataTooLong> {
2145317bbafSopenharmony_ci
2155317bbafSopenharmony_ci		assert!(minversion <= maxversion, "Invalid value");
2165317bbafSopenharmony_ci
2175317bbafSopenharmony_ci		// Find the minimal version number to use
2185317bbafSopenharmony_ci		let mut version: Version = minversion;
2195317bbafSopenharmony_ci		let datausedbits: usize = loop {
2205317bbafSopenharmony_ci			let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;  // Number of data bits available
2215317bbafSopenharmony_ci			let dataused: Option<usize> = QrSegment::get_total_bits(segs, version);
2225317bbafSopenharmony_ci			if dataused.map_or(false, |n| n <= datacapacitybits) {
2235317bbafSopenharmony_ci				break dataused.unwrap();  // This version number is found to be suitable
2245317bbafSopenharmony_ci			} else if version >= maxversion {  // All versions in the range could not fit the given data
2255317bbafSopenharmony_ci				return Err(match dataused {
2265317bbafSopenharmony_ci					None => DataTooLong::SegmentTooLong,
2275317bbafSopenharmony_ci					Some(n) => DataTooLong::DataOverCapacity(n, datacapacitybits),
2285317bbafSopenharmony_ci				});
2295317bbafSopenharmony_ci			} else {
2305317bbafSopenharmony_ci				version = Version::new(version.value() + 1);
2315317bbafSopenharmony_ci			}
2325317bbafSopenharmony_ci		};
2335317bbafSopenharmony_ci
2345317bbafSopenharmony_ci		// Increase the error correction level while the data still fits in the current version number
2355317bbafSopenharmony_ci		for &newecl in &[QrCodeEcc::Medium, QrCodeEcc::Quartile, QrCodeEcc::High] {  // From low to high
2365317bbafSopenharmony_ci			if boostecl && datausedbits <= QrCode::get_num_data_codewords(version, newecl) * 8 {
2375317bbafSopenharmony_ci				ecl = newecl;
2385317bbafSopenharmony_ci			}
2395317bbafSopenharmony_ci		}
2405317bbafSopenharmony_ci
2415317bbafSopenharmony_ci		// Concatenate all segments to create the data bit string
2425317bbafSopenharmony_ci		let mut bb = BitBuffer(Vec::new());
2435317bbafSopenharmony_ci		for seg in segs {
2445317bbafSopenharmony_ci			bb.append_bits(seg.mode.mode_bits(), 4);
2455317bbafSopenharmony_ci			bb.append_bits(u32::try_from(seg.numchars).unwrap(), seg.mode.num_char_count_bits(version));
2465317bbafSopenharmony_ci			bb.0.extend_from_slice(&seg.data);
2475317bbafSopenharmony_ci		}
2485317bbafSopenharmony_ci		debug_assert_eq!(bb.0.len(), datausedbits);
2495317bbafSopenharmony_ci
2505317bbafSopenharmony_ci		// Add terminator and pad up to a byte if applicable
2515317bbafSopenharmony_ci		let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;
2525317bbafSopenharmony_ci		debug_assert!(bb.0.len() <= datacapacitybits);
2535317bbafSopenharmony_ci		let numzerobits: usize = std::cmp::min(4, datacapacitybits - bb.0.len());
2545317bbafSopenharmony_ci		bb.append_bits(0, u8::try_from(numzerobits).unwrap());
2555317bbafSopenharmony_ci		let numzerobits: usize = bb.0.len().wrapping_neg() & 7;
2565317bbafSopenharmony_ci		bb.append_bits(0, u8::try_from(numzerobits).unwrap());
2575317bbafSopenharmony_ci		debug_assert_eq!(bb.0.len() % 8, 0);
2585317bbafSopenharmony_ci
2595317bbafSopenharmony_ci		// Pad with alternating bytes until data capacity is reached
2605317bbafSopenharmony_ci		for &padbyte in [0xEC, 0x11].iter().cycle() {
2615317bbafSopenharmony_ci			if bb.0.len() >= datacapacitybits {
2625317bbafSopenharmony_ci				break;
2635317bbafSopenharmony_ci			}
2645317bbafSopenharmony_ci			bb.append_bits(padbyte, 8);
2655317bbafSopenharmony_ci		}
2665317bbafSopenharmony_ci
2675317bbafSopenharmony_ci		// Pack bits into bytes in big endian
2685317bbafSopenharmony_ci		let mut datacodewords = vec![0u8; bb.0.len() / 8];
2695317bbafSopenharmony_ci		for (i, &bit) in bb.0.iter().enumerate() {
2705317bbafSopenharmony_ci			datacodewords[i >> 3] |= u8::from(bit) << (7 - (i & 7));
2715317bbafSopenharmony_ci		}
2725317bbafSopenharmony_ci
2735317bbafSopenharmony_ci		// Create the QR Code object
2745317bbafSopenharmony_ci		Ok(QrCode::encode_codewords(version, ecl, &datacodewords, mask))
2755317bbafSopenharmony_ci	}
2765317bbafSopenharmony_ci
2775317bbafSopenharmony_ci
2785317bbafSopenharmony_ci	/*---- Constructor (low level) ----*/
2795317bbafSopenharmony_ci
2805317bbafSopenharmony_ci	/// Creates a new QR Code with the given version number,
2815317bbafSopenharmony_ci	/// error correction level, data codeword bytes, and mask number.
2825317bbafSopenharmony_ci	///
2835317bbafSopenharmony_ci	/// This is a low-level API that most users should not use directly.
2845317bbafSopenharmony_ci	/// A mid-level API is the `encode_segments()` function.
2855317bbafSopenharmony_ci	pub fn encode_codewords(ver: Version, ecl: QrCodeEcc, datacodewords: &[u8], mut msk: Option<Mask>) -> Self {
2865317bbafSopenharmony_ci		// Initialize fields
2875317bbafSopenharmony_ci		let size = usize::from(ver.value()) * 4 + 17;
2885317bbafSopenharmony_ci		let mut result = Self {
2895317bbafSopenharmony_ci			version: ver,
2905317bbafSopenharmony_ci			size: size as i32,
2915317bbafSopenharmony_ci			mask: Mask::new(0),  // Dummy value
2925317bbafSopenharmony_ci			errorcorrectionlevel: ecl,
2935317bbafSopenharmony_ci			modules   : vec![false; size * size],  // Initially all light
2945317bbafSopenharmony_ci			isfunction: vec![false; size * size],
2955317bbafSopenharmony_ci		};
2965317bbafSopenharmony_ci
2975317bbafSopenharmony_ci		// Compute ECC, draw modules
2985317bbafSopenharmony_ci		result.draw_function_patterns();
2995317bbafSopenharmony_ci		let allcodewords: Vec<u8> = result.add_ecc_and_interleave(datacodewords);
3005317bbafSopenharmony_ci		result.draw_codewords(&allcodewords);
3015317bbafSopenharmony_ci
3025317bbafSopenharmony_ci		// Do masking
3035317bbafSopenharmony_ci		if msk.is_none() {  // Automatically choose best mask
3045317bbafSopenharmony_ci			let mut minpenalty = std::i32::MAX;
3055317bbafSopenharmony_ci			for i in 0u8 .. 8 {
3065317bbafSopenharmony_ci				let i = Mask::new(i);
3075317bbafSopenharmony_ci				result.apply_mask(i);
3085317bbafSopenharmony_ci				result.draw_format_bits(i);
3095317bbafSopenharmony_ci				let penalty: i32 = result.get_penalty_score();
3105317bbafSopenharmony_ci				if penalty < minpenalty {
3115317bbafSopenharmony_ci					msk = Some(i);
3125317bbafSopenharmony_ci					minpenalty = penalty;
3135317bbafSopenharmony_ci				}
3145317bbafSopenharmony_ci				result.apply_mask(i);  // Undoes the mask due to XOR
3155317bbafSopenharmony_ci			}
3165317bbafSopenharmony_ci		}
3175317bbafSopenharmony_ci		let msk: Mask = msk.unwrap();
3185317bbafSopenharmony_ci		result.mask = msk;
3195317bbafSopenharmony_ci		result.apply_mask(msk);  // Apply the final choice of mask
3205317bbafSopenharmony_ci		result.draw_format_bits(msk);  // Overwrite old format bits
3215317bbafSopenharmony_ci
3225317bbafSopenharmony_ci		result.isfunction.clear();
3235317bbafSopenharmony_ci		result.isfunction.shrink_to_fit();
3245317bbafSopenharmony_ci		result
3255317bbafSopenharmony_ci	}
3265317bbafSopenharmony_ci
3275317bbafSopenharmony_ci
3285317bbafSopenharmony_ci	/*---- Public methods ----*/
3295317bbafSopenharmony_ci
3305317bbafSopenharmony_ci	/// Returns this QR Code's version, in the range [1, 40].
3315317bbafSopenharmony_ci	pub fn version(&self) -> Version {
3325317bbafSopenharmony_ci		self.version
3335317bbafSopenharmony_ci	}
3345317bbafSopenharmony_ci
3355317bbafSopenharmony_ci
3365317bbafSopenharmony_ci	/// Returns this QR Code's size, in the range [21, 177].
3375317bbafSopenharmony_ci	pub fn size(&self) -> i32 {
3385317bbafSopenharmony_ci		self.size
3395317bbafSopenharmony_ci	}
3405317bbafSopenharmony_ci
3415317bbafSopenharmony_ci
3425317bbafSopenharmony_ci	/// Returns this QR Code's error correction level.
3435317bbafSopenharmony_ci	pub fn error_correction_level(&self) -> QrCodeEcc {
3445317bbafSopenharmony_ci		self.errorcorrectionlevel
3455317bbafSopenharmony_ci	}
3465317bbafSopenharmony_ci
3475317bbafSopenharmony_ci
3485317bbafSopenharmony_ci	/// Returns this QR Code's mask, in the range [0, 7].
3495317bbafSopenharmony_ci	pub fn mask(&self) -> Mask {
3505317bbafSopenharmony_ci		self.mask
3515317bbafSopenharmony_ci	}
3525317bbafSopenharmony_ci
3535317bbafSopenharmony_ci
3545317bbafSopenharmony_ci	/// Returns the color of the module (pixel) at the given coordinates,
3555317bbafSopenharmony_ci	/// which is `false` for light or `true` for dark.
3565317bbafSopenharmony_ci	///
3575317bbafSopenharmony_ci	/// The top left corner has the coordinates (x=0, y=0). If the given
3585317bbafSopenharmony_ci	/// coordinates are out of bounds, then `false` (light) is returned.
3595317bbafSopenharmony_ci	pub fn get_module(&self, x: i32, y: i32) -> bool {
3605317bbafSopenharmony_ci		(0 .. self.size).contains(&x) && (0 .. self.size).contains(&y) && self.module(x, y)
3615317bbafSopenharmony_ci	}
3625317bbafSopenharmony_ci
3635317bbafSopenharmony_ci
3645317bbafSopenharmony_ci	// Returns the color of the module at the given coordinates, which must be in bounds.
3655317bbafSopenharmony_ci	fn module(&self, x: i32, y: i32) -> bool {
3665317bbafSopenharmony_ci		self.modules[(y * self.size + x) as usize]
3675317bbafSopenharmony_ci	}
3685317bbafSopenharmony_ci
3695317bbafSopenharmony_ci
3705317bbafSopenharmony_ci	// Returns a mutable reference to the module's color at the given coordinates, which must be in bounds.
3715317bbafSopenharmony_ci	fn module_mut(&mut self, x: i32, y: i32) -> &mut bool {
3725317bbafSopenharmony_ci		&mut self.modules[(y * self.size + x) as usize]
3735317bbafSopenharmony_ci	}
3745317bbafSopenharmony_ci
3755317bbafSopenharmony_ci
3765317bbafSopenharmony_ci	/*---- Private helper methods for constructor: Drawing function modules ----*/
3775317bbafSopenharmony_ci
3785317bbafSopenharmony_ci	// Reads this object's version field, and draws and marks all function modules.
3795317bbafSopenharmony_ci	fn draw_function_patterns(&mut self) {
3805317bbafSopenharmony_ci		// Draw horizontal and vertical timing patterns
3815317bbafSopenharmony_ci		let size: i32 = self.size;
3825317bbafSopenharmony_ci		for i in 0 .. size {
3835317bbafSopenharmony_ci			self.set_function_module(6, i, i % 2 == 0);
3845317bbafSopenharmony_ci			self.set_function_module(i, 6, i % 2 == 0);
3855317bbafSopenharmony_ci		}
3865317bbafSopenharmony_ci
3875317bbafSopenharmony_ci		// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
3885317bbafSopenharmony_ci		self.draw_finder_pattern(3, 3);
3895317bbafSopenharmony_ci		self.draw_finder_pattern(size - 4, 3);
3905317bbafSopenharmony_ci		self.draw_finder_pattern(3, size - 4);
3915317bbafSopenharmony_ci
3925317bbafSopenharmony_ci		// Draw numerous alignment patterns
3935317bbafSopenharmony_ci		let alignpatpos: Vec<i32> = self.get_alignment_pattern_positions();
3945317bbafSopenharmony_ci		let numalign: usize = alignpatpos.len();
3955317bbafSopenharmony_ci		for i in 0 .. numalign {
3965317bbafSopenharmony_ci			for j in 0 .. numalign {
3975317bbafSopenharmony_ci				// Don't draw on the three finder corners
3985317bbafSopenharmony_ci				if !(i == 0 && j == 0 || i == 0 && j == numalign - 1 || i == numalign - 1 && j == 0) {
3995317bbafSopenharmony_ci					self.draw_alignment_pattern(alignpatpos[i], alignpatpos[j]);
4005317bbafSopenharmony_ci				}
4015317bbafSopenharmony_ci			}
4025317bbafSopenharmony_ci		}
4035317bbafSopenharmony_ci
4045317bbafSopenharmony_ci		// Draw configuration data
4055317bbafSopenharmony_ci		self.draw_format_bits(Mask::new(0));  // Dummy mask value; overwritten later in the constructor
4065317bbafSopenharmony_ci		self.draw_version();
4075317bbafSopenharmony_ci	}
4085317bbafSopenharmony_ci
4095317bbafSopenharmony_ci
4105317bbafSopenharmony_ci	// Draws two copies of the format bits (with its own error correction code)
4115317bbafSopenharmony_ci	// based on the given mask and this object's error correction level field.
4125317bbafSopenharmony_ci	fn draw_format_bits(&mut self, mask: Mask) {
4135317bbafSopenharmony_ci		// Calculate error correction code and pack bits
4145317bbafSopenharmony_ci		let bits: u32 = {
4155317bbafSopenharmony_ci			// errcorrlvl is uint2, mask is uint3
4165317bbafSopenharmony_ci			let data: u32 = u32::from(self.errorcorrectionlevel.format_bits() << 3 | mask.value());
4175317bbafSopenharmony_ci			let mut rem: u32 = data;
4185317bbafSopenharmony_ci			for _ in 0 .. 10 {
4195317bbafSopenharmony_ci				rem = (rem << 1) ^ ((rem >> 9) * 0x537);
4205317bbafSopenharmony_ci			}
4215317bbafSopenharmony_ci			(data << 10 | rem) ^ 0x5412  // uint15
4225317bbafSopenharmony_ci		};
4235317bbafSopenharmony_ci		debug_assert_eq!(bits >> 15, 0);
4245317bbafSopenharmony_ci
4255317bbafSopenharmony_ci		// Draw first copy
4265317bbafSopenharmony_ci		for i in 0 .. 6 {
4275317bbafSopenharmony_ci			self.set_function_module(8, i, get_bit(bits, i));
4285317bbafSopenharmony_ci		}
4295317bbafSopenharmony_ci		self.set_function_module(8, 7, get_bit(bits, 6));
4305317bbafSopenharmony_ci		self.set_function_module(8, 8, get_bit(bits, 7));
4315317bbafSopenharmony_ci		self.set_function_module(7, 8, get_bit(bits, 8));
4325317bbafSopenharmony_ci		for i in 9 .. 15 {
4335317bbafSopenharmony_ci			self.set_function_module(14 - i, 8, get_bit(bits, i));
4345317bbafSopenharmony_ci		}
4355317bbafSopenharmony_ci
4365317bbafSopenharmony_ci		// Draw second copy
4375317bbafSopenharmony_ci		let size: i32 = self.size;
4385317bbafSopenharmony_ci		for i in 0 .. 8 {
4395317bbafSopenharmony_ci			self.set_function_module(size - 1 - i, 8, get_bit(bits, i));
4405317bbafSopenharmony_ci		}
4415317bbafSopenharmony_ci		for i in 8 .. 15 {
4425317bbafSopenharmony_ci			self.set_function_module(8, size - 15 + i, get_bit(bits, i));
4435317bbafSopenharmony_ci		}
4445317bbafSopenharmony_ci		self.set_function_module(8, size - 8, true);  // Always dark
4455317bbafSopenharmony_ci	}
4465317bbafSopenharmony_ci
4475317bbafSopenharmony_ci
4485317bbafSopenharmony_ci	// Draws two copies of the version bits (with its own error correction code),
4495317bbafSopenharmony_ci	// based on this object's version field, iff 7 <= version <= 40.
4505317bbafSopenharmony_ci	fn draw_version(&mut self) {
4515317bbafSopenharmony_ci		if self.version.value() < 7 {
4525317bbafSopenharmony_ci			return;
4535317bbafSopenharmony_ci		}
4545317bbafSopenharmony_ci
4555317bbafSopenharmony_ci		// Calculate error correction code and pack bits
4565317bbafSopenharmony_ci		let bits: u32 = {
4575317bbafSopenharmony_ci			let data = u32::from(self.version.value());  // uint6, in the range [7, 40]
4585317bbafSopenharmony_ci			let mut rem: u32 = data;
4595317bbafSopenharmony_ci			for _ in 0 .. 12 {
4605317bbafSopenharmony_ci				rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
4615317bbafSopenharmony_ci			}
4625317bbafSopenharmony_ci			data << 12 | rem  // uint18
4635317bbafSopenharmony_ci		};
4645317bbafSopenharmony_ci		debug_assert_eq!(bits >> 18, 0);
4655317bbafSopenharmony_ci
4665317bbafSopenharmony_ci		// Draw two copies
4675317bbafSopenharmony_ci		for i in 0 .. 18 {
4685317bbafSopenharmony_ci			let bit: bool = get_bit(bits, i);
4695317bbafSopenharmony_ci			let a: i32 = self.size - 11 + i % 3;
4705317bbafSopenharmony_ci			let b: i32 = i / 3;
4715317bbafSopenharmony_ci			self.set_function_module(a, b, bit);
4725317bbafSopenharmony_ci			self.set_function_module(b, a, bit);
4735317bbafSopenharmony_ci		}
4745317bbafSopenharmony_ci	}
4755317bbafSopenharmony_ci
4765317bbafSopenharmony_ci
4775317bbafSopenharmony_ci	// Draws a 9*9 finder pattern including the border separator,
4785317bbafSopenharmony_ci	// with the center module at (x, y). Modules can be out of bounds.
4795317bbafSopenharmony_ci	fn draw_finder_pattern(&mut self, x: i32, y: i32) {
4805317bbafSopenharmony_ci		for dy in -4 ..= 4 {
4815317bbafSopenharmony_ci			for dx in -4 ..= 4 {
4825317bbafSopenharmony_ci				let xx: i32 = x + dx;
4835317bbafSopenharmony_ci				let yy: i32 = y + dy;
4845317bbafSopenharmony_ci				if (0 .. self.size).contains(&xx) && (0 .. self.size).contains(&yy) {
4855317bbafSopenharmony_ci					let dist: i32 = std::cmp::max(dx.abs(), dy.abs());  // Chebyshev/infinity norm
4865317bbafSopenharmony_ci					self.set_function_module(xx, yy, dist != 2 && dist != 4);
4875317bbafSopenharmony_ci				}
4885317bbafSopenharmony_ci			}
4895317bbafSopenharmony_ci		}
4905317bbafSopenharmony_ci	}
4915317bbafSopenharmony_ci
4925317bbafSopenharmony_ci
4935317bbafSopenharmony_ci	// Draws a 5*5 alignment pattern, with the center module
4945317bbafSopenharmony_ci	// at (x, y). All modules must be in bounds.
4955317bbafSopenharmony_ci	fn draw_alignment_pattern(&mut self, x: i32, y: i32) {
4965317bbafSopenharmony_ci		for dy in -2 ..= 2 {
4975317bbafSopenharmony_ci			for dx in -2 ..= 2 {
4985317bbafSopenharmony_ci				self.set_function_module(x + dx, y + dy, std::cmp::max(dx.abs(), dy.abs()) != 1);
4995317bbafSopenharmony_ci			}
5005317bbafSopenharmony_ci		}
5015317bbafSopenharmony_ci	}
5025317bbafSopenharmony_ci
5035317bbafSopenharmony_ci
5045317bbafSopenharmony_ci	// Sets the color of a module and marks it as a function module.
5055317bbafSopenharmony_ci	// Only used by the constructor. Coordinates must be in bounds.
5065317bbafSopenharmony_ci	fn set_function_module(&mut self, x: i32, y: i32, isdark: bool) {
5075317bbafSopenharmony_ci		*self.module_mut(x, y) = isdark;
5085317bbafSopenharmony_ci		self.isfunction[(y * self.size + x) as usize] = true;
5095317bbafSopenharmony_ci	}
5105317bbafSopenharmony_ci
5115317bbafSopenharmony_ci
5125317bbafSopenharmony_ci	/*---- Private helper methods for constructor: Codewords and masking ----*/
5135317bbafSopenharmony_ci
5145317bbafSopenharmony_ci	// Returns a new byte string representing the given data with the appropriate error correction
5155317bbafSopenharmony_ci	// codewords appended to it, based on this object's version and error correction level.
5165317bbafSopenharmony_ci	fn add_ecc_and_interleave(&self, data: &[u8]) -> Vec<u8> {
5175317bbafSopenharmony_ci		let ver: Version = self.version;
5185317bbafSopenharmony_ci		let ecl: QrCodeEcc = self.errorcorrectionlevel;
5195317bbafSopenharmony_ci		assert_eq!(data.len(), QrCode::get_num_data_codewords(ver, ecl), "Illegal argument");
5205317bbafSopenharmony_ci
5215317bbafSopenharmony_ci		// Calculate parameter numbers
5225317bbafSopenharmony_ci		let numblocks: usize = QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl);
5235317bbafSopenharmony_ci		let blockecclen: usize = QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK  , ver, ecl);
5245317bbafSopenharmony_ci		let rawcodewords: usize = QrCode::get_num_raw_data_modules(ver) / 8;
5255317bbafSopenharmony_ci		let numshortblocks: usize = numblocks - rawcodewords % numblocks;
5265317bbafSopenharmony_ci		let shortblocklen: usize = rawcodewords / numblocks;
5275317bbafSopenharmony_ci
5285317bbafSopenharmony_ci		// Split data into blocks and append ECC to each block
5295317bbafSopenharmony_ci		let mut blocks = Vec::<Vec<u8>>::with_capacity(numblocks);
5305317bbafSopenharmony_ci		let rsdiv: Vec<u8> = QrCode::reed_solomon_compute_divisor(blockecclen);
5315317bbafSopenharmony_ci		let mut k: usize = 0;
5325317bbafSopenharmony_ci		for i in 0 .. numblocks {
5335317bbafSopenharmony_ci			let datlen: usize = shortblocklen - blockecclen + usize::from(i >= numshortblocks);
5345317bbafSopenharmony_ci			let mut dat = data[k .. k+datlen].to_vec();
5355317bbafSopenharmony_ci			k += datlen;
5365317bbafSopenharmony_ci			let ecc: Vec<u8> = QrCode::reed_solomon_compute_remainder(&dat, &rsdiv);
5375317bbafSopenharmony_ci			if i < numshortblocks {
5385317bbafSopenharmony_ci				dat.push(0);
5395317bbafSopenharmony_ci			}
5405317bbafSopenharmony_ci			dat.extend_from_slice(&ecc);
5415317bbafSopenharmony_ci			blocks.push(dat);
5425317bbafSopenharmony_ci		}
5435317bbafSopenharmony_ci
5445317bbafSopenharmony_ci		// Interleave (not concatenate) the bytes from every block into a single sequence
5455317bbafSopenharmony_ci		let mut result = Vec::<u8>::with_capacity(rawcodewords);
5465317bbafSopenharmony_ci		for i in 0 ..= shortblocklen {
5475317bbafSopenharmony_ci			for (j, block) in blocks.iter().enumerate() {
5485317bbafSopenharmony_ci				// Skip the padding byte in short blocks
5495317bbafSopenharmony_ci				if i != shortblocklen - blockecclen || j >= numshortblocks {
5505317bbafSopenharmony_ci					result.push(block[i]);
5515317bbafSopenharmony_ci				}
5525317bbafSopenharmony_ci			}
5535317bbafSopenharmony_ci		}
5545317bbafSopenharmony_ci		result
5555317bbafSopenharmony_ci	}
5565317bbafSopenharmony_ci
5575317bbafSopenharmony_ci
5585317bbafSopenharmony_ci	// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
5595317bbafSopenharmony_ci	// data area of this QR Code. Function modules need to be marked off before this is called.
5605317bbafSopenharmony_ci	fn draw_codewords(&mut self, data: &[u8]) {
5615317bbafSopenharmony_ci		assert_eq!(data.len(), QrCode::get_num_raw_data_modules(self.version) / 8, "Illegal argument");
5625317bbafSopenharmony_ci
5635317bbafSopenharmony_ci		let mut i: usize = 0;  // Bit index into the data
5645317bbafSopenharmony_ci		// Do the funny zigzag scan
5655317bbafSopenharmony_ci		let mut right: i32 = self.size - 1;
5665317bbafSopenharmony_ci		while right >= 1 {  // Index of right column in each column pair
5675317bbafSopenharmony_ci			if right == 6 {
5685317bbafSopenharmony_ci				right = 5;
5695317bbafSopenharmony_ci			}
5705317bbafSopenharmony_ci			for vert in 0 .. self.size {  // Vertical counter
5715317bbafSopenharmony_ci				for j in 0 .. 2 {
5725317bbafSopenharmony_ci					let x: i32 = right - j;  // Actual x coordinate
5735317bbafSopenharmony_ci					let upward: bool = (right + 1) & 2 == 0;
5745317bbafSopenharmony_ci					let y: i32 = if upward { self.size - 1 - vert } else { vert };  // Actual y coordinate
5755317bbafSopenharmony_ci					if !self.isfunction[(y * self.size + x) as usize] && i < data.len() * 8 {
5765317bbafSopenharmony_ci						*self.module_mut(x, y) = get_bit(u32::from(data[i >> 3]), 7 - ((i as i32) & 7));
5775317bbafSopenharmony_ci						i += 1;
5785317bbafSopenharmony_ci					}
5795317bbafSopenharmony_ci					// If this QR Code has any remainder bits (0 to 7), they were assigned as
5805317bbafSopenharmony_ci					// 0/false/light by the constructor and are left unchanged by this method
5815317bbafSopenharmony_ci				}
5825317bbafSopenharmony_ci			}
5835317bbafSopenharmony_ci			right -= 2;
5845317bbafSopenharmony_ci		}
5855317bbafSopenharmony_ci		debug_assert_eq!(i, data.len() * 8);
5865317bbafSopenharmony_ci	}
5875317bbafSopenharmony_ci
5885317bbafSopenharmony_ci
5895317bbafSopenharmony_ci	// XORs the codeword modules in this QR Code with the given mask pattern.
5905317bbafSopenharmony_ci	// The function modules must be marked and the codeword bits must be drawn
5915317bbafSopenharmony_ci	// before masking. Due to the arithmetic of XOR, calling apply_mask() with
5925317bbafSopenharmony_ci	// the same mask value a second time will undo the mask. A final well-formed
5935317bbafSopenharmony_ci	// QR Code needs exactly one (not zero, two, etc.) mask applied.
5945317bbafSopenharmony_ci	fn apply_mask(&mut self, mask: Mask) {
5955317bbafSopenharmony_ci		for y in 0 .. self.size {
5965317bbafSopenharmony_ci			for x in 0 .. self.size {
5975317bbafSopenharmony_ci				let invert: bool = match mask.value() {
5985317bbafSopenharmony_ci					0 => (x + y) % 2 == 0,
5995317bbafSopenharmony_ci					1 => y % 2 == 0,
6005317bbafSopenharmony_ci					2 => x % 3 == 0,
6015317bbafSopenharmony_ci					3 => (x + y) % 3 == 0,
6025317bbafSopenharmony_ci					4 => (x / 3 + y / 2) % 2 == 0,
6035317bbafSopenharmony_ci					5 => x * y % 2 + x * y % 3 == 0,
6045317bbafSopenharmony_ci					6 => (x * y % 2 + x * y % 3) % 2 == 0,
6055317bbafSopenharmony_ci					7 => ((x + y) % 2 + x * y % 3) % 2 == 0,
6065317bbafSopenharmony_ci					_ => unreachable!(),
6075317bbafSopenharmony_ci				};
6085317bbafSopenharmony_ci				*self.module_mut(x, y) ^= invert & !self.isfunction[(y * self.size + x) as usize];
6095317bbafSopenharmony_ci			}
6105317bbafSopenharmony_ci		}
6115317bbafSopenharmony_ci	}
6125317bbafSopenharmony_ci
6135317bbafSopenharmony_ci
6145317bbafSopenharmony_ci	// Calculates and returns the penalty score based on state of this QR Code's current modules.
6155317bbafSopenharmony_ci	// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
6165317bbafSopenharmony_ci	fn get_penalty_score(&self) -> i32 {
6175317bbafSopenharmony_ci		let mut result: i32 = 0;
6185317bbafSopenharmony_ci		let size: i32 = self.size;
6195317bbafSopenharmony_ci
6205317bbafSopenharmony_ci		// Adjacent modules in row having same color, and finder-like patterns
6215317bbafSopenharmony_ci		for y in 0 .. size {
6225317bbafSopenharmony_ci			let mut runcolor = false;
6235317bbafSopenharmony_ci			let mut runx: i32 = 0;
6245317bbafSopenharmony_ci			let mut runhistory = FinderPenalty::new(size);
6255317bbafSopenharmony_ci			for x in 0 .. size {
6265317bbafSopenharmony_ci				if self.module(x, y) == runcolor {
6275317bbafSopenharmony_ci					runx += 1;
6285317bbafSopenharmony_ci					if runx == 5 {
6295317bbafSopenharmony_ci						result += PENALTY_N1;
6305317bbafSopenharmony_ci					} else if runx > 5 {
6315317bbafSopenharmony_ci						result += 1;
6325317bbafSopenharmony_ci					}
6335317bbafSopenharmony_ci				} else {
6345317bbafSopenharmony_ci					runhistory.add_history(runx);
6355317bbafSopenharmony_ci					if !runcolor {
6365317bbafSopenharmony_ci						result += runhistory.count_patterns() * PENALTY_N3;
6375317bbafSopenharmony_ci					}
6385317bbafSopenharmony_ci					runcolor = self.module(x, y);
6395317bbafSopenharmony_ci					runx = 1;
6405317bbafSopenharmony_ci				}
6415317bbafSopenharmony_ci			}
6425317bbafSopenharmony_ci			result += runhistory.terminate_and_count(runcolor, runx) * PENALTY_N3;
6435317bbafSopenharmony_ci		}
6445317bbafSopenharmony_ci		// Adjacent modules in column having same color, and finder-like patterns
6455317bbafSopenharmony_ci		for x in 0 .. size {
6465317bbafSopenharmony_ci			let mut runcolor = false;
6475317bbafSopenharmony_ci			let mut runy: i32 = 0;
6485317bbafSopenharmony_ci			let mut runhistory = FinderPenalty::new(size);
6495317bbafSopenharmony_ci			for y in 0 .. size {
6505317bbafSopenharmony_ci				if self.module(x, y) == runcolor {
6515317bbafSopenharmony_ci					runy += 1;
6525317bbafSopenharmony_ci					if runy == 5 {
6535317bbafSopenharmony_ci						result += PENALTY_N1;
6545317bbafSopenharmony_ci					} else if runy > 5 {
6555317bbafSopenharmony_ci						result += 1;
6565317bbafSopenharmony_ci					}
6575317bbafSopenharmony_ci				} else {
6585317bbafSopenharmony_ci					runhistory.add_history(runy);
6595317bbafSopenharmony_ci					if !runcolor {
6605317bbafSopenharmony_ci						result += runhistory.count_patterns() * PENALTY_N3;
6615317bbafSopenharmony_ci					}
6625317bbafSopenharmony_ci					runcolor = self.module(x, y);
6635317bbafSopenharmony_ci					runy = 1;
6645317bbafSopenharmony_ci				}
6655317bbafSopenharmony_ci			}
6665317bbafSopenharmony_ci			result += runhistory.terminate_and_count(runcolor, runy) * PENALTY_N3;
6675317bbafSopenharmony_ci		}
6685317bbafSopenharmony_ci
6695317bbafSopenharmony_ci		// 2*2 blocks of modules having same color
6705317bbafSopenharmony_ci		for y in 0 .. size-1 {
6715317bbafSopenharmony_ci			for x in 0 .. size-1 {
6725317bbafSopenharmony_ci				let color: bool = self.module(x, y);
6735317bbafSopenharmony_ci				if color == self.module(x + 1, y) &&
6745317bbafSopenharmony_ci				   color == self.module(x, y + 1) &&
6755317bbafSopenharmony_ci				   color == self.module(x + 1, y + 1) {
6765317bbafSopenharmony_ci					result += PENALTY_N2;
6775317bbafSopenharmony_ci				}
6785317bbafSopenharmony_ci			}
6795317bbafSopenharmony_ci		}
6805317bbafSopenharmony_ci
6815317bbafSopenharmony_ci		// Balance of dark and light modules
6825317bbafSopenharmony_ci		let dark: i32 = self.modules.iter().copied().map(i32::from).sum();
6835317bbafSopenharmony_ci		let total: i32 = size * size;  // Note that size is odd, so dark/total != 1/2
6845317bbafSopenharmony_ci		// Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
6855317bbafSopenharmony_ci		let k: i32 = ((dark * 20 - total * 10).abs() + total - 1) / total - 1;
6865317bbafSopenharmony_ci		debug_assert!(0 <= k && k <= 9);
6875317bbafSopenharmony_ci		result += k * PENALTY_N4;
6885317bbafSopenharmony_ci		debug_assert!(0 <= result && result <= 2568888);  // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
6895317bbafSopenharmony_ci		result
6905317bbafSopenharmony_ci	}
6915317bbafSopenharmony_ci
6925317bbafSopenharmony_ci
6935317bbafSopenharmony_ci	/*---- Private helper functions ----*/
6945317bbafSopenharmony_ci
6955317bbafSopenharmony_ci	// Returns an ascending list of positions of alignment patterns for this version number.
6965317bbafSopenharmony_ci	// Each position is in the range [0,177), and are used on both the x and y axes.
6975317bbafSopenharmony_ci	// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
6985317bbafSopenharmony_ci	fn get_alignment_pattern_positions(&self) -> Vec<i32> {
6995317bbafSopenharmony_ci		let ver: u8 = self.version.value();
7005317bbafSopenharmony_ci		if ver == 1 {
7015317bbafSopenharmony_ci			vec![]
7025317bbafSopenharmony_ci		} else {
7035317bbafSopenharmony_ci			let numalign = i32::from(ver) / 7 + 2;
7045317bbafSopenharmony_ci			let step: i32 = if ver == 32 { 26 } else
7055317bbafSopenharmony_ci				{(i32::from(ver) * 4 + numalign * 2 + 1) / (numalign * 2 - 2) * 2};
7065317bbafSopenharmony_ci			let mut result: Vec<i32> = (0 .. numalign-1).map(
7075317bbafSopenharmony_ci				|i| self.size - 7 - i * step).collect();
7085317bbafSopenharmony_ci			result.push(6);
7095317bbafSopenharmony_ci			result.reverse();
7105317bbafSopenharmony_ci			result
7115317bbafSopenharmony_ci		}
7125317bbafSopenharmony_ci	}
7135317bbafSopenharmony_ci
7145317bbafSopenharmony_ci
7155317bbafSopenharmony_ci	// Returns the number of data bits that can be stored in a QR Code of the given version number, after
7165317bbafSopenharmony_ci	// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
7175317bbafSopenharmony_ci	// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
7185317bbafSopenharmony_ci	fn get_num_raw_data_modules(ver: Version) -> usize {
7195317bbafSopenharmony_ci		let ver = usize::from(ver.value());
7205317bbafSopenharmony_ci		let mut result: usize = (16 * ver + 128) * ver + 64;
7215317bbafSopenharmony_ci		if ver >= 2 {
7225317bbafSopenharmony_ci			let numalign: usize = ver / 7 + 2;
7235317bbafSopenharmony_ci			result -= (25 * numalign - 10) * numalign - 55;
7245317bbafSopenharmony_ci			if ver >= 7 {
7255317bbafSopenharmony_ci				result -= 36;
7265317bbafSopenharmony_ci			}
7275317bbafSopenharmony_ci		}
7285317bbafSopenharmony_ci		debug_assert!((208 ..= 29648).contains(&result));
7295317bbafSopenharmony_ci		result
7305317bbafSopenharmony_ci	}
7315317bbafSopenharmony_ci
7325317bbafSopenharmony_ci
7335317bbafSopenharmony_ci	// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
7345317bbafSopenharmony_ci	// QR Code of the given version number and error correction level, with remainder bits discarded.
7355317bbafSopenharmony_ci	// This stateless pure function could be implemented as a (40*4)-cell lookup table.
7365317bbafSopenharmony_ci	fn get_num_data_codewords(ver: Version, ecl: QrCodeEcc) -> usize {
7375317bbafSopenharmony_ci		QrCode::get_num_raw_data_modules(ver) / 8
7385317bbafSopenharmony_ci			- QrCode::table_get(&ECC_CODEWORDS_PER_BLOCK    , ver, ecl)
7395317bbafSopenharmony_ci			* QrCode::table_get(&NUM_ERROR_CORRECTION_BLOCKS, ver, ecl)
7405317bbafSopenharmony_ci	}
7415317bbafSopenharmony_ci
7425317bbafSopenharmony_ci
7435317bbafSopenharmony_ci	// Returns an entry from the given table based on the given values.
7445317bbafSopenharmony_ci	fn table_get(table: &'static [[i8; 41]; 4], ver: Version, ecl: QrCodeEcc) -> usize {
7455317bbafSopenharmony_ci		table[ecl.ordinal()][usize::from(ver.value())] as usize
7465317bbafSopenharmony_ci	}
7475317bbafSopenharmony_ci
7485317bbafSopenharmony_ci
7495317bbafSopenharmony_ci	// Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
7505317bbafSopenharmony_ci	// implemented as a lookup table over all possible parameter values, instead of as an algorithm.
7515317bbafSopenharmony_ci	fn reed_solomon_compute_divisor(degree: usize) -> Vec<u8> {
7525317bbafSopenharmony_ci		assert!((1 ..= 255).contains(&degree), "Degree out of range");
7535317bbafSopenharmony_ci		// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
7545317bbafSopenharmony_ci		// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
7555317bbafSopenharmony_ci		let mut result = vec![0u8; degree - 1];
7565317bbafSopenharmony_ci		result.push(1);  // Start off with the monomial x^0
7575317bbafSopenharmony_ci
7585317bbafSopenharmony_ci		// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
7595317bbafSopenharmony_ci		// and drop the highest monomial term which is always 1x^degree.
7605317bbafSopenharmony_ci		// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
7615317bbafSopenharmony_ci		let mut root: u8 = 1;
7625317bbafSopenharmony_ci		for _ in 0 .. degree {  // Unused variable i
7635317bbafSopenharmony_ci			// Multiply the current product by (x - r^i)
7645317bbafSopenharmony_ci			for j in 0 .. degree {
7655317bbafSopenharmony_ci				result[j] = QrCode::reed_solomon_multiply(result[j], root);
7665317bbafSopenharmony_ci				if j + 1 < result.len() {
7675317bbafSopenharmony_ci					result[j] ^= result[j + 1];
7685317bbafSopenharmony_ci				}
7695317bbafSopenharmony_ci			}
7705317bbafSopenharmony_ci			root = QrCode::reed_solomon_multiply(root, 0x02);
7715317bbafSopenharmony_ci		}
7725317bbafSopenharmony_ci		result
7735317bbafSopenharmony_ci	}
7745317bbafSopenharmony_ci
7755317bbafSopenharmony_ci
7765317bbafSopenharmony_ci	// Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
7775317bbafSopenharmony_ci	fn reed_solomon_compute_remainder(data: &[u8], divisor: &[u8]) -> Vec<u8> {
7785317bbafSopenharmony_ci		let mut result = vec![0u8; divisor.len()];
7795317bbafSopenharmony_ci		for b in data {  // Polynomial division
7805317bbafSopenharmony_ci			let factor: u8 = b ^ result.remove(0);
7815317bbafSopenharmony_ci			result.push(0);
7825317bbafSopenharmony_ci			for (x, &y) in result.iter_mut().zip(divisor.iter()) {
7835317bbafSopenharmony_ci				*x ^= QrCode::reed_solomon_multiply(y, factor);
7845317bbafSopenharmony_ci			}
7855317bbafSopenharmony_ci		}
7865317bbafSopenharmony_ci		result
7875317bbafSopenharmony_ci	}
7885317bbafSopenharmony_ci
7895317bbafSopenharmony_ci
7905317bbafSopenharmony_ci	// Returns the product of the two given field elements modulo GF(2^8/0x11D).
7915317bbafSopenharmony_ci	// All inputs are valid. This could be implemented as a 256*256 lookup table.
7925317bbafSopenharmony_ci	fn reed_solomon_multiply(x: u8, y: u8) -> u8 {
7935317bbafSopenharmony_ci		// Russian peasant multiplication
7945317bbafSopenharmony_ci		let mut z: u8 = 0;
7955317bbafSopenharmony_ci		for i in (0 .. 8).rev() {
7965317bbafSopenharmony_ci			z = (z << 1) ^ ((z >> 7) * 0x1D);
7975317bbafSopenharmony_ci			z ^= ((y >> i) & 1) * x;
7985317bbafSopenharmony_ci		}
7995317bbafSopenharmony_ci		z
8005317bbafSopenharmony_ci	}
8015317bbafSopenharmony_ci
8025317bbafSopenharmony_ci}
8035317bbafSopenharmony_ci
8045317bbafSopenharmony_ci
8055317bbafSopenharmony_ci/*---- Helper struct for get_penalty_score() ----*/
8065317bbafSopenharmony_ci
8075317bbafSopenharmony_cistruct FinderPenalty {
8085317bbafSopenharmony_ci	qr_size: i32,
8095317bbafSopenharmony_ci	run_history: [i32; 7],
8105317bbafSopenharmony_ci}
8115317bbafSopenharmony_ci
8125317bbafSopenharmony_ci
8135317bbafSopenharmony_ciimpl FinderPenalty {
8145317bbafSopenharmony_ci
8155317bbafSopenharmony_ci	pub fn new(size: i32) -> Self {
8165317bbafSopenharmony_ci		Self {
8175317bbafSopenharmony_ci			qr_size: size,
8185317bbafSopenharmony_ci			run_history: [0i32; 7],
8195317bbafSopenharmony_ci		}
8205317bbafSopenharmony_ci	}
8215317bbafSopenharmony_ci
8225317bbafSopenharmony_ci
8235317bbafSopenharmony_ci	// Pushes the given value to the front and drops the last value.
8245317bbafSopenharmony_ci	pub fn add_history(&mut self, mut currentrunlength: i32) {
8255317bbafSopenharmony_ci		if self.run_history[0] == 0 {
8265317bbafSopenharmony_ci			currentrunlength += self.qr_size;  // Add light border to initial run
8275317bbafSopenharmony_ci		}
8285317bbafSopenharmony_ci		let rh = &mut self.run_history;
8295317bbafSopenharmony_ci		for i in (0 .. rh.len()-1).rev() {
8305317bbafSopenharmony_ci			rh[i + 1] = rh[i];
8315317bbafSopenharmony_ci		}
8325317bbafSopenharmony_ci		rh[0] = currentrunlength;
8335317bbafSopenharmony_ci	}
8345317bbafSopenharmony_ci
8355317bbafSopenharmony_ci
8365317bbafSopenharmony_ci	// Can only be called immediately after a light run is added, and returns either 0, 1, or 2.
8375317bbafSopenharmony_ci	pub fn count_patterns(&self) -> i32 {
8385317bbafSopenharmony_ci		let rh = &self.run_history;
8395317bbafSopenharmony_ci		let n = rh[1];
8405317bbafSopenharmony_ci		debug_assert!(n <= self.qr_size * 3);
8415317bbafSopenharmony_ci		let core = n > 0 && rh[2] == n && rh[3] == n * 3 && rh[4] == n && rh[5] == n;
8425317bbafSopenharmony_ci		( i32::from(core && rh[0] >= n * 4 && rh[6] >= n)
8435317bbafSopenharmony_ci		+ i32::from(core && rh[6] >= n * 4 && rh[0] >= n))
8445317bbafSopenharmony_ci	}
8455317bbafSopenharmony_ci
8465317bbafSopenharmony_ci
8475317bbafSopenharmony_ci	// Must be called at the end of a line (row or column) of modules.
8485317bbafSopenharmony_ci	pub fn terminate_and_count(mut self, currentruncolor: bool, mut currentrunlength: i32) -> i32 {
8495317bbafSopenharmony_ci		if currentruncolor {  // Terminate dark run
8505317bbafSopenharmony_ci			self.add_history(currentrunlength);
8515317bbafSopenharmony_ci			currentrunlength = 0;
8525317bbafSopenharmony_ci		}
8535317bbafSopenharmony_ci		currentrunlength += self.qr_size;  // Add light border to final run
8545317bbafSopenharmony_ci		self.add_history(currentrunlength);
8555317bbafSopenharmony_ci		self.count_patterns()
8565317bbafSopenharmony_ci	}
8575317bbafSopenharmony_ci
8585317bbafSopenharmony_ci}
8595317bbafSopenharmony_ci
8605317bbafSopenharmony_ci
8615317bbafSopenharmony_ci/*---- Constants and tables ----*/
8625317bbafSopenharmony_ci
8635317bbafSopenharmony_ci// For use in get_penalty_score(), when evaluating which mask is best.
8645317bbafSopenharmony_ciconst PENALTY_N1: i32 =  3;
8655317bbafSopenharmony_ciconst PENALTY_N2: i32 =  3;
8665317bbafSopenharmony_ciconst PENALTY_N3: i32 = 40;
8675317bbafSopenharmony_ciconst PENALTY_N4: i32 = 10;
8685317bbafSopenharmony_ci
8695317bbafSopenharmony_ci
8705317bbafSopenharmony_cistatic ECC_CODEWORDS_PER_BLOCK: [[i8; 41]; 4] = [
8715317bbafSopenharmony_ci	// Version: (note that index 0 is for padding, and is set to an illegal value)
8725317bbafSopenharmony_ci	//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
8735317bbafSopenharmony_ci	[-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
8745317bbafSopenharmony_ci	[-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
8755317bbafSopenharmony_ci	[-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
8765317bbafSopenharmony_ci	[-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
8775317bbafSopenharmony_ci];
8785317bbafSopenharmony_ci
8795317bbafSopenharmony_cistatic NUM_ERROR_CORRECTION_BLOCKS: [[i8; 41]; 4] = [
8805317bbafSopenharmony_ci	// Version: (note that index 0 is for padding, and is set to an illegal value)
8815317bbafSopenharmony_ci	//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
8825317bbafSopenharmony_ci	[-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
8835317bbafSopenharmony_ci	[-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
8845317bbafSopenharmony_ci	[-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
8855317bbafSopenharmony_ci	[-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
8865317bbafSopenharmony_ci];
8875317bbafSopenharmony_ci
8885317bbafSopenharmony_ci
8895317bbafSopenharmony_ci
8905317bbafSopenharmony_ci/*---- QrCodeEcc functionality ----*/
8915317bbafSopenharmony_ci
8925317bbafSopenharmony_ci/// The error correction level in a QR Code symbol.
8935317bbafSopenharmony_ci#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
8945317bbafSopenharmony_cipub enum QrCodeEcc {
8955317bbafSopenharmony_ci	/// The QR Code can tolerate about  7% erroneous codewords.
8965317bbafSopenharmony_ci	Low     ,
8975317bbafSopenharmony_ci	/// The QR Code can tolerate about 15% erroneous codewords.
8985317bbafSopenharmony_ci	Medium  ,
8995317bbafSopenharmony_ci	/// The QR Code can tolerate about 25% erroneous codewords.
9005317bbafSopenharmony_ci	Quartile,
9015317bbafSopenharmony_ci	/// The QR Code can tolerate about 30% erroneous codewords.
9025317bbafSopenharmony_ci	High    ,
9035317bbafSopenharmony_ci}
9045317bbafSopenharmony_ci
9055317bbafSopenharmony_ci
9065317bbafSopenharmony_ciimpl QrCodeEcc {
9075317bbafSopenharmony_ci
9085317bbafSopenharmony_ci	// Returns an unsigned 2-bit integer (in the range 0 to 3).
9095317bbafSopenharmony_ci	fn ordinal(self) -> usize {
9105317bbafSopenharmony_ci		use QrCodeEcc::*;
9115317bbafSopenharmony_ci		match self {
9125317bbafSopenharmony_ci			Low      => 0,
9135317bbafSopenharmony_ci			Medium   => 1,
9145317bbafSopenharmony_ci			Quartile => 2,
9155317bbafSopenharmony_ci			High     => 3,
9165317bbafSopenharmony_ci		}
9175317bbafSopenharmony_ci	}
9185317bbafSopenharmony_ci
9195317bbafSopenharmony_ci
9205317bbafSopenharmony_ci	// Returns an unsigned 2-bit integer (in the range 0 to 3).
9215317bbafSopenharmony_ci	fn format_bits(self) -> u8 {
9225317bbafSopenharmony_ci		use QrCodeEcc::*;
9235317bbafSopenharmony_ci		match self {
9245317bbafSopenharmony_ci			Low      => 1,
9255317bbafSopenharmony_ci			Medium   => 0,
9265317bbafSopenharmony_ci			Quartile => 3,
9275317bbafSopenharmony_ci			High     => 2,
9285317bbafSopenharmony_ci		}
9295317bbafSopenharmony_ci	}
9305317bbafSopenharmony_ci
9315317bbafSopenharmony_ci}
9325317bbafSopenharmony_ci
9335317bbafSopenharmony_ci
9345317bbafSopenharmony_ci
9355317bbafSopenharmony_ci/*---- QrSegment functionality ----*/
9365317bbafSopenharmony_ci
9375317bbafSopenharmony_ci/// A segment of character/binary/control data in a QR Code symbol.
9385317bbafSopenharmony_ci///
9395317bbafSopenharmony_ci/// Instances of this struct are immutable.
9405317bbafSopenharmony_ci///
9415317bbafSopenharmony_ci/// The mid-level way to create a segment is to take the payload data
9425317bbafSopenharmony_ci/// and call a static factory function such as `QrSegment::make_numeric()`.
9435317bbafSopenharmony_ci/// The low-level way to create a segment is to custom-make the bit buffer
9445317bbafSopenharmony_ci/// and call the `QrSegment::new()` constructor with appropriate values.
9455317bbafSopenharmony_ci///
9465317bbafSopenharmony_ci/// This segment struct imposes no length restrictions, but QR Codes have restrictions.
9475317bbafSopenharmony_ci/// Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
9485317bbafSopenharmony_ci/// Any segment longer than this is meaningless for the purpose of generating QR Codes.
9495317bbafSopenharmony_ci#[derive(Clone, PartialEq, Eq)]
9505317bbafSopenharmony_cipub struct QrSegment {
9515317bbafSopenharmony_ci
9525317bbafSopenharmony_ci	// The mode indicator of this segment. Accessed through mode().
9535317bbafSopenharmony_ci	mode: QrSegmentMode,
9545317bbafSopenharmony_ci
9555317bbafSopenharmony_ci	// The length of this segment's unencoded data. Measured in characters for
9565317bbafSopenharmony_ci	// numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
9575317bbafSopenharmony_ci	// Not the same as the data's bit length. Accessed through num_chars().
9585317bbafSopenharmony_ci	numchars: usize,
9595317bbafSopenharmony_ci
9605317bbafSopenharmony_ci	// The data bits of this segment. Accessed through data().
9615317bbafSopenharmony_ci	data: Vec<bool>,
9625317bbafSopenharmony_ci
9635317bbafSopenharmony_ci}
9645317bbafSopenharmony_ci
9655317bbafSopenharmony_ci
9665317bbafSopenharmony_ciimpl QrSegment {
9675317bbafSopenharmony_ci
9685317bbafSopenharmony_ci	/*---- Static factory functions (mid level) ----*/
9695317bbafSopenharmony_ci
9705317bbafSopenharmony_ci	/// Returns a segment representing the given binary data encoded in byte mode.
9715317bbafSopenharmony_ci	///
9725317bbafSopenharmony_ci	/// All input byte slices are acceptable.
9735317bbafSopenharmony_ci	///
9745317bbafSopenharmony_ci	/// Any text string can be converted to UTF-8 bytes and encoded as a byte mode segment.
9755317bbafSopenharmony_ci	pub fn make_bytes(data: &[u8]) -> Self {
9765317bbafSopenharmony_ci		let mut bb = BitBuffer(Vec::with_capacity(data.len() * 8));
9775317bbafSopenharmony_ci		for &b in data {
9785317bbafSopenharmony_ci			bb.append_bits(u32::from(b), 8);
9795317bbafSopenharmony_ci		}
9805317bbafSopenharmony_ci		QrSegment::new(QrSegmentMode::Byte, data.len(), bb.0)
9815317bbafSopenharmony_ci	}
9825317bbafSopenharmony_ci
9835317bbafSopenharmony_ci
9845317bbafSopenharmony_ci	/// Returns a segment representing the given string of decimal digits encoded in numeric mode.
9855317bbafSopenharmony_ci	///
9865317bbafSopenharmony_ci	/// Panics if the string contains non-digit characters.
9875317bbafSopenharmony_ci	pub fn make_numeric(text: &str) -> Self {
9885317bbafSopenharmony_ci		let mut bb = BitBuffer(Vec::with_capacity(text.len() * 3 + (text.len() + 2) / 3));
9895317bbafSopenharmony_ci		let mut accumdata: u32 = 0;
9905317bbafSopenharmony_ci		let mut accumcount: u8 = 0;
9915317bbafSopenharmony_ci		for b in text.bytes() {
9925317bbafSopenharmony_ci			assert!((b'0' ..= b'9').contains(&b), "String contains non-numeric characters");
9935317bbafSopenharmony_ci			accumdata = accumdata * 10 + u32::from(b - b'0');
9945317bbafSopenharmony_ci			accumcount += 1;
9955317bbafSopenharmony_ci			if accumcount == 3 {
9965317bbafSopenharmony_ci				bb.append_bits(accumdata, 10);
9975317bbafSopenharmony_ci				accumdata = 0;
9985317bbafSopenharmony_ci				accumcount = 0;
9995317bbafSopenharmony_ci			}
10005317bbafSopenharmony_ci		}
10015317bbafSopenharmony_ci		if accumcount > 0 {  // 1 or 2 digits remaining
10025317bbafSopenharmony_ci			bb.append_bits(accumdata, accumcount * 3 + 1);
10035317bbafSopenharmony_ci		}
10045317bbafSopenharmony_ci		QrSegment::new(QrSegmentMode::Numeric, text.len(), bb.0)
10055317bbafSopenharmony_ci	}
10065317bbafSopenharmony_ci
10075317bbafSopenharmony_ci
10085317bbafSopenharmony_ci	/// Returns a segment representing the given text string encoded in alphanumeric mode.
10095317bbafSopenharmony_ci	///
10105317bbafSopenharmony_ci	/// The characters allowed are: 0 to 9, A to Z (uppercase only), space,
10115317bbafSopenharmony_ci	/// dollar, percent, asterisk, plus, hyphen, period, slash, colon.
10125317bbafSopenharmony_ci	///
10135317bbafSopenharmony_ci	/// Panics if the string contains non-encodable characters.
10145317bbafSopenharmony_ci	pub fn make_alphanumeric(text: &str) -> Self {
10155317bbafSopenharmony_ci		let mut bb = BitBuffer(Vec::with_capacity(text.len() * 5 + (text.len() + 1) / 2));
10165317bbafSopenharmony_ci		let mut accumdata: u32 = 0;
10175317bbafSopenharmony_ci		let mut accumcount: u32 = 0;
10185317bbafSopenharmony_ci		for c in text.chars() {
10195317bbafSopenharmony_ci			let i: usize = ALPHANUMERIC_CHARSET.find(c)
10205317bbafSopenharmony_ci				.expect("String contains unencodable characters in alphanumeric mode");
10215317bbafSopenharmony_ci			accumdata = accumdata * 45 + u32::try_from(i).unwrap();
10225317bbafSopenharmony_ci			accumcount += 1;
10235317bbafSopenharmony_ci			if accumcount == 2 {
10245317bbafSopenharmony_ci				bb.append_bits(accumdata, 11);
10255317bbafSopenharmony_ci				accumdata = 0;
10265317bbafSopenharmony_ci				accumcount = 0;
10275317bbafSopenharmony_ci			}
10285317bbafSopenharmony_ci		}
10295317bbafSopenharmony_ci		if accumcount > 0 {  // 1 character remaining
10305317bbafSopenharmony_ci			bb.append_bits(accumdata, 6);
10315317bbafSopenharmony_ci		}
10325317bbafSopenharmony_ci		QrSegment::new(QrSegmentMode::Alphanumeric, text.len(), bb.0)
10335317bbafSopenharmony_ci	}
10345317bbafSopenharmony_ci
10355317bbafSopenharmony_ci
10365317bbafSopenharmony_ci	/// Returns a list of zero or more segments to represent the given Unicode text string.
10375317bbafSopenharmony_ci	///
10385317bbafSopenharmony_ci	/// The result may use various segment modes and switch
10395317bbafSopenharmony_ci	/// modes to optimize the length of the bit stream.
10405317bbafSopenharmony_ci	pub fn make_segments(text: &str) -> Vec<Self> {
10415317bbafSopenharmony_ci		if text.is_empty() {
10425317bbafSopenharmony_ci			vec![]
10435317bbafSopenharmony_ci		} else {
10445317bbafSopenharmony_ci			vec![
10455317bbafSopenharmony_ci				if QrSegment::is_numeric(text) {
10465317bbafSopenharmony_ci					QrSegment::make_numeric(text)
10475317bbafSopenharmony_ci				} else if QrSegment::is_alphanumeric(text) {
10485317bbafSopenharmony_ci					QrSegment::make_alphanumeric(text)
10495317bbafSopenharmony_ci				} else {
10505317bbafSopenharmony_ci					QrSegment::make_bytes(text.as_bytes())
10515317bbafSopenharmony_ci				}
10525317bbafSopenharmony_ci			]
10535317bbafSopenharmony_ci		}
10545317bbafSopenharmony_ci	}
10555317bbafSopenharmony_ci
10565317bbafSopenharmony_ci
10575317bbafSopenharmony_ci	/// Returns a segment representing an Extended Channel Interpretation
10585317bbafSopenharmony_ci	/// (ECI) designator with the given assignment value.
10595317bbafSopenharmony_ci	pub fn make_eci(assignval: u32) -> Self {
10605317bbafSopenharmony_ci		let mut bb = BitBuffer(Vec::with_capacity(24));
10615317bbafSopenharmony_ci		if assignval < (1 << 7) {
10625317bbafSopenharmony_ci			bb.append_bits(assignval, 8);
10635317bbafSopenharmony_ci		} else if assignval < (1 << 14) {
10645317bbafSopenharmony_ci			bb.append_bits(0b10, 2);
10655317bbafSopenharmony_ci			bb.append_bits(assignval, 14);
10665317bbafSopenharmony_ci		} else if assignval < 1_000_000 {
10675317bbafSopenharmony_ci			bb.append_bits(0b110, 3);
10685317bbafSopenharmony_ci			bb.append_bits(assignval, 21);
10695317bbafSopenharmony_ci		} else {
10705317bbafSopenharmony_ci			panic!("ECI assignment value out of range");
10715317bbafSopenharmony_ci		}
10725317bbafSopenharmony_ci		QrSegment::new(QrSegmentMode::Eci, 0, bb.0)
10735317bbafSopenharmony_ci	}
10745317bbafSopenharmony_ci
10755317bbafSopenharmony_ci
10765317bbafSopenharmony_ci	/*---- Constructor (low level) ----*/
10775317bbafSopenharmony_ci
10785317bbafSopenharmony_ci	/// Creates a new QR Code segment with the given attributes and data.
10795317bbafSopenharmony_ci	///
10805317bbafSopenharmony_ci	/// The character count (numchars) must agree with the mode and
10815317bbafSopenharmony_ci	/// the bit buffer length, but the constraint isn't checked.
10825317bbafSopenharmony_ci	pub fn new(mode: QrSegmentMode, numchars: usize, data: Vec<bool>) -> Self {
10835317bbafSopenharmony_ci		Self { mode, numchars, data }
10845317bbafSopenharmony_ci	}
10855317bbafSopenharmony_ci
10865317bbafSopenharmony_ci
10875317bbafSopenharmony_ci	/*---- Instance field getters ----*/
10885317bbafSopenharmony_ci
10895317bbafSopenharmony_ci	/// Returns the mode indicator of this segment.
10905317bbafSopenharmony_ci	pub fn mode(&self) -> QrSegmentMode {
10915317bbafSopenharmony_ci		self.mode
10925317bbafSopenharmony_ci	}
10935317bbafSopenharmony_ci
10945317bbafSopenharmony_ci
10955317bbafSopenharmony_ci	/// Returns the character count field of this segment.
10965317bbafSopenharmony_ci	pub fn num_chars(&self) -> usize {
10975317bbafSopenharmony_ci		self.numchars
10985317bbafSopenharmony_ci	}
10995317bbafSopenharmony_ci
11005317bbafSopenharmony_ci
11015317bbafSopenharmony_ci	/// Returns the data bits of this segment.
11025317bbafSopenharmony_ci	pub fn data(&self) -> &Vec<bool> {
11035317bbafSopenharmony_ci		&self.data
11045317bbafSopenharmony_ci	}
11055317bbafSopenharmony_ci
11065317bbafSopenharmony_ci
11075317bbafSopenharmony_ci	/*---- Other static functions ----*/
11085317bbafSopenharmony_ci
11095317bbafSopenharmony_ci	// Calculates and returns the number of bits needed to encode the given
11105317bbafSopenharmony_ci	// segments at the given version. The result is None if a segment has too many
11115317bbafSopenharmony_ci	// characters to fit its length field, or the total bits exceeds usize::MAX.
11125317bbafSopenharmony_ci	fn get_total_bits(segs: &[Self], version: Version) -> Option<usize> {
11135317bbafSopenharmony_ci		let mut result: usize = 0;
11145317bbafSopenharmony_ci		for seg in segs {
11155317bbafSopenharmony_ci			let ccbits: u8 = seg.mode.num_char_count_bits(version);
11165317bbafSopenharmony_ci			// ccbits can be as large as 16, but usize can be as small as 16
11175317bbafSopenharmony_ci			if let Some(limit) = 1usize.checked_shl(ccbits.into()) {
11185317bbafSopenharmony_ci				if seg.numchars >= limit {
11195317bbafSopenharmony_ci					return None;  // The segment's length doesn't fit the field's bit width
11205317bbafSopenharmony_ci				}
11215317bbafSopenharmony_ci			}
11225317bbafSopenharmony_ci			result = result.checked_add(4 + usize::from(ccbits))?;
11235317bbafSopenharmony_ci			result = result.checked_add(seg.data.len())?;
11245317bbafSopenharmony_ci		}
11255317bbafSopenharmony_ci		Some(result)
11265317bbafSopenharmony_ci	}
11275317bbafSopenharmony_ci
11285317bbafSopenharmony_ci
11295317bbafSopenharmony_ci	/// Tests whether the given string can be encoded as a segment in numeric mode.
11305317bbafSopenharmony_ci	///
11315317bbafSopenharmony_ci	/// A string is encodable iff each character is in the range 0 to 9.
11325317bbafSopenharmony_ci	pub fn is_numeric(text: &str) -> bool {
11335317bbafSopenharmony_ci		text.chars().all(|c| ('0' ..= '9').contains(&c))
11345317bbafSopenharmony_ci	}
11355317bbafSopenharmony_ci
11365317bbafSopenharmony_ci
11375317bbafSopenharmony_ci	/// Tests whether the given string can be encoded as a segment in alphanumeric mode.
11385317bbafSopenharmony_ci	///
11395317bbafSopenharmony_ci	/// A string is encodable iff each character is in the following set: 0 to 9, A to Z
11405317bbafSopenharmony_ci	/// (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
11415317bbafSopenharmony_ci	pub fn is_alphanumeric(text: &str) -> bool {
11425317bbafSopenharmony_ci		text.chars().all(|c| ALPHANUMERIC_CHARSET.contains(c))
11435317bbafSopenharmony_ci	}
11445317bbafSopenharmony_ci
11455317bbafSopenharmony_ci}
11465317bbafSopenharmony_ci
11475317bbafSopenharmony_ci
11485317bbafSopenharmony_ci// The set of all legal characters in alphanumeric mode,
11495317bbafSopenharmony_ci// where each character value maps to the index in the string.
11505317bbafSopenharmony_cistatic ALPHANUMERIC_CHARSET: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
11515317bbafSopenharmony_ci
11525317bbafSopenharmony_ci
11535317bbafSopenharmony_ci
11545317bbafSopenharmony_ci/*---- QrSegmentMode functionality ----*/
11555317bbafSopenharmony_ci
11565317bbafSopenharmony_ci/// Describes how a segment's data bits are interpreted.
11575317bbafSopenharmony_ci#[derive(Clone, Copy, PartialEq, Eq, Debug)]
11585317bbafSopenharmony_cipub enum QrSegmentMode {
11595317bbafSopenharmony_ci	Numeric,
11605317bbafSopenharmony_ci	Alphanumeric,
11615317bbafSopenharmony_ci	Byte,
11625317bbafSopenharmony_ci	Kanji,
11635317bbafSopenharmony_ci	Eci,
11645317bbafSopenharmony_ci}
11655317bbafSopenharmony_ci
11665317bbafSopenharmony_ci
11675317bbafSopenharmony_ciimpl QrSegmentMode {
11685317bbafSopenharmony_ci
11695317bbafSopenharmony_ci	// Returns an unsigned 4-bit integer value (range 0 to 15)
11705317bbafSopenharmony_ci	// representing the mode indicator bits for this mode object.
11715317bbafSopenharmony_ci	fn mode_bits(self) -> u32 {
11725317bbafSopenharmony_ci		use QrSegmentMode::*;
11735317bbafSopenharmony_ci		match self {
11745317bbafSopenharmony_ci			Numeric      => 0x1,
11755317bbafSopenharmony_ci			Alphanumeric => 0x2,
11765317bbafSopenharmony_ci			Byte         => 0x4,
11775317bbafSopenharmony_ci			Kanji        => 0x8,
11785317bbafSopenharmony_ci			Eci          => 0x7,
11795317bbafSopenharmony_ci		}
11805317bbafSopenharmony_ci	}
11815317bbafSopenharmony_ci
11825317bbafSopenharmony_ci
11835317bbafSopenharmony_ci	// Returns the bit width of the character count field for a segment in this mode
11845317bbafSopenharmony_ci	// in a QR Code at the given version number. The result is in the range [0, 16].
11855317bbafSopenharmony_ci	fn num_char_count_bits(self, ver: Version) -> u8 {
11865317bbafSopenharmony_ci		use QrSegmentMode::*;
11875317bbafSopenharmony_ci		(match self {
11885317bbafSopenharmony_ci			Numeric      => [10, 12, 14],
11895317bbafSopenharmony_ci			Alphanumeric => [ 9, 11, 13],
11905317bbafSopenharmony_ci			Byte         => [ 8, 16, 16],
11915317bbafSopenharmony_ci			Kanji        => [ 8, 10, 12],
11925317bbafSopenharmony_ci			Eci          => [ 0,  0,  0],
11935317bbafSopenharmony_ci		})[usize::from((ver.value() + 7) / 17)]
11945317bbafSopenharmony_ci	}
11955317bbafSopenharmony_ci
11965317bbafSopenharmony_ci}
11975317bbafSopenharmony_ci
11985317bbafSopenharmony_ci
11995317bbafSopenharmony_ci
12005317bbafSopenharmony_ci/*---- Bit buffer functionality ----*/
12015317bbafSopenharmony_ci
12025317bbafSopenharmony_ci/// An appendable sequence of bits (0s and 1s).
12035317bbafSopenharmony_ci///
12045317bbafSopenharmony_ci/// Mainly used by QrSegment.
12055317bbafSopenharmony_cipub struct BitBuffer(pub Vec<bool>);
12065317bbafSopenharmony_ci
12075317bbafSopenharmony_ci
12085317bbafSopenharmony_ciimpl BitBuffer {
12095317bbafSopenharmony_ci	/// Appends the given number of low-order bits of the given value to this buffer.
12105317bbafSopenharmony_ci	///
12115317bbafSopenharmony_ci	/// Requires len &#x2264; 31 and val &lt; 2<sup>len</sup>.
12125317bbafSopenharmony_ci	pub fn append_bits(&mut self, val: u32, len: u8) {
12135317bbafSopenharmony_ci		assert!(len <= 31 && val >> len == 0, "Value out of range");
12145317bbafSopenharmony_ci		self.0.extend((0 .. i32::from(len)).rev().map(|i| get_bit(val, i)));  // Append bit by bit
12155317bbafSopenharmony_ci	}
12165317bbafSopenharmony_ci}
12175317bbafSopenharmony_ci
12185317bbafSopenharmony_ci
12195317bbafSopenharmony_ci
12205317bbafSopenharmony_ci/*---- Miscellaneous values ----*/
12215317bbafSopenharmony_ci
12225317bbafSopenharmony_ci/// The error type when the supplied data does not fit any QR Code version.
12235317bbafSopenharmony_ci///
12245317bbafSopenharmony_ci/// Ways to handle this exception include:
12255317bbafSopenharmony_ci///
12265317bbafSopenharmony_ci/// - Decrease the error correction level if it was greater than `QrCodeEcc::Low`.
12275317bbafSopenharmony_ci/// - If the `encode_segments_advanced()` function was called, then increase the maxversion
12285317bbafSopenharmony_ci///   argument if it was less than `Version::MAX`. (This advice does not apply to the
12295317bbafSopenharmony_ci///   other factory functions because they search all versions up to `Version::MAX`.)
12305317bbafSopenharmony_ci/// - Split the text data into better or optimal segments in order to reduce the number of bits required.
12315317bbafSopenharmony_ci/// - Change the text or binary data to be shorter.
12325317bbafSopenharmony_ci/// - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric).
12335317bbafSopenharmony_ci/// - Propagate the error upward to the caller/user.
12345317bbafSopenharmony_ci#[derive(Debug, Clone)]
12355317bbafSopenharmony_cipub enum DataTooLong {
12365317bbafSopenharmony_ci	SegmentTooLong,
12375317bbafSopenharmony_ci	DataOverCapacity(usize, usize),
12385317bbafSopenharmony_ci}
12395317bbafSopenharmony_ci
12405317bbafSopenharmony_ciimpl std::error::Error for DataTooLong {}
12415317bbafSopenharmony_ci
12425317bbafSopenharmony_ciimpl std::fmt::Display for DataTooLong {
12435317bbafSopenharmony_ci	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
12445317bbafSopenharmony_ci		match *self {
12455317bbafSopenharmony_ci			Self::SegmentTooLong => write!(f, "Segment too long"),
12465317bbafSopenharmony_ci			Self::DataOverCapacity(datalen, maxcapacity) =>
12475317bbafSopenharmony_ci				write!(f, "Data length = {} bits, Max capacity = {} bits", datalen, maxcapacity),
12485317bbafSopenharmony_ci		}
12495317bbafSopenharmony_ci	}
12505317bbafSopenharmony_ci}
12515317bbafSopenharmony_ci
12525317bbafSopenharmony_ci
12535317bbafSopenharmony_ci/// A number between 1 and 40 (inclusive).
12545317bbafSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
12555317bbafSopenharmony_cipub struct Version(u8);
12565317bbafSopenharmony_ci
12575317bbafSopenharmony_ciimpl Version {
12585317bbafSopenharmony_ci	/// The minimum version number supported in the QR Code Model 2 standard.
12595317bbafSopenharmony_ci	pub const MIN: Version = Version( 1);
12605317bbafSopenharmony_ci
12615317bbafSopenharmony_ci	/// The maximum version number supported in the QR Code Model 2 standard.
12625317bbafSopenharmony_ci	pub const MAX: Version = Version(40);
12635317bbafSopenharmony_ci
12645317bbafSopenharmony_ci	/// Creates a version object from the given number.
12655317bbafSopenharmony_ci	///
12665317bbafSopenharmony_ci	/// Panics if the number is outside the range [1, 40].
12675317bbafSopenharmony_ci	pub fn new(ver: u8) -> Self {
12685317bbafSopenharmony_ci		assert!((Version::MIN.value() ..= Version::MAX.value()).contains(&ver), "Version number out of range");
12695317bbafSopenharmony_ci		Self(ver)
12705317bbafSopenharmony_ci	}
12715317bbafSopenharmony_ci
12725317bbafSopenharmony_ci	/// Returns the value, which is in the range [1, 40].
12735317bbafSopenharmony_ci	pub fn value(self) -> u8 {
12745317bbafSopenharmony_ci		self.0
12755317bbafSopenharmony_ci	}
12765317bbafSopenharmony_ci}
12775317bbafSopenharmony_ci
12785317bbafSopenharmony_ci
12795317bbafSopenharmony_ci/// A number between 0 and 7 (inclusive).
12805317bbafSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
12815317bbafSopenharmony_cipub struct Mask(u8);
12825317bbafSopenharmony_ci
12835317bbafSopenharmony_ciimpl Mask {
12845317bbafSopenharmony_ci	/// Creates a mask object from the given number.
12855317bbafSopenharmony_ci	///
12865317bbafSopenharmony_ci	/// Panics if the number is outside the range [0, 7].
12875317bbafSopenharmony_ci	pub fn new(mask: u8) -> Self {
12885317bbafSopenharmony_ci		assert!(mask <= 7, "Mask value out of range");
12895317bbafSopenharmony_ci		Self(mask)
12905317bbafSopenharmony_ci	}
12915317bbafSopenharmony_ci
12925317bbafSopenharmony_ci	/// Returns the value, which is in the range [0, 7].
12935317bbafSopenharmony_ci	pub fn value(self) -> u8 {
12945317bbafSopenharmony_ci		self.0
12955317bbafSopenharmony_ci	}
12965317bbafSopenharmony_ci}
12975317bbafSopenharmony_ci
12985317bbafSopenharmony_ci
12995317bbafSopenharmony_ci// Returns true iff the i'th bit of x is set to 1.
13005317bbafSopenharmony_cifn get_bit(x: u32, i: i32) -> bool {
13015317bbafSopenharmony_ci	(x >> i) & 1 != 0
13025317bbafSopenharmony_ci}
1303