diff --git a/.travis.yml b/.travis.yml index 65d4f6c..d0e0851 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,20 +15,16 @@ addons: matrix: include: - os: linux - rust: 1.17.0 + rust: 1.20.0 - os: linux - rust: 1.21.0 + rust: stable - os: osx - rust: 1.21.0 + rust: stable - os: linux rust: beta - os: linux rust: nightly -matrix: - allow_failures: - - rust: beta - install: - if [ "$TRAVIS_OS_NAME" = 'linux' ]; then OS=unknown-linux-gnu; else OS=apple-darwin; fi - rustup target add i686-$OS diff --git a/Cargo.toml b/Cargo.toml index 9859984..fd1e2cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ maintenance = { status = "passively-maintained" } [dependencies] image = { version = "0.17", optional = true } +checked_int_cast = "1" [features] default = ["image", "svg"] diff --git a/README.md b/README.md index c4fd2b9..68ca04a 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,14 @@ Cargo.toml ```toml [dependencies] -qrcode = "0.4" +qrcode = "0.5" ``` The default settings will depend on the `image` crate. If you don't need image generation capability, disable the `default-features`: ```toml [dependencies] -qrcode = { version = "0.4", default-features = false } +qrcode = { version = "0.5", default-features = false } ``` Example diff --git a/examples/encode_image.rs b/examples/encode_image.rs index 6e32801..dc3eed5 100644 --- a/examples/encode_image.rs +++ b/examples/encode_image.rs @@ -1,5 +1,5 @@ -extern crate qrcode; extern crate image; +extern crate qrcode; use qrcode::QrCode; use image::Luma; diff --git a/examples/encode_svg.rs b/examples/encode_svg.rs index 2b68018..b64c159 100644 --- a/examples/encode_svg.rs +++ b/examples/encode_svg.rs @@ -1,6 +1,6 @@ extern crate qrcode; -use qrcode::{QrCode, Version, EcLevel}; +use qrcode::{EcLevel, QrCode, Version}; use qrcode::render::svg; fn main() { diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..1a5f8dd --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,8 @@ +array_width = 100 +chain_width = 100 +fn_call_width = 100 +# single_line_if_else_max_width = 100 +struct_lit_width = 100 +struct_variant_width = 100 +error_on_line_overflow = false + diff --git a/src/bin/qrencode.rs b/src/bin/qrencode.rs index 3e776db..8af80fc 100644 --- a/src/bin/qrencode.rs +++ b/src/bin/qrencode.rs @@ -6,9 +6,11 @@ pub fn main() { let arg = env::args().nth(1).unwrap(); let code = qrcode::QrCode::new(arg.as_bytes()).unwrap(); - print!("{}", code.render() - .dark_color("\x1b[7m \x1b[0m") - .light_color("\x1b[49m \x1b[0m") - .build()); + print!( + "{}", + code.render() + .dark_color("\x1b[7m \x1b[0m") + .light_color("\x1b[49m \x1b[0m") + .build() + ); } - diff --git a/src/bits.rs b/src/bits.rs index ff20504..16680bf 100644 --- a/src/bits.rs +++ b/src/bits.rs @@ -2,11 +2,12 @@ use std::cmp::min; -#[cfg(feature="bench")] +#[cfg(feature = "bench")] use test::Bencher; -use types::{QrResult, QrError, Mode, EcLevel, Version}; -use optimize::{Parser, Optimizer, total_encoded_len, Segment}; +use types::{EcLevel, Mode, QrError, QrResult, Version}; +use optimize::{total_encoded_len, Optimizer, Parser, Segment}; +use cast::{As, Truncate}; //------------------------------------------------------------------------------ //{{{ Bits @@ -20,8 +21,8 @@ pub struct Bits { impl Bits { /// Constructs a new, empty bits structure. - pub fn new(version: Version) -> Bits { - Bits { data: Vec::new(), bit_offset: 0, version: version } + pub fn new(version: Version) -> Self { + Self { data: Vec::new(), bit_offset: 0, version: version } } /// Pushes an N-bit big-endian integer to the end of the bits. @@ -30,29 +31,34 @@ impl Bits { /// `n` bit in size. Otherwise the excess bits may stomp on the existing /// ones. fn push_number(&mut self, n: usize, number: u16) { - debug_assert!(n == 16 || n < 16 && number < (1 << n), - "{} is too big as a {}-bit number", number, n); + debug_assert!( + n == 16 || n < 16 && number < (1 << n), + "{} is too big as a {}-bit number", + number, + n + ); let b = self.bit_offset + n; + let last_index = self.data.len().wrapping_sub(1); match (self.bit_offset, b) { (0, 0...8) => { - self.data.push((number << (8-b)) as u8); + self.data.push((number << (8 - b)).truncate_as_u8()); } (0, _) => { - self.data.push((number >> (b-8)) as u8); - self.data.push((number << (16-b)) as u8); + self.data.push((number >> (b - 8)).truncate_as_u8()); + self.data.push((number << (16 - b)).truncate_as_u8()); } (_, 0...8) => { - *self.data.last_mut().unwrap() |= (number << (8-b)) as u8; + self.data[last_index] |= (number << (8 - b)).truncate_as_u8(); } (_, 9...16) => { - *self.data.last_mut().unwrap() |= (number >> (b-8)) as u8; - self.data.push((number << (16-b)) as u8); + self.data[last_index] |= (number >> (b - 8)).truncate_as_u8(); + self.data.push((number << (16 - b)).truncate_as_u8()); } _ => { - *self.data.last_mut().unwrap() |= (number >> (b-8)) as u8; - self.data.push((number >> (b-16)) as u8); - self.data.push((number << (24-b)) as u8); + self.data[last_index] |= (number >> (b - 8)).truncate_as_u8(); + self.data.push((number >> (b - 16)).truncate_as_u8()); + self.data.push((number << (24 - b)).truncate_as_u8()); } } self.bit_offset = b & 7; @@ -66,7 +72,7 @@ impl Bits { if n > 16 || number >= (1 << n) { Err(QrError::DataTooLong) } else { - self.push_number(n, number as u16); + self.push_number(n, number.as_u16()); Ok(()) } } @@ -91,6 +97,11 @@ impl Bits { } } + /// Whether there are any bits pushed. + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } + /// The maximum number of bits allowed by the provided QR code version and /// error correction level. pub fn max_len(&self, ec_level: EcLevel) -> QrResult { @@ -107,34 +118,39 @@ impl Bits { fn test_push_number() { let mut bits = Bits::new(Version::Normal(1)); - bits.push_number(3, 0b010); // 0:0 .. 0:3 - bits.push_number(3, 0b110); // 0:3 .. 0:6 - bits.push_number(3, 0b101); // 0:6 .. 1:1 - bits.push_number(7, 0b001_1010);// 1:1 .. 2:0 - bits.push_number(4, 0b1100); // 2:0 .. 2:4 + bits.push_number(3, 0b010); // 0:0 .. 0:3 + bits.push_number(3, 0b110); // 0:3 .. 0:6 + bits.push_number(3, 0b101); // 0:6 .. 1:1 + bits.push_number(7, 0b001_1010); // 1:1 .. 2:0 + bits.push_number(4, 0b1100); // 2:0 .. 2:4 bits.push_number(12, 0b1011_0110_1101); // 2:4 .. 4:0 - bits.push_number(10, 0b01_1001_0001); // 4:0 .. 5:2 + bits.push_number(10, 0b01_1001_0001); // 4:0 .. 5:2 bits.push_number(15, 0b111_0010_1110_0011); // 5:2 .. 7:1 let bytes = bits.into_bytes(); - assert_eq!(bytes, vec![0b010__110__10, // 90 - 0b1__001_1010, // 154 - 0b1100__1011, // 203 - 0b0110_1101, // 109 - 0b01_1001_00, // 100 - 0b01__111_001, // 121 - 0b0_1110_001, // 113 - 0b1__0000000]); // 128 + assert_eq!( + bytes, + vec![ + 0b010__110__10, // 90 + 0b1__001_1010, // 154 + 0b1100__1011, // 203 + 0b0110_1101, // 109 + 0b01_1001_00, // 100 + 0b01__111_001, // 121 + 0b0_1110_001, // 113 + 0b1__0000000, // 128 + ] + ); } -#[cfg(feature="bench")] +#[cfg(feature = "bench")] #[bench] fn bench_push_splitted_bytes(bencher: &mut Bencher) { bencher.iter(|| { let mut bits = Bits::new(Version::Normal(40)); bits.push_number(4, 0b0101); - for _ in 0 .. 1024 { + for _ in 0..1024 { bits.push_number(8, 0b10101010); } bits.into_bytes() @@ -171,6 +187,7 @@ impl Bits { /// If the mode is not supported in the provided version, this method /// returns `Err(QrError::UnsupportedCharacterSet)`. pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> { + #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] let number = match (self.version, mode) { (Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()), (Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0, @@ -188,7 +205,8 @@ impl Bits { (_, ExtendedMode::StructuredAppend) => 0b0011, }; let bits = self.version.mode_bits_count(); - self.push_number_checked(bits, number).or(Err(QrError::UnsupportedCharacterSet)) + self.push_number_checked(bits, number) + .or(Err(QrError::UnsupportedCharacterSet)) } } @@ -234,19 +252,19 @@ impl Bits { /// return `Err(QrError::InvalidECIDesignator)`. pub fn push_eci_designator(&mut self, eci_designator: u32) -> QrResult<()> { self.reserve(12); // assume the common case that eci_designator <= 127. - try!(self.push_mode_indicator(ExtendedMode::Eci)); + self.push_mode_indicator(ExtendedMode::Eci)?; match eci_designator { 0...127 => { - self.push_number(8, eci_designator as u16); + self.push_number(8, eci_designator.as_u16()); } 128...16383 => { self.push_number(2, 0b10); - self.push_number(14, eci_designator as u16); + self.push_number(14, eci_designator.as_u16()); } 16384...999999 => { self.push_number(3, 0b110); - self.push_number(5, (eci_designator >> 16) as u16); - self.push_number(16, (eci_designator & 0xffff) as u16); + self.push_number(5, (eci_designator >> 16).as_u16()); + self.push_number(16, (eci_designator & 0xffff).as_u16()); } _ => return Err(QrError::InvalidEciDesignator), } @@ -257,7 +275,7 @@ impl Bits { #[cfg(test)] mod eci_tests { use bits::Bits; - use types::{Version, QrError}; + use types::{QrError, Version}; #[test] fn test_9() { @@ -277,10 +295,7 @@ mod eci_tests { fn test_999999() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_eci_designator(999999), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0111__110_0, - 0b11110100, - 0b00100011, - 0b1111__0000]); + assert_eq!(bits.into_bytes(), vec![0b0111__110_0, 0b11110100, 0b00100011, 0b1111__0000]); } #[test] @@ -304,8 +319,8 @@ impl Bits { fn push_header(&mut self, mode: Mode, raw_data_len: usize) -> QrResult<()> { let length_bits = mode.length_bits_count(self.version); self.reserve(length_bits + 4 + mode.data_bits_count(raw_data_len)); - try!(self.push_mode_indicator(ExtendedMode::Data(mode))); - try!(self.push_number_checked(length_bits, raw_data_len)); + self.push_mode_indicator(ExtendedMode::Data(mode))?; + self.push_number_checked(length_bits, raw_data_len)?; Ok(()) } @@ -313,9 +328,12 @@ impl Bits { /// /// The data should only contain the characters 0 to 9. pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> { - try!(self.push_header(Mode::Numeric, data.len())); + self.push_header(Mode::Numeric, data.len())?; for chunk in data.chunks(3) { - let number = chunk.iter().map(|b| (*b - b'0') as u16).fold(0, |a, b| a*10 + b); + let number = chunk + .iter() + .map(|b| u16::from(*b - b'0')) + .fold(0, |a, b| a * 10 + b); let length = chunk.len() * 3 + 1; self.push_number(length, number); } @@ -326,47 +344,55 @@ impl Bits { #[cfg(test)] mod numeric_tests { use bits::Bits; - use types::{Version, QrError}; + use types::{QrError, Version}; #[test] fn test_iso_18004_2006_example_1() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_numeric_data(b"01234567"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0001_0000, - 0b001000_00, - 0b00001100, - 0b01010110, - 0b01_100001, - 0b1__0000000]); + assert_eq!( + bits.into_bytes(), + vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b01_100001, 0b1__0000000] + ); } #[test] fn test_iso_18004_2000_example_2() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0001_0000, - 0b010000_00, - 0b00001100, - 0b01010110, - 0b01_101010, - 0b0110_1110, - 0b000101_00, - 0b11101010, - 0b0101__0000]); + assert_eq!( + bits.into_bytes(), + vec![ + 0b0001_0000, + 0b010000_00, + 0b00001100, + 0b01010110, + 0b01_101010, + 0b0110_1110, + 0b000101_00, + 0b11101010, + 0b0101__0000, + ] + ); } #[test] fn test_iso_18004_2006_example_2() { let mut bits = Bits::new(Version::Micro(3)); assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b00_10000_0, - 0b00000110, - 0b0_0101011, - 0b001_10101, - 0b00110_111, - 0b0000101_0, - 0b01110101, - 0b00101__000]); + assert_eq!( + bits.into_bytes(), + vec![ + 0b00_10000_0, + 0b00000110, + 0b0_0101011, + 0b001_10101, + 0b00110_111, + 0b0000101_0, + 0b01110101, + 0b00101__000, + ] + ); } #[test] @@ -380,16 +406,16 @@ mod numeric_tests { //------------------------------------------------------------------------------ //{{{ Mode::Alphanumeric mode -/// In QR code "Mode::Alphanumeric" mode, a pair of alphanumeric characters will be -/// encoded as a base-45 integer. `alphanumeric_digit` converts each character -/// into its corresponding base-45 digit. +/// In QR code `Mode::Alphanumeric` mode, a pair of alphanumeric characters will +/// be encoded as a base-45 integer. `alphanumeric_digit` converts each +/// character into its corresponding base-45 digit. /// /// The conversion is specified in ISO/IEC 18004:2006, §8.4.3, Table 5. #[inline] fn alphanumeric_digit(character: u8) -> u16 { match character { - b'0' ... b'9' => (character - b'0') as u16, - b'A' ... b'Z' => (character - b'A') as u16 + 10, + b'0'...b'9' => u16::from(character - b'0'), + b'A'...b'Z' => u16::from(character - b'A') + 10, b' ' => 36, b'$' => 37, b'%' => 38, @@ -409,9 +435,12 @@ impl Bits { /// The data should only contain the charaters A to Z (excluding lowercase), /// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`. pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> { - try!(self.push_header(Mode::Alphanumeric, data.len())); + self.push_header(Mode::Alphanumeric, data.len())?; for chunk in data.chunks(2) { - let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a*45 + b); + let number = chunk + .iter() + .map(|b| alphanumeric_digit(*b)) + .fold(0, |a, b| a * 45 + b); let length = chunk.len() * 5 + 1; self.push_number(length, number); } @@ -422,18 +451,16 @@ impl Bits { #[cfg(test)] mod alphanumeric_tests { use bits::Bits; - use types::{Version, QrError}; + use types::{QrError, Version}; #[test] fn test_iso_18004_2006_example() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_alphanumeric_data(b"AC-42"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0010_0000, - 0b00101_001, - 0b11001110, - 0b11100111, - 0b001_00001, - 0b0__0000000]); + assert_eq!( + bits.into_bytes(), + vec![0b0010_0000, 0b00101_001, 0b11001110, 0b11100111, 0b001_00001, 0b0__0000000] + ); } #[test] @@ -456,9 +483,9 @@ mod alphanumeric_tests { impl Bits { /// Encodes 8-bit byte data to the bits. pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> { - try!(self.push_header(Mode::Byte, data.len())); + self.push_header(Mode::Byte, data.len())?; for b in data { - self.push_number(8, *b as u16); + self.push_number(8, u16::from(*b)); } Ok(()) } @@ -467,22 +494,27 @@ impl Bits { #[cfg(test)] mod byte_tests { use bits::Bits; - use types::{Version, QrError}; + use types::{QrError, Version}; #[test] fn test() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_byte_data(b"\x12\x34\x56\x78\x9a\xbc\xde\xf0"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b0100_0000, - 0b1000_0001, - 0b0010_0011, - 0b0100_0101, - 0b0110_0111, - 0b1000_1001, - 0b1010_1011, - 0b1100_1101, - 0b1110_1111, - 0b0000__0000]); + assert_eq!( + bits.into_bytes(), + vec![ + 0b0100_0000, + 0b1000_0001, + 0b0010_0011, + 0b0100_0101, + 0b0110_0111, + 0b1000_1001, + 0b1010_1011, + 0b1100_1101, + 0b1110_1111, + 0b0000__0000, + ] + ); } #[test] @@ -505,13 +537,17 @@ mod byte_tests { impl Bits { /// Encodes Shift JIS double-byte data to the bits. pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> { - try!(self.push_header(Mode::Kanji, data.len()/2)); + self.push_header(Mode::Kanji, data.len() / 2)?; for kanji in data.chunks(2) { if kanji.len() != 2 { return Err(QrError::InvalidCharacter); } - let cp = (kanji[0] as u16) * 256 + (kanji[1] as u16); - let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 }; + let cp = u16::from(kanji[0]) * 256 + u16::from(kanji[1]); + let bytes = if cp < 0xe040 { + cp - 0x8140 + } else { + cp - 0xc140 + }; let number = (bytes >> 8) * 0xc0 + (bytes & 0xff); self.push_number(13, number); } @@ -522,17 +558,16 @@ impl Bits { #[cfg(test)] mod kanji_tests { use bits::Bits; - use types::{Version, QrError}; + use types::{QrError, Version}; #[test] fn test_iso_18004_example() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_kanji_data(b"\x93\x5f\xe4\xaa"), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b1000_0000, - 0b0010_0110, - 0b11001111, - 0b1_1101010, - 0b101010__00]); + assert_eq!( + bits.into_bytes(), + vec![0b1000_0000, 0b0010_0110, 0b11001111, 0b1_1101010, 0b101010__00] + ); } #[test] @@ -544,8 +579,10 @@ mod kanji_tests { #[test] fn test_data_too_long() { let mut bits = Bits::new(Version::Micro(3)); - assert_eq!(bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"), - Err(QrError::DataTooLong)); + assert_eq!( + bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"), + Err(QrError::DataTooLong) + ); } } @@ -593,8 +630,8 @@ impl Bits { /// bits.push_fnc1_second_position(b'A' + 100); /// ``` pub fn push_fnc1_second_position(&mut self, application_indicator: u8) -> QrResult<()> { - try!(self.push_mode_indicator(ExtendedMode::Fnc1Second)); - self.push_number(8, application_indicator as u16); + self.push_mode_indicator(ExtendedMode::Fnc1Second)?; + self.push_number(8, u16::from(application_indicator)); Ok(()) } } @@ -646,7 +683,6 @@ static DATA_LENGTHS: [[usize; 4]; 44] = [ [21616, 16816, 12016, 9136], [22496, 17728, 12656, 9776], [23648, 18672, 13328, 10208], - // Micro versions [20, 0, 0, 0], [40, 32, 0, 0], @@ -658,12 +694,12 @@ impl Bits { /// Pushes the ending bits to indicate no more data. pub fn push_terminator(&mut self, ec_level: EcLevel) -> QrResult<()> { let terminator_size = match self.version { - Version::Micro(a) => (a as usize) * 2 + 1, + Version::Micro(a) => a.as_usize() * 2 + 1, _ => 4, }; let cur_length = self.len(); - let data_length = try!(self.max_len(ec_level)); + let data_length = self.max_len(ec_level)?; if cur_length > data_length { return Err(QrError::DataTooLong); } @@ -679,7 +715,11 @@ impl Bits { self.bit_offset = 0; let data_bytes_length = data_length / 8; let padding_bytes_count = data_bytes_length - self.data.len(); - let padding = PADDING_BYTES.iter().cloned().cycle().take(padding_bytes_count); + let padding = PADDING_BYTES + .iter() + .cloned() + .cycle() + .take(padding_bytes_count); self.data.extend(padding); } @@ -694,18 +734,31 @@ impl Bits { #[cfg(test)] mod finish_tests { use bits::Bits; - use types::{Version, EcLevel, QrError}; + use types::{EcLevel, QrError, Version}; #[test] fn test_hello_world() { let mut bits = Bits::new(Version::Normal(1)); assert_eq!(bits.push_alphanumeric_data(b"HELLO WORLD"), Ok(())); assert_eq!(bits.push_terminator(EcLevel::Q), Ok(())); - assert_eq!(bits.into_bytes(), vec![0b00100000, 0b01011011, 0b00001011, - 0b01111000, 0b11010001, 0b01110010, - 0b11011100, 0b01001101, 0b01000011, - 0b01000000, 0b11101100, 0b00010001, - 0b11101100]); + assert_eq!( + bits.into_bytes(), + vec![ + 0b00100000, + 0b01011011, + 0b00001011, + 0b01111000, + 0b11010001, + 0b01110010, + 0b11011100, + 0b01001101, + 0b01000011, + 0b01000000, + 0b11101100, + 0b00010001, + 0b11101100, + ] + ); } #[test] @@ -755,16 +808,17 @@ mod finish_tests { impl Bits { /// Push a segmented data to the bits, and then terminate it. pub fn push_segments(&mut self, data: &[u8], segments_iter: I) -> QrResult<()> - where I: Iterator + where + I: Iterator, { for segment in segments_iter { - let slice = &data[segment.begin .. segment.end]; - try!(match segment.mode { + let slice = &data[segment.begin..segment.end]; + match segment.mode { Mode::Numeric => self.push_numeric_data(slice), Mode::Alphanumeric => self.push_alphanumeric_data(slice), Mode::Byte => self.push_byte_data(slice), Mode::Kanji => self.push_kanji_data(slice), - }); + }?; } Ok(()) } @@ -774,36 +828,50 @@ impl Bits { let segments = Parser::new(data).optimize(self.version); self.push_segments(data, segments) } - } #[cfg(test)] mod encode_tests { use bits::Bits; - use types::{Version, QrError, QrResult, EcLevel}; + use types::{EcLevel, QrError, QrResult, Version}; fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult> { let mut bits = Bits::new(version); - try!(bits.push_optimal_data(data)); - try!(bits.push_terminator(ec_level)); + bits.push_optimal_data(data)?; + bits.push_terminator(ec_level)?; Ok(bits.into_bytes()) } #[test] fn test_alphanumeric() { let res = encode(b"HELLO WORLD", Version::Normal(1), EcLevel::Q); - assert_eq!(res, Ok(vec![0b00100000, 0b01011011, 0b00001011, - 0b01111000, 0b11010001, 0b01110010, - 0b11011100, 0b01001101, 0b01000011, - 0b01000000, 0b11101100, 0b00010001, - 0b11101100])); + assert_eq!( + res, + Ok(vec![ + 0b00100000, + 0b01011011, + 0b00001011, + 0b01111000, + 0b11010001, + 0b01110010, + 0b11011100, + 0b01001101, + 0b01000011, + 0b01000000, + 0b11101100, + 0b00010001, + 0b11101100, + ]) + ); } #[test] fn test_auto_mode_switch() { let res = encode(b"123A", Version::Micro(2), EcLevel::L); - assert_eq!(res, Ok(vec![0b0_0011_000, 0b1111011_1, 0b001_00101, - 0b0_00000__00, 0b11101100])); + assert_eq!( + res, + Ok(vec![0b0_0011_000, 0b1111011_1, 0b001_00101, 0b0_00000__00, 0b11101100]) + ); } #[test] @@ -824,15 +892,17 @@ mod encode_tests { pub fn encode_auto(data: &[u8], ec_level: EcLevel) -> QrResult { let segments = Parser::new(data).collect::>(); for version in &[Version::Normal(9), Version::Normal(26), Version::Normal(40)] { - let opt_segments = Optimizer::new(segments.iter().map(|s| *s), *version).collect::>(); + let opt_segments = Optimizer::new(segments.iter().cloned(), *version).collect::>(); let total_len = total_encoded_len(&*opt_segments, *version); - let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).unwrap(); + let data_capacity = version + .fetch(ec_level, &DATA_LENGTHS) + .expect("invalid DATA_LENGTHS"); if total_len <= data_capacity { let min_version = find_min_version(total_len, ec_level); let mut bits = Bits::new(min_version); bits.reserve(total_len); - try!(bits.push_segments(data, opt_segments.into_iter())); - try!(bits.push_terminator(ec_level)); + bits.push_segments(data, opt_segments.into_iter())?; + bits.push_terminator(ec_level)?; return Ok(bits); } } @@ -852,13 +922,13 @@ fn find_min_version(length: usize, ec_level: EcLevel) -> Version { max = half; } } - Version::Normal((min + 1) as i16) + Version::Normal((min + 1).as_i16()) } #[cfg(test)] mod encode_auto_tests { - use bits::{find_min_version, encode_auto}; - use types::{Version, EcLevel}; + use bits::{encode_auto, find_min_version}; + use types::{EcLevel, Version}; #[test] fn test_find_min_version() { @@ -893,5 +963,3 @@ mod encode_auto_tests { //}}} //------------------------------------------------------------------------------ - - diff --git a/src/canvas.rs b/src/canvas.rs index 798f863..316c5c3 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -12,11 +12,12 @@ use std::cmp::max; use std::ops::Range; -use types::{Version, EcLevel, Color}; +use types::{Color, EcLevel, Version}; +use cast::As; -// TODO remove this after `p ... q` becomes stable. See rust-lang/rust#28237. +// TODO remove this after `p..=q` becomes stable. See rust-lang/rust#28237. fn range_inclusive(from: i16, to: i16) -> Range { - from .. (to + 1) + from..(to + 1) } //------------------------------------------------------------------------------ @@ -37,7 +38,7 @@ pub enum Module { } impl From for Color { - fn from(module: Module) -> Color { + fn from(module: Module) -> Self { match module { Module::Empty => Color::Light, Module::Masked(c) | Module::Unmasked(c) => c, @@ -62,13 +63,12 @@ impl Module { /// assert_eq!(Module::Masked(Color::Dark).mask(true), Module::Masked(Color::Dark)); /// assert_eq!(Module::Masked(Color::Dark).mask(false), Module::Masked(Color::Dark)); /// - pub fn mask(self, should_invert: bool) -> Module { + pub fn mask(self, should_invert: bool) -> Self { match (self, should_invert) { (Module::Empty, true) => Module::Masked(Color::Dark), (Module::Empty, false) => Module::Masked(Color::Light), (Module::Unmasked(c), true) => Module::Masked(!c), - (Module::Unmasked(c), false) | - (Module::Masked(c), _) => Module::Masked(c), + (Module::Unmasked(c), false) | (Module::Masked(c), _) => Module::Masked(c), } } } @@ -97,13 +97,13 @@ pub struct Canvas { impl Canvas { /// Constructs a new canvas big enough for a QR code of the given version. - pub fn new(version: Version, ec_level: EcLevel) -> Canvas { + pub fn new(version: Version, ec_level: EcLevel) -> Self { let width = version.width(); - Canvas { + Self { width: width, version: version, ec_level: ec_level, - modules: vec![Module::Empty; (width*width) as usize], + modules: vec![Module::Empty; (width * width).as_usize()], } } @@ -112,9 +112,9 @@ impl Canvas { fn to_debug_str(&self) -> String { let width = self.width; let mut res = String::with_capacity((width * (width + 1)) as usize); - for y in 0 .. width { + for y in 0..width { res.push('\n'); - for x in 0 .. width { + for x in 0..width { res.push(match self.get(x, y) { Module::Empty => '?', Module::Masked(Color::Light) => '.', @@ -128,9 +128,9 @@ impl Canvas { } fn coords_to_index(&self, x: i16, y: i16) -> usize { - let x = if x < 0 { x + self.width } else { x } as usize; - let y = if y < 0 { y + self.width } else { y } as usize; - y * (self.width as usize) + x + let x = if x < 0 { x + self.width } else { x }.as_usize(); + let y = if y < 0 { y + self.width } else { y }.as_usize(); + y * self.width.as_usize() + x } /// Obtains a module at the given coordinates. For convenience, negative @@ -156,7 +156,7 @@ impl Canvas { #[cfg(test)] mod basic_canvas_tests { use canvas::{Canvas, Module}; - use types::{Version, EcLevel, Color}; + use types::{Color, EcLevel, Version}; #[test] fn test_index() { @@ -164,21 +164,21 @@ mod basic_canvas_tests { assert_eq!(c.get(0, 4), Module::Empty); assert_eq!(c.get(-1, -7), Module::Empty); - assert_eq!(c.get(21-1, 21-7), Module::Empty); + assert_eq!(c.get(21 - 1, 21 - 7), Module::Empty); c.put(0, 0, Color::Dark); c.put(-1, -7, Color::Light); assert_eq!(c.get(0, 0), Module::Masked(Color::Dark)); - assert_eq!(c.get(21-1, -7), Module::Masked(Color::Light)); - assert_eq!(c.get(-1, 21-7), Module::Masked(Color::Light)); + assert_eq!(c.get(21 - 1, -7), Module::Masked(Color::Light)); + assert_eq!(c.get(-1, 21 - 7), Module::Masked(Color::Light)); } #[test] fn test_debug_str() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); - for i in 3i16 .. 20 { - for j in 3i16 .. 20 { + for i in 3i16..20 { + for j in 3i16..20 { *c.get_mut(i, j) = match ((i * 3) ^ j) % 5 { 0 => Module::Empty, 1 => Module::Masked(Color::Light), @@ -190,28 +190,31 @@ mod basic_canvas_tests { } } - assert_eq!(&*c.to_debug_str(), "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????####****....---?\n\ - ???--.##-..##?..#??.?\n\ - ???#*?-.*?#.-*#?-*.??\n\ - ?????*?*?****-*-*---?\n\ - ???*.-.-.-?-?#?#?#*#?\n\ - ???.*#.*.*#.*#*#.*#*?\n\ - ?????.#-#--??.?.#---?\n\ - ???-.?*.-#?-.?#*-#?.?\n\ - ???##*??*..##*--*..??\n\ - ?????-???--??---?---?\n\ - ???*.#.*.#**.#*#.#*#?\n\ - ???##.-##..##..?#..??\n\ - ???.-?*.-?#.-?#*-?#*?\n\ - ????-.#?-.**#?-.#?-.?\n\ - ???**?-**??--**?-**??\n\ - ???#?*?#?*#.*-.-*-.-?\n\ - ???..-...--??###?###?\n\ - ?????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????####****....---?\n\ + ???--.##-..##?..#??.?\n\ + ???#*?-.*?#.-*#?-*.??\n\ + ?????*?*?****-*-*---?\n\ + ???*.-.-.-?-?#?#?#*#?\n\ + ???.*#.*.*#.*#*#.*#*?\n\ + ?????.#-#--??.?.#---?\n\ + ???-.?*.-#?-.?#*-#?.?\n\ + ???##*??*..##*--*..??\n\ + ?????-???--??---?---?\n\ + ???*.#.*.#**.#*#.#*#?\n\ + ???##.-##..##..?#..??\n\ + ???.-?*.-?#.-?#*-?#*?\n\ + ????-.#?-.**#?-.#?-.?\n\ + ???**?-**??--**?-**??\n\ + ???#?*?#?*#.*-.-*-.-?\n\ + ???..-...--??###?###?\n\ + ?????????????????????" + ); } } @@ -226,12 +229,17 @@ impl Canvas { let (dy_top, dy_bottom) = if y >= 0 { (-3, 4) } else { (-4, 3) }; for j in range_inclusive(dy_top, dy_bottom) { for i in range_inclusive(dx_left, dx_right) { - self.put(x+i, y+j, match (i, j) { - (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light, - (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark, - (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light, - _ => Color::Dark, - }); + self.put( + x + i, + y + j, + #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] + match (i, j) { + (4, _) | (_, 4) | (-4, _) | (_, -4) => Color::Light, + (3, _) | (_, 3) | (-3, _) | (_, -3) => Color::Dark, + (2, _) | (_, 2) | (-2, _) | (_, -2) => Color::Light, + _ => Color::Dark, + }, + ); } } } @@ -245,7 +253,7 @@ impl Canvas { self.draw_finder_pattern_at(3, 3); match self.version { - Version::Micro(_) => { return; } + Version::Micro(_) => {} Version::Normal(_) => { self.draw_finder_pattern_at(-4, 3); self.draw_finder_pattern_at(3, -4); @@ -257,52 +265,58 @@ impl Canvas { #[cfg(test)] mod finder_pattern_tests { use canvas::Canvas; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_qr() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_finder_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.?????.#######\n\ - #.....#.?????.#.....#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.....#.?????.#.....#\n\ - #######.?????.#######\n\ - ........?????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ........?????????????\n\ - #######.?????????????\n\ - #.....#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.....#.?????????????\n\ - #######.?????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.?????.#######\n\ + #.....#.?????.#.....#\n\ + #.###.#.?????.#.###.#\n\ + #.###.#.?????.#.###.#\n\ + #.###.#.?????.#.###.#\n\ + #.....#.?????.#.....#\n\ + #######.?????.#######\n\ + ........?????........\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ........?????????????\n\ + #######.?????????????\n\ + #.....#.?????????????\n\ + #.###.#.?????????????\n\ + #.###.#.?????????????\n\ + #.###.#.?????????????\n\ + #.....#.?????????????\n\ + #######.?????????????" + ); } #[test] fn test_micro_qr() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); c.draw_finder_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.???\n\ - #.....#.???\n\ - #.###.#.???\n\ - #.###.#.???\n\ - #.###.#.???\n\ - #.....#.???\n\ - #######.???\n\ - ........???\n\ - ???????????\n\ - ???????????\n\ - ???????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.???\n\ + #.....#.???\n\ + #.###.#.???\n\ + #.###.#.???\n\ + #.###.#.???\n\ + #.....#.???\n\ + #######.???\n\ + ........???\n\ + ???????????\n\ + ???????????\n\ + ???????????" + ); } } @@ -318,10 +332,14 @@ impl Canvas { } for j in range_inclusive(-2, 2) { for i in range_inclusive(-2, 2) { - self.put(x+i, y+j, match (i, j) { - (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark, - _ => Color::Light, - }); + self.put( + x + i, + y + j, + match (i, j) { + (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Color::Dark, + _ => Color::Light, + }, + ); } } } @@ -332,10 +350,10 @@ impl Canvas { /// to help the scanner create the square grid. fn draw_alignment_patterns(&mut self) { match self.version { - Version::Micro(_) | Version::Normal(1) => { return; } + Version::Micro(_) | Version::Normal(1) => {} Version::Normal(2...6) => self.draw_alignment_pattern_at(-7, -7), Version::Normal(a) => { - let positions = ALIGNMENT_PATTERN_POSITIONS[a as usize - 7]; + let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()]; for x in positions.iter() { for y in positions.iter() { self.draw_alignment_pattern_at(*x, *y); @@ -349,35 +367,38 @@ impl Canvas { #[cfg(test)] mod alignment_pattern_tests { use canvas::Canvas; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_draw_alignment_patterns_1() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_finder_patterns(); c.draw_alignment_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.?????.#######\n\ - #.....#.?????.#.....#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.###.#.?????.#.###.#\n\ - #.....#.?????.#.....#\n\ - #######.?????.#######\n\ - ........?????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ........?????????????\n\ - #######.?????????????\n\ - #.....#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.###.#.?????????????\n\ - #.....#.?????????????\n\ - #######.?????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.?????.#######\n\ + #.....#.?????.#.....#\n\ + #.###.#.?????.#.###.#\n\ + #.###.#.?????.#.###.#\n\ + #.###.#.?????.#.###.#\n\ + #.....#.?????.#.....#\n\ + #######.?????.#######\n\ + ........?????........\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ........?????????????\n\ + #######.?????????????\n\ + #.....#.?????????????\n\ + #.###.#.?????????????\n\ + #.###.#.?????????????\n\ + #.###.#.?????????????\n\ + #.....#.?????????????\n\ + #######.?????????????" + ); } #[test] @@ -385,36 +406,39 @@ mod alignment_pattern_tests { let mut c = Canvas::new(Version::Normal(3), EcLevel::L); c.draw_finder_patterns(); c.draw_alignment_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.?????????????.#######\n\ - #.....#.?????????????.#.....#\n\ - #.###.#.?????????????.#.###.#\n\ - #.###.#.?????????????.#.###.#\n\ - #.###.#.?????????????.#.###.#\n\ - #.....#.?????????????.#.....#\n\ - #######.?????????????.#######\n\ - ........?????????????........\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ?????????????????????????????\n\ - ????????????????????#####????\n\ - ........????????????#...#????\n\ - #######.????????????#.#.#????\n\ - #.....#.????????????#...#????\n\ - #.###.#.????????????#####????\n\ - #.###.#.?????????????????????\n\ - #.###.#.?????????????????????\n\ - #.....#.?????????????????????\n\ - #######.?????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.?????????????.#######\n\ + #.....#.?????????????.#.....#\n\ + #.###.#.?????????????.#.###.#\n\ + #.###.#.?????????????.#.###.#\n\ + #.###.#.?????????????.#.###.#\n\ + #.....#.?????????????.#.....#\n\ + #######.?????????????.#######\n\ + ........?????????????........\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ?????????????????????????????\n\ + ????????????????????#####????\n\ + ........????????????#...#????\n\ + #######.????????????#.#.#????\n\ + #.....#.????????????#...#????\n\ + #.###.#.????????????#####????\n\ + #.###.#.?????????????????????\n\ + #.###.#.?????????????????????\n\ + #.....#.?????????????????????\n\ + #######.?????????????????????" + ); } #[test] @@ -422,52 +446,55 @@ mod alignment_pattern_tests { let mut c = Canvas::new(Version::Normal(7), EcLevel::L); c.draw_finder_patterns(); c.draw_alignment_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.?????????????????????????????.#######\n\ - #.....#.?????????????????????????????.#.....#\n\ - #.###.#.?????????????????????????????.#.###.#\n\ - #.###.#.?????????????????????????????.#.###.#\n\ - #.###.#.????????????#####????????????.#.###.#\n\ - #.....#.????????????#...#????????????.#.....#\n\ - #######.????????????#.#.#????????????.#######\n\ - ........????????????#...#????????????........\n\ - ????????????????????#####????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ????#####???????????#####???????????#####????\n\ - ????#...#???????????#...#???????????#...#????\n\ - ????#.#.#???????????#.#.#???????????#.#.#????\n\ - ????#...#???????????#...#???????????#...#????\n\ - ????#####???????????#####???????????#####????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ????????????????????#####???????????#####????\n\ - ........????????????#...#???????????#...#????\n\ - #######.????????????#.#.#???????????#.#.#????\n\ - #.....#.????????????#...#???????????#...#????\n\ - #.###.#.????????????#####???????????#####????\n\ - #.###.#.?????????????????????????????????????\n\ - #.###.#.?????????????????????????????????????\n\ - #.....#.?????????????????????????????????????\n\ - #######.?????????????????????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.?????????????????????????????.#######\n\ + #.....#.?????????????????????????????.#.....#\n\ + #.###.#.?????????????????????????????.#.###.#\n\ + #.###.#.?????????????????????????????.#.###.#\n\ + #.###.#.????????????#####????????????.#.###.#\n\ + #.....#.????????????#...#????????????.#.....#\n\ + #######.????????????#.#.#????????????.#######\n\ + ........????????????#...#????????????........\n\ + ????????????????????#####????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ????#####???????????#####???????????#####????\n\ + ????#...#???????????#...#???????????#...#????\n\ + ????#.#.#???????????#.#.#???????????#.#.#????\n\ + ????#...#???????????#...#???????????#...#????\n\ + ????#####???????????#####???????????#####????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ????????????????????#####???????????#####????\n\ + ........????????????#...#???????????#...#????\n\ + #######.????????????#.#.#???????????#.#.#????\n\ + #.....#.????????????#...#???????????#...#????\n\ + #.###.#.????????????#####???????????#####????\n\ + #.###.#.?????????????????????????????????????\n\ + #.###.#.?????????????????????????????????????\n\ + #.....#.?????????????????????????????????????\n\ + #######.?????????????????????????????????????" + ); } } @@ -527,15 +554,24 @@ impl Canvas { /// `color_odd` will be plotted instead. Thus the timing pattern can be /// drawn using this method. /// - fn draw_line(&mut self, x1: i16, y1: i16, x2: i16, y2: i16, - color_even: Color, color_odd: Color) { + fn draw_line( + &mut self, + x1: i16, + y1: i16, + x2: i16, + y2: i16, + color_even: Color, + color_odd: Color, + ) { debug_assert!(x1 == x2 || y1 == y2); - if y1 == y2 { // Horizontal line. + if y1 == y2 { + // Horizontal line. for x in range_inclusive(x1, x2) { self.put(x, y1, if x % 2 == 0 { color_even } else { color_odd }); } - } else { // Vertical line. + } else { + // Vertical line. for y in range_inclusive(y1, y2) { self.put(x1, y, if y % 2 == 0 { color_even } else { color_odd }); } @@ -550,8 +586,8 @@ impl Canvas { fn draw_timing_patterns(&mut self) { let width = self.width; let (y, x1, x2) = match self.version { - Version::Micro(_) => (0, 8, width-1), - Version::Normal(_) => (6, 8, width-9), + Version::Micro(_) => (0, 8, width - 1), + Version::Normal(_) => (6, 8, width - 9), }; self.draw_line(x1, y, x2, y, Color::Dark, Color::Light); self.draw_line(y, x1, y, x2, Color::Dark, Color::Light); @@ -561,52 +597,58 @@ impl Canvas { #[cfg(test)] mod timing_pattern_tests { use canvas::Canvas; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_draw_timing_patterns_qr() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_timing_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#.#.#????????\n\ - ?????????????????????\n\ - ??????#??????????????\n\ - ??????.??????????????\n\ - ??????#??????????????\n\ - ??????.??????????????\n\ - ??????#??????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ????????#.#.#????????\n\ + ?????????????????????\n\ + ??????#??????????????\n\ + ??????.??????????????\n\ + ??????#??????????????\n\ + ??????.??????????????\n\ + ??????#??????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????" + ); } #[test] fn test_draw_timing_patterns_micro_qr() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); c.draw_timing_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ????????#.#\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - #??????????\n\ - .??????????\n\ - #??????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ????????#.#\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + #??????????\n\ + .??????????\n\ + #??????????" + ); } } @@ -621,11 +663,21 @@ impl Canvas { /// `off_color`. The coordinates will be extracted from the `coords` /// iterator. It will start from the most significant bits first, so /// *trailing* zeros will be ignored. - fn draw_number(&mut self, number: u32, bits: u32, - on_color: Color, off_color: Color, coords: &[(i16, i16)]) { + fn draw_number( + &mut self, + number: u32, + bits: u32, + on_color: Color, + off_color: Color, + coords: &[(i16, i16)], + ) { let mut mask = 1 << (bits - 1); for &(x, y) in coords { - let color = if (mask & number) == 0 { off_color } else { on_color }; + let color = if (mask & number) == 0 { + off_color + } else { + on_color + }; self.put(x, y, color); mask >>= 1; } @@ -633,17 +685,32 @@ impl Canvas { /// Draws the format info patterns for an encoded number. fn draw_format_info_patterns_with_number(&mut self, format_info: u16) { - let format_info = format_info as u32; + let format_info = u32::from(format_info); match self.version { Version::Micro(_) => { - self.draw_number(format_info, 15, Color::Dark, Color::Light, - &FORMAT_INFO_COORDS_MICRO_QR); + self.draw_number( + format_info, + 15, + Color::Dark, + Color::Light, + &FORMAT_INFO_COORDS_MICRO_QR, + ); } Version::Normal(_) => { - self.draw_number(format_info, 15, Color::Dark, Color::Light, - &FORMAT_INFO_COORDS_QR_MAIN); - self.draw_number(format_info, 15, Color::Dark, Color::Light, - &FORMAT_INFO_COORDS_QR_SIDE); + self.draw_number( + format_info, + 15, + Color::Dark, + Color::Light, + &FORMAT_INFO_COORDS_QR_MAIN, + ); + self.draw_number( + format_info, + 15, + Color::Dark, + Color::Light, + &FORMAT_INFO_COORDS_QR_SIDE, + ); self.put(8, -8, Color::Dark); // Dark module. } } @@ -657,13 +724,25 @@ impl Canvas { /// Draws the version information patterns. fn draw_version_info_patterns(&mut self) { match self.version { - Version::Micro(_) | Version::Normal(1...6) => { return; } + Version::Micro(_) | Version::Normal(1...6) => { + return; + } Version::Normal(a) => { - let version_info = VERSION_INFOS[(a - 7) as usize]; - self.draw_number(version_info, 18, Color::Dark, Color::Light, - &VERSION_INFO_COORDS_BL); - self.draw_number(version_info, 18, Color::Dark, Color::Light, - &VERSION_INFO_COORDS_TR); + let version_info = VERSION_INFOS[(a - 7).as_usize()]; + self.draw_number( + version_info, + 18, + Color::Dark, + Color::Light, + &VERSION_INFO_COORDS_BL, + ); + self.draw_number( + version_info, + 18, + Color::Dark, + Color::Light, + &VERSION_INFO_COORDS_TR, + ); } } } @@ -672,53 +751,64 @@ impl Canvas { #[cfg(test)] mod draw_version_info_tests { use canvas::Canvas; - use types::{Version, EcLevel, Color}; + use types::{Color, EcLevel, Version}; #[test] fn test_draw_number() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); - c.draw_number(0b10101101, 8, Color::Dark, Color::Light, - &[(0,0), (0,-1), (-2,-2), (-2,0)]); - assert_eq!(&*c.to_debug_str(), "\n\ - #????????.?\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ???????????\n\ - ?????????#?\n\ - .??????????"); + c.draw_number( + 0b10101101, + 8, + Color::Dark, + Color::Light, + &[(0, 0), (0, -1), (-2, -2), (-2, 0)], + ); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #????????.?\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ???????????\n\ + ?????????#?\n\ + .??????????" + ); } #[test] fn test_draw_version_info_1() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_version_info_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????" + ); } #[test] @@ -726,141 +816,241 @@ mod draw_version_info_tests { let mut c = Canvas::new(Version::Normal(7), EcLevel::L); c.draw_version_info_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ??????????????????????????????????..#????????\n\ - ??????????????????????????????????.#.????????\n\ - ??????????????????????????????????.#.????????\n\ - ??????????????????????????????????.##????????\n\ - ??????????????????????????????????###????????\n\ - ??????????????????????????????????...????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ....#.???????????????????????????????????????\n\ - .####.???????????????????????????????????????\n\ - #..##.???????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????\n\ - ?????????????????????????????????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ??????????????????????????????????..#????????\n\ + ??????????????????????????????????.#.????????\n\ + ??????????????????????????????????.#.????????\n\ + ??????????????????????????????????.##????????\n\ + ??????????????????????????????????###????????\n\ + ??????????????????????????????????...????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ....#.???????????????????????????????????????\n\ + .####.???????????????????????????????????????\n\ + #..##.???????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????\n\ + ?????????????????????????????????????????????" + ); } #[test] fn test_draw_reserved_format_info_patterns_qr() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_reserved_format_info_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ?????????????????????\n\ - ????????.????????????\n\ - ......?..????........\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????.????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ?????????????????????\n\ + ????????.????????????\n\ + ......?..????........\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ????????#????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????.????????????" + ); } #[test] fn test_draw_reserved_format_info_patterns_micro_qr() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); c.draw_reserved_format_info_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - ???????????\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ????????.??\n\ - ?........??\n\ - ???????????\n\ - ???????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ???????????\n\ + ????????.??\n\ + ????????.??\n\ + ????????.??\n\ + ????????.??\n\ + ????????.??\n\ + ????????.??\n\ + ????????.??\n\ + ?........??\n\ + ???????????\n\ + ???????????" + ); } } static VERSION_INFO_COORDS_BL: [(i16, i16); 18] = [ - (5, -9), (5, -10), (5, -11), - (4, -9), (4, -10), (4, -11), - (3, -9), (3, -10), (3, -11), - (2, -9), (2, -10), (2, -11), - (1, -9), (1, -10), (1, -11), - (0, -9), (0, -10), (0, -11), + (5, -9), + (5, -10), + (5, -11), + (4, -9), + (4, -10), + (4, -11), + (3, -9), + (3, -10), + (3, -11), + (2, -9), + (2, -10), + (2, -11), + (1, -9), + (1, -10), + (1, -11), + (0, -9), + (0, -10), + (0, -11), ]; static VERSION_INFO_COORDS_TR: [(i16, i16); 18] = [ - (-9, 5), (-10, 5), (-11, 5), - (-9, 4), (-10, 4), (-11, 4), - (-9, 3), (-10, 3), (-11, 3), - (-9, 2), (-10, 2), (-11, 2), - (-9, 1), (-10, 1), (-11, 1), - (-9, 0), (-10, 0), (-11, 0), + (-9, 5), + (-10, 5), + (-11, 5), + (-9, 4), + (-10, 4), + (-11, 4), + (-9, 3), + (-10, 3), + (-11, 3), + (-9, 2), + (-10, 2), + (-11, 2), + (-9, 1), + (-10, 1), + (-11, 1), + (-9, 0), + (-10, 0), + (-11, 0), ]; static FORMAT_INFO_COORDS_QR_MAIN: [(i16, i16); 15] = [ - (0, 8), (1, 8), (2, 8), (3, 8), (4, 8), (5, 8), - (7, 8), (8, 8), (8, 7), - (8, 5), (8, 4), (8, 3), (8, 2), (8, 1), (8, 0), + (0, 8), + (1, 8), + (2, 8), + (3, 8), + (4, 8), + (5, 8), + (7, 8), + (8, 8), + (8, 7), + (8, 5), + (8, 4), + (8, 3), + (8, 2), + (8, 1), + (8, 0), ]; static FORMAT_INFO_COORDS_QR_SIDE: [(i16, i16); 15] = [ - (8, -1), (8, -2), (8, -3), (8, -4), (8, -5), (8, -6), (8, -7), - (-8, 8), (-7, 8), (-6, 8), (-5, 8), (-4, 8), (-3, 8), (-2, 8), (-1, 8), + (8, -1), + (8, -2), + (8, -3), + (8, -4), + (8, -5), + (8, -6), + (8, -7), + (-8, 8), + (-7, 8), + (-6, 8), + (-5, 8), + (-4, 8), + (-3, 8), + (-2, 8), + (-1, 8), ]; static FORMAT_INFO_COORDS_MICRO_QR: [(i16, i16); 15] = [ - (1, 8), (2, 8), (3, 8), (4, 8), (5, 8), (6, 8), (7, 8), (8, 8), - (8, 7), (8, 6), (8, 5), (8, 4), (8, 3), (8, 2), (8, 1), + (1, 8), + (2, 8), + (3, 8), + (4, 8), + (5, 8), + (6, 8), + (7, 8), + (8, 8), + (8, 7), + (8, 6), + (8, 5), + (8, 4), + (8, 3), + (8, 2), + (8, 1), ]; static VERSION_INFOS: [u32; 34] = [ - 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, - 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, - 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, - 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, - 0x27541, 0x28c69, + 0x07c94, + 0x085bc, + 0x09a99, + 0x0a4d3, + 0x0bbf6, + 0x0c762, + 0x0d847, + 0x0e60d, + 0x0f928, + 0x10b78, + 0x1145d, + 0x12a17, + 0x13532, + 0x149a6, + 0x15683, + 0x168c9, + 0x177ec, + 0x18ec4, + 0x191e1, + 0x1afab, + 0x1b08e, + 0x1cc1a, + 0x1d33f, + 0x1ed75, + 0x1f250, + 0x209d5, + 0x216f0, + 0x228ba, + 0x2379f, + 0x24b0b, + 0x2542e, + 0x26a64, + 0x27541, + 0x28c69, ]; //}}} @@ -894,11 +1084,10 @@ pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool { match version { Version::Micro(_) => x == 0 || y == 0 || (x < 9 && y < 9), Version::Normal(a) => { - let non_alignment_test = - x == 6 || y == 6 || // Timing patterns - (x < 9 && y < 9) || // Top-left finder pattern - (x < 9 && y >= width-8) || // Bottom-left finder pattern - (x >= width-8 && y < 9); // Top-right finder pattern + let non_alignment_test = x == 6 || y == 6 || // Timing patterns + (x < 9 && y < 9) || // Top-left finder pattern + (x < 9 && y >= width-8) || // Bottom-left finder pattern + (x >= width-8 && y < 9); // Top-right finder pattern if non_alignment_test { true } else if a == 1 { @@ -906,7 +1095,7 @@ pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool { } else if 2 <= a && a <= 6 { (width - 7 - x).abs() <= 2 && (width - 7 - y).abs() <= 2 } else { - let positions = ALIGNMENT_PATTERN_POSITIONS[a as usize - 7]; + let positions = ALIGNMENT_PATTERN_POSITIONS[(a - 7).as_usize()]; let last = positions.len() - 1; for (i, align_x) in positions.iter().enumerate() { for (j, align_y) in positions.iter().enumerate() { @@ -917,66 +1106,72 @@ pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool { return true; } } - }; + } false } - }, + } } } #[cfg(test)] mod all_functional_patterns_tests { - use canvas::{Canvas, is_functional}; - use types::{Version, EcLevel}; + use canvas::{is_functional, Canvas}; + use types::{EcLevel, Version}; #[test] fn test_all_functional_patterns_qr() { let mut c = Canvas::new(Version::Normal(2), EcLevel::L); c.draw_all_functional_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######..????????.#######\n\ - #.....#..????????.#.....#\n\ - #.###.#..????????.#.###.#\n\ - #.###.#..????????.#.###.#\n\ - #.###.#..????????.#.###.#\n\ - #.....#..????????.#.....#\n\ - #######.#.#.#.#.#.#######\n\ - .........????????........\n\ - ......#..????????........\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#??????????????????\n\ - ??????.??????????????????\n\ - ??????#?????????#####????\n\ - ........#???????#...#????\n\ - #######..???????#.#.#????\n\ - #.....#..???????#...#????\n\ - #.###.#..???????#####????\n\ - #.###.#..????????????????\n\ - #.###.#..????????????????\n\ - #.....#..????????????????\n\ - #######..????????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######..????????.#######\n\ + #.....#..????????.#.....#\n\ + #.###.#..????????.#.###.#\n\ + #.###.#..????????.#.###.#\n\ + #.###.#..????????.#.###.#\n\ + #.....#..????????.#.....#\n\ + #######.#.#.#.#.#.#######\n\ + .........????????........\n\ + ......#..????????........\n\ + ??????.??????????????????\n\ + ??????#??????????????????\n\ + ??????.??????????????????\n\ + ??????#??????????????????\n\ + ??????.??????????????????\n\ + ??????#??????????????????\n\ + ??????.??????????????????\n\ + ??????#?????????#####????\n\ + ........#???????#...#????\n\ + #######..???????#.#.#????\n\ + #.....#..???????#...#????\n\ + #.###.#..???????#####????\n\ + #.###.#..????????????????\n\ + #.###.#..????????????????\n\ + #.....#..????????????????\n\ + #######..????????????????" + ); } #[test] fn test_all_functional_patterns_micro_qr() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); c.draw_all_functional_patterns(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.#.#\n\ - #.....#..??\n\ - #.###.#..??\n\ - #.###.#..??\n\ - #.###.#..??\n\ - #.....#..??\n\ - #######..??\n\ - .........??\n\ - #........??\n\ - .??????????\n\ - #??????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.#.#\n\ + #.....#..??\n\ + #.###.#..??\n\ + #.###.#..??\n\ + #.###.#..??\n\ + #.....#..??\n\ + #######..??\n\ + .........??\n\ + #........??\n\ + .??????????\n\ + #??????????" + ); } #[test] @@ -1043,16 +1238,16 @@ struct DataModuleIter { } impl DataModuleIter { - fn new(version: Version) -> DataModuleIter { + fn new(version: Version) -> Self { let width = version.width(); - DataModuleIter { + Self { x: width - 1, y: width - 1, width: width, timing_pattern_column: match version { Version::Micro(_) => 0, Version::Normal(_) => 6, - } + }, } } } @@ -1095,6 +1290,7 @@ impl Iterator for DataModuleIter { } #[cfg(test)] +#[cfg_attr(rustfmt, rustfmt_skip)] // skip to prevent file becoming too long. mod data_iter_tests { use canvas::DataModuleIter; use types::Version; @@ -1264,22 +1460,23 @@ mod data_iter_tests { //{{{ Data placement impl Canvas { - fn draw_codewords<'a, I>(&mut self, - codewords: &[u8], - is_half_codeword_at_end: bool, - coords: &mut I) - where I: Iterator + fn draw_codewords(&mut self, codewords: &[u8], is_half_codeword_at_end: bool, coords: &mut I) + where + I: Iterator, { let length = codewords.len(); - let last_word = if is_half_codeword_at_end { length-1 } else { length }; + let last_word = if is_half_codeword_at_end { + length - 1 + } else { + length + }; for (i, b) in codewords.iter().enumerate() { let bits_end = if i == last_word { 4 } else { 0 }; - 'outside: - for j in range_inclusive(bits_end, 7).rev() { - let color = if (*b & (1 << j)) != 0 { - Color::Dark - } else { + 'outside: for j in range_inclusive(bits_end, 7).rev() { + let color = if (*b & (1 << j)) == 0 { Color::Light + } else { + Color::Dark }; while let Some((x, y)) = coords.next() { let r = self.get_mut(x, y); @@ -1309,58 +1506,68 @@ impl Canvas { #[cfg(test)] mod draw_codewords_test { use canvas::Canvas; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_micro_qr_1() { let mut c = Canvas::new(Version::Micro(1), EcLevel::L); c.draw_all_functional_patterns(); c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63"); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.#.#\n\ - #.....#..-*\n\ - #.###.#..**\n\ - #.###.#..*-\n\ - #.###.#..**\n\ - #.....#..*-\n\ - #######..*-\n\ - .........-*\n\ - #........**\n\ - .***-**---*\n\ - #---*-*-**-"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.#.#\n\ + #.....#..-*\n\ + #.###.#..**\n\ + #.###.#..*-\n\ + #.###.#..**\n\ + #.....#..*-\n\ + #######..*-\n\ + .........-*\n\ + #........**\n\ + .***-**---*\n\ + #---*-*-**-" + ); } #[test] fn test_qr_2() { let mut c = Canvas::new(Version::Normal(2), EcLevel::L); c.draw_all_functional_patterns(); - c.draw_data(b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$", b""); - assert_eq!(&*c.to_debug_str(), "\n\ - #######..--*---*-.#######\n\ - #.....#..-*-*-*-*.#.....#\n\ - #.###.#..*---*---.#.###.#\n\ - #.###.#..--*---*-.#.###.#\n\ - #.###.#..-*-*-*-*.#.###.#\n\ - #.....#..*---*---.#.....#\n\ - #######.#.#.#.#.#.#######\n\ - .........--*---*-........\n\ - ......#..-*-*-*-*........\n\ - --*-*-.-**---*---*--**--*\n\ - -*-*--#----*---*---------\n\ - *----*.*--*-*-*-*-**--**-\n\ - --*-*-#-**---*---*--**--*\n\ - -*-*--.----*---*---------\n\ - *----*#*--*-*-*-*-**--**-\n\ - --*-*-.-**---*---*--**--*\n\ - -*-*--#----*---*#####----\n\ - ........#-*-*-*-#...#-**-\n\ - #######..*---*--#.#.#*--*\n\ - #.....#..--*---*#...#----\n\ - #.###.#..-*-*-*-#####-**-\n\ - #.###.#..*---*--*----*--*\n\ - #.###.#..--*------**-----\n\ - #.....#..-*-*-**-*--*-**-\n\ - #######..*---*--*----*--*"); + c.draw_data( + b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\ + \x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$", + b"", + ); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######..--*---*-.#######\n\ + #.....#..-*-*-*-*.#.....#\n\ + #.###.#..*---*---.#.###.#\n\ + #.###.#..--*---*-.#.###.#\n\ + #.###.#..-*-*-*-*.#.###.#\n\ + #.....#..*---*---.#.....#\n\ + #######.#.#.#.#.#.#######\n\ + .........--*---*-........\n\ + ......#..-*-*-*-*........\n\ + --*-*-.-**---*---*--**--*\n\ + -*-*--#----*---*---------\n\ + *----*.*--*-*-*-*-**--**-\n\ + --*-*-#-**---*---*--**--*\n\ + -*-*--.----*---*---------\n\ + *----*#*--*-*-*-*-**--**-\n\ + --*-*-.-**---*---*--**--*\n\ + -*-*--#----*---*#####----\n\ + ........#-*-*-*-#...#-**-\n\ + #######..*---*--#.#.#*--*\n\ + #.....#..--*---*#...#----\n\ + #.###.#..-*-*-*-#####-**-\n\ + #.###.#..*---*--*----*--*\n\ + #.###.#..--*------**-----\n\ + #.....#..-*-*-**-*--*-**-\n\ + #######..*---*--*----*--*" + ); } } //}}} @@ -1397,14 +1604,30 @@ pub enum MaskPattern { } mod mask_functions { - pub fn checkerboard(x: i16, y: i16) -> bool { (x + y) % 2 == 0 } - pub fn horizontal_lines(_: i16, y: i16) -> bool { y % 2 == 0 } - pub fn vertical_lines(x: i16, _: i16) -> bool { x % 3 == 0 } - pub fn diagonal_lines(x: i16, y: i16) -> bool { (x + y) % 3 == 0 } - pub fn large_checkerboard(x: i16, y: i16) -> bool { ((y/2) + (x/3)) % 2 == 0 } - pub fn fields(x: i16, y: i16) -> bool { (x*y)%2 + (x*y)%3 == 0 } - pub fn diamonds(x: i16, y: i16) -> bool { ((x*y)%2 + (x*y)%3) % 2 == 0 } - pub fn meadow(x: i16, y: i16) -> bool { ((x+y)%2 + (x*y)%3) % 2 == 0 } + pub fn checkerboard(x: i16, y: i16) -> bool { + (x + y) % 2 == 0 + } + pub fn horizontal_lines(_: i16, y: i16) -> bool { + y % 2 == 0 + } + pub fn vertical_lines(x: i16, _: i16) -> bool { + x % 3 == 0 + } + pub fn diagonal_lines(x: i16, y: i16) -> bool { + (x + y) % 3 == 0 + } + pub fn large_checkerboard(x: i16, y: i16) -> bool { + ((y / 2) + (x / 3)) % 2 == 0 + } + pub fn fields(x: i16, y: i16) -> bool { + (x * y) % 2 + (x * y) % 3 == 0 + } + pub fn diamonds(x: i16, y: i16) -> bool { + ((x * y) % 2 + (x * y) % 3) % 2 == 0 + } + pub fn meadow(x: i16, y: i16) -> bool { + ((x + y) % 2 + (x * y) % 3) % 2 == 0 + } } fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool { @@ -1425,8 +1648,8 @@ impl Canvas { /// patterns. pub fn apply_mask(&mut self, pattern: MaskPattern) { let mask_fn = get_mask_function(pattern); - for x in 0 .. self.width { - for y in 0 .. self.width { + for x in 0..self.width { + for y in 0..self.width { let module = self.get_mut(x, y); *module = module.mask(mask_fn(x, y)); } @@ -1476,7 +1699,7 @@ impl Canvas { #[cfg(test)] mod mask_tests { use canvas::{Canvas, MaskPattern}; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_apply_mask_qr() { @@ -1484,91 +1707,156 @@ mod mask_tests { c.draw_all_functional_patterns(); c.apply_mask(MaskPattern::Checkerboard); - assert_eq!(&*c.to_debug_str(), "\n\ - #######...#.#.#######\n\ - #.....#..#.#..#.....#\n\ - #.###.#.#.#.#.#.###.#\n\ - #.###.#..#.#..#.###.#\n\ - #.###.#...#.#.#.###.#\n\ - #.....#..#.#..#.....#\n\ - #######.#.#.#.#######\n\ - ........##.#.........\n\ - ###.#####.#.###...#..\n\ - .#.#.#.#.#.#.#.#.#.#.\n\ - #.#.#.#.#.#.#.#.#.#.#\n\ - .#.#.#.#.#.#.#.#.#.#.\n\ - #.#.#.#.#.#.#.#.#.#.#\n\ - ........##.#.#.#.#.#.\n\ - #######.#.#.#.#.#.#.#\n\ - #.....#.##.#.#.#.#.#.\n\ - #.###.#.#.#.#.#.#.#.#\n\ - #.###.#..#.#.#.#.#.#.\n\ - #.###.#.#.#.#.#.#.#.#\n\ - #.....#.##.#.#.#.#.#.\n\ - #######.#.#.#.#.#.#.#"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######...#.#.#######\n\ + #.....#..#.#..#.....#\n\ + #.###.#.#.#.#.#.###.#\n\ + #.###.#..#.#..#.###.#\n\ + #.###.#...#.#.#.###.#\n\ + #.....#..#.#..#.....#\n\ + #######.#.#.#.#######\n\ + ........##.#.........\n\ + ###.#####.#.###...#..\n\ + .#.#.#.#.#.#.#.#.#.#.\n\ + #.#.#.#.#.#.#.#.#.#.#\n\ + .#.#.#.#.#.#.#.#.#.#.\n\ + #.#.#.#.#.#.#.#.#.#.#\n\ + ........##.#.#.#.#.#.\n\ + #######.#.#.#.#.#.#.#\n\ + #.....#.##.#.#.#.#.#.\n\ + #.###.#.#.#.#.#.#.#.#\n\ + #.###.#..#.#.#.#.#.#.\n\ + #.###.#.#.#.#.#.#.#.#\n\ + #.....#.##.#.#.#.#.#.\n\ + #######.#.#.#.#.#.#.#" + ); } #[test] fn test_draw_format_info_patterns_qr() { let mut c = Canvas::new(Version::Normal(1), EcLevel::L); c.draw_format_info_patterns(MaskPattern::LargeCheckerboard); - assert_eq!(&*c.to_debug_str(), "\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ?????????????????????\n\ - ????????.????????????\n\ - ##..##?..????..#.####\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ?????????????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ????????#????????????\n\ - ????????.????????????\n\ - ????????.????????????\n\ - ????????#????????????\n\ - ????????#????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ????????#????????????\n\ + ????????#????????????\n\ + ????????#????????????\n\ + ????????#????????????\n\ + ????????.????????????\n\ + ????????#????????????\n\ + ?????????????????????\n\ + ????????.????????????\n\ + ##..##?..????..#.####\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ?????????????????????\n\ + ????????#????????????\n\ + ????????.????????????\n\ + ????????#????????????\n\ + ????????#????????????\n\ + ????????.????????????\n\ + ????????.????????????\n\ + ????????#????????????\n\ + ????????#????????????" + ); } #[test] fn test_draw_format_info_patterns_micro_qr() { let mut c = Canvas::new(Version::Micro(2), EcLevel::L); c.draw_format_info_patterns(MaskPattern::LargeCheckerboard); - assert_eq!(&*c.to_debug_str(), "\n\ - ?????????????\n\ - ????????#????\n\ - ????????.????\n\ - ????????.????\n\ - ????????#????\n\ - ????????#????\n\ - ????????.????\n\ - ????????.????\n\ - ?#.#....#????\n\ - ?????????????\n\ - ?????????????\n\ - ?????????????\n\ - ?????????????"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + ?????????????\n\ + ????????#????\n\ + ????????.????\n\ + ????????.????\n\ + ????????#????\n\ + ????????#????\n\ + ????????.????\n\ + ????????.????\n\ + ?#.#....#????\n\ + ?????????????\n\ + ?????????????\n\ + ?????????????\n\ + ?????????????" + ); } } static FORMAT_INFOS_QR: [u16; 32] = [ - 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, - 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, - 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, - 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, + 0x5412, + 0x5125, + 0x5e7c, + 0x5b4b, + 0x45f9, + 0x40ce, + 0x4f97, + 0x4aa0, + 0x77c4, + 0x72f3, + 0x7daa, + 0x789d, + 0x662f, + 0x6318, + 0x6c41, + 0x6976, + 0x1689, + 0x13be, + 0x1ce7, + 0x19d0, + 0x0762, + 0x0255, + 0x0d0c, + 0x083b, + 0x355f, + 0x3068, + 0x3f31, + 0x3a06, + 0x24b4, + 0x2183, + 0x2eda, + 0x2bed, ]; static FORMAT_INFOS_MICRO_QR: [u16; 32] = [ - 0x4445, 0x4172, 0x4e2b, 0x4b1c, 0x55ae, 0x5099, 0x5fc0, 0x5af7, - 0x6793, 0x62a4, 0x6dfd, 0x68ca, 0x7678, 0x734f, 0x7c16, 0x7921, - 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, - 0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3, 0x31d4, 0x3e8d, 0x3bba, + 0x4445, + 0x4172, + 0x4e2b, + 0x4b1c, + 0x55ae, + 0x5099, + 0x5fc0, + 0x5af7, + 0x6793, + 0x62a4, + 0x6dfd, + 0x68ca, + 0x7678, + 0x734f, + 0x7c16, + 0x7921, + 0x06de, + 0x03e9, + 0x0cb0, + 0x0987, + 0x1735, + 0x1202, + 0x1d5b, + 0x186c, + 0x2508, + 0x203f, + 0x2f66, + 0x2a51, + 0x34e3, + 0x31d4, + 0x3e8d, + 0x3bba, ]; //}}} @@ -1584,17 +1872,18 @@ impl Canvas { fn compute_adjacent_penalty_score(&self, is_horizontal: bool) -> u16 { let mut total_score = 0; - for i in 0 .. self.width { + for i in 0..self.width { let map_fn = |j| if is_horizontal { self.get(j, i) } else { self.get(i, j) }; - let colors = (0 .. self.width).map(map_fn) - .chain(Some(Module::Empty).into_iter()); + let colors = (0..self.width) + .map(map_fn) + .chain(Some(Module::Empty).into_iter()); let mut last_color = Module::Empty; - let mut consecutive_len = 1u16; + let mut consecutive_len = 1_u16; for color in colors { if color == last_color { @@ -1620,12 +1909,12 @@ impl Canvas { fn compute_block_penalty_score(&self) -> u16 { let mut total_score = 0; - for i in 0 .. self.width-1 { - for j in 0 .. self.width-1 { + for i in 0..self.width - 1 { + for j in 0..self.width - 1 { let this = self.get(i, j); - let right = self.get(i+1, j); - let bottom = self.get(i, j+1); - let bottom_right = self.get(i+1, j+1); + let right = self.get(i + 1, j); + let bottom = self.get(i, j + 1); + let bottom_right = self.get(i + 1, j + 1); if this == right && right == bottom && bottom == bottom_right { total_score += 3; } @@ -1642,14 +1931,19 @@ impl Canvas { /// 40 points. fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 { static PATTERN: [Color; 7] = [ - Color::Dark, Color::Light, Color::Dark, Color::Dark, - Color::Dark, Color::Light, Color::Dark, + Color::Dark, + Color::Light, + Color::Dark, + Color::Dark, + Color::Dark, + Color::Light, + Color::Dark, ]; let mut total_score = 0; - for i in 0 .. self.width { - for j in 0 .. self.width-6 { + for i in 0..self.width { + for j in 0..self.width - 6 { // TODO a ref to a closure should be enough? let get: Box Color> = if is_horizontal { Box::new(|k| self.get(k, i).into()) @@ -1657,12 +1951,12 @@ impl Canvas { Box::new(|k| self.get(i, k).into()) }; - if (j .. j+7).map(&*get).ne(PATTERN.iter().cloned()) { + if (j..(j + 7)).map(&*get).ne(PATTERN.iter().cloned()) { continue; } let check = |k| 0 <= k && k < self.width && get(k) != Color::Light; - if !(j-4 .. j).any(&check) || !(j+7 .. j+11).any(&check) { + if !((j - 4)..j).any(&check) || !((j + 7)..(j + 11)).any(&check) { total_score += 40; } } @@ -1683,11 +1977,11 @@ impl Canvas { let dark_modules = self.modules.iter().filter(|m| m.is_dark()).count(); let total_modules = self.modules.len(); let ratio = dark_modules * 200 / total_modules; - (if ratio >= 100 { + if ratio >= 100 { ratio - 100 } else { 100 - ratio - }) as u16 + }.as_u16() } /// Compute the penalty score for having too many light modules on the sides. @@ -1698,10 +1992,14 @@ impl Canvas { /// has the inverse meaning of this method, but it is very easy to convert /// between the two (this score is (16×width − standard-score)). fn compute_light_side_penalty_score(&self) -> u16 { - let h = (1 .. self.width).filter(|j| !self.get(*j, -1).is_dark()).count(); - let v = (1 .. self.width).filter(|j| !self.get(-1, *j).is_dark()).count(); + let h = (1..self.width) + .filter(|j| !self.get(*j, -1).is_dark()) + .count(); + let v = (1..self.width) + .filter(|j| !self.get(-1, *j).is_dark()) + .count(); - (h + v + 15 * max(h, v)) as u16 + (h + v + 15 * max(h, v)).as_u16() } /// Compute the total penalty scores. A QR code having higher points is less @@ -1725,13 +2023,15 @@ impl Canvas { #[cfg(test)] mod penalty_tests { use canvas::{Canvas, MaskPattern}; - use types::{Version, EcLevel, Color}; + use types::{Color, EcLevel, Version}; fn create_test_canvas() -> Canvas { let mut c = Canvas::new(Version::Normal(1), EcLevel::Q); c.draw_all_functional_patterns(); - c.draw_data(b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00", - b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10"); + c.draw_data( + b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00", + b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10", + ); c.apply_mask(MaskPattern::Checkerboard); c } @@ -1739,28 +2039,31 @@ mod penalty_tests { #[test] fn check_penalty_canvas() { let c = create_test_canvas(); - assert_eq!(&*c.to_debug_str(), "\n\ - #######.##....#######\n\ - #.....#.#..#..#.....#\n\ - #.###.#.#..##.#.###.#\n\ - #.###.#.#.....#.###.#\n\ - #.###.#.#.#...#.###.#\n\ - #.....#...#...#.....#\n\ - #######.#.#.#.#######\n\ - ........#............\n\ - .##.#.##....#.#.#####\n\ - .#......####....#...#\n\ - ..##.###.##...#.##...\n\ - .##.##.#..##.#.#.###.\n\ - #...#.#.#.###.###.#.#\n\ - ........##.#..#...#.#\n\ - #######.#.#....#.##..\n\ - #.....#..#.##.##.#...\n\ - #.###.#.#.#...#######\n\ - #.###.#..#.#.#.#...#.\n\ - #.###.#.#...####.#..#\n\ - #.....#.#.##.#...#.##\n\ - #######.....####....#"); + assert_eq!( + &*c.to_debug_str(), + "\n\ + #######.##....#######\n\ + #.....#.#..#..#.....#\n\ + #.###.#.#..##.#.###.#\n\ + #.###.#.#.....#.###.#\n\ + #.###.#.#.#...#.###.#\n\ + #.....#...#...#.....#\n\ + #######.#.#.#.#######\n\ + ........#............\n\ + .##.#.##....#.#.#####\n\ + .#......####....#...#\n\ + ..##.###.##...#.##...\n\ + .##.##.#..##.#.#.###.\n\ + #...#.#.#.###.###.#.#\n\ + ........##.#..#...#.#\n\ + #######.#.#....#.##..\n\ + #.....#..#.##.##.#...\n\ + #.###.#.#.#...#######\n\ + #.###.#..#.#.#.#...#.\n\ + #.###.#.#...####.#..#\n\ + #.....#.#.##.#...#.##\n\ + #######.....####....#" + ); } #[test] @@ -1792,22 +2095,46 @@ mod penalty_tests { #[test] fn test_penalty_score_light_sides() { static HORIZONTAL_SIDE: [Color; 17] = [ - Color::Dark, Color::Light, Color::Light, Color::Dark, - Color::Dark, Color::Dark, Color::Light, Color::Light, - Color::Dark, Color::Light, Color::Dark, Color::Light, - Color::Light, Color::Dark, Color::Light, Color::Light, + Color::Dark, + Color::Light, + Color::Light, + Color::Dark, + Color::Dark, + Color::Dark, + Color::Light, + Color::Light, + Color::Dark, + Color::Light, + Color::Dark, + Color::Light, + Color::Light, + Color::Dark, + Color::Light, + Color::Light, Color::Light, ]; static VERTICAL_SIDE: [Color; 17] = [ - Color::Dark, Color::Dark, Color::Dark, Color::Light, - Color::Light, Color::Dark, Color::Dark, Color::Light, - Color::Dark, Color::Light, Color::Dark, Color::Light, - Color::Dark, Color::Light, Color::Light, Color::Dark, + Color::Dark, + Color::Dark, + Color::Dark, + Color::Light, + Color::Light, + Color::Dark, + Color::Dark, + Color::Light, + Color::Dark, + Color::Light, + Color::Dark, + Color::Light, + Color::Dark, + Color::Light, + Color::Light, + Color::Dark, Color::Light, ]; let mut c = Canvas::new(Version::Micro(4), EcLevel::Q); - for i in 0i16 .. 17 { + for i in 0i16..17 { c.put(i, -1, HORIZONTAL_SIDE[i as usize]); c.put(-1, i, VERTICAL_SIDE[i as usize]); } @@ -1821,47 +2148,41 @@ mod penalty_tests { //{{{ Select mask with lowest penalty score static ALL_PATTERNS_QR: [MaskPattern; 8] = [ - MaskPattern::Checkerboard, MaskPattern::HorizontalLines, - MaskPattern::VerticalLines, MaskPattern::DiagonalLines, - MaskPattern::LargeCheckerboard, MaskPattern::Fields, - MaskPattern::Diamonds, MaskPattern::Meadow, + MaskPattern::Checkerboard, + MaskPattern::HorizontalLines, + MaskPattern::VerticalLines, + MaskPattern::DiagonalLines, + MaskPattern::LargeCheckerboard, + MaskPattern::Fields, + MaskPattern::Diamonds, + MaskPattern::Meadow, ]; static ALL_PATTERNS_MICRO_QR: [MaskPattern; 4] = [ - MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard, - MaskPattern::Diamonds, MaskPattern::Meadow, + MaskPattern::HorizontalLines, + MaskPattern::LargeCheckerboard, + MaskPattern::Diamonds, + MaskPattern::Meadow, ]; impl Canvas { /// Construct a new canvas and apply the best masking that gives the lowest /// penalty score. - pub fn apply_best_mask(&self) -> Canvas { - let patterns = match self.version { + pub fn apply_best_mask(&self) -> Self { + match self.version { Version::Normal(_) => ALL_PATTERNS_QR.iter(), Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(), - }; - - let mut patterns = patterns.map(|ptn| { + }.map(|ptn| { let mut c = self.clone(); c.apply_mask(*ptn); c - }); - - // TODO revert to `min_by` after it is stable. - let mut best_pattern = patterns.next().unwrap(); - let mut best_pattern_score = best_pattern.compute_total_penalty_scores(); - for c in patterns { - let score = c.compute_total_penalty_scores(); - if score < best_pattern_score { - best_pattern = c; - best_pattern_score = score; - } - } - best_pattern + }) + .min_by_key(Self::compute_total_penalty_scores) + .expect("at least one pattern") } /// Convert the modules into a vector of booleans. - #[deprecated(since="0.4.0", note="use `into_colors()` instead")] + #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")] pub fn to_bools(&self) -> Vec { self.modules.iter().map(|m| m.is_dark()).collect() } @@ -1874,5 +2195,3 @@ impl Canvas { //}}} //------------------------------------------------------------------------------ - - diff --git a/src/cast.rs b/src/cast.rs new file mode 100644 index 0000000..fa6c86b --- /dev/null +++ b/src/cast.rs @@ -0,0 +1,90 @@ +use std::fmt::Display; + +#[cfg(debug_assertions)] +use checked_int_cast::CheckedIntCast; + +pub trait Truncate { + fn truncate_as_u8(self) -> u8; +} + +impl Truncate for u16 { + #[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))] + fn truncate_as_u8(self) -> u8 { + (self & 0xff) as u8 + } +} + +pub trait As { + fn as_u16(self) -> u16; + fn as_i16(self) -> i16; + fn as_u32(self) -> u32; + fn as_usize(self) -> usize; + fn as_isize(self) -> isize; +} + +trait ExpectOrOverflow { + type Output; + fn expect_or_overflow(self, value: D, ty: &str) -> Self::Output; +} + +impl ExpectOrOverflow for Option { + type Output = T; + fn expect_or_overflow(self, value: D, ty: &str) -> Self::Output { + match self { + Some(v) => v, + None => panic!("{} overflows {}", value, ty), + } + } +} + +macro_rules! impl_as { + ($ty:ty) => { + #[cfg(debug_assertions)] + impl As for $ty { + fn as_u16(self) -> u16 { + self.as_u16_checked().expect_or_overflow(self, "u16") + } + + fn as_i16(self) -> i16 { + self.as_i16_checked().expect_or_overflow(self, "i16") + } + + fn as_u32(self) -> u32 { + self.as_u32_checked().expect_or_overflow(self, "u32") + } + + fn as_usize(self) -> usize { + self.as_usize_checked().expect_or_overflow(self, "usize") + } + + fn as_isize(self) -> isize { + self.as_isize_checked().expect_or_overflow(self, "usize") + } + } + + #[cfg(not(debug_assertions))] + #[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))] + impl As for $ty { + fn as_u16(self) -> u16 { + self as u16 + } + fn as_i16(self) -> i16 { + self as i16 + } + fn as_u32(self) -> u32 { + self as u32 + } + fn as_usize(self) -> usize { + self as usize + } + fn as_isize(self) -> isize { + self as isize + } + } + } +} + +impl_as!(i16); +impl_as!(u32); +impl_as!(usize); +impl_as!(isize); diff --git a/src/ec.rs b/src/ec.rs index 10e10b9..2549bb3 100644 --- a/src/ec.rs +++ b/src/ec.rs @@ -1,9 +1,8 @@ //! The `ec` module applies the Reed-Solomon error correction codes. -use std::iter::repeat; use std::ops::Deref; -use types::{QrResult, Version, EcLevel}; +use types::{EcLevel, QrResult, Version}; //------------------------------------------------------------------------------ //{{{ Error correction primitive @@ -18,25 +17,27 @@ use types::{QrResult, Version, EcLevel}; /// GF(256), and then computes the polynomial modulus with a generator /// polynomial of degree N. pub fn create_error_correction_code(data: &[u8], ec_code_size: usize) -> Vec { - let mut res = data.to_vec(); - res.extend(repeat(0).take(ec_code_size)); - let data_len = data.len(); let log_den = GENERATOR_POLYNOMIALS[ec_code_size]; - for i in 0 .. data_len { + let mut res = data.to_vec(); + res.resize(ec_code_size + data_len, 0); + + // rust-lang-nursery/rust-clippy#2213 + #[cfg_attr(feature = "cargo-clippy", allow(needless_range_loop))] + for i in 0..data_len { let lead_coeff = res[i] as usize; if lead_coeff == 0 { continue; } - let log_lead_coeff = LOG_TABLE[lead_coeff] as usize; - for (u, v) in res[i+1 ..].iter_mut().zip(log_den.iter()) { - *u ^= EXP_TABLE[((*v as usize + log_lead_coeff) % 255) as usize]; + let log_lead_coeff = usize::from(LOG_TABLE[lead_coeff]); + for (u, v) in res[i + 1..].iter_mut().zip(log_den.iter()) { + *u ^= EXP_TABLE[(usize::from(*v) + log_lead_coeff) % 255]; } } - res.into_iter().skip(data_len).collect() + res.split_off(data_len) } #[cfg(test)] @@ -73,10 +74,10 @@ mod ec_tests { /// /// The longest slice must be at the last of `blocks`, and `blocks` must not be /// empty. -fn interleave>(blocks: &Vec) -> Vec { - let last_block_len = blocks.last().unwrap().len(); +fn interleave>(blocks: &[V]) -> Vec { + let last_block_len = blocks.last().expect("non-empty blocks").len(); let mut res = Vec::with_capacity(last_block_len * blocks.len()); - for i in 0 .. last_block_len { + for i in 0..last_block_len { for t in blocks { if i < t.len() { res.push(t[i]); @@ -88,7 +89,7 @@ fn interleave>(blocks: &Vec) -> Vec { #[test] fn test_interleave() { - let res = interleave(&vec![&b"1234"[..], b"5678", b"abcdef", b"ghijkl"]); + let res = interleave(&[&b"1234"[..], b"5678", b"abcdef", b"ghijkl"]); assert_eq!(&*res, b"15ag26bh37ci48djekfl"); } @@ -98,11 +99,13 @@ fn test_interleave() { /// Constructs data and error correction codewords ready to be put in the QR /// code matrix. -pub fn construct_codewords(rawbits: &[u8], - version: Version, - ec_level: EcLevel) -> QrResult<(Vec, Vec)> { +pub fn construct_codewords( + rawbits: &[u8], + version: Version, + ec_level: EcLevel, +) -> QrResult<(Vec, Vec)> { let (block_1_size, block_1_count, block_2_size, block_2_count) = - try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)); + version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)?; let blocks_count = block_1_count + block_2_count; let block_1_end = block_1_size * block_1_count; @@ -118,10 +121,11 @@ pub fn construct_codewords(rawbits: &[u8], } // Generate EC codes. - let ec_bytes = try!(version.fetch(ec_level, &EC_BYTES_PER_BLOCK)); - let ec_codes = blocks.iter() - .map(|block| create_error_correction_code(*block, ec_bytes)) - .collect::>>(); + let ec_bytes = version.fetch(ec_level, &EC_BYTES_PER_BLOCK)?; + let ec_codes = blocks + .iter() + .map(|block| create_error_correction_code(*block, ec_bytes)) + .collect::>>(); let blocks_vec = interleave(&blocks); let ec_vec = interleave(&ec_codes); @@ -132,24 +136,34 @@ pub fn construct_codewords(rawbits: &[u8], #[cfg(test)] mod construct_codewords_test { use ec::construct_codewords; - use types::{Version, EcLevel}; + use types::{EcLevel, Version}; #[test] fn test_add_ec_simple() { let msg = b" [\x0bx\xd1r\xdcMC@\xec\x11\xec\x11\xec\x11"; - let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(1), EcLevel::M).unwrap(); + let (blocks_vec, ec_vec) = + construct_codewords(msg, Version::Normal(1), EcLevel::M).unwrap(); assert_eq!(&*blocks_vec, msg); assert_eq!(&*ec_vec, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17"); } #[test] fn test_add_ec_complex() { - let msg = b"CUF\x86W&U\xc2w2\x06\x12\x06g&\xf6\xf6B\x07v\x86\xf2\x07&V\x16\xc6\xc7\x92\x06\xb6\xe6\xf7w2\x07v\x86W&R\x06\x86\x972\x07F\xf7vV\xc2\x06\x972\x10\xec\x11\xec\x11\xec\x11\xec"; - let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(5), EcLevel::Q).unwrap(); - assert_eq!(&*blocks_vec, - &b"C\xf6\xb6FU\xf6\xe6\xf7FB\xf7v\x86\x07wVWv2\xc2&\x86\x07\x06U\xf2v\x97\xc2\x07\x862w&W\x102V&\xec\x06\x16R\x11\x12\xc6\x06\xec\x06\xc7\x86\x11g\x92\x97\xec&\x062\x11\x07\xec"[..]); - assert_eq!(&*ec_vec, - &b"\xd5W\x94\xeb\xc7\xcct\x9f\x0b`\xb1\x05-<\xd4\xads\xcaL\x18\xf7\xb6\x85\x93\xf1|K;\xdf\x9d\xf2!\xe5\xc8\xeej\xf8\x86L(\x9a\x1b\xc3\xffu\x81\xe6\xac\x9a\xd1\xbdRo\x11\n\x02V\xa3l\x83\xa1\xa3\xf0 ox\xc0\xb2'\x85\x8d\xec"[..]); + let msg = b"CUF\x86W&U\xc2w2\x06\x12\x06g&\xf6\xf6B\x07v\x86\xf2\x07&V\x16\xc6\xc7\x92\x06\ + \xb6\xe6\xf7w2\x07v\x86W&R\x06\x86\x972\x07F\xf7vV\xc2\x06\x972\x10\xec\x11\xec\ + \x11\xec\x11\xec"; + let expected_blocks = b"C\xf6\xb6FU\xf6\xe6\xf7FB\xf7v\x86\x07wVWv2\xc2&\x86\x07\x06U\xf2v\ + \x97\xc2\x07\x862w&W\x102V&\xec\x06\x16R\x11\x12\xc6\x06\xec\x06\ + \xc7\x86\x11g\x92\x97\xec&\x062\x11\x07\xec"; + let expected_ec = b"\xd5W\x94\xeb\xc7\xcct\x9f\x0b`\xb1\x05-<\xd4\xads\xcaL\x18\xf7\xb6\x85\ + \x93\xf1|K;\xdf\x9d\xf2!\xe5\xc8\xeej\xf8\x86L(\x9a\x1b\xc3\xffu\x81\ + \xe6\xac\x9a\xd1\xbdRo\x11\n\x02V\xa3l\x83\xa1\xa3\xf0 ox\xc0\xb2'\x85\ + \x8d\xec"; + + let (blocks_vec, ec_vec) = + construct_codewords(msg, Version::Normal(5), EcLevel::Q).unwrap(); + assert_eq!(&*blocks_vec, &expected_blocks[..]); + assert_eq!(&*ec_vec, &expected_ec[..]); } } @@ -170,8 +184,8 @@ pub fn max_allowed_errors(version: Version, ec_level: EcLevel) -> QrResult 0, }; - let ec_bytes_per_block = try!(version.fetch(ec_level, &EC_BYTES_PER_BLOCK)); - let (_, count1, _, count2) = try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)); + let ec_bytes_per_block = version.fetch(ec_level, &EC_BYTES_PER_BLOCK)?; + let (_, count1, _, count2) = version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)?; let ec_bytes = (count1 + count2) * ec_bytes_per_block; Ok((ec_bytes - p) / 2) @@ -180,7 +194,7 @@ pub fn max_allowed_errors(version: Version, ec_level: EcLevel) -> QrResultn in the Galois Field GF(256). -static EXP_TABLE: &'static [u8] = b"\x01\x02\x04\x08\x10\x20\x40\x80\x1d\x3a\x74\xe8\xcd\x87\x13\x26\x4c\x98\x2d\x5a\xb4\x75\xea\xc9\x8f\x03\x06\x0c\x18\x30\x60\xc0\x9d\x27\x4e\x9c\x25\x4a\x94\x35\x6a\xd4\xb5\x77\xee\xc1\x9f\x23\x46\x8c\x05\x0a\x14\x28\x50\xa0\x5d\xba\x69\xd2\xb9\x6f\xde\xa1\x5f\xbe\x61\xc2\x99\x2f\x5e\xbc\x65\xca\x89\x0f\x1e\x3c\x78\xf0\xfd\xe7\xd3\xbb\x6b\xd6\xb1\x7f\xfe\xe1\xdf\xa3\x5b\xb6\x71\xe2\xd9\xaf\x43\x86\x11\x22\x44\x88\x0d\x1a\x34\x68\xd0\xbd\x67\xce\x81\x1f\x3e\x7c\xf8\xed\xc7\x93\x3b\x76\xec\xc5\x97\x33\x66\xcc\x85\x17\x2e\x5c\xb8\x6d\xda\xa9\x4f\x9e\x21\x42\x84\x15\x2a\x54\xa8\x4d\x9a\x29\x52\xa4\x55\xaa\x49\x92\x39\x72\xe4\xd5\xb7\x73\xe6\xd1\xbf\x63\xc6\x91\x3f\x7e\xfc\xe5\xd7\xb3\x7b\xf6\xf1\xff\xe3\xdb\xab\x4b\x96\x31\x62\xc4\x95\x37\x6e\xdc\xa5\x57\xae\x41\x82\x19\x32\x64\xc8\x8d\x07\x0e\x1c\x38\x70\xe0\xdd\xa7\x53\xa6\x51\xa2\x59\xb2\x79\xf2\xf9\xef\xc3\x9b\x2b\x56\xac\x45\x8a\x09\x12\x24\x48\x90\x3d\x7a\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16\x2c\x58\xb0\x7d\xfa\xe9\xcf\x83\x1b\x36\x6c\xd8\xad\x47\x8e\x01"; +static EXP_TABLE: &'static [u8] = b"\ +\x01\x02\x04\x08\x10\x20\x40\x80\x1d\x3a\x74\xe8\xcd\x87\x13\x26\ +\x4c\x98\x2d\x5a\xb4\x75\xea\xc9\x8f\x03\x06\x0c\x18\x30\x60\xc0\ +\x9d\x27\x4e\x9c\x25\x4a\x94\x35\x6a\xd4\xb5\x77\xee\xc1\x9f\x23\ +\x46\x8c\x05\x0a\x14\x28\x50\xa0\x5d\xba\x69\xd2\xb9\x6f\xde\xa1\ +\x5f\xbe\x61\xc2\x99\x2f\x5e\xbc\x65\xca\x89\x0f\x1e\x3c\x78\xf0\ +\xfd\xe7\xd3\xbb\x6b\xd6\xb1\x7f\xfe\xe1\xdf\xa3\x5b\xb6\x71\xe2\ +\xd9\xaf\x43\x86\x11\x22\x44\x88\x0d\x1a\x34\x68\xd0\xbd\x67\xce\ +\x81\x1f\x3e\x7c\xf8\xed\xc7\x93\x3b\x76\xec\xc5\x97\x33\x66\xcc\ +\x85\x17\x2e\x5c\xb8\x6d\xda\xa9\x4f\x9e\x21\x42\x84\x15\x2a\x54\ +\xa8\x4d\x9a\x29\x52\xa4\x55\xaa\x49\x92\x39\x72\xe4\xd5\xb7\x73\ +\xe6\xd1\xbf\x63\xc6\x91\x3f\x7e\xfc\xe5\xd7\xb3\x7b\xf6\xf1\xff\ +\xe3\xdb\xab\x4b\x96\x31\x62\xc4\x95\x37\x6e\xdc\xa5\x57\xae\x41\ +\x82\x19\x32\x64\xc8\x8d\x07\x0e\x1c\x38\x70\xe0\xdd\xa7\x53\xa6\ +\x51\xa2\x59\xb2\x79\xf2\xf9\xef\xc3\x9b\x2b\x56\xac\x45\x8a\x09\ +\x12\x24\x48\x90\x3d\x7a\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16\ +\x2c\x58\xb0\x7d\xfa\xe9\xcf\x83\x1b\x36\x6c\xd8\xad\x47\x8e\x01"; /// `LOG_TABLE` is the inverse function of `EXP_TABLE`. -static LOG_TABLE: &'static [u8] = b"\xff\x00\x01\x19\x02\x32\x1a\xc6\x03\xdf\x33\xee\x1b\x68\xc7\x4b\x04\x64\xe0\x0e\x34\x8d\xef\x81\x1c\xc1\x69\xf8\xc8\x08\x4c\x71\x05\x8a\x65\x2f\xe1\x24\x0f\x21\x35\x93\x8e\xda\xf0\x12\x82\x45\x1d\xb5\xc2\x7d\x6a\x27\xf9\xb9\xc9\x9a\x09\x78\x4d\xe4\x72\xa6\x06\xbf\x8b\x62\x66\xdd\x30\xfd\xe2\x98\x25\xb3\x10\x91\x22\x88\x36\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\x5c\x83\x38\x46\x40\x1e\x42\xb6\xa3\xc3\x48\x7e\x6e\x6b\x3a\x28\x54\xfa\x85\xba\x3d\xca\x5e\x9b\x9f\x0a\x15\x79\x2b\x4e\xd4\xe5\xac\x73\xf3\xa7\x57\x07\x70\xc0\xf7\x8c\x80\x63\x0d\x67\x4a\xde\xed\x31\xc5\xfe\x18\xe3\xa5\x99\x77\x26\xb8\xb4\x7c\x11\x44\x92\xd9\x23\x20\x89\x2e\x37\x3f\xd1\x5b\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbe\x61\xf2\x56\xd3\xab\x14\x2a\x5d\x9e\x84\x3c\x39\x53\x47\x6d\x41\xa2\x1f\x2d\x43\xd8\xb7\x7b\xa4\x76\xc4\x17\x49\xec\x7f\x0c\x6f\xf6\x6c\xa1\x3b\x52\x29\x9d\x55\xaa\xfb\x60\x86\xb1\xbb\xcc\x3e\x5a\xcb\x59\x5f\xb0\x9c\xa9\xa0\x51\x0b\xf5\x16\xeb\x7a\x75\x2c\xd7\x4f\xae\xd5\xe9\xe6\xe7\xad\xe8\x74\xd6\xf4\xea\xa8\x50\x58\xaf"; +static LOG_TABLE: &'static [u8] = b"\ +\xff\x00\x01\x19\x02\x32\x1a\xc6\x03\xdf\x33\xee\x1b\x68\xc7\x4b\ +\x04\x64\xe0\x0e\x34\x8d\xef\x81\x1c\xc1\x69\xf8\xc8\x08\x4c\x71\ +\x05\x8a\x65\x2f\xe1\x24\x0f\x21\x35\x93\x8e\xda\xf0\x12\x82\x45\ +\x1d\xb5\xc2\x7d\x6a\x27\xf9\xb9\xc9\x9a\x09\x78\x4d\xe4\x72\xa6\ +\x06\xbf\x8b\x62\x66\xdd\x30\xfd\xe2\x98\x25\xb3\x10\x91\x22\x88\ +\x36\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\x5c\x83\x38\x46\x40\ +\x1e\x42\xb6\xa3\xc3\x48\x7e\x6e\x6b\x3a\x28\x54\xfa\x85\xba\x3d\ +\xca\x5e\x9b\x9f\x0a\x15\x79\x2b\x4e\xd4\xe5\xac\x73\xf3\xa7\x57\ +\x07\x70\xc0\xf7\x8c\x80\x63\x0d\x67\x4a\xde\xed\x31\xc5\xfe\x18\ +\xe3\xa5\x99\x77\x26\xb8\xb4\x7c\x11\x44\x92\xd9\x23\x20\x89\x2e\ +\x37\x3f\xd1\x5b\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbe\x61\ +\xf2\x56\xd3\xab\x14\x2a\x5d\x9e\x84\x3c\x39\x53\x47\x6d\x41\xa2\ +\x1f\x2d\x43\xd8\xb7\x7b\xa4\x76\xc4\x17\x49\xec\x7f\x0c\x6f\xf6\ +\x6c\xa1\x3b\x52\x29\x9d\x55\xaa\xfb\x60\x86\xb1\xbb\xcc\x3e\x5a\ +\xcb\x59\x5f\xb0\x9c\xa9\xa0\x51\x0b\xf5\x16\xeb\x7a\x75\x2c\xd7\ +\x4f\xae\xd5\xe9\xe6\xe7\xad\xe8\x74\xd6\xf4\xea\xa8\x50\x58\xaf"; /// The generator polynomial list. /// @@ -245,6 +291,8 @@ static LOG_TABLE: &'static [u8] = b"\xff\x00\x01\x19\x02\x32\x1a\xc6\x03\xdf\x33 /// is the Reed-Solomon error correction code. /// /// A partial list can be found from ISO/IEC 18004:2006 Annex A. +#[cfg_attr(rustfmt, rustfmt_skip)] +// ^ this attribute is currently useless, see rust-lang-nursery/rustfmt#1080 and 1298 static GENERATOR_POLYNOMIALS: [&'static [u8]; 70] = [ b"", b"\x00", @@ -329,55 +377,51 @@ static GENERATOR_POLYNOMIALS: [&'static [u8]; 70] = [ /// by the sum of the 6th column). static EC_BYTES_PER_BLOCK: [[usize; 4]; 44] = [ // Normal versions. - [7, 10, 13, 17], // 1 - [10, 16, 22, 28], // 2 - [15, 26, 18, 22], // 3 - [20, 18, 26, 16], // 4 - [26, 24, 18, 22], // 5 - [18, 16, 24, 28], // 6 - [20, 18, 18, 26], // 7 - [24, 22, 22, 26], // 8 - [30, 22, 20, 24], // 9 - [18, 26, 24, 28], // 10 - - [20, 30, 28, 24], // 11 - [24, 22, 26, 28], // 12 - [26, 22, 24, 22], // 13 - [30, 24, 20, 24], // 14 - [22, 24, 30, 24], // 15 - [24, 28, 24, 30], // 16 - [28, 28, 28, 28], // 17 - [30, 26, 28, 28], // 18 - [28, 26, 26, 26], // 19 - [28, 26, 30, 28], // 20 - - [28, 26, 28, 30], // 21 - [28, 28, 30, 24], // 22 - [30, 28, 30, 30], // 23 - [30, 28, 30, 30], // 24 - [26, 28, 30, 30], // 25 - [28, 28, 28, 30], // 26 - [30, 28, 30, 30], // 27 - [30, 28, 30, 30], // 28 - [30, 28, 30, 30], // 29 - [30, 28, 30, 30], // 30 - - [30, 28, 30, 30], // 31 - [30, 28, 30, 30], // 32 - [30, 28, 30, 30], // 33 - [30, 28, 30, 30], // 34 - [30, 28, 30, 30], // 35 - [30, 28, 30, 30], // 36 - [30, 28, 30, 30], // 37 - [30, 28, 30, 30], // 38 - [30, 28, 30, 30], // 39 - [30, 28, 30, 30], // 40 - + [7, 10, 13, 17], // 1 + [10, 16, 22, 28], // 2 + [15, 26, 18, 22], // 3 + [20, 18, 26, 16], // 4 + [26, 24, 18, 22], // 5 + [18, 16, 24, 28], // 6 + [20, 18, 18, 26], // 7 + [24, 22, 22, 26], // 8 + [30, 22, 20, 24], // 9 + [18, 26, 24, 28], // 10 + [20, 30, 28, 24], // 11 + [24, 22, 26, 28], // 12 + [26, 22, 24, 22], // 13 + [30, 24, 20, 24], // 14 + [22, 24, 30, 24], // 15 + [24, 28, 24, 30], // 16 + [28, 28, 28, 28], // 17 + [30, 26, 28, 28], // 18 + [28, 26, 26, 26], // 19 + [28, 26, 30, 28], // 20 + [28, 26, 28, 30], // 21 + [28, 28, 30, 24], // 22 + [30, 28, 30, 30], // 23 + [30, 28, 30, 30], // 24 + [26, 28, 30, 30], // 25 + [28, 28, 28, 30], // 26 + [30, 28, 30, 30], // 27 + [30, 28, 30, 30], // 28 + [30, 28, 30, 30], // 29 + [30, 28, 30, 30], // 30 + [30, 28, 30, 30], // 31 + [30, 28, 30, 30], // 32 + [30, 28, 30, 30], // 33 + [30, 28, 30, 30], // 34 + [30, 28, 30, 30], // 35 + [30, 28, 30, 30], // 36 + [30, 28, 30, 30], // 37 + [30, 28, 30, 30], // 38 + [30, 28, 30, 30], // 39 + [30, 28, 30, 30], // 40 // Micro versions. - [2, 0, 0, 0], // M1 - [5, 6, 0, 0], // M2 - [6, 8, 0, 0], // M3 - [8, 10, 14, 0], // M4 + [2, 0, 0, 0], // M1 + [5, 6, 0, 0], // M2 + [6, 8, 0, 0], // M3 + [8, 10, 14, 0], // M4 ]; /// `DATA_BYTES_PER_BLOCK` provides the number of codewords (bytes) used for @@ -391,57 +435,51 @@ static EC_BYTES_PER_BLOCK: [[usize; 4]; 44] = [ /// 20 blocks with 15 bytes in size, and 61 blocks with 16 bytes in size. static DATA_BYTES_PER_BLOCK: [[(usize, usize, usize, usize); 4]; 44] = [ // Normal versions. - [(19, 1, 0, 0), (16, 1, 0, 0), (13, 1, 0, 0), (9, 1, 0, 0)], // 1 - [(34, 1, 0, 0), (28, 1, 0, 0), (22, 1, 0, 0), (16, 1, 0, 0)], // 2 - [(55, 1, 0, 0), (44, 1, 0, 0), (17, 2, 0, 0), (13, 2, 0, 0)], // 3 - [(80, 1, 0, 0), (32, 2, 0, 0), (24, 2, 0, 0), (9, 4, 0, 0)], // 4 - [(108, 1, 0, 0), (43, 2, 0, 0), (15, 2, 16, 2), (11, 2, 12, 2)], // 5 - [(68, 2, 0, 0), (27, 4, 0, 0), (19, 4, 0, 0), (15, 4, 0, 0)], // 6 - [(78, 2, 0, 0), (31, 4, 0, 0), (14, 2, 15, 4), (13, 4, 14, 1)], // 7 - [(97, 2, 0, 0), (38, 2, 39, 2), (18, 4, 19, 2), (14, 4, 15, 2)], // 8 - [(116, 2, 0, 0), (36, 3, 37, 2), (16, 4, 17, 4), (12, 4, 13, 4)], // 9 - [(68, 2, 69, 2), (43, 4, 44, 1), (19, 6, 20, 2), (15, 6, 16, 2)], // 10 - - [(81, 4, 0, 0), (50, 1, 51, 4), (22, 4, 23, 4), (12, 3, 13, 8)], // 11 - [(92, 2, 93, 2), (36, 6, 37, 2), (20, 4, 21, 6), (14, 7, 15, 4)], // 12 - [(107, 4, 0, 0), (37, 8, 38, 1), (20, 8, 21, 4), (11, 12, 12, 4)], // 13 - [(115, 3, 116, 1), (40, 4, 41, 5), (16, 11, 17, 5), (12, 11, 13, 5)], // 14 - [(87, 5, 88, 1), (41, 5, 42, 5), (24, 5, 25, 7), (12, 11, 13, 7)], // 15 - [(98, 5, 99, 1), (45, 7, 46, 3), (19, 15, 20, 2), (15, 3, 16, 13)], // 16 - [(107, 1, 108, 5), (46, 10, 47, 1), (22, 1, 23, 15), (14, 2, 15, 17)], // 17 - [(120, 5, 121, 1), (43, 9, 44, 4), (22, 17, 23, 1), (14, 2, 15, 19)], // 18 - [(113, 3, 114, 4), (44, 3, 45, 11), (21, 17, 22, 4), (13, 9, 14, 16)], // 19 - [(107, 3, 108, 5), (41, 3, 42, 13), (24, 15, 25, 5), (15, 15, 16, 10)], // 20 - - [(116, 4, 117, 4), (42, 17, 0, 0), (22, 17, 23, 6), (16, 19, 17, 6)], // 21 - [(111, 2, 112, 7), (46, 17, 0, 0), (24, 7, 25, 16), (13, 34, 0, 0)], // 22 - [(121, 4, 122, 5), (47, 4, 48, 14), (24, 11, 25, 14), (15, 16, 16, 14)], // 23 - [(117, 6, 118, 4), (45, 6, 46, 14), (24, 11, 25, 16), (16, 30, 17, 2)], // 24 - [(106, 8, 107, 4), (47, 8, 48, 13), (24, 7, 25, 22), (15, 22, 16, 13)], // 25 - [(114, 10, 115, 2), (46, 19, 47, 4), (22, 28, 23, 6), (16, 33, 17, 4)], // 26 - [(122, 8, 123, 4), (45, 22, 46, 3), (23, 8, 24, 26), (15, 12, 16, 28)], // 27 - [(117, 3, 118, 10), (45, 3, 46, 23), (24, 4, 25, 31), (15, 11, 16, 31)], // 28 - [(116, 7, 117, 7), (45, 21, 46, 7), (23, 1, 24, 37), (15, 19, 16, 26)], // 29 - [(115, 5, 116, 10), (47, 19, 48, 10), (24, 15, 25, 25), (15, 23, 16, 25)], // 30 - - [(115, 13, 116, 3), (46, 2, 47, 29), (24, 42, 25, 1), (15, 23, 16, 28)], // 31 - [(115, 17, 0, 0), (46, 10, 47, 23), (24, 10, 25, 35), (15, 19, 16, 35)], // 32 - [(115, 17, 116, 1), (46, 14, 47, 21), (24, 29, 25, 19), (15, 11, 16, 46)], // 33 - [(115, 13, 116, 6), (46, 14, 47, 23), (24, 44, 25, 7), (16, 59, 17, 1)], // 34 - [(121, 12, 122, 7), (47, 12, 48, 26), (24, 39, 25, 14), (15, 22, 16, 41)], // 35 - [(121, 6, 122, 14), (47, 6, 48, 34), (24, 46, 25, 10), (15, 2, 16, 64)], // 36 - [(122, 17, 123, 4), (46, 29, 47, 14), (24, 49, 25, 10), (15, 24, 16, 46)], // 37 - [(122, 4, 123, 18), (46, 13, 47, 32), (24, 48, 25, 14), (15, 42, 16, 32)], // 38 - [(117, 20, 118, 4), (47, 40, 48, 7), (24, 43, 25, 22), (15, 10, 16, 67)], // 39 - [(118, 19, 119, 6), (47, 18, 48, 31), (24, 34, 25, 34), (15, 20, 16, 61)], // 40 - + [(19, 1, 0, 0), (16, 1, 0, 0), (13, 1, 0, 0), (9, 1, 0, 0)], // 1 + [(34, 1, 0, 0), (28, 1, 0, 0), (22, 1, 0, 0), (16, 1, 0, 0)], // 2 + [(55, 1, 0, 0), (44, 1, 0, 0), (17, 2, 0, 0), (13, 2, 0, 0)], // 3 + [(80, 1, 0, 0), (32, 2, 0, 0), (24, 2, 0, 0), (9, 4, 0, 0)], // 4 + [(108, 1, 0, 0), (43, 2, 0, 0), (15, 2, 16, 2), (11, 2, 12, 2)], // 5 + [(68, 2, 0, 0), (27, 4, 0, 0), (19, 4, 0, 0), (15, 4, 0, 0)], // 6 + [(78, 2, 0, 0), (31, 4, 0, 0), (14, 2, 15, 4), (13, 4, 14, 1)], // 7 + [(97, 2, 0, 0), (38, 2, 39, 2), (18, 4, 19, 2), (14, 4, 15, 2)], // 8 + [(116, 2, 0, 0), (36, 3, 37, 2), (16, 4, 17, 4), (12, 4, 13, 4)], // 9 + [(68, 2, 69, 2), (43, 4, 44, 1), (19, 6, 20, 2), (15, 6, 16, 2)], // 10 + [(81, 4, 0, 0), (50, 1, 51, 4), (22, 4, 23, 4), (12, 3, 13, 8)], // 11 + [(92, 2, 93, 2), (36, 6, 37, 2), (20, 4, 21, 6), (14, 7, 15, 4)], // 12 + [(107, 4, 0, 0), (37, 8, 38, 1), (20, 8, 21, 4), (11, 12, 12, 4)], // 13 + [(115, 3, 116, 1), (40, 4, 41, 5), (16, 11, 17, 5), (12, 11, 13, 5)], // 14 + [(87, 5, 88, 1), (41, 5, 42, 5), (24, 5, 25, 7), (12, 11, 13, 7)], // 15 + [(98, 5, 99, 1), (45, 7, 46, 3), (19, 15, 20, 2), (15, 3, 16, 13)], // 16 + [(107, 1, 108, 5), (46, 10, 47, 1), (22, 1, 23, 15), (14, 2, 15, 17)], // 17 + [(120, 5, 121, 1), (43, 9, 44, 4), (22, 17, 23, 1), (14, 2, 15, 19)], // 18 + [(113, 3, 114, 4), (44, 3, 45, 11), (21, 17, 22, 4), (13, 9, 14, 16)], // 19 + [(107, 3, 108, 5), (41, 3, 42, 13), (24, 15, 25, 5), (15, 15, 16, 10)], // 20 + [(116, 4, 117, 4), (42, 17, 0, 0), (22, 17, 23, 6), (16, 19, 17, 6)], // 21 + [(111, 2, 112, 7), (46, 17, 0, 0), (24, 7, 25, 16), (13, 34, 0, 0)], // 22 + [(121, 4, 122, 5), (47, 4, 48, 14), (24, 11, 25, 14), (15, 16, 16, 14)], // 23 + [(117, 6, 118, 4), (45, 6, 46, 14), (24, 11, 25, 16), (16, 30, 17, 2)], // 24 + [(106, 8, 107, 4), (47, 8, 48, 13), (24, 7, 25, 22), (15, 22, 16, 13)], // 25 + [(114, 10, 115, 2), (46, 19, 47, 4), (22, 28, 23, 6), (16, 33, 17, 4)], // 26 + [(122, 8, 123, 4), (45, 22, 46, 3), (23, 8, 24, 26), (15, 12, 16, 28)], // 27 + [(117, 3, 118, 10), (45, 3, 46, 23), (24, 4, 25, 31), (15, 11, 16, 31)], // 28 + [(116, 7, 117, 7), (45, 21, 46, 7), (23, 1, 24, 37), (15, 19, 16, 26)], // 29 + [(115, 5, 116, 10), (47, 19, 48, 10), (24, 15, 25, 25), (15, 23, 16, 25)], // 30 + [(115, 13, 116, 3), (46, 2, 47, 29), (24, 42, 25, 1), (15, 23, 16, 28)], // 31 + [(115, 17, 0, 0), (46, 10, 47, 23), (24, 10, 25, 35), (15, 19, 16, 35)], // 32 + [(115, 17, 116, 1), (46, 14, 47, 21), (24, 29, 25, 19), (15, 11, 16, 46)], // 33 + [(115, 13, 116, 6), (46, 14, 47, 23), (24, 44, 25, 7), (16, 59, 17, 1)], // 34 + [(121, 12, 122, 7), (47, 12, 48, 26), (24, 39, 25, 14), (15, 22, 16, 41)], // 35 + [(121, 6, 122, 14), (47, 6, 48, 34), (24, 46, 25, 10), (15, 2, 16, 64)], // 36 + [(122, 17, 123, 4), (46, 29, 47, 14), (24, 49, 25, 10), (15, 24, 16, 46)], // 37 + [(122, 4, 123, 18), (46, 13, 47, 32), (24, 48, 25, 14), (15, 42, 16, 32)], // 38 + [(117, 20, 118, 4), (47, 40, 48, 7), (24, 43, 25, 22), (15, 10, 16, 67)], // 39 + [(118, 19, 119, 6), (47, 18, 48, 31), (24, 34, 25, 34), (15, 20, 16, 61)], // 40 // Micro versions. - [(3, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M1 - [(5, 1, 0, 0), (4, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M2 - [(11, 1, 0, 0), (9, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M3 - [(16, 1, 0, 0), (14, 1, 0, 0), (10, 1, 0, 0), (0, 0, 0, 0)], // M4 + [(3, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M1 + [(5, 1, 0, 0), (4, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M2 + [(11, 1, 0, 0), (9, 1, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)], // M3 + [(16, 1, 0, 0), (14, 1, 0, 0), (10, 1, 0, 0), (0, 0, 0, 0)], // M4 ]; //}}} - - diff --git a/src/lib.rs b/src/lib.rs index e2eb75c..05d1574 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,8 @@ //! //! This crate provides a QR code and Micro QR code encoder for binary data. //! -#![cfg_attr(feature="image", doc=" ```rust")] -#![cfg_attr(not(feature="image"), doc="```ignore")] +#![cfg_attr(feature = "image", doc = " ```rust")] +#![cfg_attr(not(feature = "image"), doc = "```ignore")] //! extern crate qrcode; //! extern crate image; //! @@ -29,10 +29,17 @@ //! } //! ``` -#![cfg_attr(feature="bench", feature(test))] // Unstable libraries +#![cfg_attr(feature = "bench", feature(test))] // Unstable libraries +#![cfg_attr(feature = "cargo-clippy", deny(warnings, clippy_pedantic))] +#![cfg_attr(feature = "cargo-clippy", + allow(unreadable_literal, missing_docs_in_private_items, shadow_reuse, + range_plus_one))] -#[cfg(feature="bench")] extern crate test; -#[cfg(feature="image")] extern crate image; +extern crate checked_int_cast; +#[cfg(feature = "image")] +extern crate image; +#[cfg(feature = "bench")] +extern crate test; use std::ops::Index; @@ -42,10 +49,13 @@ pub mod optimize; pub mod ec; pub mod canvas; pub mod render; +mod cast; -pub use types::{QrResult, Color, EcLevel, Version}; +pub use types::{Color, EcLevel, QrResult, Version}; use render::{Pixel, Renderer}; +use checked_int_cast::CheckedIntCast; +use cast::As; /// The encoded QR code symbol. #[derive(Clone)] @@ -66,8 +76,8 @@ impl QrCode { /// /// let code = QrCode::new(b"Some data").unwrap(); /// - pub fn new>(data: D) -> QrResult { - QrCode::with_error_correction_level(data, EcLevel::M) + pub fn new>(data: D) -> QrResult { + Self::with_error_correction_level(data, EcLevel::M) } /// Constructs a new QR code which automatically encodes the given data at a @@ -79,9 +89,12 @@ impl QrCode { /// /// let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap(); /// - pub fn with_error_correction_level>(data: D, ec_level: EcLevel) -> QrResult { - let bits = try!(bits::encode_auto(data.as_ref(), ec_level)); - QrCode::with_bits(bits, ec_level) + pub fn with_error_correction_level>( + data: D, + ec_level: EcLevel, + ) -> QrResult { + let bits = bits::encode_auto(data.as_ref(), ec_level)?; + Self::with_bits(bits, ec_level) } /// Constructs a new QR code for the given version and error correction @@ -97,11 +110,15 @@ impl QrCode { /// /// let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap(); /// - pub fn with_version>(data: D, version: Version, ec_level: EcLevel) -> QrResult { + pub fn with_version>( + data: D, + version: Version, + ec_level: EcLevel, + ) -> QrResult { let mut bits = bits::Bits::new(version); - try!(bits.push_optimal_data(data.as_ref())); - try!(bits.push_terminator(ec_level)); - QrCode::with_bits(bits, ec_level) + bits.push_optimal_data(data.as_ref())?; + bits.push_terminator(ec_level)?; + Self::with_bits(bits, ec_level) } /// Constructs a new QR code with encoded bits. @@ -126,19 +143,19 @@ impl QrCode { /// bits.push_terminator(EcLevel::L); /// let qrcode = QrCode::with_bits(bits, EcLevel::L); /// - pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult { + pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult { let version = bits.version(); let data = bits.into_bytes(); - let (encoded_data, ec_data) = try!(ec::construct_codewords(&*data, version, ec_level)); + let (encoded_data, ec_data) = ec::construct_codewords(&*data, version, ec_level)?; let mut canvas = canvas::Canvas::new(version, ec_level); canvas.draw_all_functional_patterns(); canvas.draw_data(&*encoded_data, &*ec_data); let canvas = canvas.apply_best_mask(); - Ok(QrCode { + Ok(Self { content: canvas.into_colors(), version: version, ec_level: ec_level, - width: version.width() as usize, + width: version.width().as_usize(), }) } @@ -163,13 +180,17 @@ impl QrCode { /// before the data becomes corrupted. Note that errors should not be /// introduced to functional modules. pub fn max_allowed_errors(&self) -> usize { - ec::max_allowed_errors(self.version, self.ec_level).unwrap() + ec::max_allowed_errors(self.version, self.ec_level).expect("invalid version or ec_level") } /// Checks whether a module at coordinate (x, y) is a functional module or /// not. pub fn is_functional(&self, x: usize, y: usize) -> bool { - canvas::is_functional(self.version, self.version.width(), x as i16, y as i16) + let x = x.as_i16_checked() + .expect("coordinate is too large for QR code"); + let y = y.as_i16_checked() + .expect("coordinate is too large for QR code"); + canvas::is_functional(self.version, self.version.width(), x, y) } /// Converts the QR code into a human-readable string. This is mainly for @@ -184,16 +205,19 @@ impl QrCode { /// Converts the QR code to a vector of booleans. Each entry represents the /// color of the module, with "true" means dark and "false" means light. - #[deprecated(since="0.4.0", note="use `to_colors()` instead")] + #[deprecated(since = "0.4.0", note = "use `to_colors()` instead")] pub fn to_vec(&self) -> Vec { self.content.iter().map(|c| *c != Color::Light).collect() } /// Converts the QR code to a vector of booleans. Each entry represents the /// color of the module, with "true" means dark and "false" means light. - #[deprecated(since="0.4.0", note="use `into_colors()` instead")] + #[deprecated(since = "0.4.0", note = "use `into_colors()` instead")] pub fn into_vec(self) -> Vec { - self.content.into_iter().map(|c| c != Color::Light).collect() + self.content + .into_iter() + .map(|c| c != Color::Light) + .collect() } /// Converts the QR code to a vector of colors. @@ -212,8 +236,8 @@ impl QrCode { /// /// # Examples /// - #[cfg_attr(feature="image", doc=" ```rust")] - #[cfg_attr(not(feature="image"), doc=" ```ignore")] + #[cfg_attr(feature = "image", doc = " ```rust")] + #[cfg_attr(not(feature = "image"), doc = " ```ignore")] /// # extern crate image; /// # extern crate qrcode; /// # use qrcode::QrCode; @@ -250,66 +274,74 @@ impl Index<(usize, usize)> for QrCode { #[cfg(test)] mod tests { - use {QrCode, Version, EcLevel}; + use {EcLevel, QrCode, Version}; #[test] fn test_annex_i_qr() { // This uses the ISO Annex I as test vector. let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap(); - assert_eq!(&*code.to_debug_str('#', '.'), "\ - #######..#.##.#######\n\ - #.....#..####.#.....#\n\ - #.###.#.#.....#.###.#\n\ - #.###.#.##....#.###.#\n\ - #.###.#.#.###.#.###.#\n\ - #.....#.#...#.#.....#\n\ - #######.#.#.#.#######\n\ - ........#..##........\n\ - #.#####..#..#.#####..\n\ - ...#.#.##.#.#..#.##..\n\ - ..#...##.#.#.#..#####\n\ - ....#....#.....####..\n\ - ...######..#.#..#....\n\ - ........#.#####..##..\n\ - #######..##.#.##.....\n\ - #.....#.#.#####...#.#\n\ - #.###.#.#...#..#.##..\n\ - #.###.#.##..#..#.....\n\ - #.###.#.#.##.#..#.#..\n\ - #.....#........##.##.\n\ - #######.####.#..#.#.."); + assert_eq!( + &*code.to_debug_str('#', '.'), + "\ + #######..#.##.#######\n\ + #.....#..####.#.....#\n\ + #.###.#.#.....#.###.#\n\ + #.###.#.##....#.###.#\n\ + #.###.#.#.###.#.###.#\n\ + #.....#.#...#.#.....#\n\ + #######.#.#.#.#######\n\ + ........#..##........\n\ + #.#####..#..#.#####..\n\ + ...#.#.##.#.#..#.##..\n\ + ..#...##.#.#.#..#####\n\ + ....#....#.....####..\n\ + ...######..#.#..#....\n\ + ........#.#####..##..\n\ + #######..##.#.##.....\n\ + #.....#.#.#####...#.#\n\ + #.###.#.#...#..#.##..\n\ + #.###.#.##..#..#.....\n\ + #.###.#.#.##.#..#.#..\n\ + #.....#........##.##.\n\ + #######.####.#..#.#.." + ); } #[test] fn test_annex_i_micro_qr() { let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap(); - assert_eq!(&*code.to_debug_str('#', '.'), "\ - #######.#.#.#\n\ - #.....#.###.#\n\ - #.###.#..##.#\n\ - #.###.#..####\n\ - #.###.#.###..\n\ - #.....#.#...#\n\ - #######..####\n\ - .........##..\n\ - ##.#....#...#\n\ - .##.#.#.#.#.#\n\ - ###..#######.\n\ - ...#.#....##.\n\ - ###.#..##.###"); + assert_eq!( + &*code.to_debug_str('#', '.'), + "\ + #######.#.#.#\n\ + #.....#.###.#\n\ + #.###.#..##.#\n\ + #.###.#..####\n\ + #.###.#.###..\n\ + #.....#.#...#\n\ + #######..####\n\ + .........##..\n\ + ##.#....#...#\n\ + .##.#.#.#.#.#\n\ + ###..#######.\n\ + ...#.#....##.\n\ + ###.#..##.###" + ); } } -#[cfg(all(test, feature="image"))] +#[cfg(all(test, feature = "image"))] mod image_tests { - use image::{Luma, Rgb, load_from_memory}; - use {QrCode, Version, EcLevel}; + use image::{load_from_memory, Luma, Rgb}; + use {EcLevel, QrCode, Version}; #[test] fn test_annex_i_qr_as_image() { let code = QrCode::new(b"01234567").unwrap(); let image = code.render::>().build(); - let expected = load_from_memory(include_bytes!("test_annex_i_qr_as_image.png")).unwrap().to_luma(); + let expected = load_from_memory(include_bytes!("test_annex_i_qr_as_image.png")) + .unwrap() + .to_luma(); assert_eq!(image.dimensions(), expected.dimensions()); assert_eq!(image.into_raw(), expected.into_raw()); } @@ -322,16 +354,18 @@ mod image_tests { .dark_color(Rgb { data: [128, 0, 0] }) .light_color(Rgb { data: [255, 255, 128] }) .build(); - let expected = load_from_memory(include_bytes!("test_annex_i_micro_qr_as_image.png")).unwrap().to_rgb(); + let expected = load_from_memory(include_bytes!("test_annex_i_micro_qr_as_image.png")) + .unwrap() + .to_rgb(); assert_eq!(image.dimensions(), expected.dimensions()); assert_eq!(image.into_raw(), expected.into_raw()); } } -#[cfg(all(test, feature="svg"))] +#[cfg(all(test, feature = "svg"))] mod svg_tests { use render::svg::Color as SvgColor; - use {QrCode, Version, EcLevel}; + use {EcLevel, QrCode, Version}; #[test] fn test_annex_i_qr_as_svg() { @@ -353,4 +387,3 @@ mod svg_tests { assert_eq!(&image, expected); } } - diff --git a/src/optimize.rs b/src/optimize.rs index 017fe8a..6a73b7f 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -2,7 +2,7 @@ use std::slice::Iter; use types::{Mode, Version}; -#[cfg(feature="bench")] +#[cfg(feature = "bench")] use test::Bencher; //------------------------------------------------------------------------------ @@ -26,7 +26,11 @@ impl Segment { /// length bits) when this segment is encoded. pub fn encoded_len(&self, version: Version) -> usize { let byte_size = self.end - self.begin; - let chars_count = if self.mode == Mode::Kanji { byte_size / 2 } else { byte_size }; + let chars_count = if self.mode == Mode::Kanji { + byte_size / 2 + } else { + byte_size + }; let mode_bits_count = version.mode_bits_count(); let length_bits_count = self.mode.length_bits_count(version); @@ -56,7 +60,7 @@ struct EcsIter { ended: bool, } -impl<'a, I: Iterator> Iterator for EcsIter { +impl<'a, I: Iterator> Iterator for EcsIter { type Item = (usize, ExclCharSet); fn next(&mut self) -> Option<(usize, ExclCharSet)> { @@ -115,24 +119,20 @@ impl<'a> Iterator for Parser<'a> { if self.pending_single_byte { self.pending_single_byte = false; self.begin += 1; - return Some(Segment { - mode: Mode::Byte, - begin: self.begin-1, - end: self.begin, - }); + return Some(Segment { mode: Mode::Byte, begin: self.begin - 1, end: self.begin }); } loop { let (i, ecs) = match self.ecs_iter.next() { - None => { return None; }, - Some(a) => a + None => return None, + Some(a) => a, }; let (next_state, action) = STATE_TRANSITION[self.state as usize + ecs as usize]; self.state = next_state; let old_begin = self.begin; let push_mode = match action { - Action::Idle => { continue; } + Action::Idle => continue, Action::Numeric => Mode::Numeric, Action::Alpha => Mode::Alphanumeric, Action::Byte => Mode::Byte, @@ -144,21 +144,15 @@ impl<'a> Iterator for Parser<'a> { } else { self.pending_single_byte = true; self.begin = next_begin; - return Some(Segment { - mode: Mode::Kanji, - begin: old_begin, - end: next_begin, - }); + return Some( + Segment { mode: Mode::Kanji, begin: old_begin, end: next_begin }, + ); } } }; self.begin = i; - return Some(Segment { - mode: push_mode, - begin: old_begin, - end: i, - }); + return Some(Segment { mode: push_mode, begin: old_begin, end: i }); } } } @@ -175,39 +169,59 @@ mod parse_tests { #[test] fn test_parse_1() { let segs = parse(b"01049123451234591597033130128%10ABC123"); - assert_eq!(segs, vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, - Segment { mode: Mode::Numeric, begin: 30, end: 32 }, - Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, - Segment { mode: Mode::Numeric, begin: 35, end: 38 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 29 }, + Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, + Segment { mode: Mode::Numeric, begin: 30, end: 32 }, + Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, + Segment { mode: Mode::Numeric, begin: 35, end: 38 }, + ] + ); } #[test] fn test_parse_shift_jis_example_1() { - let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ" - assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, - Segment { mode: Mode::Byte, begin: 5, end: 6 }, - Segment { mode: Mode::Kanji, begin: 6, end: 8 }]); + let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ" + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 4 }, + Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, + Segment { mode: Mode::Byte, begin: 5, end: 6 }, + Segment { mode: Mode::Kanji, begin: 6, end: 8 }, + ] + ); } #[test] fn test_parse_utf_8() { // Mojibake? let segs = parse(b"\xe3\x81\x82\xe3\x80\x81A\xef\xbd\xb1\xe2\x84\xab"); - assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Byte, begin: 4, end: 5 }, - Segment { mode: Mode::Kanji, begin: 5, end: 7 }, - Segment { mode: Mode::Byte, begin: 7, end: 10 }, - Segment { mode: Mode::Kanji, begin: 10, end: 12 }, - Segment { mode: Mode::Byte, begin: 12, end: 13 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 4 }, + Segment { mode: Mode::Byte, begin: 4, end: 5 }, + Segment { mode: Mode::Kanji, begin: 5, end: 7 }, + Segment { mode: Mode::Byte, begin: 7, end: 10 }, + Segment { mode: Mode::Kanji, begin: 10, end: 12 }, + Segment { mode: Mode::Byte, begin: 12, end: 13 }, + ] + ); } #[test] fn test_not_kanji_1() { let segs = parse(b"\x81\x30"); - assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, - Segment { mode: Mode::Numeric, begin: 1, end: 2 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Byte, begin: 0, end: 1 }, + Segment { mode: Mode::Numeric, begin: 1, end: 2 }, + ] + ); } #[test] @@ -215,22 +229,37 @@ mod parse_tests { // Note that it's implementation detail that the byte seq is split into // two. Perhaps adjust the test to check for this. let segs = parse(b"\xeb\xc0"); - assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, - Segment { mode: Mode::Byte, begin: 1, end: 2 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Byte, begin: 0, end: 1 }, + Segment { mode: Mode::Byte, begin: 1, end: 2 }, + ] + ); } #[test] fn test_not_kanji_3() { let segs = parse(b"\x81\x7f"); - assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 }, - Segment { mode: Mode::Byte, begin: 1, end: 2 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Byte, begin: 0, end: 1 }, + Segment { mode: Mode::Byte, begin: 1, end: 2 }, + ] + ); } #[test] fn test_not_kanji_4() { let segs = parse(b"\x81\x40\x81"); - assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 2 }, - Segment { mode: Mode::Byte, begin: 2, end: 3 }]); + assert_eq!( + segs, + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 2 }, + Segment { mode: Mode::Byte, begin: 2, end: 3 }, + ] + ); } } @@ -238,6 +267,7 @@ mod parse_tests { //------------------------------------------------------------------------------ //{{{ Optimizer +#[cfg_attr(feature = "cargo-clippy", allow(stutter))] // rust-lang-nursery/rust-clippy#2212 ಠ_ಠ pub struct Optimizer { parser: I, last_segment: Segment, @@ -246,23 +276,23 @@ pub struct Optimizer { ended: bool, } -impl> Optimizer { +impl> Optimizer { /// Optimize the segments by combining adjacent segments when possible. /// /// Currently this method uses a greedy algorithm by combining segments from /// left to right until the new segment is longer than before. This method /// does *not* use Annex J from the ISO standard. /// - pub fn new(mut segments: I, version: Version) -> Optimizer { + pub fn new(mut segments: I, version: Version) -> Self { match segments.next() { - None => Optimizer { + None => Self { parser: segments, last_segment: Segment { mode: Mode::Numeric, begin: 0, end: 0 }, last_segment_size: 0, version: version, ended: true, }, - Some(segment) => Optimizer { + Some(segment) => Self { parser: segments, last_segment: segment, last_segment_size: segment.encoded_len(version), @@ -279,7 +309,7 @@ impl<'a> Parser<'a> { } } -impl> Iterator for Optimizer { +impl> Iterator for Optimizer { type Item = Segment; fn next(&mut self) -> Option { @@ -321,12 +351,14 @@ impl> Iterator for Optimizer { /// Computes the total encoded length of all segments. pub fn total_encoded_len(segments: &[Segment], version: Version) -> usize { // TODO revert to `.map().sum()` after `sum()` is stable. - segments.iter().fold(0, |acc, seg| acc + seg.encoded_len(version)) + segments + .iter() + .fold(0, |acc, seg| acc + seg.encoded_len(version)) } #[cfg(test)] mod optimize_tests { - use optimize::{Optimizer, total_encoded_len, Segment}; + use optimize::{total_encoded_len, Optimizer, Segment}; use types::{Mode, Version}; fn test_optimization_result(given: Vec, expected: Vec, version: Version) { @@ -336,130 +368,143 @@ mod optimize_tests { if given != opt_segs { assert!(prev_len > new_len, "{} > {}", prev_len, new_len); } - assert!(opt_segs == expected, - "Optimization gave something better: {} < {} ({:?})", - new_len, total_encoded_len(&*expected, version), opt_segs); + assert!( + opt_segs == expected, + "Optimization gave something better: {} < {} ({:?})", + new_len, + total_encoded_len(&*expected, version), + opt_segs + ); } #[test] fn test_example_1() { test_optimization_result( - - vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 3 }, - Segment { mode: Mode::Numeric, begin: 3, end: 6 }, - Segment { mode: Mode::Byte, begin: 6, end: 10 }], - - vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 }, - Segment { mode: Mode::Byte, begin: 6, end: 10 }], - - Version::Normal(1) - + vec![ + Segment { mode: Mode::Alphanumeric, begin: 0, end: 3 }, + Segment { mode: Mode::Numeric, begin: 3, end: 6 }, + Segment { mode: Mode::Byte, begin: 6, end: 10 }, + ], + vec![ + Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 }, + Segment { mode: Mode::Byte, begin: 6, end: 10 }, + ], + Version::Normal(1), ); } #[test] fn test_example_2() { test_optimization_result( - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, - Segment { mode: Mode::Numeric, begin: 30, end: 32 }, - Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, - Segment { mode: Mode::Numeric, begin: 35, end: 38 }], - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 }, - Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }], - - Version::Normal(9) - + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 29 }, + Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 }, + Segment { mode: Mode::Numeric, begin: 30, end: 32 }, + Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 }, + Segment { mode: Mode::Numeric, begin: 35, end: 38 }, + ], + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 29 }, + Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }, + ], + Version::Normal(9), ); } #[test] fn test_example_3() { test_optimization_result( - - vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 }, - Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, - Segment { mode: Mode::Byte, begin: 5, end: 6 }, - Segment { mode: Mode::Kanji, begin: 6, end: 8 }], - + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 4 }, + Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 }, + Segment { mode: Mode::Byte, begin: 5, end: 6 }, + Segment { mode: Mode::Kanji, begin: 6, end: 8 }, + ], vec![Segment { mode: Mode::Byte, begin: 0, end: 8 }], - - Version::Normal(1) - + Version::Normal(1), ); } #[test] fn test_example_4() { test_optimization_result( - - vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 }, - Segment { mode: Mode::Byte, begin: 10, end: 11 }], - - vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 }, - Segment { mode: Mode::Byte, begin: 10, end: 11 }], - - Version::Normal(1) - + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 10 }, + Segment { mode: Mode::Byte, begin: 10, end: 11 }, + ], + vec![ + Segment { mode: Mode::Kanji, begin: 0, end: 10 }, + Segment { mode: Mode::Byte, begin: 10, end: 11 }, + ], + Version::Normal(1), ); } #[test] fn test_annex_j_guideline_1a() { test_optimization_result( - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }], - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }], - - Version::Micro(2) - + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 3 }, + Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, + ], + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 3 }, + Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, + ], + Version::Micro(2), ); } #[test] fn test_annex_j_guideline_1b() { test_optimization_result( - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 2 }, - Segment { mode: Mode::Alphanumeric, begin: 2, end: 4 }], - + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 2 }, + Segment { mode: Mode::Alphanumeric, begin: 2, end: 4 }, + ], vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }], - - Version::Micro(2) - + Version::Micro(2), ); } #[test] fn test_annex_j_guideline_1c() { test_optimization_result( - - vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 }, - Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }], - + vec![ + Segment { mode: Mode::Numeric, begin: 0, end: 3 }, + Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }, + ], vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }], - - Version::Micro(3) - + Version::Micro(3), ); } } -#[cfg(feature="bench")] +#[cfg(feature = "bench")] #[bench] fn bench_optimize(bencher: &mut Bencher) { use types::Version; - let data = b"QR\x83R\x81[\x83h\x81i\x83L\x83\x85\x81[\x83A\x81[\x83\x8b\x83R\x81[\x83h\x81j\x82\xc6\x82\xcd\x81A1994\x94N\x82\xc9\x83f\x83\x93\x83\\\x81[\x82\xcc\x8aJ\x94\xad\x95\x94\x96\xe5\x81i\x8c\xbb\x8d\xdd\x82\xcd\x95\xaa\x97\xa3\x82\xb5\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x81j\x82\xaa\x8aJ\x94\xad\x82\xb5\x82\xbd\x83}\x83g\x83\x8a\x83b\x83N\x83X\x8c^\x93\xf1\x8e\x9f\x8c\xb3\x83R\x81[\x83h\x82\xc5\x82\xa0\x82\xe9\x81B\x82\xc8\x82\xa8\x81AQR\x83R\x81[\x83h\x82\xc6\x82\xa2\x82\xa4\x96\xbc\x8f\xcc\x81i\x82\xa8\x82\xe6\x82\xd1\x92P\x8c\xea\x81j\x82\xcd\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x82\xcc\x93o\x98^\x8f\xa4\x95W\x81i\x91\xe64075066\x8d\x86\x81j\x82\xc5\x82\xa0\x82\xe9\x81BQR\x82\xcdQuick Response\x82\xc9\x97R\x97\x88\x82\xb5\x81A\x8d\x82\x91\xac\x93\xc7\x82\xdd\x8e\xe6\x82\xe8\x82\xaa\x82\xc5\x82\xab\x82\xe9\x82\xe6\x82\xa4\x82\xc9\x8aJ\x94\xad\x82\xb3\x82\xea\x82\xbd\x81B\x93\x96\x8f\x89\x82\xcd\x8e\xa9\x93\xae\x8e\xd4\x95\x94\x95i\x8dH\x8f\xea\x82\xe2\x94z\x91\x97\x83Z\x83\x93\x83^\x81[\x82\xc8\x82\xc7\x82\xc5\x82\xcc\x8eg\x97p\x82\xf0\x94O\x93\xaa\x82\xc9\x8aJ\x94\xad\x82\xb3\x82\xea\x82\xbd\x82\xaa\x81A\x8c\xbb\x8d\xdd\x82\xc5\x82\xcd\x83X\x83}\x81[\x83g\x83t\x83H\x83\x93\x82\xcc\x95\x81\x8by\x82\xc8\x82\xc7\x82\xc9\x82\xe6\x82\xe8\x93\xfa\x96{\x82\xc9\x8c\xc0\x82\xe7\x82\xb8\x90\xa2\x8aE\x93I\x82\xc9\x95\x81\x8by\x82\xb5\x82\xc4\x82\xa2\x82\xe9\x81B"; - bencher.iter(|| { - Parser::new(data).optimize(Version::Normal(15)) - }); + let data = b"QR\x83R\x81[\x83h\x81i\x83L\x83\x85\x81[\x83A\x81[\x83\x8b\x83R\x81[\x83h\x81j\ + \x82\xc6\x82\xcd\x81A1994\x94N\x82\xc9\x83f\x83\x93\x83\\\x81[\x82\xcc\x8aJ\ + \x94\xad\x95\x94\x96\xe5\x81i\x8c\xbb\x8d\xdd\x82\xcd\x95\xaa\x97\xa3\x82\xb5\x83f\ + \x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x81j\x82\xaa\x8aJ\x94\xad\x82\xb5\x82\xbd\ + \x83}\x83g\x83\x8a\x83b\x83N\x83X\x8c^\x93\xf1\x8e\x9f\x8c\xb3\x83R\x81[\x83h\ + \x82\xc5\x82\xa0\x82\xe9\x81B\x82\xc8\x82\xa8\x81AQR\x83R\x81[\x83h\x82\xc6\ + \x82\xa2\x82\xa4\x96\xbc\x8f\xcc\x81i\x82\xa8\x82\xe6\x82\xd1\x92P\x8c\xea\x81j\ + \x82\xcd\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x82\xcc\x93o\x98^\x8f\xa4\ + \x95W\x81i\x91\xe64075066\x8d\x86\x81j\x82\xc5\x82\xa0\x82\xe9\x81BQR\x82\xcd\ + Quick Response\x82\xc9\x97R\x97\x88\x82\xb5\x81A\x8d\x82\x91\xac\x93\xc7\x82\xdd\ + \x8e\xe6\x82\xe8\x82\xaa\x82\xc5\x82\xab\x82\xe9\x82\xe6\x82\xa4\x82\xc9\x8aJ\ + \x94\xad\x82\xb3\x82\xea\x82\xbd\x81B\x93\x96\x8f\x89\x82\xcd\x8e\xa9\x93\xae\ + \x8e\xd4\x95\x94\x95i\x8dH\x8f\xea\x82\xe2\x94z\x91\x97\x83Z\x83\x93\x83^\x81[\ + \x82\xc8\x82\xc7\x82\xc5\x82\xcc\x8eg\x97p\x82\xf0\x94O\x93\xaa\x82\xc9\x8aJ\ + \x94\xad\x82\xb3\x82\xea\x82\xbd\x82\xaa\x81A\x8c\xbb\x8d\xdd\x82\xc5\x82\xcd\x83X\ + \x83}\x81[\x83g\x83t\x83H\x83\x93\x82\xcc\x95\x81\x8by\x82\xc8\x82\xc7\x82\xc9\ + \x82\xe6\x82\xe8\x93\xfa\x96{\x82\xc9\x8c\xc0\x82\xe7\x82\xb8\x90\xa2\x8aE\x93I\ + \x82\xc9\x95\x81\x8by\x82\xb5\x82\xc4\x82\xa2\x82\xe9\x81B"; + bencher.iter(|| Parser::new(data).optimize(Version::Normal(15))); } @@ -514,17 +559,17 @@ enum ExclCharSet { impl ExclCharSet { /// Determines which character set a byte is in. - fn from_u8(c: u8) -> ExclCharSet { + fn from_u8(c: u8) -> Self { match c { - 0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ExclCharSet::Symbol, - 0x30 ... 0x39 => ExclCharSet::Numeric, - 0x41 ... 0x5a => ExclCharSet::Alpha, - 0x81 ... 0x9f => ExclCharSet::KanjiHi1, - 0xe0 ... 0xea => ExclCharSet::KanjiHi2, + 0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d...0x2f | 0x3a => ExclCharSet::Symbol, + 0x30...0x39 => ExclCharSet::Numeric, + 0x41...0x5a => ExclCharSet::Alpha, + 0x81...0x9f => ExclCharSet::KanjiHi1, + 0xe0...0xea => ExclCharSet::KanjiHi2, 0xeb => ExclCharSet::KanjiHi3, - 0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => ExclCharSet::KanjiLo1, - 0xc0 ... 0xdf | 0xec ... 0xfc => ExclCharSet::KanjiLo2, - _ => ExclCharSet::Byte + 0x40 | 0x5b...0x7e | 0x80 | 0xa0...0xbf => ExclCharSet::KanjiLo1, + 0xc0...0xdf | 0xec...0xfc => ExclCharSet::KanjiLo2, + _ => ExclCharSet::Byte, } } } @@ -583,97 +628,82 @@ static STATE_TRANSITION: [(State, Action); 70] = [ // STATE_TRANSITION[current_state + next_character] == (next_state, what_to_do) // Init state: - - (State::Init, Action::Idle), // End - (State::Alpha, Action::Idle), // Symbol - (State::Numeric, Action::Idle), // Numeric - (State::Alpha, Action::Idle), // Alpha - (State::KanjiHi12, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::Idle), // KanjiHi2 - (State::KanjiHi3, Action::Idle), // KanjiHi3 - (State::Byte, Action::Idle), // KanjiLo1 - (State::Byte, Action::Idle), // KanjiLo2 - (State::Byte, Action::Idle), // Byte - + (State::Init, Action::Idle), // End + (State::Alpha, Action::Idle), // Symbol + (State::Numeric, Action::Idle), // Numeric + (State::Alpha, Action::Idle), // Alpha + (State::KanjiHi12, Action::Idle), // KanjiHi1 + (State::KanjiHi12, Action::Idle), // KanjiHi2 + (State::KanjiHi3, Action::Idle), // KanjiHi3 + (State::Byte, Action::Idle), // KanjiLo1 + (State::Byte, Action::Idle), // KanjiLo2 + (State::Byte, Action::Idle), // Byte // Numeric state: - - (State::Init, Action::Numeric), // End - (State::Alpha, Action::Numeric), // Symbol - (State::Numeric, Action::Idle), // Numeric - (State::Alpha, Action::Numeric), // Alpha - (State::KanjiHi12, Action::Numeric), // KanjiHi1 - (State::KanjiHi12, Action::Numeric), // KanjiHi2 - (State::KanjiHi3, Action::Numeric), // KanjiHi3 - (State::Byte, Action::Numeric), // KanjiLo1 - (State::Byte, Action::Numeric), // KanjiLo2 - (State::Byte, Action::Numeric), // Byte - + (State::Init, Action::Numeric), // End + (State::Alpha, Action::Numeric), // Symbol + (State::Numeric, Action::Idle), // Numeric + (State::Alpha, Action::Numeric), // Alpha + (State::KanjiHi12, Action::Numeric), // KanjiHi1 + (State::KanjiHi12, Action::Numeric), // KanjiHi2 + (State::KanjiHi3, Action::Numeric), // KanjiHi3 + (State::Byte, Action::Numeric), // KanjiLo1 + (State::Byte, Action::Numeric), // KanjiLo2 + (State::Byte, Action::Numeric), // Byte // Alpha state: - - (State::Init, Action::Alpha), // End - (State::Alpha, Action::Idle), // Symbol - (State::Numeric, Action::Alpha), // Numeric - (State::Alpha, Action::Idle), // Alpha - (State::KanjiHi12, Action::Alpha), // KanjiHi1 - (State::KanjiHi12, Action::Alpha), // KanjiHi2 - (State::KanjiHi3, Action::Alpha), // KanjiHi3 - (State::Byte, Action::Alpha), // KanjiLo1 - (State::Byte, Action::Alpha), // KanjiLo2 - (State::Byte, Action::Alpha), // Byte - + (State::Init, Action::Alpha), // End + (State::Alpha, Action::Idle), // Symbol + (State::Numeric, Action::Alpha), // Numeric + (State::Alpha, Action::Idle), // Alpha + (State::KanjiHi12, Action::Alpha), // KanjiHi1 + (State::KanjiHi12, Action::Alpha), // KanjiHi2 + (State::KanjiHi3, Action::Alpha), // KanjiHi3 + (State::Byte, Action::Alpha), // KanjiLo1 + (State::Byte, Action::Alpha), // KanjiLo2 + (State::Byte, Action::Alpha), // Byte // Byte state: - - (State::Init, Action::Byte), // End - (State::Alpha, Action::Byte), // Symbol - (State::Numeric, Action::Byte), // Numeric - (State::Alpha, Action::Byte), // Alpha - (State::KanjiHi12, Action::Byte), // KanjiHi1 - (State::KanjiHi12, Action::Byte), // KanjiHi2 - (State::KanjiHi3, Action::Byte), // KanjiHi3 - (State::Byte, Action::Idle), // KanjiLo1 - (State::Byte, Action::Idle), // KanjiLo2 - (State::Byte, Action::Idle), // Byte - + (State::Init, Action::Byte), // End + (State::Alpha, Action::Byte), // Symbol + (State::Numeric, Action::Byte), // Numeric + (State::Alpha, Action::Byte), // Alpha + (State::KanjiHi12, Action::Byte), // KanjiHi1 + (State::KanjiHi12, Action::Byte), // KanjiHi2 + (State::KanjiHi3, Action::Byte), // KanjiHi3 + (State::Byte, Action::Idle), // KanjiLo1 + (State::Byte, Action::Idle), // KanjiLo2 + (State::Byte, Action::Idle), // Byte // KanjiHi12 state: - - (State::Init, Action::KanjiAndSingleByte), // End - (State::Alpha, Action::KanjiAndSingleByte), // Symbol - (State::Numeric, Action::KanjiAndSingleByte), // Numeric - (State::Kanji, Action::Idle), // Alpha - (State::Kanji, Action::Idle), // KanjiHi1 - (State::Kanji, Action::Idle), // KanjiHi2 - (State::Kanji, Action::Idle), // KanjiHi3 - (State::Kanji, Action::Idle), // KanjiLo1 - (State::Kanji, Action::Idle), // KanjiLo2 - (State::Byte, Action::KanjiAndSingleByte), // Byte - + (State::Init, Action::KanjiAndSingleByte), // End + (State::Alpha, Action::KanjiAndSingleByte), // Symbol + (State::Numeric, Action::KanjiAndSingleByte), // Numeric + (State::Kanji, Action::Idle), // Alpha + (State::Kanji, Action::Idle), // KanjiHi1 + (State::Kanji, Action::Idle), // KanjiHi2 + (State::Kanji, Action::Idle), // KanjiHi3 + (State::Kanji, Action::Idle), // KanjiLo1 + (State::Kanji, Action::Idle), // KanjiLo2 + (State::Byte, Action::KanjiAndSingleByte), // Byte // KanjiHi3 state: - - (State::Init, Action::KanjiAndSingleByte), // End - (State::Alpha, Action::KanjiAndSingleByte), // Symbol - (State::Numeric, Action::KanjiAndSingleByte), // Numeric - (State::Kanji, Action::Idle), // Alpha - (State::Kanji, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::KanjiAndSingleByte), // KanjiHi2 - (State::KanjiHi3, Action::KanjiAndSingleByte), // KanjiHi3 - (State::Kanji, Action::Idle), // KanjiLo1 - (State::Byte, Action::KanjiAndSingleByte), // KanjiLo2 - (State::Byte, Action::KanjiAndSingleByte), // Byte - + (State::Init, Action::KanjiAndSingleByte), // End + (State::Alpha, Action::KanjiAndSingleByte), // Symbol + (State::Numeric, Action::KanjiAndSingleByte), // Numeric + (State::Kanji, Action::Idle), // Alpha + (State::Kanji, Action::Idle), // KanjiHi1 + (State::KanjiHi12, Action::KanjiAndSingleByte), // KanjiHi2 + (State::KanjiHi3, Action::KanjiAndSingleByte), // KanjiHi3 + (State::Kanji, Action::Idle), // KanjiLo1 + (State::Byte, Action::KanjiAndSingleByte), // KanjiLo2 + (State::Byte, Action::KanjiAndSingleByte), // Byte // Kanji state: - - (State::Init, Action::Kanji), // End - (State::Alpha, Action::Kanji), // Symbol - (State::Numeric, Action::Kanji), // Numeric - (State::Alpha, Action::Kanji), // Alpha - (State::KanjiHi12, Action::Idle), // KanjiHi1 - (State::KanjiHi12, Action::Idle), // KanjiHi2 - (State::KanjiHi3, Action::Idle), // KanjiHi3 - (State::Byte, Action::Kanji), // KanjiLo1 - (State::Byte, Action::Kanji), // KanjiLo2 - (State::Byte, Action::Kanji), // Byte + (State::Init, Action::Kanji), // End + (State::Alpha, Action::Kanji), // Symbol + (State::Numeric, Action::Kanji), // Numeric + (State::Alpha, Action::Kanji), // Alpha + (State::KanjiHi12, Action::Idle), // KanjiHi1 + (State::KanjiHi12, Action::Idle), // KanjiHi2 + (State::KanjiHi3, Action::Idle), // KanjiHi3 + (State::Byte, Action::Kanji), // KanjiLo1 + (State::Byte, Action::Kanji), // KanjiLo2 + (State::Byte, Action::Kanji), // Byte ]; //}}} - - diff --git a/src/render/image.rs b/src/render/image.rs index 02b8deb..c318c89 100644 --- a/src/render/image.rs +++ b/src/render/image.rs @@ -1,9 +1,9 @@ #![cfg(feature="image")] -use render::{Pixel, Canvas}; +use render::{Canvas, Pixel}; use types::Color; -use image::{Pixel as ImagePixel, Rgb, Rgba, Luma, LumaA, Primitive, ImageBuffer}; +use image::{ImageBuffer, Luma, LumaA, Pixel as ImagePixel, Primitive, Rgb, Rgba}; macro_rules! impl_pixel_for_image_pixel { ($p:ident<$s:ident>: $c:pat => $d:expr) => { @@ -50,12 +50,26 @@ mod render_tests { #[test] fn test_render_luma8_unsized() { - let image = Renderer::>::new(&[ - Color::Light, Color::Dark, Color::Dark, - Color::Dark, Color::Light, Color::Light, - Color::Light, Color::Dark, Color::Light, - ], 3, 1).module_dimensions(1, 1).build(); + let image = Renderer::>::new( + &[ + Color::Light, + Color::Dark, + Color::Dark, + // + Color::Dark, + Color::Light, + Color::Light, + // + Color::Light, + Color::Dark, + Color::Light, + ], + 3, + 1, + ).module_dimensions(1, 1) + .build(); + #[cfg_attr(rustfmt, rustfmt_skip)] let expected = [ 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, @@ -68,11 +82,12 @@ mod render_tests { #[test] fn test_render_rgba_unsized() { - let image = Renderer::>::new(&[ - Color::Light, Color::Dark, - Color::Dark, Color::Dark, - ], 2, 1).module_dimensions(1, 1).build(); + let image = + Renderer::>::new(&[Color::Light, Color::Dark, Color::Dark, Color::Dark], 2, 1) + .module_dimensions(1, 1) + .build(); + #[cfg_attr(rustfmt, rustfmt_skip)] let expected: &[u8] = &[ 255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, 0, 0, 0,255, 255,255,255,255, @@ -85,11 +100,14 @@ mod render_tests { #[test] fn test_render_resized_min() { - let image = Renderer::>::new(&[ - Color::Dark, Color::Light, - Color::Light, Color::Dark, - ], 2, 1).min_dimensions(10, 10).build(); + let image = Renderer::>::new( + &[Color::Dark, Color::Light, Color::Light, Color::Dark], + 2, + 1, + ).min_dimensions(10, 10) + .build(); + #[cfg_attr(rustfmt, rustfmt_skip)] let expected: &[u8] = &[ 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, @@ -114,11 +132,14 @@ mod render_tests { #[test] fn test_render_resized_max() { - let image = Renderer::>::new(&[ - Color::Dark, Color::Light, - Color::Light, Color::Dark, - ], 2, 1).max_dimensions(10, 5).build(); + let image = Renderer::>::new( + &[Color::Dark, Color::Light, Color::Light, Color::Dark], + 2, + 1, + ).max_dimensions(10, 5) + .build(); + #[cfg_attr(rustfmt, rustfmt_skip)] let expected: &[u8] = &[ 255,255, 255,255, 255,255, 255,255, diff --git a/src/render/mod.rs b/src/render/mod.rs index c09a38c..33f3376 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -2,6 +2,7 @@ use std::cmp::max; use types::Color; +use cast::As; pub mod image; pub mod string; @@ -17,7 +18,7 @@ pub trait Pixel: Copy + Sized { /// The type that stores an intermediate buffer before finalizing to a /// concrete image - type Canvas: Canvas; + type Canvas: Canvas; /// Obtains the default module size. The result must be at least 1×1. fn default_unit_size() -> (u32, u32) { @@ -40,8 +41,8 @@ pub trait Canvas: Sized { fn draw_dark_pixel(&mut self, x: u32, y: u32); fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) { - for y in top .. (top + height) { - for x in left .. (left + width) { + for y in top..(top + height) { + for x in left..(left + width) { self.draw_dark_pixel(x, y); } } @@ -57,6 +58,7 @@ pub trait Canvas: Sized { /// A QR code renderer. This is a builder type which converts a bool-vector into /// an image. +#[cfg_attr(feature = "cargo-clippy", allow(stutter))] // rust-lang-nursery/rust-clippy#2212 ಠ_ಠ pub struct Renderer<'a, P: Pixel> { content: &'a [Color], modules_count: u32, // <- we call it `modules_count` here to avoid ambiguity of `width`. @@ -74,7 +76,7 @@ impl<'a, P: Pixel> Renderer<'a, P> { assert!(modules_count * modules_count == content.len()); Renderer { content, - modules_count: modules_count as u32, + modules_count: modules_count.as_u32(), quiet_zone, module_size: P::default_unit_size(), dark_color: P::default_color(Color::Dark), @@ -102,7 +104,7 @@ impl<'a, P: Pixel> Renderer<'a, P> { } /// Sets the size of each module in pixels. Default is 8px. - #[deprecated(since="0.4.0", note="use `.module_dimensions(width, width)` instead")] + #[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")] pub fn module_size(&mut self, width: u32) -> &mut Self { self.module_dimensions(width, width) } @@ -113,7 +115,7 @@ impl<'a, P: Pixel> Renderer<'a, P> { self } - #[deprecated(since="0.4.0", note="use `.min_dimensions(width, width)` instead")] + #[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")] pub fn min_width(&mut self, width: u32) -> &mut Self { self.min_dimensions(width, width) } @@ -154,7 +156,8 @@ impl<'a, P: Pixel> Renderer<'a, P> { } /// Renders the QR code into an image. - #[deprecated(since="0.4.0", note="renamed to `.build()` to de-emphasize the image connection")] + #[deprecated(since = "0.4.0", + note = "renamed to `.build()` to de-emphasize the image connection")] pub fn to_image(&self) -> P::Image { self.build() } @@ -162,7 +165,11 @@ impl<'a, P: Pixel> Renderer<'a, P> { /// Renders the QR code into an image. pub fn build(&self) -> P::Image { let w = self.modules_count; - let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 }; + let qz = if self.has_quiet_zone { + self.quiet_zone + } else { + 0 + }; let width = w + 2 * qz; let (mw, mh) = self.module_size; @@ -171,11 +178,11 @@ impl<'a, P: Pixel> Renderer<'a, P> { let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color); let mut i = 0; - for y in 0 .. width { - for x in 0 .. width { + for y in 0..width { + for x in 0..width { if qz <= x && x < w + qz && qz <= y && y < w + qz { if self.content[i] != Color::Light { - canvas.draw_dark_rect(x*mw, y*mh, mw, mh); + canvas.draw_dark_rect(x * mw, y * mh, mw, mh); } i += 1; } @@ -186,4 +193,4 @@ impl<'a, P: Pixel> Renderer<'a, P> { } } -//}}} \ No newline at end of file +//}}} diff --git a/src/render/string.rs b/src/render/string.rs index bc92831..973593a 100644 --- a/src/render/string.rs +++ b/src/render/string.rs @@ -1,7 +1,8 @@ //! String rendering support. -use render::{Pixel, Canvas as RenderCanvas}; +use render::{Canvas as RenderCanvas, Pixel}; use types::Color; +use cast::As; pub trait Element: Copy { fn default_color(color: Color) -> Self; @@ -11,7 +12,7 @@ pub trait Element: Copy { impl Element for char { fn default_color(color: Color) -> Self { - color.select('█', ' ') + color.select('\u{2588}', ' ') } fn strlen(self) -> usize { @@ -25,7 +26,7 @@ impl Element for char { impl<'a> Element for &'a str { fn default_color(color: Color) -> Self { - color.select("█", " ") + color.select("\u{2588}", " ") } fn strlen(self) -> usize { @@ -47,7 +48,7 @@ pub struct Canvas { } impl Pixel for P { - type Canvas = Canvas

; + type Canvas = Canvas; type Image = String; fn default_unit_size() -> (u32, u32) { @@ -64,29 +65,29 @@ impl RenderCanvas for Canvas

{ type Image = String; fn new(width: u32, height: u32, dark_pixel: P, light_pixel: P) -> Self { - let width = width as usize; - let height = height as isize; - let dark_cap = dark_pixel.strlen() as isize; - let light_cap = light_pixel.strlen() as isize; - Canvas { - buffer: vec![light_pixel; width * (height as usize)], + let width = width.as_usize(); + let height = height.as_isize(); + let dark_cap = dark_pixel.strlen().as_isize(); + let light_cap = light_pixel.strlen().as_isize(); + Self { + buffer: vec![light_pixel; width * height.as_usize()], width, dark_pixel, dark_cap_inc: dark_cap - light_cap, - capacity: light_cap * (width as isize) * height + (height - 1), + capacity: light_cap * width.as_isize() * height + (height - 1), } } fn draw_dark_pixel(&mut self, x: u32, y: u32) { - let x = x as usize; - let y = y as usize; + let x = x.as_usize(); + let y = y.as_usize(); self.capacity += self.dark_cap_inc; - self.buffer[x + y*self.width] = self.dark_pixel; + self.buffer[x + y * self.width] = self.dark_pixel; } fn into_image(self) -> String { - let mut result = String::with_capacity(self.capacity as usize); + let mut result = String::with_capacity(self.capacity.as_usize()); for (i, pixel) in self.buffer.into_iter().enumerate() { if i != 0 && i % self.width == 0 { result.push('\n'); @@ -101,12 +102,9 @@ impl RenderCanvas for Canvas

{ fn test_render_to_string() { use render::Renderer; - let colors = &[ - Color::Dark, Color::Light, - Color::Light, Color::Dark, - ]; + let colors = &[Color::Dark, Color::Light, Color::Light, Color::Dark]; let image: String = Renderer::::new(colors, 2, 1).build(); - assert_eq!(&image, " \n █ \n █ \n "); + assert_eq!(&image, " \n \u{2588} \n \u{2588} \n "); let image2 = Renderer::new(colors, 2, 1) .light_color("A") @@ -114,13 +112,15 @@ fn test_render_to_string() { .module_dimensions(2, 2) .build(); - assert_eq!(&image2, "\ - AAAAAAAA\n\ - AAAAAAAA\n\ - AA!B!!B!AAAA\n\ - AA!B!!B!AAAA\n\ - AAAA!B!!B!AA\n\ - AAAA!B!!B!AA\n\ - AAAAAAAA\n\ - AAAAAAAA"); + assert_eq!( + &image2, + "AAAAAAAA\n\ + AAAAAAAA\n\ + AA!B!!B!AAAA\n\ + AA!B!!B!AAAA\n\ + AAAA!B!!B!AA\n\ + AAAA!B!!B!AA\n\ + AAAAAAAA\n\ + AAAAAAAA" + ); } diff --git a/src/render/svg.rs b/src/render/svg.rs index 4779d69..72d43ef 100644 --- a/src/render/svg.rs +++ b/src/render/svg.rs @@ -19,7 +19,7 @@ use std::fmt::Write; use std::marker::PhantomData; -use render::{Pixel, Canvas as RenderCanvas}; +use render::{Canvas as RenderCanvas, Pixel}; use types::Color as ModuleColor; /// An SVG color. @@ -48,8 +48,17 @@ impl<'a> RenderCanvas for Canvas<'a> { fn new(width: u32, height: u32, dark_pixel: Color<'a>, light_pixel: Color<'a>) -> Self { Canvas { svg: format!( - r#""#, + r#""#, + r#""#, + r#" RenderCanvas for Canvas<'a> { } fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) { - write!(self.svg, "M{l} {t}h{w}v{h}H{l}V{t}", l=left, t=top, w=width, h=height).unwrap(); + write!(self.svg, "M{l} {t}h{w}v{h}H{l}V{t}", l = left, t = top, w = width, h = height) + .unwrap(); } - fn into_image(self) -> String { - self.svg + r#""/>"# + fn into_image(mut self) -> String { + self.svg.push_str(r#""/>"#); + self.svg } } diff --git a/src/types.rs b/src/types.rs index 1f447f1..98bc593 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,7 +1,8 @@ use std::default::Default; -use std::cmp::{PartialOrd, Ordering}; -use std::fmt::{Display, Formatter, Error}; +use std::cmp::{Ordering, PartialOrd}; +use std::fmt::{Display, Error, Formatter}; use std::ops::Not; +use cast::As; //------------------------------------------------------------------------------ //{{{ QrResult @@ -76,8 +77,8 @@ impl Color { } impl Not for Color { - type Output = Color; - fn not(self) -> Color { + type Output = Self; + fn not(self) -> Self { match self { Color::Light => Color::Dark, Color::Dark => Color::Light, @@ -146,26 +147,28 @@ impl Version { /// If the entry compares equal to the default value of T, this method /// returns `Err(QrError::InvalidVersion)`. pub fn fetch(&self, ec_level: EcLevel, table: &[[T; 4]]) -> QrResult - where T: PartialEq + Default + Copy + where + T: PartialEq + Default + Copy, { match *self { - Version::Normal(v @ 1...40) => Ok(table[v as usize - 1][ec_level as usize]), + Version::Normal(v @ 1...40) => { + return Ok(table[(v - 1).as_usize()][ec_level as usize]); + } Version::Micro(v @ 1...4) => { - let obj = table[v as usize + 39][ec_level as usize]; - if obj != Default::default() { - Ok(obj) - } else { - Err(QrError::InvalidVersion) + let obj = table[(v + 39).as_usize()][ec_level as usize]; + if obj != T::default() { + return Ok(obj); } } - _ => Err(QrError::InvalidVersion) + _ => {} } + Err(QrError::InvalidVersion) } /// The number of bits needed to encode the mode indicator. pub fn mode_bits_count(&self) -> usize { match *self { - Version::Micro(a) => (a - 1) as usize, + Version::Micro(a) => (a - 1).as_usize(), _ => 4, } } @@ -213,7 +216,7 @@ impl Mode { pub fn length_bits_count(&self, version: Version) -> usize { match version { Version::Micro(a) => { - let a = a as usize; + let a = a.as_usize(); match *self { Mode::Numeric => 2 + a, Mode::Alphanumeric | Mode::Byte => 1 + a, @@ -223,8 +226,7 @@ impl Mode { Version::Normal(1...9) => match *self { Mode::Numeric => 10, Mode::Alphanumeric => 9, - Mode::Byte => 8, - Mode::Kanji => 8, + Mode::Byte | Mode::Kanji => 8, }, Version::Normal(10...26) => match *self { Mode::Numeric => 12, @@ -268,7 +270,7 @@ impl Mode { /// assert!(a <= c); /// assert!(b <= c); /// - pub fn max(&self, other: Mode) -> Mode { + pub fn max(&self, other: Self) -> Self { match self.partial_cmp(&other) { Some(Ordering::Less) | Some(Ordering::Equal) => other, Some(Ordering::Greater) => *self, @@ -280,15 +282,15 @@ impl Mode { impl PartialOrd for Mode { /// Defines a partial ordering between modes. If `a <= b`, then `b` contains /// a superset of all characters supported by `a`. - fn partial_cmp(&self, other: &Mode) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { match (*self, *other) { - (Mode::Numeric, Mode::Alphanumeric) => Some(Ordering::Less), - (Mode::Alphanumeric, Mode::Numeric) => Some(Ordering::Greater), - (Mode::Numeric, Mode::Byte) => Some(Ordering::Less), - (Mode::Byte, Mode::Numeric) => Some(Ordering::Greater), - (Mode::Alphanumeric, Mode::Byte) => Some(Ordering::Less), - (Mode::Byte, Mode::Alphanumeric) => Some(Ordering::Greater), + (Mode::Numeric, Mode::Alphanumeric) | + (Mode::Numeric, Mode::Byte) | + (Mode::Alphanumeric, Mode::Byte) | (Mode::Kanji, Mode::Byte) => Some(Ordering::Less), + (Mode::Alphanumeric, Mode::Numeric) | + (Mode::Byte, Mode::Numeric) | + (Mode::Byte, Mode::Alphanumeric) | (Mode::Byte, Mode::Kanji) => Some(Ordering::Greater), (a, b) if a == b => Some(Ordering::Equal), _ => None, @@ -298,7 +300,7 @@ impl PartialOrd for Mode { #[cfg(test)] mod mode_tests { - use types::Mode::{Numeric, Alphanumeric, Byte, Kanji}; + use types::Mode::{Alphanumeric, Byte, Kanji, Numeric}; #[test] fn test_mode_order() { @@ -321,5 +323,3 @@ mod mode_tests { } //}}} - -