rustup. Quantify all enums, and renamed (shortened) a few types.
This commit is contained in:
parent
74bdb39149
commit
a4ae80b1b7
248
src/bits.rs
248
src/bits.rs
|
@ -7,10 +7,7 @@ use std::cmp::min;
|
|||
#[cfg(test)]
|
||||
use test::Bencher;
|
||||
|
||||
use types::{QrResult, DataTooLong, UnsupportedCharacterSet, InvalidEciDesignator,
|
||||
InvalidCharacter,
|
||||
Mode, Numeric, Alphanumeric, Byte, Kanji,
|
||||
ErrorCorrectionLevel, QrVersion, Version, MicroVersion};
|
||||
use types::{QrResult, QrError, Mode, EcLevel, Version};
|
||||
use optimize::{Parser, Optimizer, total_encoded_len, Segment};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -20,12 +17,12 @@ use optimize::{Parser, Optimizer, total_encoded_len, Segment};
|
|||
pub struct Bits {
|
||||
data: Vec<u8>,
|
||||
bit_offset: uint,
|
||||
version: QrVersion,
|
||||
version: Version,
|
||||
}
|
||||
|
||||
impl Bits {
|
||||
/// Constructs a new, empty bits structure.
|
||||
pub fn new(version: QrVersion) -> Bits {
|
||||
pub fn new(version: Version) -> Bits {
|
||||
Bits { data: Vec::new(), bit_offset: 0, version: version }
|
||||
}
|
||||
|
||||
|
@ -66,10 +63,10 @@ impl Bits {
|
|||
/// Pushes an N-bit big-endian integer to the end of the bits, and check
|
||||
/// that the number does not overflow the bits.
|
||||
///
|
||||
/// Returns `Err(DataTooLong)` on overflow.
|
||||
/// Returns `Err(QrError::DataTooLong)` on overflow.
|
||||
fn push_number_checked(&mut self, n: uint, number: uint) -> QrResult<()> {
|
||||
if n > 16 || number >= (1 << n) {
|
||||
Err(DataTooLong)
|
||||
Err(QrError::DataTooLong)
|
||||
} else {
|
||||
self.push_number(n, number as u16);
|
||||
Ok(())
|
||||
|
@ -97,14 +94,14 @@ impl Bits {
|
|||
}
|
||||
|
||||
/// Version of the QR code.
|
||||
pub fn version(&self) -> QrVersion {
|
||||
pub fn version(&self) -> Version {
|
||||
self.version
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_number() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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
|
||||
|
@ -130,7 +127,7 @@ fn test_push_number() {
|
|||
#[bench]
|
||||
fn bench_push_splitted_bytes(bencher: &mut Bencher) {
|
||||
bencher.iter(|| {
|
||||
let mut bits = Bits::new(Version(40));
|
||||
let mut bits = Bits::new(Version::Normal(40));
|
||||
bits.push_number(4, 0b0101);
|
||||
for _ in range(0u, 1024) {
|
||||
bits.push_number(8, 0b10101010);
|
||||
|
@ -166,27 +163,27 @@ impl Bits {
|
|||
/// Push the mode indicator to the end of the bits.
|
||||
///
|
||||
/// If the mode is not supported in the provided version, this method
|
||||
/// returns `Err(UnsupportedCharacterSet)`.
|
||||
/// returns `Err(QrError::UnsupportedCharacterSet)`.
|
||||
#[unstable]
|
||||
pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> {
|
||||
let number = match (self.version, mode) {
|
||||
(MicroVersion(1), Data(Numeric)) => return Ok(()),
|
||||
(MicroVersion(_), Data(Numeric)) => 0,
|
||||
(MicroVersion(_), Data(Alphanumeric)) => 1,
|
||||
(MicroVersion(_), Data(Byte)) => 0b10,
|
||||
(MicroVersion(_), Data(Kanji)) => 0b11,
|
||||
(MicroVersion(_), _) => return Err(UnsupportedCharacterSet),
|
||||
(_, Data(Numeric)) => 0b0001,
|
||||
(_, Data(Alphanumeric)) => 0b0010,
|
||||
(_, Data(Byte)) => 0b0100,
|
||||
(_, Data(Kanji)) => 0b1000,
|
||||
(_, Eci) => 0b0111,
|
||||
(_, Fnc1First) => 0b0101,
|
||||
(_, Fnc1Second) => 0b1001,
|
||||
(_, StructuredAppend) => 0b0011,
|
||||
(Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()),
|
||||
(Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0,
|
||||
(Version::Micro(_), ExtendedMode::Data(Mode::Alphanumeric)) => 1,
|
||||
(Version::Micro(_), ExtendedMode::Data(Mode::Byte)) => 0b10,
|
||||
(Version::Micro(_), ExtendedMode::Data(Mode::Kanji)) => 0b11,
|
||||
(Version::Micro(_), _) => return Err(QrError::UnsupportedCharacterSet),
|
||||
(_, ExtendedMode::Data(Mode::Numeric)) => 0b0001,
|
||||
(_, ExtendedMode::Data(Mode::Alphanumeric)) => 0b0010,
|
||||
(_, ExtendedMode::Data(Mode::Byte)) => 0b0100,
|
||||
(_, ExtendedMode::Data(Mode::Kanji)) => 0b1000,
|
||||
(_, ExtendedMode::Eci) => 0b0111,
|
||||
(_, ExtendedMode::Fnc1First) => 0b0101,
|
||||
(_, ExtendedMode::Fnc1Second) => 0b1001,
|
||||
(_, ExtendedMode::StructuredAppend) => 0b0011,
|
||||
};
|
||||
let bits = self.version.mode_bits_count();
|
||||
self.push_number_checked(bits, number).or(Err(UnsupportedCharacterSet))
|
||||
self.push_number_checked(bits, number).or(Err(QrError::UnsupportedCharacterSet))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +203,7 @@ impl Bits {
|
|||
/// use qrcode::bits::Bits;
|
||||
/// use qrcode::types::Version;
|
||||
///
|
||||
/// let mut bits = Bits::new(Version(1));
|
||||
/// let mut bits = Bits::new(Version::Normal(1));
|
||||
/// bits.push_eci_designator(9); // 9 = ISO-8859-7 (Greek).
|
||||
/// bits.push_byte_data(b"\xa1\xa2\xa3\xa4\xa5"); // ΑΒΓΔΕ
|
||||
///
|
||||
|
@ -226,13 +223,13 @@ impl Bits {
|
|||
/// 30 | EUC-KR (Korean)
|
||||
///
|
||||
/// If the QR code version does not support ECI, this method will return
|
||||
/// `Err(UnsupportedCharacterSet)`.
|
||||
/// `Err(QrError::UnsupportedCharacterSet)`.
|
||||
///
|
||||
/// If the designator is outside of the expected range, this method will
|
||||
/// return `Err(InvalidECIDesignator)`.
|
||||
/// 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(Eci));
|
||||
try!(self.push_mode_indicator(ExtendedMode::Eci));
|
||||
match eci_designator {
|
||||
0...127 => {
|
||||
self.push_number(8, eci_designator as u16);
|
||||
|
@ -246,7 +243,7 @@ impl Bits {
|
|||
self.push_number(5, (eci_designator >> 16) as u16);
|
||||
self.push_number(16, (eci_designator & 0xffff) as u16);
|
||||
}
|
||||
_ => return Err(InvalidEciDesignator),
|
||||
_ => return Err(QrError::InvalidEciDesignator),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -255,25 +252,25 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod eci_tests {
|
||||
use bits::Bits;
|
||||
use types::{MicroVersion, Version, InvalidEciDesignator, UnsupportedCharacterSet};
|
||||
use types::{Version, QrError};
|
||||
|
||||
#[test]
|
||||
fn test_9() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_eci_designator(9), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b0111__0000, 0b1001__0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_899() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_eci_designator(899), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b0111__10_00, 0b00111000, 0b0011__0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_999999() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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,
|
||||
|
@ -283,26 +280,26 @@ mod eci_tests {
|
|||
|
||||
#[test]
|
||||
fn test_invalid_designator() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
assert_eq!(bits.push_eci_designator(1000000), Err(InvalidEciDesignator));
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_eci_designator(1000000), Err(QrError::InvalidEciDesignator));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unsupported_character_set() {
|
||||
let mut bits = Bits::new(MicroVersion(4));
|
||||
assert_eq!(bits.push_eci_designator(9), Err(UnsupportedCharacterSet));
|
||||
let mut bits = Bits::new(Version::Micro(4));
|
||||
assert_eq!(bits.push_eci_designator(9), Err(QrError::UnsupportedCharacterSet));
|
||||
}
|
||||
}
|
||||
|
||||
//}}}
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Numeric mode
|
||||
//{{{ Mode::Numeric mode
|
||||
|
||||
impl Bits {
|
||||
fn push_header(&mut self, mode: Mode, raw_data_len: uint) -> 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(Data(mode)));
|
||||
try!(self.push_mode_indicator(ExtendedMode::Data(mode)));
|
||||
try!(self.push_number_checked(length_bits, raw_data_len));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -312,7 +309,7 @@ impl Bits {
|
|||
/// The data should only contain the characters 0 to 9.
|
||||
#[unstable]
|
||||
pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> {
|
||||
try!(self.push_header(Numeric, data.len()));
|
||||
try!(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 length = chunk.len() * 3 + 1;
|
||||
|
@ -325,11 +322,11 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod numeric_tests {
|
||||
use bits::Bits;
|
||||
use types::{Version, MicroVersion, DataTooLong};
|
||||
use types::{Version, QrError};
|
||||
|
||||
#[test]
|
||||
fn test_iso_18004_2006_example_1() {
|
||||
let mut bits = Bits::new(Version(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,
|
||||
|
@ -341,7 +338,7 @@ mod numeric_tests {
|
|||
|
||||
#[test]
|
||||
fn test_iso_18004_2000_example_2() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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,
|
||||
|
@ -356,7 +353,7 @@ mod numeric_tests {
|
|||
|
||||
#[test]
|
||||
fn test_iso_18004_2006_example_2() {
|
||||
let mut bits = Bits::new(MicroVersion(3));
|
||||
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,
|
||||
|
@ -370,16 +367,16 @@ mod numeric_tests {
|
|||
|
||||
#[test]
|
||||
fn test_data_too_long_error() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
assert_eq!(bits.push_numeric_data(b"12345678"), Err(DataTooLong));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b"12345678"), Err(QrError::DataTooLong));
|
||||
}
|
||||
}
|
||||
|
||||
//}}}
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Alphanumeric mode
|
||||
//{{{ Mode::Alphanumeric mode
|
||||
|
||||
/// In QR code "Alphanumeric" mode, a pair of alphanumeric characters will be
|
||||
/// 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.
|
||||
///
|
||||
|
@ -409,7 +406,7 @@ impl Bits {
|
|||
/// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`.
|
||||
#[unstable]
|
||||
pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> {
|
||||
try!(self.push_header(Alphanumeric, data.len()));
|
||||
try!(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 length = chunk.len() * 5 + 1;
|
||||
|
@ -422,11 +419,11 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod alphanumeric_tests {
|
||||
use bits::Bits;
|
||||
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong};
|
||||
use types::{Version, QrError};
|
||||
|
||||
#[test]
|
||||
fn test_iso_18004_2006_example() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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,
|
||||
|
@ -438,26 +435,26 @@ mod alphanumeric_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr_unsupported() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"A"), Err(UnsupportedCharacterSet));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"A"), Err(QrError::UnsupportedCharacterSet));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_too_long() {
|
||||
let mut bits = Bits::new(MicroVersion(2));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(DataTooLong));
|
||||
let mut bits = Bits::new(Version::Micro(2));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(QrError::DataTooLong));
|
||||
}
|
||||
}
|
||||
|
||||
//}}}
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Byte mode
|
||||
//{{{ Mode::Byte mode
|
||||
|
||||
impl Bits {
|
||||
/// Encodes 8-bit byte data to the bits.
|
||||
#[unstable]
|
||||
pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> {
|
||||
try!(self.push_header(Byte, data.len()));
|
||||
try!(self.push_header(Mode::Byte, data.len()));
|
||||
for b in data.iter() {
|
||||
self.push_number(8, *b as u16);
|
||||
}
|
||||
|
@ -468,11 +465,11 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod byte_tests {
|
||||
use bits::Bits;
|
||||
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong};
|
||||
use types::{Version, QrError};
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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,
|
||||
|
@ -488,29 +485,29 @@ mod byte_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr_unsupported() {
|
||||
let mut bits = Bits::new(MicroVersion(2));
|
||||
assert_eq!(bits.push_byte_data(b"?"), Err(UnsupportedCharacterSet));
|
||||
let mut bits = Bits::new(Version::Micro(2));
|
||||
assert_eq!(bits.push_byte_data(b"?"), Err(QrError::UnsupportedCharacterSet));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_too_long() {
|
||||
let mut bits = Bits::new(MicroVersion(3));
|
||||
assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(DataTooLong));
|
||||
let mut bits = Bits::new(Version::Micro(3));
|
||||
assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(QrError::DataTooLong));
|
||||
}
|
||||
}
|
||||
|
||||
//}}}
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Kanji mode
|
||||
//{{{ Mode::Kanji mode
|
||||
|
||||
impl Bits {
|
||||
/// Encodes Shift JIS double-byte data to the bits.
|
||||
#[unstable]
|
||||
pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> {
|
||||
try!(self.push_header(Kanji, data.len()/2));
|
||||
try!(self.push_header(Mode::Kanji, data.len()/2));
|
||||
for kanji in data.chunks(2) {
|
||||
if kanji.len() != 2 {
|
||||
return Err(InvalidCharacter);
|
||||
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 };
|
||||
|
@ -524,11 +521,11 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod kanji_tests {
|
||||
use bits::Bits;
|
||||
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong};
|
||||
use types::{Version, QrError};
|
||||
|
||||
#[test]
|
||||
fn test_iso_18004_example() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
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,
|
||||
|
@ -539,15 +536,15 @@ mod kanji_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr_unsupported() {
|
||||
let mut bits = Bits::new(MicroVersion(2));
|
||||
assert_eq!(bits.push_kanji_data(b"?"), Err(UnsupportedCharacterSet));
|
||||
let mut bits = Bits::new(Version::Micro(2));
|
||||
assert_eq!(bits.push_kanji_data(b"?"), Err(QrError::UnsupportedCharacterSet));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_too_long() {
|
||||
let mut bits = Bits::new(MicroVersion(3));
|
||||
let mut bits = Bits::new(Version::Micro(3));
|
||||
assert_eq!(bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"),
|
||||
Err(DataTooLong));
|
||||
Err(QrError::DataTooLong));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,14 +561,14 @@ impl Bits {
|
|||
/// use qrcode::bits::Bits;
|
||||
/// use qrcode::types::Version;
|
||||
///
|
||||
/// let mut bits = Bits::new(Version(1));
|
||||
/// let mut bits = Bits::new(Version::Normal(1));
|
||||
/// bits.push_fnc1_first_position();
|
||||
/// bits.push_numeric_data(b"01049123451234591597033130128");
|
||||
/// bits.push_alphanumeric_data(b"%10ABC123");
|
||||
///
|
||||
/// In QR code, the character `%` is used as the data field separator (0x1D).
|
||||
pub fn push_fnc1_first_position(&mut self) -> QrResult<()> {
|
||||
self.push_mode_indicator(Fnc1First)
|
||||
self.push_mode_indicator(ExtendedMode::Fnc1First)
|
||||
}
|
||||
|
||||
/// Encodes an indicator that the following data are formatted in accordance
|
||||
|
@ -583,7 +580,7 @@ impl Bits {
|
|||
/// use qrcode::bits::Bits;
|
||||
/// use qrcode::types::Version;
|
||||
///
|
||||
/// let mut bits = Bits::new(Version(1));
|
||||
/// let mut bits = Bits::new(Version::Normal(1));
|
||||
/// bits.push_fnc1_second_position(37);
|
||||
/// bits.push_alphanumeric_data(b"AA1234BBB112");
|
||||
/// bits.push_byte_data(b"text text text text\r");
|
||||
|
@ -595,7 +592,7 @@ 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(Fnc1Second));
|
||||
try!(self.push_mode_indicator(ExtendedMode::Fnc1Second));
|
||||
self.push_number(8, application_indicator as u16);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -659,16 +656,16 @@ static DATA_LENGTHS: [[uint, ..4], ..44] = [
|
|||
impl Bits {
|
||||
/// Pushes the ending bits to indicate no more data.
|
||||
#[unstable]
|
||||
pub fn push_terminator(&mut self, ec_level: ErrorCorrectionLevel) -> QrResult<()> {
|
||||
pub fn push_terminator(&mut self, ec_level: EcLevel) -> QrResult<()> {
|
||||
let terminator_size = match self.version {
|
||||
MicroVersion(a) => (a as uint) * 2 + 1,
|
||||
Version::Micro(a) => (a as uint) * 2 + 1,
|
||||
_ => 4,
|
||||
};
|
||||
|
||||
let cur_length = self.len();
|
||||
let data_length = try!(self.version.fetch(ec_level, &DATA_LENGTHS));
|
||||
if cur_length > data_length {
|
||||
return Err(DataTooLong);
|
||||
return Err(QrError::DataTooLong);
|
||||
}
|
||||
|
||||
let terminator_size = min(terminator_size, data_length - cur_length);
|
||||
|
@ -695,13 +692,13 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod finish_tests {
|
||||
use bits::Bits;
|
||||
use types::{Version, MicroVersion, L, Q, DataTooLong};
|
||||
use types::{Version, EcLevel, QrError};
|
||||
|
||||
#[test]
|
||||
fn test_hello_world() {
|
||||
let mut bits = Bits::new(Version(1));
|
||||
let mut bits = Bits::new(Version::Normal(1));
|
||||
assert_eq!(bits.push_alphanumeric_data(b"HELLO WORLD"), Ok(()));
|
||||
assert_eq!(bits.push_terminator(Q), Ok(()));
|
||||
assert_eq!(bits.push_terminator(EcLevel::Q), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b00100000, 0b01011011, 0b00001011,
|
||||
0b01111000, 0b11010001, 0b01110010,
|
||||
0b11011100, 0b01001101, 0b01000011,
|
||||
|
@ -711,40 +708,40 @@ mod finish_tests {
|
|||
|
||||
#[test]
|
||||
fn test_too_long() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b"9999999"), Ok(()));
|
||||
assert_eq!(bits.push_terminator(L), Err(DataTooLong));
|
||||
assert_eq!(bits.push_terminator(EcLevel::L), Err(QrError::DataTooLong));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_terminator() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b"99999"), Ok(()));
|
||||
assert_eq!(bits.push_terminator(L), Ok(()));
|
||||
assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b101_11111, 0b00111_110, 0b0011__0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_padding() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b"9999"), Ok(()));
|
||||
assert_eq!(bits.push_terminator(L), Ok(()));
|
||||
assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b100_11111, 0b00111_100, 0b1_000__0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_micro_version_1_half_byte_padding() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b"999"), Ok(()));
|
||||
assert_eq!(bits.push_terminator(L), Ok(()));
|
||||
assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b011_11111, 0b00111_000, 0b0000__0000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_micro_version_1_full_byte_padding() {
|
||||
let mut bits = Bits::new(MicroVersion(1));
|
||||
let mut bits = Bits::new(Version::Micro(1));
|
||||
assert_eq!(bits.push_numeric_data(b""), Ok(()));
|
||||
assert_eq!(bits.push_terminator(L), Ok(()));
|
||||
assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
|
||||
assert_eq!(bits.into_bytes(), vec![0b000_000_00, 0b11101100, 0]);
|
||||
}
|
||||
}
|
||||
|
@ -761,10 +758,10 @@ impl Bits {
|
|||
for segment in segments_iter {
|
||||
let slice = data[segment.begin..segment.end];
|
||||
try!(match segment.mode {
|
||||
Numeric => self.push_numeric_data(slice),
|
||||
Alphanumeric => self.push_alphanumeric_data(slice),
|
||||
Byte => self.push_byte_data(slice),
|
||||
Kanji => self.push_kanji_data(slice),
|
||||
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(())
|
||||
|
@ -781,12 +778,9 @@ impl Bits {
|
|||
#[cfg(test)]
|
||||
mod encode_tests {
|
||||
use bits::Bits;
|
||||
use types::{QrVersion, Version, MicroVersion, DataTooLong, QrResult,
|
||||
L, Q, H, ErrorCorrectionLevel};
|
||||
use types::{Version, QrError, QrResult, EcLevel};
|
||||
|
||||
fn encode(data: &[u8],
|
||||
version: QrVersion,
|
||||
ec_level: ErrorCorrectionLevel) -> QrResult<Vec<u8>> {
|
||||
fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<Vec<u8>> {
|
||||
let mut bits = Bits::new(version);
|
||||
try!(bits.push_optimal_data(data));
|
||||
try!(bits.push_terminator(ec_level));
|
||||
|
@ -795,7 +789,7 @@ mod encode_tests {
|
|||
|
||||
#[test]
|
||||
fn test_alphanumeric() {
|
||||
let res = encode(b"HELLO WORLD", Version(1), Q);
|
||||
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,
|
||||
|
@ -805,15 +799,15 @@ mod encode_tests {
|
|||
|
||||
#[test]
|
||||
fn test_auto_mode_switch() {
|
||||
let res = encode(b"123A", MicroVersion(2), L);
|
||||
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]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_long() {
|
||||
let res = encode(b">>>>>>>>", Version(1), H);
|
||||
assert_eq!(res, Err(DataTooLong));
|
||||
let res = encode(b">>>>>>>>", Version::Normal(1), EcLevel::H);
|
||||
assert_eq!(res, Err(QrError::DataTooLong));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,9 +819,9 @@ mod encode_tests {
|
|||
/// the result.
|
||||
///
|
||||
/// This method will not consider any Micro QR code versions.
|
||||
pub fn encode_auto(data: &[u8], ec_level: ErrorCorrectionLevel) -> QrResult<Bits> {
|
||||
pub fn encode_auto(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> {
|
||||
let segments = Parser::new(data).collect::<Vec<Segment>>();
|
||||
for version in [Version(9), Version(26), Version(40)].iter() {
|
||||
for version in [Version::Normal(9), Version::Normal(26), Version::Normal(40)].iter() {
|
||||
let opt_segments = Optimizer::new(segments.iter().map(|s| *s), *version).collect::<Vec<Segment>>();
|
||||
let total_len = total_encoded_len(&*opt_segments, *version);
|
||||
let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).unwrap();
|
||||
|
@ -840,13 +834,13 @@ pub fn encode_auto(data: &[u8], ec_level: ErrorCorrectionLevel) -> QrResult<Bits
|
|||
return Ok(bits);
|
||||
}
|
||||
}
|
||||
Err(DataTooLong)
|
||||
Err(QrError::DataTooLong)
|
||||
}
|
||||
|
||||
/// Finds the smallest version (QR code only) that can store N bits of data
|
||||
/// in the given error correction level.
|
||||
#[unstable]
|
||||
fn find_min_version(length: uint, ec_level: ErrorCorrectionLevel) -> QrVersion {
|
||||
fn find_min_version(length: uint, ec_level: EcLevel) -> Version {
|
||||
let mut min = 0u;
|
||||
let mut max = 39u;
|
||||
while min < max {
|
||||
|
@ -857,42 +851,42 @@ fn find_min_version(length: uint, ec_level: ErrorCorrectionLevel) -> QrVersion {
|
|||
max = half;
|
||||
}
|
||||
}
|
||||
Version((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, L, Q, H};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_find_min_version() {
|
||||
assert_eq!(find_min_version(60, L), Version(1));
|
||||
assert_eq!(find_min_version(200, L), Version(2));
|
||||
assert_eq!(find_min_version(200, H), Version(3));
|
||||
assert_eq!(find_min_version(20000, L), Version(37));
|
||||
assert_eq!(find_min_version(640, L), Version(4));
|
||||
assert_eq!(find_min_version(641, L), Version(5));
|
||||
assert_eq!(find_min_version(999999, H), Version(40));
|
||||
assert_eq!(find_min_version(60, EcLevel::L), Version::Normal(1));
|
||||
assert_eq!(find_min_version(200, EcLevel::L), Version::Normal(2));
|
||||
assert_eq!(find_min_version(200, EcLevel::H), Version::Normal(3));
|
||||
assert_eq!(find_min_version(20000, EcLevel::L), Version::Normal(37));
|
||||
assert_eq!(find_min_version(640, EcLevel::L), Version::Normal(4));
|
||||
assert_eq!(find_min_version(641, EcLevel::L), Version::Normal(5));
|
||||
assert_eq!(find_min_version(999999, EcLevel::H), Version::Normal(40));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_alpha_q() {
|
||||
let bits = encode_auto(b"HELLO WORLD", Q).unwrap();
|
||||
assert_eq!(bits.version(), Version(1));
|
||||
let bits = encode_auto(b"HELLO WORLD", EcLevel::Q).unwrap();
|
||||
assert_eq!(bits.version(), Version::Normal(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_alpha_h() {
|
||||
let bits = encode_auto(b"HELLO WORLD", H).unwrap();
|
||||
assert_eq!(bits.version(), Version(2));
|
||||
let bits = encode_auto(b"HELLO WORLD", EcLevel::H).unwrap();
|
||||
assert_eq!(bits.version(), Version::Normal(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mixed() {
|
||||
let bits = encode_auto(b"This is a mixed data test. 1234567890", H).unwrap();
|
||||
assert_eq!(bits.version(), Version(4));
|
||||
let bits = encode_auto(b"This is a mixed data test. 1234567890", EcLevel::H).unwrap();
|
||||
assert_eq!(bits.version(), Version::Normal(4));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
326
src/canvas.rs
326
src/canvas.rs
|
@ -1,12 +1,12 @@
|
|||
//! The `canvas` module puts raw bits into the QR code canvas.
|
||||
//!
|
||||
//! use qrcode::types::{Version, L};
|
||||
//! use qrcode::canvas::{Canvas, Checkerboard};
|
||||
//! use qrcode::types::{Version, EcLevel};
|
||||
//! use qrcode::canvas::{Canvas, MaskPattern};
|
||||
//!
|
||||
//! let mut c = Canvas::new(Version(1), L);
|
||||
//! let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
//! c.draw_all_functional_patterns();
|
||||
//! c.draw_data(b"data_here", b"ec_code_here");
|
||||
//! c.apply_mask(Checkerboard);
|
||||
//! c.apply_mask(MaskPattern::Checkerboard);
|
||||
//! let bools = c.to_bools();
|
||||
|
||||
use std::iter::range_inclusive;
|
||||
|
@ -14,7 +14,7 @@ use std::iter::order::equals;
|
|||
use std::num::Int;
|
||||
use std::cmp::max;
|
||||
|
||||
use types::{QrVersion, Version, MicroVersion, ErrorCorrectionLevel, L, M, Q};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Modules
|
||||
|
@ -46,27 +46,27 @@ impl Module {
|
|||
/// Checks whether a module is dark.
|
||||
pub fn is_dark(&self) -> bool {
|
||||
match *self {
|
||||
Dark | DarkUnmasked => true,
|
||||
Module::Dark | Module::DarkUnmasked => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a mask to the unmasked modules.
|
||||
///
|
||||
/// use qrcode::canvas::{LightUnmasked, Light, DarkUnmasked, Dark};
|
||||
/// use qrcode::canvas::Module;
|
||||
///
|
||||
/// assert_eq!(LightUnmasked.mask(true), Dark);
|
||||
/// assert_eq!(DarkUnmasked.mask(true), Light);
|
||||
/// assert_eq!(LightUnmasked.mask(false), Light);
|
||||
/// assert_eq!(Dark.mask(true), Dark);
|
||||
/// assert_eq!(Dark.mask(false), Dark);
|
||||
/// assert_eq!(Module::LightUnmasked.mask(true), Module::Dark);
|
||||
/// assert_eq!(Module::DarkUnmasked.mask(true), Module::Light);
|
||||
/// assert_eq!(Module::LightUnmasked.mask(false), Module::Light);
|
||||
/// assert_eq!(Module::Dark.mask(true), Module::Dark);
|
||||
/// assert_eq!(Module::Dark.mask(false), Module::Dark);
|
||||
///
|
||||
pub fn mask(&self, should_invert: bool) -> Module {
|
||||
match (*self, should_invert) {
|
||||
(Empty, true) | (LightUnmasked, true) => Dark,
|
||||
(Empty, false) | (LightUnmasked, false) => Light,
|
||||
(DarkUnmasked, true) => Light,
|
||||
(DarkUnmasked, false) => Dark,
|
||||
(Module::Empty, true) | (Module::LightUnmasked, true) => Module::Dark,
|
||||
(Module::Empty, false) | (Module::LightUnmasked, false) => Module::Light,
|
||||
(Module::DarkUnmasked, true) => Module::Light,
|
||||
(Module::DarkUnmasked, false) => Module::Dark,
|
||||
(a, _) => a,
|
||||
}
|
||||
}
|
||||
|
@ -84,10 +84,10 @@ pub struct Canvas {
|
|||
width: i16,
|
||||
|
||||
/// The version of the QR code.
|
||||
version: QrVersion,
|
||||
version: Version,
|
||||
|
||||
/// The error correction level of the QR code.
|
||||
ec_level: ErrorCorrectionLevel,
|
||||
ec_level: EcLevel,
|
||||
|
||||
/// The modules of the QR code. Modules are arranged in left-to-right, then
|
||||
/// top-to-bottom order.
|
||||
|
@ -96,13 +96,13 @@ pub struct Canvas {
|
|||
|
||||
impl Canvas {
|
||||
/// Constructs a new canvas big enough for a QR code of the given version.
|
||||
pub fn new(version: QrVersion, ec_level: ErrorCorrectionLevel) -> Canvas {
|
||||
pub fn new(version: Version, ec_level: EcLevel) -> Canvas {
|
||||
let width = version.width();
|
||||
Canvas {
|
||||
width: width,
|
||||
version: version,
|
||||
ec_level: ec_level,
|
||||
modules: Vec::from_elem((width*width) as uint, Empty),
|
||||
modules: Vec::from_elem((width*width) as uint, Module::Empty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,11 +115,11 @@ impl Canvas {
|
|||
res.push('\n');
|
||||
for x in range(0, width) {
|
||||
res.push(match self.get(x, y) {
|
||||
Empty => '?',
|
||||
Light => '.',
|
||||
Dark => '#',
|
||||
LightUnmasked => '-',
|
||||
DarkUnmasked => '*',
|
||||
Module::Empty => '?',
|
||||
Module::Light => '.',
|
||||
Module::Dark => '#',
|
||||
Module::LightUnmasked => '-',
|
||||
Module::DarkUnmasked => '*',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -155,36 +155,36 @@ impl Canvas {
|
|||
|
||||
#[cfg(test)]
|
||||
mod basic_canvas_tests {
|
||||
use canvas::{Canvas, Empty, Dark, Light, DarkUnmasked, LightUnmasked};
|
||||
use types::{Version, L};
|
||||
use canvas::{Canvas, Module};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_index() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
|
||||
assert_eq!(c.get(0, 4), Empty);
|
||||
assert_eq!(c.get(-1, -7), Empty);
|
||||
assert_eq!(c.get(21-1, 21-7), Empty);
|
||||
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);
|
||||
|
||||
c.put(0, 0, Dark);
|
||||
c.put(-1, -7, Light);
|
||||
assert_eq!(c.get(0, 0), Dark);
|
||||
assert_eq!(c.get(21-1, -7), Light);
|
||||
assert_eq!(c.get(-1, 21-7), Light);
|
||||
c.put(0, 0, Module::Dark);
|
||||
c.put(-1, -7, Module::Light);
|
||||
assert_eq!(c.get(0, 0), Module::Dark);
|
||||
assert_eq!(c.get(21-1, -7), Module::Light);
|
||||
assert_eq!(c.get(-1, 21-7), Module::Light);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_str() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
|
||||
for i in range(3i16, 20) {
|
||||
for j in range(3i16, 20) {
|
||||
c.put(i, j, match ((i * 3) ^ j) % 5 {
|
||||
0 => Empty,
|
||||
1 => Light,
|
||||
2 => Dark,
|
||||
3 => LightUnmasked,
|
||||
4 => DarkUnmasked,
|
||||
0 => Module::Empty,
|
||||
1 => Module::Light,
|
||||
2 => Module::Dark,
|
||||
3 => Module::LightUnmasked,
|
||||
4 => Module::DarkUnmasked,
|
||||
_ => panic!(),
|
||||
});
|
||||
}
|
||||
|
@ -227,10 +227,10 @@ impl Canvas {
|
|||
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) => Light,
|
||||
(3, _) | (_, 3) | (-3, _) | (_, -3) => Dark,
|
||||
(2, _) | (_, 2) | (-2, _) | (_, -2) => Light,
|
||||
_ => Dark,
|
||||
(4, _) | (_, 4) | (-4, _) | (_, -4) => Module::Light,
|
||||
(3, _) | (_, 3) | (-3, _) | (_, -3) => Module::Dark,
|
||||
(2, _) | (_, 2) | (-2, _) | (_, -2) => Module::Light,
|
||||
_ => Module::Dark,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -245,8 +245,8 @@ impl Canvas {
|
|||
self.draw_finder_pattern_at(3, 3);
|
||||
|
||||
match self.version {
|
||||
MicroVersion(_) => { return; }
|
||||
Version(_) => {
|
||||
Version::Micro(_) => { return; }
|
||||
Version::Normal(_) => {
|
||||
self.draw_finder_pattern_at(-4, 3);
|
||||
self.draw_finder_pattern_at(3, -4);
|
||||
}
|
||||
|
@ -257,11 +257,11 @@ impl Canvas {
|
|||
#[cfg(test)]
|
||||
mod finder_pattern_tests {
|
||||
use canvas::Canvas;
|
||||
use types::{Version, MicroVersion, L};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_qr() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
c.draw_finder_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#######.?????.#######\n\
|
||||
|
@ -289,7 +289,7 @@ mod finder_pattern_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
|
||||
c.draw_finder_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#######.???\n\
|
||||
|
@ -313,14 +313,14 @@ mod finder_pattern_tests {
|
|||
impl Canvas {
|
||||
/// Draws a alignment pattern with the center at (x, y).
|
||||
fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) {
|
||||
if self.get(x, y) != Empty {
|
||||
if self.get(x, y) != Module::Empty {
|
||||
return;
|
||||
}
|
||||
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) => Dark,
|
||||
_ => Light,
|
||||
(2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Module::Dark,
|
||||
_ => Module::Light,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -332,9 +332,9 @@ impl Canvas {
|
|||
/// to help the scanner create the square grid.
|
||||
fn draw_alignment_patterns(&mut self) {
|
||||
match self.version {
|
||||
MicroVersion(_) | Version(1) => { return; }
|
||||
Version(2...6) => self.draw_alignment_pattern_at(-7, -7),
|
||||
Version(a) => {
|
||||
Version::Micro(_) | Version::Normal(1) => { return; }
|
||||
Version::Normal(2...6) => self.draw_alignment_pattern_at(-7, -7),
|
||||
Version::Normal(a) => {
|
||||
let positions = ALIGNMENT_PATTERN_POSITIONS[a as uint - 7];
|
||||
for x in positions.iter() {
|
||||
for y in positions.iter() {
|
||||
|
@ -349,11 +349,11 @@ impl Canvas {
|
|||
#[cfg(test)]
|
||||
mod alignment_pattern_tests {
|
||||
use canvas::Canvas;
|
||||
use types::{Version, L};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_draw_alignment_patterns_1() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
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\
|
||||
|
@ -382,7 +382,7 @@ mod alignment_pattern_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_alignment_patterns_3() {
|
||||
let mut c = Canvas::new(Version(3), L);
|
||||
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\
|
||||
|
@ -419,7 +419,7 @@ mod alignment_pattern_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_alignment_patterns_7() {
|
||||
let mut c = Canvas::new(Version(7), L);
|
||||
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\
|
||||
|
@ -550,22 +550,22 @@ impl Canvas {
|
|||
fn draw_timing_patterns(&mut self) {
|
||||
let width = self.width;
|
||||
let (y, x1, x2) = match self.version {
|
||||
MicroVersion(_) => (0, 8, width-1),
|
||||
Version(_) => (6, 8, width-9),
|
||||
Version::Micro(_) => (0, 8, width-1),
|
||||
Version::Normal(_) => (6, 8, width-9),
|
||||
};
|
||||
self.draw_line(x1, y, x2, y, Dark, Light);
|
||||
self.draw_line(y, x1, y, x2, Dark, Light);
|
||||
self.draw_line(x1, y, x2, y, Module::Dark, Module::Light);
|
||||
self.draw_line(y, x1, y, x2, Module::Dark, Module::Light);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod timing_pattern_tests {
|
||||
use canvas::Canvas;
|
||||
use types::{Version, MicroVersion, L};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_draw_timing_patterns_qr() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
c.draw_timing_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
?????????????????????\n\
|
||||
|
@ -593,7 +593,7 @@ mod timing_pattern_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_timing_patterns_micro_qr() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
|
||||
c.draw_timing_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
????????#.#\n\
|
||||
|
@ -636,13 +636,16 @@ impl Canvas {
|
|||
/// Draws the format info patterns for an encoded number.
|
||||
fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
|
||||
match self.version {
|
||||
MicroVersion(_) => {
|
||||
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_MICRO_QR);
|
||||
Version::Micro(_) => {
|
||||
self.draw_number(format_info, Module::Dark, Module::Light,
|
||||
&FORMAT_INFO_COORDS_MICRO_QR);
|
||||
}
|
||||
Version(_) => {
|
||||
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_QR_MAIN);
|
||||
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_QR_SIDE);
|
||||
self.put(8, -8, Dark); // Dark module.
|
||||
Version::Normal(_) => {
|
||||
self.draw_number(format_info, Module::Dark, Module::Light,
|
||||
&FORMAT_INFO_COORDS_QR_MAIN);
|
||||
self.draw_number(format_info, Module::Dark, Module::Light,
|
||||
&FORMAT_INFO_COORDS_QR_SIDE);
|
||||
self.put(8, -8, Module::Dark); // Dark module.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -655,11 +658,13 @@ impl Canvas {
|
|||
/// Draws the version information patterns.
|
||||
fn draw_version_info_patterns(&mut self) {
|
||||
match self.version {
|
||||
MicroVersion(_) | Version(1...6) => { return; }
|
||||
Version(a) => {
|
||||
Version::Micro(_) | Version::Normal(1...6) => { return; }
|
||||
Version::Normal(a) => {
|
||||
let version_info = VERSION_INFOS[(a - 7) as uint] << 14;
|
||||
self.draw_number(version_info, Dark, Light, VERSION_INFO_COORDS_BL);
|
||||
self.draw_number(version_info, Dark, Light, VERSION_INFO_COORDS_TR);
|
||||
self.draw_number(version_info, Module::Dark, Module::Light,
|
||||
&VERSION_INFO_COORDS_BL);
|
||||
self.draw_number(version_info, Module::Dark, Module::Light,
|
||||
&VERSION_INFO_COORDS_TR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -667,13 +672,14 @@ impl Canvas {
|
|||
|
||||
#[cfg(test)]
|
||||
mod draw_version_info_tests {
|
||||
use canvas::{Canvas, Light, Dark};
|
||||
use types::{MicroVersion, Version, L};
|
||||
use canvas::{Canvas, Module};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_draw_number() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
c.draw_number(0b10101101u8, Dark, Light, [(0,0), (0,-1), (-2,-2), (-2,0)]);
|
||||
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
|
||||
c.draw_number(0b10101101u8, Module::Dark, Module::Light,
|
||||
&[(0,0), (0,-1), (-2,-2), (-2,0)]);
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#????????.?\n\
|
||||
???????????\n\
|
||||
|
@ -690,7 +696,7 @@ mod draw_version_info_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_version_info_1() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
c.draw_version_info_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
?????????????????????\n\
|
||||
|
@ -718,7 +724,7 @@ mod draw_version_info_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_version_info_7() {
|
||||
let mut c = Canvas::new(Version(7), L);
|
||||
let mut c = Canvas::new(Version::Normal(7), EcLevel::L);
|
||||
c.draw_version_info_patterns();
|
||||
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
|
@ -771,7 +777,7 @@ mod draw_version_info_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_reserved_format_info_patterns_qr() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
c.draw_reserved_format_info_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
????????.????????????\n\
|
||||
|
@ -799,7 +805,7 @@ mod draw_version_info_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_reserved_format_info_patterns_micro_qr() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
|
||||
c.draw_reserved_format_info_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
???????????\n\
|
||||
|
@ -881,11 +887,11 @@ impl Canvas {
|
|||
#[cfg(test)]
|
||||
mod all_functional_patterns_tests {
|
||||
use canvas::Canvas;
|
||||
use types::{Version, MicroVersion, L};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_all_functional_patterns_qr() {
|
||||
let mut c = Canvas::new(Version(2), L);
|
||||
let mut c = Canvas::new(Version::Normal(2), EcLevel::L);
|
||||
c.draw_all_functional_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#######..????????.#######\n\
|
||||
|
@ -917,7 +923,7 @@ mod all_functional_patterns_tests {
|
|||
|
||||
#[test]
|
||||
fn test_all_functional_patterns_micro_qr() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
|
||||
c.draw_all_functional_patterns();
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#######.#.#\n\
|
||||
|
@ -946,15 +952,15 @@ struct DataModuleIter {
|
|||
}
|
||||
|
||||
impl DataModuleIter {
|
||||
fn new(version: QrVersion) -> DataModuleIter {
|
||||
fn new(version: Version) -> DataModuleIter {
|
||||
let width = version.width();
|
||||
DataModuleIter {
|
||||
x: width - 1,
|
||||
y: width - 1,
|
||||
width: width,
|
||||
timing_pattern_column: match version {
|
||||
MicroVersion(_) => 0,
|
||||
Version(_) => 6,
|
||||
Version::Micro(_) => 0,
|
||||
Version::Normal(_) => 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -998,11 +1004,11 @@ impl Iterator<(i16, i16)> for DataModuleIter {
|
|||
#[cfg(test)]
|
||||
mod data_iter_tests {
|
||||
use canvas::DataModuleIter;
|
||||
use types::{Version, MicroVersion};
|
||||
use types::Version;
|
||||
|
||||
#[test]
|
||||
fn test_qr() {
|
||||
let res = DataModuleIter::new(Version(1)).collect::<Vec<(i16, i16)>>();
|
||||
let res = DataModuleIter::new(Version::Normal(1)).collect::<Vec<(i16, i16)>>();
|
||||
assert_eq!(res, vec![
|
||||
(20, 20), (19, 20), (20, 19), (19, 19), (20, 18), (19, 18),
|
||||
(20, 17), (19, 17), (20, 16), (19, 16), (20, 15), (19, 15),
|
||||
|
@ -1088,7 +1094,7 @@ mod data_iter_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr() {
|
||||
let res = DataModuleIter::new(MicroVersion(1)).collect::<Vec<(i16, i16)>>();
|
||||
let res = DataModuleIter::new(Version::Micro(1)).collect::<Vec<(i16, i16)>>();
|
||||
assert_eq!(res, vec![
|
||||
(10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8),
|
||||
(10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5),
|
||||
|
@ -1119,7 +1125,7 @@ mod data_iter_tests {
|
|||
|
||||
#[test]
|
||||
fn test_micro_qr_2() {
|
||||
let res = DataModuleIter::new(MicroVersion(2)).collect::<Vec<(i16, i16)>>();
|
||||
let res = DataModuleIter::new(Version::Micro(2)).collect::<Vec<(i16, i16)>>();
|
||||
assert_eq!(res, vec![
|
||||
(12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10),
|
||||
(12, 9), (11, 9), (12, 8), (11, 8), (12, 7), (11, 7),
|
||||
|
@ -1177,10 +1183,14 @@ impl Canvas {
|
|||
let bits_end = if i == last_word { 4 } else { 0 };
|
||||
'outside:
|
||||
for j in range_inclusive(bits_end, 7u).rev() {
|
||||
let color = if (*b & (1 << j)) != 0 { DarkUnmasked } else { LightUnmasked };
|
||||
let color = if (*b & (1 << j)) != 0 {
|
||||
Module::DarkUnmasked
|
||||
} else {
|
||||
Module::LightUnmasked
|
||||
};
|
||||
while let Some((x, y)) = coords.next() {
|
||||
let r = self.get_mut(x, y);
|
||||
if *r == Empty {
|
||||
if *r == Module::Empty {
|
||||
*r = color;
|
||||
continue 'outside;
|
||||
}
|
||||
|
@ -1193,7 +1203,7 @@ impl Canvas {
|
|||
/// Draws the encoded data and error correction codes to the empty modules.
|
||||
pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
|
||||
let is_half_codeword_at_end = match (self.version, self.ec_level) {
|
||||
(MicroVersion(1), L) | (MicroVersion(3), M) => true,
|
||||
(Version::Micro(1), EcLevel::L) | (Version::Micro(3), EcLevel::M) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
@ -1206,11 +1216,11 @@ impl Canvas {
|
|||
#[cfg(test)]
|
||||
mod draw_codewords_test {
|
||||
use canvas::Canvas;
|
||||
use types::{Version, MicroVersion, L};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_micro_qr_1() {
|
||||
let mut c = Canvas::new(MicroVersion(1), L);
|
||||
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\
|
||||
|
@ -1229,7 +1239,7 @@ mod draw_codewords_test {
|
|||
|
||||
#[test]
|
||||
fn test_qr_2() {
|
||||
let mut c = Canvas::new(Version(2), L);
|
||||
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\
|
||||
|
@ -1306,14 +1316,14 @@ mod mask_functions {
|
|||
|
||||
fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
|
||||
match pattern {
|
||||
Checkerboard => mask_functions::checkerboard,
|
||||
HorizontalLines => mask_functions::horizontal_lines,
|
||||
VerticalLines => mask_functions::vertical_lines,
|
||||
DiagonalLines => mask_functions::diagonal_lines,
|
||||
LargeCheckerboard => mask_functions::large_checkerboard,
|
||||
Fields => mask_functions::fields,
|
||||
Diamonds => mask_functions::diamonds,
|
||||
Meadow => mask_functions::meadow,
|
||||
MaskPattern::Checkerboard => mask_functions::checkerboard,
|
||||
MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
|
||||
MaskPattern::VerticalLines => mask_functions::vertical_lines,
|
||||
MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
|
||||
MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
|
||||
MaskPattern::Fields => mask_functions::fields,
|
||||
MaskPattern::Diamonds => mask_functions::diamonds,
|
||||
MaskPattern::Meadow => mask_functions::meadow,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,27 +1349,27 @@ impl Canvas {
|
|||
/// current QR code version, this method will fail.
|
||||
fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
|
||||
let format_number = match self.version {
|
||||
Version(_) => {
|
||||
Version::Normal(_) => {
|
||||
let simple_format_number = ((self.ec_level as uint) ^ 1) << 3 | (pattern as uint);
|
||||
FORMAT_INFOS_QR[simple_format_number]
|
||||
}
|
||||
MicroVersion(a) => {
|
||||
Version::Micro(a) => {
|
||||
let micro_pattern_number = match pattern {
|
||||
HorizontalLines => 0b00,
|
||||
LargeCheckerboard => 0b01,
|
||||
Diamonds => 0b10,
|
||||
Meadow => 0b11,
|
||||
MaskPattern::HorizontalLines => 0b00,
|
||||
MaskPattern::LargeCheckerboard => 0b01,
|
||||
MaskPattern::Diamonds => 0b10,
|
||||
MaskPattern::Meadow => 0b11,
|
||||
_ => panic!("Unsupported mask pattern in Micro QR code"),
|
||||
};
|
||||
let symbol_number = match (a, self.ec_level) {
|
||||
(1, L) => 0b000,
|
||||
(2, L) => 0b001,
|
||||
(2, M) => 0b010,
|
||||
(3, L) => 0b011,
|
||||
(3, M) => 0b100,
|
||||
(4, L) => 0b101,
|
||||
(4, M) => 0b110,
|
||||
(4, Q) => 0b111,
|
||||
(1, EcLevel::L) => 0b000,
|
||||
(2, EcLevel::L) => 0b001,
|
||||
(2, EcLevel::M) => 0b010,
|
||||
(3, EcLevel::L) => 0b011,
|
||||
(3, EcLevel::M) => 0b100,
|
||||
(4, EcLevel::L) => 0b101,
|
||||
(4, EcLevel::M) => 0b110,
|
||||
(4, EcLevel::Q) => 0b111,
|
||||
_ => panic!("Unsupported version/ec_level combination in Micro QR code"),
|
||||
};
|
||||
let simple_format_number = symbol_number << 2 | micro_pattern_number;
|
||||
|
@ -1372,14 +1382,14 @@ impl Canvas {
|
|||
|
||||
#[cfg(test)]
|
||||
mod mask_tests {
|
||||
use canvas::{Canvas, Checkerboard, LargeCheckerboard};
|
||||
use types::{Version, MicroVersion, L};
|
||||
use canvas::{Canvas, MaskPattern};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_apply_mask_qr() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
|
||||
c.draw_all_functional_patterns();
|
||||
c.apply_mask(Checkerboard);
|
||||
c.apply_mask(MaskPattern::Checkerboard);
|
||||
|
||||
assert_eq!(&*c.to_debug_str(), "\n\
|
||||
#######...#.#.#######\n\
|
||||
|
@ -1407,8 +1417,8 @@ mod mask_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_format_info_patterns_qr() {
|
||||
let mut c = Canvas::new(Version(1), L);
|
||||
c.draw_format_info_patterns(LargeCheckerboard);
|
||||
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\
|
||||
|
@ -1435,8 +1445,8 @@ mod mask_tests {
|
|||
|
||||
#[test]
|
||||
fn test_draw_format_info_patterns_micro_qr() {
|
||||
let mut c = Canvas::new(MicroVersion(2), L);
|
||||
c.draw_format_info_patterns(LargeCheckerboard);
|
||||
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\
|
||||
|
@ -1488,9 +1498,9 @@ impl Canvas {
|
|||
|j| self.get(i, j)
|
||||
};
|
||||
|
||||
let mut colors = range(0, self.width).map(map_fn).chain(Some(Empty).into_iter());
|
||||
|
||||
let mut last_color = Empty;
|
||||
let mut colors = range(0, self.width).map(map_fn)
|
||||
.chain(Some(Module::Empty).into_iter());
|
||||
let mut last_color = Module::Empty;
|
||||
let mut consecutive_len = 1u16;
|
||||
|
||||
for color in colors {
|
||||
|
@ -1538,7 +1548,10 @@ impl Canvas {
|
|||
/// Every pattern that looks like `#.###.#....` in any orientation will add
|
||||
/// 40 points.
|
||||
fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 {
|
||||
static PATTERN: [Module, ..7] = [Dark, Light, Dark, Dark, Dark, Light, Dark];
|
||||
static PATTERN: [Module, ..7] = [
|
||||
Module::Dark, Module::Light, Module::Dark, Module::Dark,
|
||||
Module::Dark, Module::Light, Module::Dark,
|
||||
];
|
||||
|
||||
let mut total_score = 0;
|
||||
|
||||
|
@ -1602,7 +1615,7 @@ impl Canvas {
|
|||
fn compute_total_penalty_scores(&self) -> u16 {
|
||||
|
||||
match self.version {
|
||||
Version(_) => {
|
||||
Version::Normal(_) => {
|
||||
let s1a = self.compute_adjacent_penalty_score(true);
|
||||
let s1b = self.compute_adjacent_penalty_score(false);
|
||||
let s2 = self.compute_block_penalty_score();
|
||||
|
@ -1611,22 +1624,22 @@ impl Canvas {
|
|||
let s4 = self.compute_balance_penalty_score();
|
||||
s1a + s1b + s2 + s3a + s3b + s4
|
||||
}
|
||||
MicroVersion(_) => self.compute_light_side_penalty_score(),
|
||||
Version::Micro(_) => self.compute_light_side_penalty_score(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod penalty_tests {
|
||||
use canvas::{Canvas, Checkerboard, Module, Light, Dark};
|
||||
use types::{Version, MicroVersion, Q};
|
||||
use canvas::{Canvas, MaskPattern, Module};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
fn create_test_canvas() -> Canvas {
|
||||
let mut c = Canvas::new(Version(1), Q);
|
||||
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.apply_mask(Checkerboard);
|
||||
c.apply_mask(MaskPattern::Checkerboard);
|
||||
c
|
||||
}
|
||||
|
||||
|
@ -1686,15 +1699,21 @@ mod penalty_tests {
|
|||
#[test]
|
||||
fn test_penalty_score_light_sides() {
|
||||
static HORIZONTAL_SIDE: [Module, ..17] = [
|
||||
Dark, Light, Light, Dark, Dark, Dark, Light, Light,
|
||||
Dark, Light, Dark, Light, Light, Dark, Light, Light, Light
|
||||
Module::Dark, Module::Light, Module::Light, Module::Dark,
|
||||
Module::Dark, Module::Dark, Module::Light, Module::Light,
|
||||
Module::Dark, Module::Light, Module::Dark, Module::Light,
|
||||
Module::Light, Module::Dark, Module::Light, Module::Light,
|
||||
Module::Light,
|
||||
];
|
||||
static VERTICAL_SIDE: [Module, ..17] = [
|
||||
Dark, Dark, Dark, Light, Light, Dark, Dark, Light,
|
||||
Dark, Light, Dark, Light, Dark, Light, Light, Dark, Light
|
||||
Module::Dark, Module::Dark, Module::Dark, Module::Light,
|
||||
Module::Light, Module::Dark, Module::Dark, Module::Light,
|
||||
Module::Dark, Module::Light, Module::Dark, Module::Light,
|
||||
Module::Dark, Module::Light, Module::Light, Module::Dark,
|
||||
Module::Light,
|
||||
];
|
||||
|
||||
let mut c = Canvas::new(MicroVersion(4), Q);
|
||||
let mut c = Canvas::new(Version::Micro(4), EcLevel::Q);
|
||||
for i in range(0, 17) {
|
||||
c.put(i, -1, HORIZONTAL_SIDE[i as uint]);
|
||||
c.put(-1, i, VERTICAL_SIDE[i as uint]);
|
||||
|
@ -1709,12 +1728,15 @@ mod penalty_tests {
|
|||
//{{{ Select mask with lowest penalty score
|
||||
|
||||
static ALL_PATTERNS_QR: [MaskPattern, ..8] = [
|
||||
Checkerboard, HorizontalLines, VerticalLines, DiagonalLines,
|
||||
LargeCheckerboard, Fields, Diamonds, Meadow
|
||||
MaskPattern::Checkerboard, MaskPattern::HorizontalLines,
|
||||
MaskPattern::VerticalLines, MaskPattern::DiagonalLines,
|
||||
MaskPattern::LargeCheckerboard, MaskPattern::Fields,
|
||||
MaskPattern::Diamonds, MaskPattern::Meadow,
|
||||
];
|
||||
|
||||
static ALL_PATTERNS_MICRO_QR: [MaskPattern, ..4] = [
|
||||
HorizontalLines, LargeCheckerboard, Diamonds, Meadow
|
||||
MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard,
|
||||
MaskPattern::Diamonds, MaskPattern::Meadow,
|
||||
];
|
||||
|
||||
impl Canvas {
|
||||
|
@ -1722,8 +1744,8 @@ impl Canvas {
|
|||
/// penalty score.
|
||||
pub fn apply_best_mask(&self) -> Canvas {
|
||||
let patterns = match self.version {
|
||||
Version(_) => ALL_PATTERNS_QR.iter(),
|
||||
MicroVersion(_) => ALL_PATTERNS_MICRO_QR.iter(),
|
||||
Version::Normal(_) => ALL_PATTERNS_QR.iter(),
|
||||
Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
|
||||
};
|
||||
|
||||
patterns.map(|ptn| {
|
||||
|
|
12
src/ec.rs
12
src/ec.rs
|
@ -1,6 +1,6 @@
|
|||
//! The `ec` module applies the Reed-Solomon error correction codes.
|
||||
|
||||
use types::{QrResult, QrVersion, ErrorCorrectionLevel};
|
||||
use types::{QrResult, Version, EcLevel};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Error correction primitive
|
||||
|
@ -96,8 +96,8 @@ 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: QrVersion,
|
||||
ec_level: ErrorCorrectionLevel) -> QrResult<(Vec<u8>, Vec<u8>)> {
|
||||
version: Version,
|
||||
ec_level: EcLevel) -> QrResult<(Vec<u8>, Vec<u8>)> {
|
||||
let (block_1_size, block_1_count, block_2_size, block_2_count) =
|
||||
try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK));
|
||||
|
||||
|
@ -129,12 +129,12 @@ pub fn construct_codewords(rawbits: &[u8],
|
|||
#[cfg(test)]
|
||||
mod construct_codewords_test {
|
||||
use ec::construct_codewords;
|
||||
use types::{Version, M, Q};
|
||||
use types::{Version, EcLevel};
|
||||
|
||||
#[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(1), 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");
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ mod construct_codewords_test {
|
|||
#[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(5), Q).unwrap();
|
||||
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,
|
||||
|
|
52
src/lib.rs
52
src/lib.rs
|
@ -24,8 +24,7 @@
|
|||
|
||||
extern crate test;
|
||||
|
||||
pub use types::{QrResult, ErrorCorrectionLevel, L, M, Q, H,
|
||||
QrVersion, Version, MicroVersion};
|
||||
pub use types::{QrResult, EcLevel, Version};
|
||||
|
||||
pub mod types;
|
||||
pub mod bits;
|
||||
|
@ -37,8 +36,8 @@ pub mod canvas;
|
|||
#[deriving(Clone)]
|
||||
pub struct QrCode {
|
||||
content: Vec<bool>,
|
||||
version: QrVersion,
|
||||
ec_level: ErrorCorrectionLevel,
|
||||
version: Version,
|
||||
ec_level: EcLevel,
|
||||
width: uint,
|
||||
}
|
||||
|
||||
|
@ -53,7 +52,7 @@ impl QrCode {
|
|||
/// let code = QrCode::new(b"Some data").unwrap();
|
||||
///
|
||||
pub fn new(data: &[u8]) -> QrResult<QrCode> {
|
||||
QrCode::with_error_correction_level(data, M)
|
||||
QrCode::with_error_correction_level(data, EcLevel::M)
|
||||
}
|
||||
|
||||
/// Constructs a new QR code which automatically encodes the given data at a
|
||||
|
@ -61,11 +60,11 @@ impl QrCode {
|
|||
///
|
||||
/// This method automatically chooses the smallest QR code.
|
||||
///
|
||||
/// use qrcode::{QrCode, H};
|
||||
/// use qrcode::{QrCode, EcLevel};
|
||||
///
|
||||
/// let code = QrCode::with_error_correction_level(b"Some data", H).unwrap();
|
||||
/// let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap();
|
||||
///
|
||||
pub fn with_error_correction_level(data: &[u8], ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
|
||||
pub fn with_error_correction_level(data: &[u8], ec_level: EcLevel) -> QrResult<QrCode> {
|
||||
let bits = try!(bits::encode_auto(data, ec_level));
|
||||
QrCode::with_bits(bits, ec_level)
|
||||
}
|
||||
|
@ -73,19 +72,17 @@ impl QrCode {
|
|||
/// Constructs a new QR code for the given version and error correction
|
||||
/// level.
|
||||
///
|
||||
/// use qrcode::{QrCode, Version, M};
|
||||
/// use qrcode::{QrCode, Version, EcLevel};
|
||||
///
|
||||
/// let code = QrCode::with_version(b"Some data", Version(5), M).unwrap();
|
||||
/// let code = QrCode::with_version(b"Some data", Version::Normal(5), EcLevel::M).unwrap();
|
||||
///
|
||||
/// This method can also be used to generate Micro QR code.
|
||||
///
|
||||
/// use qrcode::{QrCode, MicroVersion, L};
|
||||
/// use qrcode::{QrCode, Version, EcLevel};
|
||||
///
|
||||
/// let micro_code = QrCode::with_version(b"123", MicroVersion(1), L).unwrap();
|
||||
/// let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap();
|
||||
///
|
||||
pub fn with_version(data: &[u8],
|
||||
version: QrVersion,
|
||||
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
|
||||
pub fn with_version(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<QrCode> {
|
||||
let mut bits = bits::Bits::new(version);
|
||||
try!(bits.push_optimal_data(data));
|
||||
try!(bits.push_terminator(ec_level));
|
||||
|
@ -103,25 +100,24 @@ impl QrCode {
|
|||
///
|
||||
/// See the `Bits` structure for detail.
|
||||
///
|
||||
/// #![allow(unused_must_use)];
|
||||
/// #![allow(unused_must_use)]
|
||||
///
|
||||
/// use qrcode::{QrCode, Version, L};
|
||||
/// use qrcode::{QrCode, Version, EcLevel};
|
||||
/// use qrcode::bits::Bits;
|
||||
///
|
||||
/// let mut bits = Bits::new(Version(1));
|
||||
/// let mut bits = Bits::new(Version::Normal(1));
|
||||
/// bits.push_eci_designator(9);
|
||||
/// bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR");
|
||||
/// bits.push_terminator(L);
|
||||
/// let qrcode = QrCode::with_bits(bits, L);
|
||||
/// bits.push_terminator(EcLevel::L);
|
||||
/// let qrcode = QrCode::with_bits(bits, EcLevel::L);
|
||||
///
|
||||
pub fn with_bits(bits: bits::Bits,
|
||||
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
|
||||
pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<QrCode> {
|
||||
let version = bits.version();
|
||||
let data = bits.into_bytes();
|
||||
let (encoded_data, ec_data) = try!(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[]);
|
||||
canvas.draw_data(&*encoded_data, &*ec_data);
|
||||
let canvas = canvas.apply_best_mask();
|
||||
Ok(QrCode {
|
||||
content: canvas.to_bools(),
|
||||
|
@ -132,12 +128,12 @@ impl QrCode {
|
|||
}
|
||||
|
||||
/// Gets the version of this QR code.
|
||||
pub fn version(&self) -> QrVersion {
|
||||
pub fn version(&self) -> Version {
|
||||
self.version
|
||||
}
|
||||
|
||||
/// Gets the error correction level of this QR code.
|
||||
pub fn error_correction_level(&self) -> ErrorCorrectionLevel {
|
||||
pub fn error_correction_level(&self) -> EcLevel {
|
||||
self.ec_level
|
||||
}
|
||||
|
||||
|
@ -186,12 +182,12 @@ impl Index<(uint, uint), bool> for QrCode {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {QrCode, Version, MicroVersion, L, M};
|
||||
use {QrCode, Version, EcLevel};
|
||||
|
||||
#[test]
|
||||
fn test_annex_i_qr() {
|
||||
// This uses the ISO Annex I as test vector.
|
||||
let code = QrCode::with_version(b"01234567", Version(1), M).unwrap();
|
||||
let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap();
|
||||
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
|
||||
#######..#.##.#######\n\
|
||||
#.....#..####.#.....#\n\
|
||||
|
@ -218,7 +214,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_annex_i_micro_qr() {
|
||||
let code = QrCode::with_version(b"01234567", MicroVersion(2), L).unwrap();
|
||||
let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap();
|
||||
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
|
||||
#######.#.#.#\n\
|
||||
#.....#.###.#\n\
|
||||
|
|
414
src/optimize.rs
414
src/optimize.rs
|
@ -7,7 +7,7 @@ use std::slice::Items;
|
|||
#[cfg(test)]
|
||||
use test::Bencher;
|
||||
|
||||
use types::{Mode, QrVersion, Numeric, Alphanumeric, Byte, Kanji};
|
||||
use types::{Mode, Version};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//{{{ Segment
|
||||
|
@ -28,9 +28,9 @@ pub struct Segment {
|
|||
impl Segment {
|
||||
/// Compute the number of bits (including the size of the mode indicator and
|
||||
/// length bits) when this segment is encoded.
|
||||
pub fn encoded_len(&self, version: QrVersion) -> uint {
|
||||
pub fn encoded_len(&self, version: Version) -> uint {
|
||||
let byte_size = self.end - self.begin;
|
||||
let chars_count = if self.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);
|
||||
|
@ -47,7 +47,9 @@ impl Segment {
|
|||
/// This iterator is basically equivalent to
|
||||
///
|
||||
/// ```ignore
|
||||
/// data.map(|c| ExclusiveCharacterSet::from_u8(*c)).chain(Some(EEnd).move_iter()).enumerate()
|
||||
/// data.map(|c| ExclCharSet::from_u8(*c))
|
||||
/// .chain(Some(ExclCharSet::End).move_iter())
|
||||
/// .enumerate()
|
||||
/// ```
|
||||
///
|
||||
/// But the type is too hard to write, thus the new type.
|
||||
|
@ -58,8 +60,8 @@ struct EcsIter<I> {
|
|||
ended: bool,
|
||||
}
|
||||
|
||||
impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIter<I> {
|
||||
fn next(&mut self) -> Option<(uint, ExclusiveCharacterSet)> {
|
||||
impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclCharSet)> for EcsIter<I> {
|
||||
fn next(&mut self) -> Option<(uint, ExclCharSet)> {
|
||||
if self.ended {
|
||||
return None;
|
||||
}
|
||||
|
@ -67,12 +69,12 @@ impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIte
|
|||
match self.base.next() {
|
||||
None => {
|
||||
self.ended = true;
|
||||
Some((self.index, EEnd))
|
||||
Some((self.index, ExclCharSet::End))
|
||||
}
|
||||
Some(c) => {
|
||||
let old_index = self.index;
|
||||
self.index += 1;
|
||||
Some((old_index, ExclusiveCharacterSet::from_u8(*c)))
|
||||
Some((old_index, ExclCharSet::from_u8(*c)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +83,7 @@ impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIte
|
|||
/// QR code data parser to classify the input into distinct segments.
|
||||
pub struct Parser<'a> {
|
||||
ecs_iter: EcsIter<Items<'a, u8>>,
|
||||
state: SegmentParseState,
|
||||
state: State,
|
||||
begin: uint,
|
||||
pending_single_byte: bool,
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ impl<'a> Parser<'a> {
|
|||
pub fn new(data: &[u8]) -> Parser {
|
||||
Parser {
|
||||
ecs_iter: EcsIter { base: data.iter(), index: 0, ended: false },
|
||||
state: SInit,
|
||||
state: State::Init,
|
||||
begin: 0,
|
||||
pending_single_byte: false,
|
||||
}
|
||||
|
@ -113,7 +115,11 @@ impl<'a> Iterator<Segment> for Parser<'a> {
|
|||
if self.pending_single_byte {
|
||||
self.pending_single_byte = false;
|
||||
self.begin += 1;
|
||||
return Some(Segment { mode: Byte, begin: self.begin-1, end: self.begin });
|
||||
return Some(Segment {
|
||||
mode: Mode::Byte,
|
||||
begin: self.begin-1,
|
||||
end: self.begin,
|
||||
});
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -126,25 +132,33 @@ impl<'a> Iterator<Segment> for Parser<'a> {
|
|||
|
||||
let old_begin = self.begin;
|
||||
let push_mode = match action {
|
||||
AIdle => { continue; }
|
||||
ANumeric => Numeric,
|
||||
AAlpha => Alphanumeric,
|
||||
AByte => Byte,
|
||||
AKanji => Kanji,
|
||||
AKanjiAndSingleByte => {
|
||||
Action::Idle => { continue; }
|
||||
Action::Numeric => Mode::Numeric,
|
||||
Action::Alpha => Mode::Alphanumeric,
|
||||
Action::Byte => Mode::Byte,
|
||||
Action::Kanji => Mode::Kanji,
|
||||
Action::KanjiAndSingleByte => {
|
||||
let next_begin = i - 1;
|
||||
if self.begin == next_begin {
|
||||
Byte
|
||||
Mode::Byte
|
||||
} else {
|
||||
self.pending_single_byte = true;
|
||||
self.begin = next_begin;
|
||||
return Some(Segment { 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +166,7 @@ impl<'a> Iterator<Segment> for Parser<'a> {
|
|||
#[cfg(test)]
|
||||
mod parse_tests {
|
||||
use optimize::{Parser, Segment};
|
||||
use types::{Numeric, Alphanumeric, Byte, Kanji};
|
||||
use types::Mode;
|
||||
|
||||
fn parse(data: &[u8]) -> Vec<Segment> {
|
||||
Parser::new(data).collect()
|
||||
|
@ -161,39 +175,39 @@ mod parse_tests {
|
|||
#[test]
|
||||
fn test_parse_1() {
|
||||
let segs = parse(b"01049123451234591597033130128%10ABC123");
|
||||
assert_eq!(segs, vec![Segment { mode: Numeric, begin: 0, end: 29 },
|
||||
Segment { mode: Alphanumeric, begin: 29, end: 30 },
|
||||
Segment { mode: Numeric, begin: 30, end: 32 },
|
||||
Segment { mode: Alphanumeric, begin: 32, end: 35 },
|
||||
Segment { 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: Kanji, begin: 0, end: 4 },
|
||||
Segment { mode: Alphanumeric, begin: 4, end: 5 },
|
||||
Segment { mode: Byte, begin: 5, end: 6 },
|
||||
Segment { mode: Kanji, begin: 6, end: 8 }]);
|
||||
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: Kanji, begin: 0, end: 4 },
|
||||
Segment { mode: Byte, begin: 4, end: 5 },
|
||||
Segment { mode: Kanji, begin: 5, end: 7 },
|
||||
Segment { mode: Byte, begin: 7, end: 10 },
|
||||
Segment { mode: Kanji, begin: 10, end: 12 },
|
||||
Segment { 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: Byte, begin: 0, end: 1 },
|
||||
Segment { 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]
|
||||
|
@ -201,22 +215,22 @@ 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: Byte, begin: 0, end: 1 },
|
||||
Segment { 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: Byte, begin: 0, end: 1 },
|
||||
Segment { 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: Kanji, begin: 0, end: 2 },
|
||||
Segment { 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 }]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +242,7 @@ pub struct Optimizer<I> {
|
|||
parser: I,
|
||||
last_segment: Segment,
|
||||
last_segment_size: uint,
|
||||
version: QrVersion,
|
||||
version: Version,
|
||||
ended: bool,
|
||||
}
|
||||
|
||||
|
@ -239,11 +253,11 @@ impl<I: Iterator<Segment>> Optimizer<I> {
|
|||
/// 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: QrVersion) -> Optimizer<I> {
|
||||
pub fn new(mut segments: I, version: Version) -> Optimizer<I> {
|
||||
match segments.next() {
|
||||
None => Optimizer {
|
||||
parser: segments,
|
||||
last_segment: Segment { mode: Numeric, begin: 0, end: 0 },
|
||||
last_segment: Segment { mode: Mode::Numeric, begin: 0, end: 0 },
|
||||
last_segment_size: 0,
|
||||
version: version,
|
||||
ended: true,
|
||||
|
@ -260,7 +274,7 @@ impl<I: Iterator<Segment>> Optimizer<I> {
|
|||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn optimize(self, version: QrVersion) -> Optimizer<Parser<'a>> {
|
||||
pub fn optimize(self, version: Version) -> Optimizer<Parser<'a>> {
|
||||
Optimizer::new(self, version)
|
||||
}
|
||||
}
|
||||
|
@ -303,7 +317,7 @@ impl<I: Iterator<Segment>> Iterator<Segment> for Optimizer<I> {
|
|||
}
|
||||
|
||||
/// Computes the total encoded length of all segments.
|
||||
pub fn total_encoded_len(segments: &[Segment], version: QrVersion) -> uint {
|
||||
pub fn total_encoded_len(segments: &[Segment], version: Version) -> uint {
|
||||
use std::iter::AdditiveIterator;
|
||||
segments.iter().map(|seg| seg.encoded_len(version)).sum()
|
||||
}
|
||||
|
@ -311,11 +325,11 @@ pub fn total_encoded_len(segments: &[Segment], version: QrVersion) -> uint {
|
|||
#[cfg(test)]
|
||||
mod optimize_tests {
|
||||
use optimize::{Optimizer, total_encoded_len, Segment};
|
||||
use types::{Numeric, Alphanumeric, Byte, Kanji, QrVersion, Version, MicroVersion};
|
||||
use types::{Mode, Version};
|
||||
|
||||
fn test_optimization_result(given: Vec<Segment>, expected: Vec<Segment>, version: QrVersion) {
|
||||
fn test_optimization_result(given: Vec<Segment>, expected: Vec<Segment>, version: Version) {
|
||||
let prev_len = total_encoded_len(&*given, version);
|
||||
let opt_segs = Optimizer::new(given.iter().map(|seg| *seg), version).collect::<Vec<Segment>>();
|
||||
let opt_segs = Optimizer::new(given.iter().map(|seg| *seg), version).collect::<Vec<_>>();
|
||||
let new_len = total_encoded_len(&*opt_segs, version);
|
||||
if given != opt_segs {
|
||||
assert!(prev_len > new_len, "{} > {}", prev_len, new_len);
|
||||
|
@ -329,14 +343,14 @@ mod optimize_tests {
|
|||
fn test_example_1() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Alphanumeric, begin: 0, end: 3 },
|
||||
Segment { mode: Numeric, begin: 3, end: 6 },
|
||||
Segment { mode: Byte, begin: 6, end: 10 }],
|
||||
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: Alphanumeric, begin: 0, end: 6 },
|
||||
Segment { mode: Byte, begin: 6, end: 10 }],
|
||||
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 },
|
||||
Segment { mode: Mode::Byte, begin: 6, end: 10 }],
|
||||
|
||||
Version(1)
|
||||
Version::Normal(1)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -345,16 +359,16 @@ mod optimize_tests {
|
|||
fn test_example_2() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Numeric, begin: 0, end: 29 },
|
||||
Segment { mode: Alphanumeric, begin: 29, end: 30 },
|
||||
Segment { mode: Numeric, begin: 30, end: 32 },
|
||||
Segment { mode: Alphanumeric, begin: 32, end: 35 },
|
||||
Segment { mode: Numeric, begin: 35, end: 38 }],
|
||||
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: Numeric, begin: 0, end: 29 },
|
||||
Segment { mode: Alphanumeric, begin: 29, end: 38 }],
|
||||
vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
|
||||
Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }],
|
||||
|
||||
Version(9)
|
||||
Version::Normal(9)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -363,14 +377,14 @@ mod optimize_tests {
|
|||
fn test_example_3() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Kanji, begin: 0, end: 4 },
|
||||
Segment { mode: Alphanumeric, begin: 4, end: 5 },
|
||||
Segment { mode: Byte, begin: 5, end: 6 },
|
||||
Segment { 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: Byte, begin: 0, end: 8 }],
|
||||
vec![Segment { mode: Mode::Byte, begin: 0, end: 8 }],
|
||||
|
||||
Version(1)
|
||||
Version::Normal(1)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -379,13 +393,13 @@ mod optimize_tests {
|
|||
fn test_example_4() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Kanji, begin: 0, end: 10 },
|
||||
Segment { mode: Byte, begin: 10, end: 11 }],
|
||||
vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
|
||||
Segment { mode: Mode::Byte, begin: 10, end: 11 }],
|
||||
|
||||
vec![Segment { mode: Kanji, begin: 0, end: 10 },
|
||||
Segment { mode: Byte, begin: 10, end: 11 }],
|
||||
vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
|
||||
Segment { mode: Mode::Byte, begin: 10, end: 11 }],
|
||||
|
||||
Version(1)
|
||||
Version::Normal(1)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -394,13 +408,13 @@ mod optimize_tests {
|
|||
fn test_annex_j_guideline_1a() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Numeric, begin: 0, end: 3 },
|
||||
Segment { 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: Numeric, begin: 0, end: 3 },
|
||||
Segment { mode: Alphanumeric, begin: 3, end: 4 }],
|
||||
vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
|
||||
Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }],
|
||||
|
||||
MicroVersion(2)
|
||||
Version::Micro(2)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -409,12 +423,12 @@ mod optimize_tests {
|
|||
fn test_annex_j_guideline_1b() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Numeric, begin: 0, end: 2 },
|
||||
Segment { 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: Alphanumeric, begin: 0, end: 4 }],
|
||||
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }],
|
||||
|
||||
MicroVersion(2)
|
||||
Version::Micro(2)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -423,12 +437,12 @@ mod optimize_tests {
|
|||
fn test_annex_j_guideline_1c() {
|
||||
test_optimization_result(
|
||||
|
||||
vec![Segment { mode: Numeric, begin: 0, end: 3 },
|
||||
Segment { 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: Alphanumeric, begin: 0, end: 4 }],
|
||||
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }],
|
||||
|
||||
MicroVersion(3)
|
||||
Version::Micro(3)
|
||||
|
||||
);
|
||||
}
|
||||
|
@ -441,7 +455,7 @@ fn bench_optimize(bencher: &mut Bencher) {
|
|||
|
||||
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(15))
|
||||
Parser::new(data).optimize(Version::Normal(15))
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -450,210 +464,208 @@ fn bench_optimize(bencher: &mut Bencher) {
|
|||
//------------------------------------------------------------------------------
|
||||
//{{{ Internal types and data for parsing
|
||||
|
||||
// All the silly prefixes are to avoid name collision with each other.
|
||||
|
||||
/// All values of `u8` can be split into 9 different character sets when
|
||||
/// determining which encoding to use. This enum represents these groupings for
|
||||
/// parsing purpose.
|
||||
enum ExclusiveCharacterSet {
|
||||
enum ExclCharSet {
|
||||
/// The end of string.
|
||||
EEnd = 0,
|
||||
End = 0,
|
||||
|
||||
/// All symbols supported by the Alphanumeric encoding, i.e. space, `$`, `%`,
|
||||
/// `*`, `+`, `-`, `.`, `/` and `:`.
|
||||
ESymbol = 1,
|
||||
Symbol = 1,
|
||||
|
||||
/// All numbers (0–9).
|
||||
ENumeric = 2,
|
||||
Numeric = 2,
|
||||
|
||||
/// All uppercase letters (A–Z). These characters may also appear in the
|
||||
/// second byte of a Shift JIS 2-byte encoding.
|
||||
EAlpha = 3,
|
||||
Alpha = 3,
|
||||
|
||||
/// The first byte of a Shift JIS 2-byte encoding, in the range 0x81–0x9f.
|
||||
EKanjiHi1 = 4,
|
||||
KanjiHi1 = 4,
|
||||
|
||||
/// The first byte of a Shift JIS 2-byte encoding, in the range 0xe0–0xea.
|
||||
EKanjiHi2 = 5,
|
||||
KanjiHi2 = 5,
|
||||
|
||||
/// The first byte of a Shift JIS 2-byte encoding, of value 0xeb. This is
|
||||
/// different from the other two range that the second byte has a smaller
|
||||
/// range.
|
||||
EKanjiHi3 = 6,
|
||||
KanjiHi3 = 6,
|
||||
|
||||
/// The second byte of a Shift JIS 2-byte encoding, in the range 0x40–0xbf,
|
||||
/// excluding letters (covered by `Alpha`), 0x81–0x9f (covered by `KanjiHi1`),
|
||||
/// and the invalid byte 0x7f.
|
||||
EKanjiLo1 = 7,
|
||||
KanjiLo1 = 7,
|
||||
|
||||
/// The second byte of a Shift JIS 2-byte encoding, in the range 0xc0–0xfc,
|
||||
/// excluding the range 0xe0–0xeb (covered by `KanjiHi2` and `KanjiHi3`).
|
||||
/// This half of byte-pair cannot appear as the second byte leaded by
|
||||
/// `KanjiHi3`.
|
||||
EKanjiLo2 = 8,
|
||||
KanjiLo2 = 8,
|
||||
|
||||
/// Any other values not covered by the above character sets.
|
||||
EByte = 9,
|
||||
Byte = 9,
|
||||
}
|
||||
|
||||
impl ExclusiveCharacterSet {
|
||||
impl ExclCharSet {
|
||||
/// Determines which character set a byte is in.
|
||||
fn from_u8(c: u8) -> ExclusiveCharacterSet {
|
||||
fn from_u8(c: u8) -> ExclCharSet {
|
||||
match c {
|
||||
0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ESymbol,
|
||||
0x30 ... 0x39 => ENumeric,
|
||||
0x41 ... 0x5a => EAlpha,
|
||||
0x81 ... 0x9f => EKanjiHi1,
|
||||
0xe0 ... 0xea => EKanjiHi2,
|
||||
0xeb => EKanjiHi3,
|
||||
0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => EKanjiLo1,
|
||||
0xc0 ... 0xdf | 0xec ... 0xfc => EKanjiLo2,
|
||||
_ => EByte
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The current parsing state.
|
||||
enum SegmentParseState {
|
||||
enum State {
|
||||
/// Just initialized.
|
||||
SInit = 0,
|
||||
Init = 0,
|
||||
|
||||
/// Inside a string that can be exclusively encoded as Numeric.
|
||||
SNumeric = 10,
|
||||
Numeric = 10,
|
||||
|
||||
/// Inside a string that can be exclusively encoded as Alphanumeric.
|
||||
SAlpha = 20,
|
||||
Alpha = 20,
|
||||
|
||||
/// Inside a string that can be exclusively encoded as 8-Bit Byte.
|
||||
SByte = 30,
|
||||
Byte = 30,
|
||||
|
||||
/// Just encountered the first byte of a Shift JIS 2-byte sequence of the
|
||||
/// set `KanjiHi1` or `KanjiHi2`.
|
||||
SKanjiHi12 = 40,
|
||||
KanjiHi12 = 40,
|
||||
|
||||
/// Just encountered the first byte of a Shift JIS 2-byte sequence of the
|
||||
/// set `KanjiHi3`.
|
||||
SKanjiHi3 = 50,
|
||||
KanjiHi3 = 50,
|
||||
|
||||
/// Inside a string that can be exclusively encoded as Kanji.
|
||||
SKanji = 60,
|
||||
Kanji = 60,
|
||||
}
|
||||
|
||||
/// What should the parser do after a state transition.
|
||||
enum ParserAction {
|
||||
enum Action {
|
||||
/// The parser should do nothing.
|
||||
AIdle,
|
||||
Idle,
|
||||
|
||||
/// Push the current segment as a Numeric string, and reset the marks.
|
||||
ANumeric,
|
||||
Numeric,
|
||||
|
||||
/// Push the current segment as an Alphanumeric string, and reset the marks.
|
||||
AAlpha,
|
||||
Alpha,
|
||||
|
||||
/// Push the current segment as a 8-Bit Byte string, and reset the marks.
|
||||
AByte,
|
||||
Byte,
|
||||
|
||||
/// Push the current segment as a Kanji string, and reset the marks.
|
||||
AKanji,
|
||||
Kanji,
|
||||
|
||||
/// Push the current segment excluding the last byte as a Kanji string, then
|
||||
/// push the remaining single byte as a Byte string, and reset the marks.
|
||||
AKanjiAndSingleByte,
|
||||
KanjiAndSingleByte,
|
||||
}
|
||||
|
||||
static STATE_TRANSITION: [(SegmentParseState, ParserAction), ..70] = [
|
||||
static STATE_TRANSITION: [(State, Action), ..70] = [
|
||||
// STATE_TRANSITION[current_state + next_character] == (next_state, what_to_do)
|
||||
|
||||
// Init state:
|
||||
|
||||
(SInit, AIdle), // End
|
||||
(SAlpha, AIdle), // Symbol
|
||||
(SNumeric, AIdle), // Numeric
|
||||
(SAlpha, AIdle), // Alpha
|
||||
(SKanjiHi12, AIdle), // KanjiHi1
|
||||
(SKanjiHi12, AIdle), // KanjiHi2
|
||||
(SKanjiHi3, AIdle), // KanjiHi3
|
||||
(SByte, AIdle), // KanjiLo1
|
||||
(SByte, AIdle), // KanjiLo2
|
||||
(SByte, AIdle), // 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:
|
||||
|
||||
(SInit, ANumeric), // End
|
||||
(SAlpha, ANumeric), // Symbol
|
||||
(SNumeric, AIdle), // Numeric
|
||||
(SAlpha, ANumeric), // Alpha
|
||||
(SKanjiHi12, ANumeric), // KanjiHi1
|
||||
(SKanjiHi12, ANumeric), // KanjiHi2
|
||||
(SKanjiHi3, ANumeric), // KanjiHi3
|
||||
(SByte, ANumeric), // KanjiLo1
|
||||
(SByte, ANumeric), // KanjiLo2
|
||||
(SByte, ANumeric), // 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:
|
||||
|
||||
(SInit, AAlpha), // End
|
||||
(SAlpha, AIdle), // Symbol
|
||||
(SNumeric, AAlpha), // Numeric
|
||||
(SAlpha, AIdle), // Alpha
|
||||
(SKanjiHi12, AAlpha), // KanjiHi1
|
||||
(SKanjiHi12, AAlpha), // KanjiHi2
|
||||
(SKanjiHi3, AAlpha), // KanjiHi3
|
||||
(SByte, AAlpha), // KanjiLo1
|
||||
(SByte, AAlpha), // KanjiLo2
|
||||
(SByte, AAlpha), // 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:
|
||||
|
||||
(SInit, AByte), // End
|
||||
(SAlpha, AByte), // Symbol
|
||||
(SNumeric, AByte), // Numeric
|
||||
(SAlpha, AByte), // Alpha
|
||||
(SKanjiHi12, AByte), // KanjiHi1
|
||||
(SKanjiHi12, AByte), // KanjiHi2
|
||||
(SKanjiHi3, AByte), // KanjiHi3
|
||||
(SByte, AIdle), // KanjiLo1
|
||||
(SByte, AIdle), // KanjiLo2
|
||||
(SByte, AIdle), // 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:
|
||||
|
||||
(SInit, AKanjiAndSingleByte), // End
|
||||
(SAlpha, AKanjiAndSingleByte), // Symbol
|
||||
(SNumeric, AKanjiAndSingleByte), // Numeric
|
||||
(SKanji, AIdle), // Alpha
|
||||
(SKanji, AIdle), // KanjiHi1
|
||||
(SKanji, AIdle), // KanjiHi2
|
||||
(SKanji, AIdle), // KanjiHi3
|
||||
(SKanji, AIdle), // KanjiLo1
|
||||
(SKanji, AIdle), // KanjiLo2
|
||||
(SByte, AKanjiAndSingleByte), // 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:
|
||||
|
||||
(SInit, AKanjiAndSingleByte), // End
|
||||
(SAlpha, AKanjiAndSingleByte), // Symbol
|
||||
(SNumeric, AKanjiAndSingleByte), // Numeric
|
||||
(SKanji, AIdle), // Alpha
|
||||
(SKanji, AIdle), // KanjiHi1
|
||||
(SKanjiHi12, AKanjiAndSingleByte), // KanjiHi2
|
||||
(SKanjiHi3, AKanjiAndSingleByte), // KanjiHi3
|
||||
(SKanji, AIdle), // KanjiLo1
|
||||
(SByte, AKanjiAndSingleByte), // KanjiLo2
|
||||
(SByte, AKanjiAndSingleByte), // 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:
|
||||
|
||||
(SInit, AKanji), // End
|
||||
(SAlpha, AKanji), // Symbol
|
||||
(SNumeric, AKanji), // Numeric
|
||||
(SAlpha, AKanji), // Alpha
|
||||
(SKanjiHi12, AIdle), // KanjiHi1
|
||||
(SKanjiHi12, AIdle), // KanjiHi2
|
||||
(SKanjiHi3, AIdle), // KanjiHi3
|
||||
(SByte, AKanji), // KanjiLo1
|
||||
(SByte, AKanji), // KanjiLo2
|
||||
(SByte, AKanji), // 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
|
||||
];
|
||||
|
||||
//}}}
|
||||
|
|
123
src/types.rs
123
src/types.rs
|
@ -39,7 +39,7 @@ pub type QrResult<T> = Result<T, QrError>;
|
|||
/// even if parts of the code is damaged.
|
||||
#[deriving(Show, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
|
||||
#[unstable]
|
||||
pub enum ErrorCorrectionLevel {
|
||||
pub enum EcLevel {
|
||||
/// Low error correction. Allows up to 7% of wrong blocks.
|
||||
L = 0,
|
||||
|
||||
|
@ -61,27 +61,26 @@ pub enum ErrorCorrectionLevel {
|
|||
/// Larger version means the size of code is larger, and therefore can carry
|
||||
/// more information.
|
||||
///
|
||||
/// The smallest version is `Version(1)` of size 21×21, and the largest is
|
||||
/// `Version(40)` of size 177×177.
|
||||
/// The smallest version is `Version::Normal(1)` of size 21×21, and the largest
|
||||
/// is `Version::Normal(40)` of size 177×177.
|
||||
#[unstable]
|
||||
#[deriving(Show, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum QrVersion {
|
||||
pub enum Version {
|
||||
/// A normal QR code version. The parameter should be between 1 and 40.
|
||||
#[unstable]
|
||||
Version(i16),
|
||||
Normal(i16),
|
||||
|
||||
/// A Micro QR code version. The parameter should be between 1 and 4.
|
||||
MicroVersion(i16),
|
||||
Micro(i16),
|
||||
}
|
||||
|
||||
impl QrVersion {
|
||||
impl Version {
|
||||
/// Get the number of "modules" on each size of the QR code, i.e. the width
|
||||
/// and height of the code.
|
||||
#[unstable]
|
||||
pub fn width(&self) -> i16 {
|
||||
match *self {
|
||||
Version(v) => v * 4 + 17,
|
||||
MicroVersion(v) => v * 2 + 9,
|
||||
Version::Normal(v) => v * 4 + 17,
|
||||
Version::Micro(v) => v * 2 + 9,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,21 +93,21 @@ impl QrVersion {
|
|||
/// the order [L, M, Q, H].
|
||||
///
|
||||
/// If the entry compares equal to the default value of T, this method
|
||||
/// returns `Err(InvalidVersion)`.
|
||||
pub fn fetch<T>(&self, ec_level: ErrorCorrectionLevel, table: &[[T, ..4]]) -> QrResult<T>
|
||||
/// returns `Err(QrError::InvalidVersion)`.
|
||||
pub fn fetch<T>(&self, ec_level: EcLevel, table: &[[T, ..4]]) -> QrResult<T>
|
||||
where T: PartialEq + Default + Copy
|
||||
{
|
||||
match *self {
|
||||
Version(v @ 1...40) => Ok(table[v as uint - 1][ec_level as uint]),
|
||||
MicroVersion(v @ 1...4) => {
|
||||
Version::Normal(v @ 1...40) => Ok(table[v as uint - 1][ec_level as uint]),
|
||||
Version::Micro(v @ 1...4) => {
|
||||
let obj = table[v as uint + 39][ec_level as uint];
|
||||
if obj != Default::default() {
|
||||
Ok(obj)
|
||||
} else {
|
||||
Err(InvalidVersion)
|
||||
Err(QrError::InvalidVersion)
|
||||
}
|
||||
}
|
||||
_ => Err(InvalidVersion)
|
||||
_ => Err(QrError::InvalidVersion)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +115,7 @@ impl QrVersion {
|
|||
#[unstable]
|
||||
pub fn mode_bits_count(&self) -> uint {
|
||||
match *self {
|
||||
MicroVersion(a) => (a - 1) as uint,
|
||||
Version::Micro(a) => (a - 1) as uint,
|
||||
_ => 4,
|
||||
}
|
||||
}
|
||||
|
@ -125,8 +124,8 @@ impl QrVersion {
|
|||
#[unstable]
|
||||
pub fn is_micro(&self) -> bool {
|
||||
match *self {
|
||||
Version(_) => false,
|
||||
MicroVersion(_) => true,
|
||||
Version::Normal(_) => false,
|
||||
Version::Micro(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,68 +155,68 @@ pub enum Mode {
|
|||
impl Mode {
|
||||
/// Computes the number of bits needed to encode the data length.
|
||||
///
|
||||
/// use qrcode::types::{Version, Numeric};
|
||||
/// use qrcode::types::{Version, Mode};
|
||||
///
|
||||
/// assert_eq!(Numeric.length_bits_count(Version(1)), 10);
|
||||
/// assert_eq!(Mode::Numeric.length_bits_count(Version::Normal(1)), 10);
|
||||
///
|
||||
/// This method will return `Err(UnsupportedCharacterSet)` if the is not
|
||||
/// supported in the given version.
|
||||
/// This method will return `Err(QrError::UnsupportedCharacterSet)` if the
|
||||
/// mode is not supported in the given version.
|
||||
#[unstable]
|
||||
pub fn length_bits_count(&self, version: QrVersion) -> uint {
|
||||
pub fn length_bits_count(&self, version: Version) -> uint {
|
||||
match version {
|
||||
MicroVersion(a) => {
|
||||
Version::Micro(a) => {
|
||||
let a = a as uint;
|
||||
match *self {
|
||||
Numeric => 2 + a,
|
||||
Alphanumeric | Byte => 1 + a,
|
||||
Kanji => a,
|
||||
Mode::Numeric => 2 + a,
|
||||
Mode::Alphanumeric | Mode::Byte => 1 + a,
|
||||
Mode::Kanji => a,
|
||||
}
|
||||
}
|
||||
Version(1...9) => match *self {
|
||||
Numeric => 10,
|
||||
Alphanumeric => 9,
|
||||
Byte => 8,
|
||||
Kanji => 8,
|
||||
Version::Normal(1...9) => match *self {
|
||||
Mode::Numeric => 10,
|
||||
Mode::Alphanumeric => 9,
|
||||
Mode::Byte => 8,
|
||||
Mode::Kanji => 8,
|
||||
},
|
||||
Version(10...26) => match *self {
|
||||
Numeric => 12,
|
||||
Alphanumeric => 11,
|
||||
Byte => 16,
|
||||
Kanji => 10,
|
||||
Version::Normal(10...26) => match *self {
|
||||
Mode::Numeric => 12,
|
||||
Mode::Alphanumeric => 11,
|
||||
Mode::Byte => 16,
|
||||
Mode::Kanji => 10,
|
||||
},
|
||||
Version(_) => match *self {
|
||||
Numeric => 14,
|
||||
Alphanumeric => 13,
|
||||
Byte => 16,
|
||||
Kanji => 12,
|
||||
Version::Normal(_) => match *self {
|
||||
Mode::Numeric => 14,
|
||||
Mode::Alphanumeric => 13,
|
||||
Mode::Byte => 16,
|
||||
Mode::Kanji => 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the number of bits needed to some data of a given raw length.
|
||||
///
|
||||
/// use qrcode::types::Numeric;
|
||||
/// use qrcode::types::Mode;
|
||||
///
|
||||
/// assert_eq!(Numeric.data_bits_count(7), 24);
|
||||
/// assert_eq!(Mode::Numeric.data_bits_count(7), 24);
|
||||
///
|
||||
/// Note that in Kanji mode, the `raw_data_len` is the number of Kanjis,
|
||||
/// i.e. half the total size of bytes.
|
||||
#[unstable]
|
||||
pub fn data_bits_count(&self, raw_data_len: uint) -> uint {
|
||||
match *self {
|
||||
Numeric => (raw_data_len * 10 + 2) / 3,
|
||||
Alphanumeric => (raw_data_len * 11 + 1) / 2,
|
||||
Byte => raw_data_len * 8,
|
||||
Kanji => raw_data_len * 13,
|
||||
Mode::Numeric => (raw_data_len * 10 + 2) / 3,
|
||||
Mode::Alphanumeric => (raw_data_len * 11 + 1) / 2,
|
||||
Mode::Byte => raw_data_len * 8,
|
||||
Mode::Kanji => raw_data_len * 13,
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the lowest common mode which both modes are compatible with.
|
||||
///
|
||||
/// use qrcode::types::{Numeric, Kanji};
|
||||
/// use qrcode::types::Mode;
|
||||
///
|
||||
/// let a = Numeric;
|
||||
/// let b = Kanji;
|
||||
/// let a = Mode::Numeric;
|
||||
/// let b = Mode::Kanji;
|
||||
/// let c = a.max(b);
|
||||
/// assert!(a <= c);
|
||||
/// assert!(b <= c);
|
||||
|
@ -226,7 +225,7 @@ impl Mode {
|
|||
match self.partial_cmp(&other) {
|
||||
Some(Less) | Some(Equal) => other,
|
||||
Some(Greater) => *self,
|
||||
None => Byte,
|
||||
None => Mode::Byte,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,14 +235,14 @@ impl PartialOrd for Mode {
|
|||
/// a superset of all characters supported by `a`.
|
||||
fn partial_cmp(&self, other: &Mode) -> Option<Ordering> {
|
||||
match (*self, *other) {
|
||||
(Numeric, Alphanumeric) => Some(Less),
|
||||
(Alphanumeric, Numeric) => Some(Greater),
|
||||
(Numeric, Byte) => Some(Less),
|
||||
(Byte, Numeric) => Some(Greater),
|
||||
(Alphanumeric, Byte) => Some(Less),
|
||||
(Byte, Alphanumeric) => Some(Greater),
|
||||
(Kanji, Byte) => Some(Less),
|
||||
(Byte, Kanji) => Some(Greater),
|
||||
(Mode::Numeric, Mode::Alphanumeric) => Some(Less),
|
||||
(Mode::Alphanumeric, Mode::Numeric) => Some(Greater),
|
||||
(Mode::Numeric, Mode::Byte) => Some(Less),
|
||||
(Mode::Byte, Mode::Numeric) => Some(Greater),
|
||||
(Mode::Alphanumeric, Mode::Byte) => Some(Less),
|
||||
(Mode::Byte, Mode::Alphanumeric) => Some(Greater),
|
||||
(Mode::Kanji, Mode::Byte) => Some(Less),
|
||||
(Mode::Byte, Mode::Kanji) => Some(Greater),
|
||||
(a, b) if a == b => Some(Equal),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -252,7 +251,7 @@ impl PartialOrd for Mode {
|
|||
|
||||
#[cfg(test)]
|
||||
mod mode_tests {
|
||||
use types::{Numeric, Alphanumeric, Byte, Kanji};
|
||||
use types::Mode::{Numeric, Alphanumeric, Byte, Kanji};
|
||||
|
||||
#[test]
|
||||
fn test_mode_order() {
|
||||
|
|
Loading…
Reference in a new issue