rustup. Quantify all enums, and renamed (shortened) a few types.

This commit is contained in:
kennytm 2014-11-29 05:29:01 +08:00
parent 74bdb39149
commit a4ae80b1b7
6 changed files with 599 additions and 576 deletions

View file

@ -7,10 +7,7 @@ use std::cmp::min;
#[cfg(test)] #[cfg(test)]
use test::Bencher; use test::Bencher;
use types::{QrResult, DataTooLong, UnsupportedCharacterSet, InvalidEciDesignator, use types::{QrResult, QrError, Mode, EcLevel, Version};
InvalidCharacter,
Mode, Numeric, Alphanumeric, Byte, Kanji,
ErrorCorrectionLevel, QrVersion, Version, MicroVersion};
use optimize::{Parser, Optimizer, total_encoded_len, Segment}; use optimize::{Parser, Optimizer, total_encoded_len, Segment};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -20,12 +17,12 @@ use optimize::{Parser, Optimizer, total_encoded_len, Segment};
pub struct Bits { pub struct Bits {
data: Vec<u8>, data: Vec<u8>,
bit_offset: uint, bit_offset: uint,
version: QrVersion, version: Version,
} }
impl Bits { impl Bits {
/// Constructs a new, empty bits structure. /// 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 } 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 /// Pushes an N-bit big-endian integer to the end of the bits, and check
/// that the number does not overflow the bits. /// 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<()> { fn push_number_checked(&mut self, n: uint, number: uint) -> QrResult<()> {
if n > 16 || number >= (1 << n) { if n > 16 || number >= (1 << n) {
Err(DataTooLong) Err(QrError::DataTooLong)
} else { } else {
self.push_number(n, number as u16); self.push_number(n, number as u16);
Ok(()) Ok(())
@ -97,14 +94,14 @@ impl Bits {
} }
/// Version of the QR code. /// Version of the QR code.
pub fn version(&self) -> QrVersion { pub fn version(&self) -> Version {
self.version self.version
} }
} }
#[test] #[test]
fn test_push_number() { 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, 0b010); // 0:0 .. 0:3
bits.push_number(3, 0b110); // 0:3 .. 0:6 bits.push_number(3, 0b110); // 0:3 .. 0:6
@ -130,7 +127,7 @@ fn test_push_number() {
#[bench] #[bench]
fn bench_push_splitted_bytes(bencher: &mut Bencher) { fn bench_push_splitted_bytes(bencher: &mut Bencher) {
bencher.iter(|| { bencher.iter(|| {
let mut bits = Bits::new(Version(40)); let mut bits = Bits::new(Version::Normal(40));
bits.push_number(4, 0b0101); bits.push_number(4, 0b0101);
for _ in range(0u, 1024) { for _ in range(0u, 1024) {
bits.push_number(8, 0b10101010); bits.push_number(8, 0b10101010);
@ -166,27 +163,27 @@ impl Bits {
/// Push the mode indicator to the end of the bits. /// Push the mode indicator to the end of the bits.
/// ///
/// If the mode is not supported in the provided version, this method /// If the mode is not supported in the provided version, this method
/// returns `Err(UnsupportedCharacterSet)`. /// returns `Err(QrError::UnsupportedCharacterSet)`.
#[unstable] #[unstable]
pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> { pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> {
let number = match (self.version, mode) { let number = match (self.version, mode) {
(MicroVersion(1), Data(Numeric)) => return Ok(()), (Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()),
(MicroVersion(_), Data(Numeric)) => 0, (Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0,
(MicroVersion(_), Data(Alphanumeric)) => 1, (Version::Micro(_), ExtendedMode::Data(Mode::Alphanumeric)) => 1,
(MicroVersion(_), Data(Byte)) => 0b10, (Version::Micro(_), ExtendedMode::Data(Mode::Byte)) => 0b10,
(MicroVersion(_), Data(Kanji)) => 0b11, (Version::Micro(_), ExtendedMode::Data(Mode::Kanji)) => 0b11,
(MicroVersion(_), _) => return Err(UnsupportedCharacterSet), (Version::Micro(_), _) => return Err(QrError::UnsupportedCharacterSet),
(_, Data(Numeric)) => 0b0001, (_, ExtendedMode::Data(Mode::Numeric)) => 0b0001,
(_, Data(Alphanumeric)) => 0b0010, (_, ExtendedMode::Data(Mode::Alphanumeric)) => 0b0010,
(_, Data(Byte)) => 0b0100, (_, ExtendedMode::Data(Mode::Byte)) => 0b0100,
(_, Data(Kanji)) => 0b1000, (_, ExtendedMode::Data(Mode::Kanji)) => 0b1000,
(_, Eci) => 0b0111, (_, ExtendedMode::Eci) => 0b0111,
(_, Fnc1First) => 0b0101, (_, ExtendedMode::Fnc1First) => 0b0101,
(_, Fnc1Second) => 0b1001, (_, ExtendedMode::Fnc1Second) => 0b1001,
(_, StructuredAppend) => 0b0011, (_, ExtendedMode::StructuredAppend) => 0b0011,
}; };
let bits = self.version.mode_bits_count(); 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::bits::Bits;
/// use qrcode::types::Version; /// 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_eci_designator(9); // 9 = ISO-8859-7 (Greek).
/// bits.push_byte_data(b"\xa1\xa2\xa3\xa4\xa5"); // ΑΒΓΔΕ /// bits.push_byte_data(b"\xa1\xa2\xa3\xa4\xa5"); // ΑΒΓΔΕ
/// ///
@ -226,13 +223,13 @@ impl Bits {
/// 30 | EUC-KR (Korean) /// 30 | EUC-KR (Korean)
/// ///
/// If the QR code version does not support ECI, this method will return /// 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 /// 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<()> { pub fn push_eci_designator(&mut self, eci_designator: u32) -> QrResult<()> {
self.reserve(12); // assume the common case that eci_designator <= 127. 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 { match eci_designator {
0...127 => { 0...127 => {
self.push_number(8, eci_designator as u16); 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(5, (eci_designator >> 16) as u16);
self.push_number(16, (eci_designator & 0xffff) as u16); self.push_number(16, (eci_designator & 0xffff) as u16);
} }
_ => return Err(InvalidEciDesignator), _ => return Err(QrError::InvalidEciDesignator),
} }
Ok(()) Ok(())
} }
@ -255,25 +252,25 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod eci_tests { mod eci_tests {
use bits::Bits; use bits::Bits;
use types::{MicroVersion, Version, InvalidEciDesignator, UnsupportedCharacterSet}; use types::{Version, QrError};
#[test] #[test]
fn test_9() { 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.push_eci_designator(9), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0111__0000, 0b1001__0000]); assert_eq!(bits.into_bytes(), vec![0b0111__0000, 0b1001__0000]);
} }
#[test] #[test]
fn test_899() { 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.push_eci_designator(899), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0111__10_00, 0b00111000, 0b0011__0000]); assert_eq!(bits.into_bytes(), vec![0b0111__10_00, 0b00111000, 0b0011__0000]);
} }
#[test] #[test]
fn test_999999() { 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.push_eci_designator(999999), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0111__110_0, assert_eq!(bits.into_bytes(), vec![0b0111__110_0,
0b11110100, 0b11110100,
@ -283,26 +280,26 @@ mod eci_tests {
#[test] #[test]
fn test_invalid_designator() { fn test_invalid_designator() {
let mut bits = Bits::new(Version(1)); let mut bits = Bits::new(Version::Normal(1));
assert_eq!(bits.push_eci_designator(1000000), Err(InvalidEciDesignator)); assert_eq!(bits.push_eci_designator(1000000), Err(QrError::InvalidEciDesignator));
} }
#[test] #[test]
fn test_unsupported_character_set() { fn test_unsupported_character_set() {
let mut bits = Bits::new(MicroVersion(4)); let mut bits = Bits::new(Version::Micro(4));
assert_eq!(bits.push_eci_designator(9), Err(UnsupportedCharacterSet)); assert_eq!(bits.push_eci_designator(9), Err(QrError::UnsupportedCharacterSet));
} }
} }
//}}} //}}}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Numeric mode //{{{ Mode::Numeric mode
impl Bits { impl Bits {
fn push_header(&mut self, mode: Mode, raw_data_len: uint) -> QrResult<()> { fn push_header(&mut self, mode: Mode, raw_data_len: uint) -> QrResult<()> {
let length_bits = mode.length_bits_count(self.version); let length_bits = mode.length_bits_count(self.version);
self.reserve(length_bits + 4 + mode.data_bits_count(raw_data_len)); 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)); try!(self.push_number_checked(length_bits, raw_data_len));
Ok(()) Ok(())
} }
@ -312,7 +309,7 @@ impl Bits {
/// The data should only contain the characters 0 to 9. /// The data should only contain the characters 0 to 9.
#[unstable] #[unstable]
pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> { 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) { for chunk in data.chunks(3) {
let number = chunk.iter().map(|b| (*b - b'0') as u16).fold(0, |a, b| a*10 + b); let number = chunk.iter().map(|b| (*b - b'0') as u16).fold(0, |a, b| a*10 + b);
let length = chunk.len() * 3 + 1; let length = chunk.len() * 3 + 1;
@ -325,11 +322,11 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod numeric_tests { mod numeric_tests {
use bits::Bits; use bits::Bits;
use types::{Version, MicroVersion, DataTooLong}; use types::{Version, QrError};
#[test] #[test]
fn test_iso_18004_2006_example_1() { 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.push_numeric_data(b"01234567"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0001_0000, assert_eq!(bits.into_bytes(), vec![0b0001_0000,
0b001000_00, 0b001000_00,
@ -341,7 +338,7 @@ mod numeric_tests {
#[test] #[test]
fn test_iso_18004_2000_example_2() { 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.push_numeric_data(b"0123456789012345"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0001_0000, assert_eq!(bits.into_bytes(), vec![0b0001_0000,
0b010000_00, 0b010000_00,
@ -356,7 +353,7 @@ mod numeric_tests {
#[test] #[test]
fn test_iso_18004_2006_example_2() { 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.push_numeric_data(b"0123456789012345"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b00_10000_0, assert_eq!(bits.into_bytes(), vec![0b00_10000_0,
0b00000110, 0b00000110,
@ -370,16 +367,16 @@ mod numeric_tests {
#[test] #[test]
fn test_data_too_long_error() { fn test_data_too_long_error() {
let mut bits = Bits::new(MicroVersion(1)); let mut bits = Bits::new(Version::Micro(1));
assert_eq!(bits.push_numeric_data(b"12345678"), Err(DataTooLong)); 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 /// encoded as a base-45 integer. `alphanumeric_digit` converts each character
/// into its corresponding base-45 digit. /// into its corresponding base-45 digit.
/// ///
@ -409,7 +406,7 @@ impl Bits {
/// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`. /// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`.
#[unstable] #[unstable]
pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> { 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) { for chunk in data.chunks(2) {
let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a*45 + b); let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a*45 + b);
let length = chunk.len() * 5 + 1; let length = chunk.len() * 5 + 1;
@ -422,11 +419,11 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod alphanumeric_tests { mod alphanumeric_tests {
use bits::Bits; use bits::Bits;
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong}; use types::{Version, QrError};
#[test] #[test]
fn test_iso_18004_2006_example() { 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.push_alphanumeric_data(b"AC-42"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0010_0000, assert_eq!(bits.into_bytes(), vec![0b0010_0000,
0b00101_001, 0b00101_001,
@ -438,26 +435,26 @@ mod alphanumeric_tests {
#[test] #[test]
fn test_micro_qr_unsupported() { fn test_micro_qr_unsupported() {
let mut bits = Bits::new(MicroVersion(1)); let mut bits = Bits::new(Version::Micro(1));
assert_eq!(bits.push_alphanumeric_data(b"A"), Err(UnsupportedCharacterSet)); assert_eq!(bits.push_alphanumeric_data(b"A"), Err(QrError::UnsupportedCharacterSet));
} }
#[test] #[test]
fn test_data_too_long() { fn test_data_too_long() {
let mut bits = Bits::new(MicroVersion(2)); let mut bits = Bits::new(Version::Micro(2));
assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(DataTooLong)); assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(QrError::DataTooLong));
} }
} }
//}}} //}}}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Byte mode //{{{ Mode::Byte mode
impl Bits { impl Bits {
/// Encodes 8-bit byte data to the bits. /// Encodes 8-bit byte data to the bits.
#[unstable] #[unstable]
pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> { 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() { for b in data.iter() {
self.push_number(8, *b as u16); self.push_number(8, *b as u16);
} }
@ -468,11 +465,11 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod byte_tests { mod byte_tests {
use bits::Bits; use bits::Bits;
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong}; use types::{Version, QrError};
#[test] #[test]
fn 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.push_byte_data(b"\x12\x34\x56\x78\x9a\xbc\xde\xf0"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b0100_0000, assert_eq!(bits.into_bytes(), vec![0b0100_0000,
0b1000_0001, 0b1000_0001,
@ -488,29 +485,29 @@ mod byte_tests {
#[test] #[test]
fn test_micro_qr_unsupported() { fn test_micro_qr_unsupported() {
let mut bits = Bits::new(MicroVersion(2)); let mut bits = Bits::new(Version::Micro(2));
assert_eq!(bits.push_byte_data(b"?"), Err(UnsupportedCharacterSet)); assert_eq!(bits.push_byte_data(b"?"), Err(QrError::UnsupportedCharacterSet));
} }
#[test] #[test]
fn test_data_too_long() { fn test_data_too_long() {
let mut bits = Bits::new(MicroVersion(3)); let mut bits = Bits::new(Version::Micro(3));
assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(DataTooLong)); assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(QrError::DataTooLong));
} }
} }
//}}} //}}}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Kanji mode //{{{ Mode::Kanji mode
impl Bits { impl Bits {
/// Encodes Shift JIS double-byte data to the bits. /// Encodes Shift JIS double-byte data to the bits.
#[unstable] #[unstable]
pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> { 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) { for kanji in data.chunks(2) {
if kanji.len() != 2 { if kanji.len() != 2 {
return Err(InvalidCharacter); return Err(QrError::InvalidCharacter);
} }
let cp = (kanji[0] as u16) * 256 + (kanji[1] as u16); let cp = (kanji[0] as u16) * 256 + (kanji[1] as u16);
let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 }; let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 };
@ -524,11 +521,11 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod kanji_tests { mod kanji_tests {
use bits::Bits; use bits::Bits;
use types::{Version, MicroVersion, UnsupportedCharacterSet, DataTooLong}; use types::{Version, QrError};
#[test] #[test]
fn test_iso_18004_example() { 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.push_kanji_data(b"\x93\x5f\xe4\xaa"), Ok(()));
assert_eq!(bits.into_bytes(), vec![0b1000_0000, assert_eq!(bits.into_bytes(), vec![0b1000_0000,
0b0010_0110, 0b0010_0110,
@ -539,15 +536,15 @@ mod kanji_tests {
#[test] #[test]
fn test_micro_qr_unsupported() { fn test_micro_qr_unsupported() {
let mut bits = Bits::new(MicroVersion(2)); let mut bits = Bits::new(Version::Micro(2));
assert_eq!(bits.push_kanji_data(b"?"), Err(UnsupportedCharacterSet)); assert_eq!(bits.push_kanji_data(b"?"), Err(QrError::UnsupportedCharacterSet));
} }
#[test] #[test]
fn test_data_too_long() { 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_"), 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::bits::Bits;
/// use qrcode::types::Version; /// 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_fnc1_first_position();
/// bits.push_numeric_data(b"01049123451234591597033130128"); /// bits.push_numeric_data(b"01049123451234591597033130128");
/// bits.push_alphanumeric_data(b"%10ABC123"); /// bits.push_alphanumeric_data(b"%10ABC123");
/// ///
/// In QR code, the character `%` is used as the data field separator (0x1D). /// In QR code, the character `%` is used as the data field separator (0x1D).
pub fn push_fnc1_first_position(&mut self) -> QrResult<()> { 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 /// Encodes an indicator that the following data are formatted in accordance
@ -583,7 +580,7 @@ impl Bits {
/// use qrcode::bits::Bits; /// use qrcode::bits::Bits;
/// use qrcode::types::Version; /// 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_fnc1_second_position(37);
/// bits.push_alphanumeric_data(b"AA1234BBB112"); /// bits.push_alphanumeric_data(b"AA1234BBB112");
/// bits.push_byte_data(b"text text text text\r"); /// bits.push_byte_data(b"text text text text\r");
@ -595,7 +592,7 @@ impl Bits {
/// bits.push_fnc1_second_position(b'A' + 100); /// bits.push_fnc1_second_position(b'A' + 100);
/// ``` /// ```
pub fn push_fnc1_second_position(&mut self, application_indicator: u8) -> QrResult<()> { 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); self.push_number(8, application_indicator as u16);
Ok(()) Ok(())
} }
@ -659,16 +656,16 @@ static DATA_LENGTHS: [[uint, ..4], ..44] = [
impl Bits { impl Bits {
/// Pushes the ending bits to indicate no more data. /// Pushes the ending bits to indicate no more data.
#[unstable] #[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 { let terminator_size = match self.version {
MicroVersion(a) => (a as uint) * 2 + 1, Version::Micro(a) => (a as uint) * 2 + 1,
_ => 4, _ => 4,
}; };
let cur_length = self.len(); let cur_length = self.len();
let data_length = try!(self.version.fetch(ec_level, &DATA_LENGTHS)); let data_length = try!(self.version.fetch(ec_level, &DATA_LENGTHS));
if cur_length > data_length { if cur_length > data_length {
return Err(DataTooLong); return Err(QrError::DataTooLong);
} }
let terminator_size = min(terminator_size, data_length - cur_length); let terminator_size = min(terminator_size, data_length - cur_length);
@ -695,13 +692,13 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod finish_tests { mod finish_tests {
use bits::Bits; use bits::Bits;
use types::{Version, MicroVersion, L, Q, DataTooLong}; use types::{Version, EcLevel, QrError};
#[test] #[test]
fn test_hello_world() { 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_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, assert_eq!(bits.into_bytes(), vec![0b00100000, 0b01011011, 0b00001011,
0b01111000, 0b11010001, 0b01110010, 0b01111000, 0b11010001, 0b01110010,
0b11011100, 0b01001101, 0b01000011, 0b11011100, 0b01001101, 0b01000011,
@ -711,40 +708,40 @@ mod finish_tests {
#[test] #[test]
fn test_too_long() { 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_numeric_data(b"9999999"), Ok(()));
assert_eq!(bits.push_terminator(L), Err(DataTooLong)); assert_eq!(bits.push_terminator(EcLevel::L), Err(QrError::DataTooLong));
} }
#[test] #[test]
fn test_no_terminator() { 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_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]); assert_eq!(bits.into_bytes(), vec![0b101_11111, 0b00111_110, 0b0011__0000]);
} }
#[test] #[test]
fn test_no_padding() { 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_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]); assert_eq!(bits.into_bytes(), vec![0b100_11111, 0b00111_100, 0b1_000__0000]);
} }
#[test] #[test]
fn test_micro_version_1_half_byte_padding() { 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_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]); assert_eq!(bits.into_bytes(), vec![0b011_11111, 0b00111_000, 0b0000__0000]);
} }
#[test] #[test]
fn test_micro_version_1_full_byte_padding() { 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_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]); assert_eq!(bits.into_bytes(), vec![0b000_000_00, 0b11101100, 0]);
} }
} }
@ -761,10 +758,10 @@ impl Bits {
for segment in segments_iter { for segment in segments_iter {
let slice = data[segment.begin..segment.end]; let slice = data[segment.begin..segment.end];
try!(match segment.mode { try!(match segment.mode {
Numeric => self.push_numeric_data(slice), Mode::Numeric => self.push_numeric_data(slice),
Alphanumeric => self.push_alphanumeric_data(slice), Mode::Alphanumeric => self.push_alphanumeric_data(slice),
Byte => self.push_byte_data(slice), Mode::Byte => self.push_byte_data(slice),
Kanji => self.push_kanji_data(slice), Mode::Kanji => self.push_kanji_data(slice),
}); });
} }
Ok(()) Ok(())
@ -781,12 +778,9 @@ impl Bits {
#[cfg(test)] #[cfg(test)]
mod encode_tests { mod encode_tests {
use bits::Bits; use bits::Bits;
use types::{QrVersion, Version, MicroVersion, DataTooLong, QrResult, use types::{Version, QrError, QrResult, EcLevel};
L, Q, H, ErrorCorrectionLevel};
fn encode(data: &[u8], fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<Vec<u8>> {
version: QrVersion,
ec_level: ErrorCorrectionLevel) -> QrResult<Vec<u8>> {
let mut bits = Bits::new(version); let mut bits = Bits::new(version);
try!(bits.push_optimal_data(data)); try!(bits.push_optimal_data(data));
try!(bits.push_terminator(ec_level)); try!(bits.push_terminator(ec_level));
@ -795,7 +789,7 @@ mod encode_tests {
#[test] #[test]
fn test_alphanumeric() { 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, assert_eq!(res, Ok(vec![0b00100000, 0b01011011, 0b00001011,
0b01111000, 0b11010001, 0b01110010, 0b01111000, 0b11010001, 0b01110010,
0b11011100, 0b01001101, 0b01000011, 0b11011100, 0b01001101, 0b01000011,
@ -805,15 +799,15 @@ mod encode_tests {
#[test] #[test]
fn test_auto_mode_switch() { 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, assert_eq!(res, Ok(vec![0b0_0011_000, 0b1111011_1, 0b001_00101,
0b0_00000__00, 0b11101100])); 0b0_00000__00, 0b11101100]));
} }
#[test] #[test]
fn test_too_long() { fn test_too_long() {
let res = encode(b">>>>>>>>", Version(1), H); let res = encode(b">>>>>>>>", Version::Normal(1), EcLevel::H);
assert_eq!(res, Err(DataTooLong)); assert_eq!(res, Err(QrError::DataTooLong));
} }
} }
@ -825,9 +819,9 @@ mod encode_tests {
/// the result. /// the result.
/// ///
/// This method will not consider any Micro QR code versions. /// 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>>(); 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 opt_segments = Optimizer::new(segments.iter().map(|s| *s), *version).collect::<Vec<Segment>>();
let total_len = total_encoded_len(&*opt_segments, *version); let total_len = total_encoded_len(&*opt_segments, *version);
let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).unwrap(); let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).unwrap();
@ -840,13 +834,13 @@ pub fn encode_auto(data: &[u8], ec_level: ErrorCorrectionLevel) -> QrResult<Bits
return Ok(bits); return Ok(bits);
} }
} }
Err(DataTooLong) Err(QrError::DataTooLong)
} }
/// Finds the smallest version (QR code only) that can store N bits of data /// Finds the smallest version (QR code only) that can store N bits of data
/// in the given error correction level. /// in the given error correction level.
#[unstable] #[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 min = 0u;
let mut max = 39u; let mut max = 39u;
while min < max { while min < max {
@ -857,42 +851,42 @@ fn find_min_version(length: uint, ec_level: ErrorCorrectionLevel) -> QrVersion {
max = half; max = half;
} }
} }
Version((min + 1) as i16) Version::Normal((min + 1) as i16)
} }
#[cfg(test)] #[cfg(test)]
mod encode_auto_tests { mod encode_auto_tests {
use bits::{find_min_version, encode_auto}; use bits::{find_min_version, encode_auto};
use types::{Version, L, Q, H}; use types::{Version, EcLevel};
#[test] #[test]
fn test_find_min_version() { fn test_find_min_version() {
assert_eq!(find_min_version(60, L), Version(1)); assert_eq!(find_min_version(60, EcLevel::L), Version::Normal(1));
assert_eq!(find_min_version(200, L), Version(2)); assert_eq!(find_min_version(200, EcLevel::L), Version::Normal(2));
assert_eq!(find_min_version(200, H), Version(3)); assert_eq!(find_min_version(200, EcLevel::H), Version::Normal(3));
assert_eq!(find_min_version(20000, L), Version(37)); assert_eq!(find_min_version(20000, EcLevel::L), Version::Normal(37));
assert_eq!(find_min_version(640, L), Version(4)); assert_eq!(find_min_version(640, EcLevel::L), Version::Normal(4));
assert_eq!(find_min_version(641, L), Version(5)); assert_eq!(find_min_version(641, EcLevel::L), Version::Normal(5));
assert_eq!(find_min_version(999999, H), Version(40)); assert_eq!(find_min_version(999999, EcLevel::H), Version::Normal(40));
} }
#[test] #[test]
fn test_alpha_q() { fn test_alpha_q() {
let bits = encode_auto(b"HELLO WORLD", Q).unwrap(); let bits = encode_auto(b"HELLO WORLD", EcLevel::Q).unwrap();
assert_eq!(bits.version(), Version(1)); assert_eq!(bits.version(), Version::Normal(1));
} }
#[test] #[test]
fn test_alpha_h() { fn test_alpha_h() {
let bits = encode_auto(b"HELLO WORLD", H).unwrap(); let bits = encode_auto(b"HELLO WORLD", EcLevel::H).unwrap();
assert_eq!(bits.version(), Version(2)); assert_eq!(bits.version(), Version::Normal(2));
} }
#[test] #[test]
fn test_mixed() { fn test_mixed() {
let bits = encode_auto(b"This is a mixed data test. 1234567890", H).unwrap(); let bits = encode_auto(b"This is a mixed data test. 1234567890", EcLevel::H).unwrap();
assert_eq!(bits.version(), Version(4)); assert_eq!(bits.version(), Version::Normal(4));
} }
} }

View file

@ -1,12 +1,12 @@
//! The `canvas` module puts raw bits into the QR code canvas. //! The `canvas` module puts raw bits into the QR code canvas.
//! //!
//! use qrcode::types::{Version, L}; //! use qrcode::types::{Version, EcLevel};
//! use qrcode::canvas::{Canvas, Checkerboard}; //! 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_all_functional_patterns();
//! c.draw_data(b"data_here", b"ec_code_here"); //! c.draw_data(b"data_here", b"ec_code_here");
//! c.apply_mask(Checkerboard); //! c.apply_mask(MaskPattern::Checkerboard);
//! let bools = c.to_bools(); //! let bools = c.to_bools();
use std::iter::range_inclusive; use std::iter::range_inclusive;
@ -14,7 +14,7 @@ use std::iter::order::equals;
use std::num::Int; use std::num::Int;
use std::cmp::max; use std::cmp::max;
use types::{QrVersion, Version, MicroVersion, ErrorCorrectionLevel, L, M, Q}; use types::{Version, EcLevel};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Modules //{{{ Modules
@ -46,27 +46,27 @@ impl Module {
/// Checks whether a module is dark. /// Checks whether a module is dark.
pub fn is_dark(&self) -> bool { pub fn is_dark(&self) -> bool {
match *self { match *self {
Dark | DarkUnmasked => true, Module::Dark | Module::DarkUnmasked => true,
_ => false, _ => false,
} }
} }
/// Apply a mask to the unmasked modules. /// 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!(Module::LightUnmasked.mask(true), Module::Dark);
/// assert_eq!(DarkUnmasked.mask(true), Light); /// assert_eq!(Module::DarkUnmasked.mask(true), Module::Light);
/// assert_eq!(LightUnmasked.mask(false), Light); /// assert_eq!(Module::LightUnmasked.mask(false), Module::Light);
/// assert_eq!(Dark.mask(true), Dark); /// assert_eq!(Module::Dark.mask(true), Module::Dark);
/// assert_eq!(Dark.mask(false), Dark); /// assert_eq!(Module::Dark.mask(false), Module::Dark);
/// ///
pub fn mask(&self, should_invert: bool) -> Module { pub fn mask(&self, should_invert: bool) -> Module {
match (*self, should_invert) { match (*self, should_invert) {
(Empty, true) | (LightUnmasked, true) => Dark, (Module::Empty, true) | (Module::LightUnmasked, true) => Module::Dark,
(Empty, false) | (LightUnmasked, false) => Light, (Module::Empty, false) | (Module::LightUnmasked, false) => Module::Light,
(DarkUnmasked, true) => Light, (Module::DarkUnmasked, true) => Module::Light,
(DarkUnmasked, false) => Dark, (Module::DarkUnmasked, false) => Module::Dark,
(a, _) => a, (a, _) => a,
} }
} }
@ -84,10 +84,10 @@ pub struct Canvas {
width: i16, width: i16,
/// The version of the QR code. /// The version of the QR code.
version: QrVersion, version: Version,
/// The error correction level of the QR code. /// 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 /// The modules of the QR code. Modules are arranged in left-to-right, then
/// top-to-bottom order. /// top-to-bottom order.
@ -96,13 +96,13 @@ pub struct Canvas {
impl Canvas { impl Canvas {
/// Constructs a new canvas big enough for a QR code of the given version. /// 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(); let width = version.width();
Canvas { Canvas {
width: width, width: width,
version: version, version: version,
ec_level: ec_level, 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'); res.push('\n');
for x in range(0, width) { for x in range(0, width) {
res.push(match self.get(x, y) { res.push(match self.get(x, y) {
Empty => '?', Module::Empty => '?',
Light => '.', Module::Light => '.',
Dark => '#', Module::Dark => '#',
LightUnmasked => '-', Module::LightUnmasked => '-',
DarkUnmasked => '*', Module::DarkUnmasked => '*',
}); });
} }
} }
@ -155,36 +155,36 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod basic_canvas_tests { mod basic_canvas_tests {
use canvas::{Canvas, Empty, Dark, Light, DarkUnmasked, LightUnmasked}; use canvas::{Canvas, Module};
use types::{Version, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_index() { 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(0, 4), Module::Empty);
assert_eq!(c.get(-1, -7), Empty); assert_eq!(c.get(-1, -7), Module::Empty);
assert_eq!(c.get(21-1, 21-7), Empty); assert_eq!(c.get(21-1, 21-7), Module::Empty);
c.put(0, 0, Dark); c.put(0, 0, Module::Dark);
c.put(-1, -7, Light); c.put(-1, -7, Module::Light);
assert_eq!(c.get(0, 0), Dark); assert_eq!(c.get(0, 0), Module::Dark);
assert_eq!(c.get(21-1, -7), Light); assert_eq!(c.get(21-1, -7), Module::Light);
assert_eq!(c.get(-1, 21-7), Light); assert_eq!(c.get(-1, 21-7), Module::Light);
} }
#[test] #[test]
fn test_debug_str() { 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 i in range(3i16, 20) {
for j in range(3i16, 20) { for j in range(3i16, 20) {
c.put(i, j, match ((i * 3) ^ j) % 5 { c.put(i, j, match ((i * 3) ^ j) % 5 {
0 => Empty, 0 => Module::Empty,
1 => Light, 1 => Module::Light,
2 => Dark, 2 => Module::Dark,
3 => LightUnmasked, 3 => Module::LightUnmasked,
4 => DarkUnmasked, 4 => Module::DarkUnmasked,
_ => panic!(), _ => panic!(),
}); });
} }
@ -227,10 +227,10 @@ impl Canvas {
for j in range_inclusive(dy_top, dy_bottom) { for j in range_inclusive(dy_top, dy_bottom) {
for i in range_inclusive(dx_left, dx_right) { for i in range_inclusive(dx_left, dx_right) {
self.put(x+i, y+j, match (i, j) { self.put(x+i, y+j, match (i, j) {
(4, _) | (_, 4) | (-4, _) | (_, -4) => Light, (4, _) | (_, 4) | (-4, _) | (_, -4) => Module::Light,
(3, _) | (_, 3) | (-3, _) | (_, -3) => Dark, (3, _) | (_, 3) | (-3, _) | (_, -3) => Module::Dark,
(2, _) | (_, 2) | (-2, _) | (_, -2) => Light, (2, _) | (_, 2) | (-2, _) | (_, -2) => Module::Light,
_ => Dark, _ => Module::Dark,
}); });
} }
} }
@ -245,8 +245,8 @@ impl Canvas {
self.draw_finder_pattern_at(3, 3); self.draw_finder_pattern_at(3, 3);
match self.version { match self.version {
MicroVersion(_) => { return; } Version::Micro(_) => { return; }
Version(_) => { Version::Normal(_) => {
self.draw_finder_pattern_at(-4, 3); self.draw_finder_pattern_at(-4, 3);
self.draw_finder_pattern_at(3, -4); self.draw_finder_pattern_at(3, -4);
} }
@ -257,11 +257,11 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod finder_pattern_tests { mod finder_pattern_tests {
use canvas::Canvas; use canvas::Canvas;
use types::{Version, MicroVersion, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_qr() { 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(); c.draw_finder_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#######.?????.#######\n\ #######.?????.#######\n\
@ -289,7 +289,7 @@ mod finder_pattern_tests {
#[test] #[test]
fn test_micro_qr() { 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(); c.draw_finder_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#######.???\n\ #######.???\n\
@ -313,14 +313,14 @@ mod finder_pattern_tests {
impl Canvas { impl Canvas {
/// Draws a alignment pattern with the center at (x, y). /// Draws a alignment pattern with the center at (x, y).
fn draw_alignment_pattern_at(&mut self, x: i16, y: i16) { 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; return;
} }
for j in range_inclusive(-2, 2) { for j in range_inclusive(-2, 2) {
for i in range_inclusive(-2, 2) { for i in range_inclusive(-2, 2) {
self.put(x+i, y+j, match (i, j) { self.put(x+i, y+j, match (i, j) {
(2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Dark, (2, _) | (_, 2) | (-2, _) | (_, -2) | (0, 0) => Module::Dark,
_ => Light, _ => Module::Light,
}); });
} }
} }
@ -332,9 +332,9 @@ impl Canvas {
/// to help the scanner create the square grid. /// to help the scanner create the square grid.
fn draw_alignment_patterns(&mut self) { fn draw_alignment_patterns(&mut self) {
match self.version { match self.version {
MicroVersion(_) | Version(1) => { return; } Version::Micro(_) | Version::Normal(1) => { return; }
Version(2...6) => self.draw_alignment_pattern_at(-7, -7), Version::Normal(2...6) => self.draw_alignment_pattern_at(-7, -7),
Version(a) => { Version::Normal(a) => {
let positions = ALIGNMENT_PATTERN_POSITIONS[a as uint - 7]; let positions = ALIGNMENT_PATTERN_POSITIONS[a as uint - 7];
for x in positions.iter() { for x in positions.iter() {
for y in positions.iter() { for y in positions.iter() {
@ -349,11 +349,11 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod alignment_pattern_tests { mod alignment_pattern_tests {
use canvas::Canvas; use canvas::Canvas;
use types::{Version, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_draw_alignment_patterns_1() { 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_finder_patterns();
c.draw_alignment_patterns(); c.draw_alignment_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
@ -382,7 +382,7 @@ mod alignment_pattern_tests {
#[test] #[test]
fn test_draw_alignment_patterns_3() { 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_finder_patterns();
c.draw_alignment_patterns(); c.draw_alignment_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
@ -419,7 +419,7 @@ mod alignment_pattern_tests {
#[test] #[test]
fn test_draw_alignment_patterns_7() { 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_finder_patterns();
c.draw_alignment_patterns(); c.draw_alignment_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
@ -550,22 +550,22 @@ impl Canvas {
fn draw_timing_patterns(&mut self) { fn draw_timing_patterns(&mut self) {
let width = self.width; let width = self.width;
let (y, x1, x2) = match self.version { let (y, x1, x2) = match self.version {
MicroVersion(_) => (0, 8, width-1), Version::Micro(_) => (0, 8, width-1),
Version(_) => (6, 8, width-9), Version::Normal(_) => (6, 8, width-9),
}; };
self.draw_line(x1, y, x2, y, Dark, Light); self.draw_line(x1, y, x2, y, Module::Dark, Module::Light);
self.draw_line(y, x1, y, x2, Dark, Light); self.draw_line(y, x1, y, x2, Module::Dark, Module::Light);
} }
} }
#[cfg(test)] #[cfg(test)]
mod timing_pattern_tests { mod timing_pattern_tests {
use canvas::Canvas; use canvas::Canvas;
use types::{Version, MicroVersion, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_draw_timing_patterns_qr() { 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(); c.draw_timing_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
?????????????????????\n\ ?????????????????????\n\
@ -593,7 +593,7 @@ mod timing_pattern_tests {
#[test] #[test]
fn test_draw_timing_patterns_micro_qr() { 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(); c.draw_timing_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
????????#.#\n\ ????????#.#\n\
@ -636,13 +636,16 @@ impl Canvas {
/// Draws the format info patterns for an encoded number. /// Draws the format info patterns for an encoded number.
fn draw_format_info_patterns_with_number(&mut self, format_info: u16) { fn draw_format_info_patterns_with_number(&mut self, format_info: u16) {
match self.version { match self.version {
MicroVersion(_) => { Version::Micro(_) => {
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_MICRO_QR); self.draw_number(format_info, Module::Dark, Module::Light,
&FORMAT_INFO_COORDS_MICRO_QR);
} }
Version(_) => { Version::Normal(_) => {
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_QR_MAIN); self.draw_number(format_info, Module::Dark, Module::Light,
self.draw_number(format_info, Dark, Light, FORMAT_INFO_COORDS_QR_SIDE); &FORMAT_INFO_COORDS_QR_MAIN);
self.put(8, -8, Dark); // Dark module. 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. /// Draws the version information patterns.
fn draw_version_info_patterns(&mut self) { fn draw_version_info_patterns(&mut self) {
match self.version { match self.version {
MicroVersion(_) | Version(1...6) => { return; } Version::Micro(_) | Version::Normal(1...6) => { return; }
Version(a) => { Version::Normal(a) => {
let version_info = VERSION_INFOS[(a - 7) as uint] << 14; 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, Module::Dark, Module::Light,
self.draw_number(version_info, Dark, Light, VERSION_INFO_COORDS_TR); &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)] #[cfg(test)]
mod draw_version_info_tests { mod draw_version_info_tests {
use canvas::{Canvas, Light, Dark}; use canvas::{Canvas, Module};
use types::{MicroVersion, Version, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_draw_number() { fn test_draw_number() {
let mut c = Canvas::new(MicroVersion(1), L); let mut c = Canvas::new(Version::Micro(1), EcLevel::L);
c.draw_number(0b10101101u8, Dark, Light, [(0,0), (0,-1), (-2,-2), (-2,0)]); c.draw_number(0b10101101u8, Module::Dark, Module::Light,
&[(0,0), (0,-1), (-2,-2), (-2,0)]);
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#????????.?\n\ #????????.?\n\
???????????\n\ ???????????\n\
@ -690,7 +696,7 @@ mod draw_version_info_tests {
#[test] #[test]
fn test_draw_version_info_1() { 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(); c.draw_version_info_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
?????????????????????\n\ ?????????????????????\n\
@ -718,7 +724,7 @@ mod draw_version_info_tests {
#[test] #[test]
fn test_draw_version_info_7() { 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(); c.draw_version_info_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
@ -771,7 +777,7 @@ mod draw_version_info_tests {
#[test] #[test]
fn test_draw_reserved_format_info_patterns_qr() { 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(); c.draw_reserved_format_info_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
????????.????????????\n\ ????????.????????????\n\
@ -799,7 +805,7 @@ mod draw_version_info_tests {
#[test] #[test]
fn test_draw_reserved_format_info_patterns_micro_qr() { 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(); c.draw_reserved_format_info_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
???????????\n\ ???????????\n\
@ -881,11 +887,11 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod all_functional_patterns_tests { mod all_functional_patterns_tests {
use canvas::Canvas; use canvas::Canvas;
use types::{Version, MicroVersion, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_all_functional_patterns_qr() { 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(); c.draw_all_functional_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#######..????????.#######\n\ #######..????????.#######\n\
@ -917,7 +923,7 @@ mod all_functional_patterns_tests {
#[test] #[test]
fn test_all_functional_patterns_micro_qr() { 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(); c.draw_all_functional_patterns();
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#######.#.#\n\ #######.#.#\n\
@ -946,15 +952,15 @@ struct DataModuleIter {
} }
impl DataModuleIter { impl DataModuleIter {
fn new(version: QrVersion) -> DataModuleIter { fn new(version: Version) -> DataModuleIter {
let width = version.width(); let width = version.width();
DataModuleIter { DataModuleIter {
x: width - 1, x: width - 1,
y: width - 1, y: width - 1,
width: width, width: width,
timing_pattern_column: match version { timing_pattern_column: match version {
MicroVersion(_) => 0, Version::Micro(_) => 0,
Version(_) => 6, Version::Normal(_) => 6,
} }
} }
} }
@ -998,11 +1004,11 @@ impl Iterator<(i16, i16)> for DataModuleIter {
#[cfg(test)] #[cfg(test)]
mod data_iter_tests { mod data_iter_tests {
use canvas::DataModuleIter; use canvas::DataModuleIter;
use types::{Version, MicroVersion}; use types::Version;
#[test] #[test]
fn test_qr() { 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![ assert_eq!(res, vec![
(20, 20), (19, 20), (20, 19), (19, 19), (20, 18), (19, 18), (20, 20), (19, 20), (20, 19), (19, 19), (20, 18), (19, 18),
(20, 17), (19, 17), (20, 16), (19, 16), (20, 15), (19, 15), (20, 17), (19, 17), (20, 16), (19, 16), (20, 15), (19, 15),
@ -1088,7 +1094,7 @@ mod data_iter_tests {
#[test] #[test]
fn test_micro_qr() { 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![ assert_eq!(res, vec![
(10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8), (10, 10), (9, 10), (10, 9), (9, 9), (10, 8), (9, 8),
(10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5), (10, 7), (9, 7), (10, 6), (9, 6), (10, 5), (9, 5),
@ -1119,7 +1125,7 @@ mod data_iter_tests {
#[test] #[test]
fn test_micro_qr_2() { 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![ assert_eq!(res, vec![
(12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10), (12, 12), (11, 12), (12, 11), (11, 11), (12, 10), (11, 10),
(12, 9), (11, 9), (12, 8), (11, 8), (12, 7), (11, 7), (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 }; let bits_end = if i == last_word { 4 } else { 0 };
'outside: 'outside:
for j in range_inclusive(bits_end, 7u).rev() { 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() { while let Some((x, y)) = coords.next() {
let r = self.get_mut(x, y); let r = self.get_mut(x, y);
if *r == Empty { if *r == Module::Empty {
*r = color; *r = color;
continue 'outside; continue 'outside;
} }
@ -1193,7 +1203,7 @@ impl Canvas {
/// Draws the encoded data and error correction codes to the empty modules. /// Draws the encoded data and error correction codes to the empty modules.
pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) { pub fn draw_data(&mut self, data: &[u8], ec: &[u8]) {
let is_half_codeword_at_end = match (self.version, self.ec_level) { 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, _ => false,
}; };
@ -1206,11 +1216,11 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod draw_codewords_test { mod draw_codewords_test {
use canvas::Canvas; use canvas::Canvas;
use types::{Version, MicroVersion, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_micro_qr_1() { 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_all_functional_patterns();
c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63"); c.draw_data(b"\x6e\x5d\xe2", b"\x2b\x63");
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
@ -1229,7 +1239,7 @@ mod draw_codewords_test {
#[test] #[test]
fn test_qr_2() { 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_all_functional_patterns();
c.draw_data(b"\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$\x92I$", b""); 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\ assert_eq!(&*c.to_debug_str(), "\n\
@ -1306,14 +1316,14 @@ mod mask_functions {
fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool { fn get_mask_function(pattern: MaskPattern) -> fn(i16, i16) -> bool {
match pattern { match pattern {
Checkerboard => mask_functions::checkerboard, MaskPattern::Checkerboard => mask_functions::checkerboard,
HorizontalLines => mask_functions::horizontal_lines, MaskPattern::HorizontalLines => mask_functions::horizontal_lines,
VerticalLines => mask_functions::vertical_lines, MaskPattern::VerticalLines => mask_functions::vertical_lines,
DiagonalLines => mask_functions::diagonal_lines, MaskPattern::DiagonalLines => mask_functions::diagonal_lines,
LargeCheckerboard => mask_functions::large_checkerboard, MaskPattern::LargeCheckerboard => mask_functions::large_checkerboard,
Fields => mask_functions::fields, MaskPattern::Fields => mask_functions::fields,
Diamonds => mask_functions::diamonds, MaskPattern::Diamonds => mask_functions::diamonds,
Meadow => mask_functions::meadow, MaskPattern::Meadow => mask_functions::meadow,
} }
} }
@ -1339,27 +1349,27 @@ impl Canvas {
/// current QR code version, this method will fail. /// current QR code version, this method will fail.
fn draw_format_info_patterns(&mut self, pattern: MaskPattern) { fn draw_format_info_patterns(&mut self, pattern: MaskPattern) {
let format_number = match self.version { let format_number = match self.version {
Version(_) => { Version::Normal(_) => {
let simple_format_number = ((self.ec_level as uint) ^ 1) << 3 | (pattern as uint); let simple_format_number = ((self.ec_level as uint) ^ 1) << 3 | (pattern as uint);
FORMAT_INFOS_QR[simple_format_number] FORMAT_INFOS_QR[simple_format_number]
} }
MicroVersion(a) => { Version::Micro(a) => {
let micro_pattern_number = match pattern { let micro_pattern_number = match pattern {
HorizontalLines => 0b00, MaskPattern::HorizontalLines => 0b00,
LargeCheckerboard => 0b01, MaskPattern::LargeCheckerboard => 0b01,
Diamonds => 0b10, MaskPattern::Diamonds => 0b10,
Meadow => 0b11, MaskPattern::Meadow => 0b11,
_ => panic!("Unsupported mask pattern in Micro QR code"), _ => panic!("Unsupported mask pattern in Micro QR code"),
}; };
let symbol_number = match (a, self.ec_level) { let symbol_number = match (a, self.ec_level) {
(1, L) => 0b000, (1, EcLevel::L) => 0b000,
(2, L) => 0b001, (2, EcLevel::L) => 0b001,
(2, M) => 0b010, (2, EcLevel::M) => 0b010,
(3, L) => 0b011, (3, EcLevel::L) => 0b011,
(3, M) => 0b100, (3, EcLevel::M) => 0b100,
(4, L) => 0b101, (4, EcLevel::L) => 0b101,
(4, M) => 0b110, (4, EcLevel::M) => 0b110,
(4, Q) => 0b111, (4, EcLevel::Q) => 0b111,
_ => panic!("Unsupported version/ec_level combination in Micro QR code"), _ => panic!("Unsupported version/ec_level combination in Micro QR code"),
}; };
let simple_format_number = symbol_number << 2 | micro_pattern_number; let simple_format_number = symbol_number << 2 | micro_pattern_number;
@ -1372,14 +1382,14 @@ impl Canvas {
#[cfg(test)] #[cfg(test)]
mod mask_tests { mod mask_tests {
use canvas::{Canvas, Checkerboard, LargeCheckerboard}; use canvas::{Canvas, MaskPattern};
use types::{Version, MicroVersion, L}; use types::{Version, EcLevel};
#[test] #[test]
fn test_apply_mask_qr() { 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.draw_all_functional_patterns();
c.apply_mask(Checkerboard); c.apply_mask(MaskPattern::Checkerboard);
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
#######...#.#.#######\n\ #######...#.#.#######\n\
@ -1407,8 +1417,8 @@ mod mask_tests {
#[test] #[test]
fn test_draw_format_info_patterns_qr() { fn test_draw_format_info_patterns_qr() {
let mut c = Canvas::new(Version(1), L); let mut c = Canvas::new(Version::Normal(1), EcLevel::L);
c.draw_format_info_patterns(LargeCheckerboard); c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
????????#????????????\n\ ????????#????????????\n\
????????#????????????\n\ ????????#????????????\n\
@ -1435,8 +1445,8 @@ mod mask_tests {
#[test] #[test]
fn test_draw_format_info_patterns_micro_qr() { fn test_draw_format_info_patterns_micro_qr() {
let mut c = Canvas::new(MicroVersion(2), L); let mut c = Canvas::new(Version::Micro(2), EcLevel::L);
c.draw_format_info_patterns(LargeCheckerboard); c.draw_format_info_patterns(MaskPattern::LargeCheckerboard);
assert_eq!(&*c.to_debug_str(), "\n\ assert_eq!(&*c.to_debug_str(), "\n\
?????????????\n\ ?????????????\n\
????????#????\n\ ????????#????\n\
@ -1488,9 +1498,9 @@ impl Canvas {
|j| self.get(i, j) |j| self.get(i, j)
}; };
let mut colors = range(0, self.width).map(map_fn).chain(Some(Empty).into_iter()); let mut colors = range(0, self.width).map(map_fn)
.chain(Some(Module::Empty).into_iter());
let mut last_color = Empty; let mut last_color = Module::Empty;
let mut consecutive_len = 1u16; let mut consecutive_len = 1u16;
for color in colors { for color in colors {
@ -1538,7 +1548,10 @@ impl Canvas {
/// Every pattern that looks like `#.###.#....` in any orientation will add /// Every pattern that looks like `#.###.#....` in any orientation will add
/// 40 points. /// 40 points.
fn compute_finder_penalty_score(&self, is_horizontal: bool) -> u16 { 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; let mut total_score = 0;
@ -1602,7 +1615,7 @@ impl Canvas {
fn compute_total_penalty_scores(&self) -> u16 { fn compute_total_penalty_scores(&self) -> u16 {
match self.version { match self.version {
Version(_) => { Version::Normal(_) => {
let s1a = self.compute_adjacent_penalty_score(true); let s1a = self.compute_adjacent_penalty_score(true);
let s1b = self.compute_adjacent_penalty_score(false); let s1b = self.compute_adjacent_penalty_score(false);
let s2 = self.compute_block_penalty_score(); let s2 = self.compute_block_penalty_score();
@ -1611,22 +1624,22 @@ impl Canvas {
let s4 = self.compute_balance_penalty_score(); let s4 = self.compute_balance_penalty_score();
s1a + s1b + s2 + s3a + s3b + s4 s1a + s1b + s2 + s3a + s3b + s4
} }
MicroVersion(_) => self.compute_light_side_penalty_score(), Version::Micro(_) => self.compute_light_side_penalty_score(),
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod penalty_tests { mod penalty_tests {
use canvas::{Canvas, Checkerboard, Module, Light, Dark}; use canvas::{Canvas, MaskPattern, Module};
use types::{Version, MicroVersion, Q}; use types::{Version, EcLevel};
fn create_test_canvas() -> Canvas { 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_all_functional_patterns();
c.draw_data(b"\x20\x5b\x0b\x78\xd1\x72\xdc\x4d\x43\x40\xec\x11\x00", 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"); b"\xa8\x48\x16\x52\xd9\x36\x9c\x00\x2e\x0f\xb4\x7a\x10");
c.apply_mask(Checkerboard); c.apply_mask(MaskPattern::Checkerboard);
c c
} }
@ -1686,15 +1699,21 @@ mod penalty_tests {
#[test] #[test]
fn test_penalty_score_light_sides() { fn test_penalty_score_light_sides() {
static HORIZONTAL_SIDE: [Module, ..17] = [ static HORIZONTAL_SIDE: [Module, ..17] = [
Dark, Light, Light, Dark, Dark, Dark, Light, Light, Module::Dark, Module::Light, Module::Light, Module::Dark,
Dark, Light, Dark, Light, Light, Dark, Light, Light, Light 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] = [ static VERTICAL_SIDE: [Module, ..17] = [
Dark, Dark, Dark, Light, Light, Dark, Dark, Light, Module::Dark, Module::Dark, Module::Dark, Module::Light,
Dark, Light, Dark, Light, Dark, Light, Light, Dark, 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) { for i in range(0, 17) {
c.put(i, -1, HORIZONTAL_SIDE[i as uint]); c.put(i, -1, HORIZONTAL_SIDE[i as uint]);
c.put(-1, i, VERTICAL_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 //{{{ Select mask with lowest penalty score
static ALL_PATTERNS_QR: [MaskPattern, ..8] = [ static ALL_PATTERNS_QR: [MaskPattern, ..8] = [
Checkerboard, HorizontalLines, VerticalLines, DiagonalLines, MaskPattern::Checkerboard, MaskPattern::HorizontalLines,
LargeCheckerboard, Fields, Diamonds, Meadow MaskPattern::VerticalLines, MaskPattern::DiagonalLines,
MaskPattern::LargeCheckerboard, MaskPattern::Fields,
MaskPattern::Diamonds, MaskPattern::Meadow,
]; ];
static ALL_PATTERNS_MICRO_QR: [MaskPattern, ..4] = [ static ALL_PATTERNS_MICRO_QR: [MaskPattern, ..4] = [
HorizontalLines, LargeCheckerboard, Diamonds, Meadow MaskPattern::HorizontalLines, MaskPattern::LargeCheckerboard,
MaskPattern::Diamonds, MaskPattern::Meadow,
]; ];
impl Canvas { impl Canvas {
@ -1722,8 +1744,8 @@ impl Canvas {
/// penalty score. /// penalty score.
pub fn apply_best_mask(&self) -> Canvas { pub fn apply_best_mask(&self) -> Canvas {
let patterns = match self.version { let patterns = match self.version {
Version(_) => ALL_PATTERNS_QR.iter(), Version::Normal(_) => ALL_PATTERNS_QR.iter(),
MicroVersion(_) => ALL_PATTERNS_MICRO_QR.iter(), Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
}; };
patterns.map(|ptn| { patterns.map(|ptn| {

View file

@ -1,6 +1,6 @@
//! The `ec` module applies the Reed-Solomon error correction codes. //! The `ec` module applies the Reed-Solomon error correction codes.
use types::{QrResult, QrVersion, ErrorCorrectionLevel}; use types::{QrResult, Version, EcLevel};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Error correction primitive //{{{ Error correction primitive
@ -96,8 +96,8 @@ fn test_interleave() {
/// Constructs data and error correction codewords ready to be put in the QR /// Constructs data and error correction codewords ready to be put in the QR
/// code matrix. /// code matrix.
pub fn construct_codewords(rawbits: &[u8], pub fn construct_codewords(rawbits: &[u8],
version: QrVersion, version: Version,
ec_level: ErrorCorrectionLevel) -> QrResult<(Vec<u8>, Vec<u8>)> { ec_level: EcLevel) -> QrResult<(Vec<u8>, Vec<u8>)> {
let (block_1_size, block_1_count, block_2_size, block_2_count) = let (block_1_size, block_1_count, block_2_size, block_2_count) =
try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK)); try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK));
@ -129,12 +129,12 @@ pub fn construct_codewords(rawbits: &[u8],
#[cfg(test)] #[cfg(test)]
mod construct_codewords_test { mod construct_codewords_test {
use ec::construct_codewords; use ec::construct_codewords;
use types::{Version, M, Q}; use types::{Version, EcLevel};
#[test] #[test]
fn test_add_ec_simple() { fn test_add_ec_simple() {
let msg = b" [\x0bx\xd1r\xdcMC@\xec\x11\xec\x11\xec\x11"; 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!(&*blocks_vec, msg);
assert_eq!(&*ec_vec, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17"); assert_eq!(&*ec_vec, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17");
} }
@ -142,7 +142,7 @@ mod construct_codewords_test {
#[test] #[test]
fn test_add_ec_complex() { 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 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, 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"); 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, assert_eq!(&*ec_vec,

View file

@ -24,8 +24,7 @@
extern crate test; extern crate test;
pub use types::{QrResult, ErrorCorrectionLevel, L, M, Q, H, pub use types::{QrResult, EcLevel, Version};
QrVersion, Version, MicroVersion};
pub mod types; pub mod types;
pub mod bits; pub mod bits;
@ -37,8 +36,8 @@ pub mod canvas;
#[deriving(Clone)] #[deriving(Clone)]
pub struct QrCode { pub struct QrCode {
content: Vec<bool>, content: Vec<bool>,
version: QrVersion, version: Version,
ec_level: ErrorCorrectionLevel, ec_level: EcLevel,
width: uint, width: uint,
} }
@ -53,7 +52,7 @@ impl QrCode {
/// let code = QrCode::new(b"Some data").unwrap(); /// let code = QrCode::new(b"Some data").unwrap();
/// ///
pub fn new(data: &[u8]) -> QrResult<QrCode> { 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 /// 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. /// 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)); let bits = try!(bits::encode_auto(data, ec_level));
QrCode::with_bits(bits, 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 /// Constructs a new QR code for the given version and error correction
/// level. /// 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. /// 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], pub fn with_version(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<QrCode> {
version: QrVersion,
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
let mut bits = bits::Bits::new(version); let mut bits = bits::Bits::new(version);
try!(bits.push_optimal_data(data)); try!(bits.push_optimal_data(data));
try!(bits.push_terminator(ec_level)); try!(bits.push_terminator(ec_level));
@ -103,25 +100,24 @@ impl QrCode {
/// ///
/// See the `Bits` structure for detail. /// 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; /// 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_eci_designator(9);
/// bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR"); /// bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR");
/// bits.push_terminator(L); /// bits.push_terminator(EcLevel::L);
/// let qrcode = QrCode::with_bits(bits, L); /// let qrcode = QrCode::with_bits(bits, EcLevel::L);
/// ///
pub fn with_bits(bits: bits::Bits, pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<QrCode> {
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
let version = bits.version(); let version = bits.version();
let data = bits.into_bytes(); let data = bits.into_bytes();
let (encoded_data, ec_data) = try!(ec::construct_codewords(data[], version, ec_level)); let (encoded_data, ec_data) = try!(ec::construct_codewords(data[], version, ec_level));
let mut canvas = canvas::Canvas::new(version, ec_level); let mut canvas = canvas::Canvas::new(version, ec_level);
canvas.draw_all_functional_patterns(); 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(); let canvas = canvas.apply_best_mask();
Ok(QrCode { Ok(QrCode {
content: canvas.to_bools(), content: canvas.to_bools(),
@ -132,12 +128,12 @@ impl QrCode {
} }
/// Gets the version of this QR code. /// Gets the version of this QR code.
pub fn version(&self) -> QrVersion { pub fn version(&self) -> Version {
self.version self.version
} }
/// Gets the error correction level of this QR code. /// 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 self.ec_level
} }
@ -186,12 +182,12 @@ impl Index<(uint, uint), bool> for QrCode {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use {QrCode, Version, MicroVersion, L, M}; use {QrCode, Version, EcLevel};
#[test] #[test]
fn test_annex_i_qr() { fn test_annex_i_qr() {
// This uses the ISO Annex I as test vector. // 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\ assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######..#.##.#######\n\ #######..#.##.#######\n\
#.....#..####.#.....#\n\ #.....#..####.#.....#\n\
@ -218,7 +214,7 @@ mod tests {
#[test] #[test]
fn test_annex_i_micro_qr() { 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\ assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######.#.#.#\n\ #######.#.#.#\n\
#.....#.###.#\n\ #.....#.###.#\n\

View file

@ -7,7 +7,7 @@ use std::slice::Items;
#[cfg(test)] #[cfg(test)]
use test::Bencher; use test::Bencher;
use types::{Mode, QrVersion, Numeric, Alphanumeric, Byte, Kanji}; use types::{Mode, Version};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Segment //{{{ Segment
@ -28,9 +28,9 @@ pub struct Segment {
impl Segment { impl Segment {
/// Compute the number of bits (including the size of the mode indicator and /// Compute the number of bits (including the size of the mode indicator and
/// length bits) when this segment is encoded. /// 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 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 mode_bits_count = version.mode_bits_count();
let length_bits_count = self.mode.length_bits_count(version); let length_bits_count = self.mode.length_bits_count(version);
@ -47,7 +47,9 @@ impl Segment {
/// This iterator is basically equivalent to /// This iterator is basically equivalent to
/// ///
/// ```ignore /// ```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. /// But the type is too hard to write, thus the new type.
@ -58,8 +60,8 @@ struct EcsIter<I> {
ended: bool, ended: bool,
} }
impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIter<I> { impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclCharSet)> for EcsIter<I> {
fn next(&mut self) -> Option<(uint, ExclusiveCharacterSet)> { fn next(&mut self) -> Option<(uint, ExclCharSet)> {
if self.ended { if self.ended {
return None; return None;
} }
@ -67,12 +69,12 @@ impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIte
match self.base.next() { match self.base.next() {
None => { None => {
self.ended = true; self.ended = true;
Some((self.index, EEnd)) Some((self.index, ExclCharSet::End))
} }
Some(c) => { Some(c) => {
let old_index = self.index; let old_index = self.index;
self.index += 1; 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. /// QR code data parser to classify the input into distinct segments.
pub struct Parser<'a> { pub struct Parser<'a> {
ecs_iter: EcsIter<Items<'a, u8>>, ecs_iter: EcsIter<Items<'a, u8>>,
state: SegmentParseState, state: State,
begin: uint, begin: uint,
pending_single_byte: bool, pending_single_byte: bool,
} }
@ -101,7 +103,7 @@ impl<'a> Parser<'a> {
pub fn new(data: &[u8]) -> Parser { pub fn new(data: &[u8]) -> Parser {
Parser { Parser {
ecs_iter: EcsIter { base: data.iter(), index: 0, ended: false }, ecs_iter: EcsIter { base: data.iter(), index: 0, ended: false },
state: SInit, state: State::Init,
begin: 0, begin: 0,
pending_single_byte: false, pending_single_byte: false,
} }
@ -113,7 +115,11 @@ impl<'a> Iterator<Segment> for Parser<'a> {
if self.pending_single_byte { if self.pending_single_byte {
self.pending_single_byte = false; self.pending_single_byte = false;
self.begin += 1; 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 { loop {
@ -126,25 +132,33 @@ impl<'a> Iterator<Segment> for Parser<'a> {
let old_begin = self.begin; let old_begin = self.begin;
let push_mode = match action { let push_mode = match action {
AIdle => { continue; } Action::Idle => { continue; }
ANumeric => Numeric, Action::Numeric => Mode::Numeric,
AAlpha => Alphanumeric, Action::Alpha => Mode::Alphanumeric,
AByte => Byte, Action::Byte => Mode::Byte,
AKanji => Kanji, Action::Kanji => Mode::Kanji,
AKanjiAndSingleByte => { Action::KanjiAndSingleByte => {
let next_begin = i - 1; let next_begin = i - 1;
if self.begin == next_begin { if self.begin == next_begin {
Byte Mode::Byte
} else { } else {
self.pending_single_byte = true; self.pending_single_byte = true;
self.begin = next_begin; 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; 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)] #[cfg(test)]
mod parse_tests { mod parse_tests {
use optimize::{Parser, Segment}; use optimize::{Parser, Segment};
use types::{Numeric, Alphanumeric, Byte, Kanji}; use types::Mode;
fn parse(data: &[u8]) -> Vec<Segment> { fn parse(data: &[u8]) -> Vec<Segment> {
Parser::new(data).collect() Parser::new(data).collect()
@ -161,39 +175,39 @@ mod parse_tests {
#[test] #[test]
fn test_parse_1() { fn test_parse_1() {
let segs = parse(b"01049123451234591597033130128%10ABC123"); let segs = parse(b"01049123451234591597033130128%10ABC123");
assert_eq!(segs, vec![Segment { mode: Numeric, begin: 0, end: 29 }, assert_eq!(segs, vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 30 }, Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 },
Segment { mode: Numeric, begin: 30, end: 32 }, Segment { mode: Mode::Numeric, begin: 30, end: 32 },
Segment { mode: Alphanumeric, begin: 32, end: 35 }, Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 },
Segment { mode: Numeric, begin: 35, end: 38 }]); Segment { mode: Mode::Numeric, begin: 35, end: 38 }]);
} }
#[test] #[test]
fn test_parse_shift_jis_example_1() { fn test_parse_shift_jis_example_1() {
let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ" let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ"
assert_eq!(segs, vec![Segment { mode: Kanji, begin: 0, end: 4 }, assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Alphanumeric, begin: 4, end: 5 }, Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 },
Segment { mode: Byte, begin: 5, end: 6 }, Segment { mode: Mode::Byte, begin: 5, end: 6 },
Segment { mode: Kanji, begin: 6, end: 8 }]); Segment { mode: Mode::Kanji, begin: 6, end: 8 }]);
} }
#[test] #[test]
fn test_parse_utf_8() { fn test_parse_utf_8() {
// Mojibake? // Mojibake?
let segs = parse(b"\xe3\x81\x82\xe3\x80\x81A\xef\xbd\xb1\xe2\x84\xab"); 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 }, assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Byte, begin: 4, end: 5 }, Segment { mode: Mode::Byte, begin: 4, end: 5 },
Segment { mode: Kanji, begin: 5, end: 7 }, Segment { mode: Mode::Kanji, begin: 5, end: 7 },
Segment { mode: Byte, begin: 7, end: 10 }, Segment { mode: Mode::Byte, begin: 7, end: 10 },
Segment { mode: Kanji, begin: 10, end: 12 }, Segment { mode: Mode::Kanji, begin: 10, end: 12 },
Segment { mode: Byte, begin: 12, end: 13 }]); Segment { mode: Mode::Byte, begin: 12, end: 13 }]);
} }
#[test] #[test]
fn test_not_kanji_1() { fn test_not_kanji_1() {
let segs = parse(b"\x81\x30"); let segs = parse(b"\x81\x30");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 }, assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Numeric, begin: 1, end: 2 }]); Segment { mode: Mode::Numeric, begin: 1, end: 2 }]);
} }
#[test] #[test]
@ -201,22 +215,22 @@ mod parse_tests {
// Note that it's implementation detail that the byte seq is split into // Note that it's implementation detail that the byte seq is split into
// two. Perhaps adjust the test to check for this. // two. Perhaps adjust the test to check for this.
let segs = parse(b"\xeb\xc0"); let segs = parse(b"\xeb\xc0");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 }, assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Byte, begin: 1, end: 2 }]); Segment { mode: Mode::Byte, begin: 1, end: 2 }]);
} }
#[test] #[test]
fn test_not_kanji_3() { fn test_not_kanji_3() {
let segs = parse(b"\x81\x7f"); let segs = parse(b"\x81\x7f");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 }, assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Byte, begin: 1, end: 2 }]); Segment { mode: Mode::Byte, begin: 1, end: 2 }]);
} }
#[test] #[test]
fn test_not_kanji_4() { fn test_not_kanji_4() {
let segs = parse(b"\x81\x40\x81"); let segs = parse(b"\x81\x40\x81");
assert_eq!(segs, vec![Segment { mode: Kanji, begin: 0, end: 2 }, assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 2 },
Segment { mode: Byte, begin: 2, end: 3 }]); Segment { mode: Mode::Byte, begin: 2, end: 3 }]);
} }
} }
@ -228,7 +242,7 @@ pub struct Optimizer<I> {
parser: I, parser: I,
last_segment: Segment, last_segment: Segment,
last_segment_size: uint, last_segment_size: uint,
version: QrVersion, version: Version,
ended: bool, 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 /// left to right until the new segment is longer than before. This method
/// does *not* use Annex J from the ISO standard. /// 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() { match segments.next() {
None => Optimizer { None => Optimizer {
parser: segments, 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, last_segment_size: 0,
version: version, version: version,
ended: true, ended: true,
@ -260,7 +274,7 @@ impl<I: Iterator<Segment>> Optimizer<I> {
} }
impl<'a> Parser<'a> { 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) 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. /// 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; use std::iter::AdditiveIterator;
segments.iter().map(|seg| seg.encoded_len(version)).sum() 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)] #[cfg(test)]
mod optimize_tests { mod optimize_tests {
use optimize::{Optimizer, total_encoded_len, Segment}; 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 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); let new_len = total_encoded_len(&*opt_segs, version);
if given != opt_segs { if given != opt_segs {
assert!(prev_len > new_len, "{} > {}", prev_len, new_len); assert!(prev_len > new_len, "{} > {}", prev_len, new_len);
@ -329,14 +343,14 @@ mod optimize_tests {
fn test_example_1() { fn test_example_1() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Alphanumeric, begin: 0, end: 3 }, vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 3 },
Segment { mode: Numeric, begin: 3, end: 6 }, Segment { mode: Mode::Numeric, begin: 3, end: 6 },
Segment { mode: Byte, begin: 6, end: 10 }], Segment { mode: Mode::Byte, begin: 6, end: 10 }],
vec![Segment { mode: Alphanumeric, begin: 0, end: 6 }, vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 },
Segment { mode: Byte, begin: 6, end: 10 }], Segment { mode: Mode::Byte, begin: 6, end: 10 }],
Version(1) Version::Normal(1)
); );
} }
@ -345,16 +359,16 @@ mod optimize_tests {
fn test_example_2() { fn test_example_2() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 29 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 30 }, Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 },
Segment { mode: Numeric, begin: 30, end: 32 }, Segment { mode: Mode::Numeric, begin: 30, end: 32 },
Segment { mode: Alphanumeric, begin: 32, end: 35 }, Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 },
Segment { mode: Numeric, begin: 35, end: 38 }], Segment { mode: Mode::Numeric, begin: 35, end: 38 }],
vec![Segment { mode: Numeric, begin: 0, end: 29 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 38 }], Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }],
Version(9) Version::Normal(9)
); );
} }
@ -363,14 +377,14 @@ mod optimize_tests {
fn test_example_3() { fn test_example_3() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Kanji, begin: 0, end: 4 }, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Alphanumeric, begin: 4, end: 5 }, Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 },
Segment { mode: Byte, begin: 5, end: 6 }, Segment { mode: Mode::Byte, begin: 5, end: 6 },
Segment { mode: Kanji, begin: 6, end: 8 }], 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() { fn test_example_4() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Kanji, begin: 0, end: 10 }, vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
Segment { mode: Byte, begin: 10, end: 11 }], Segment { mode: Mode::Byte, begin: 10, end: 11 }],
vec![Segment { mode: Kanji, begin: 0, end: 10 }, vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
Segment { mode: Byte, begin: 10, end: 11 }], 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() { fn test_annex_j_guideline_1a() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 3 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }], Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Numeric, begin: 0, end: 3 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }], 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() { fn test_annex_j_guideline_1b() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 2 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 2 },
Segment { mode: Alphanumeric, begin: 2, end: 4 }], 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() { fn test_annex_j_guideline_1c() {
test_optimization_result( test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 3 }, vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }], 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"; 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(|| { 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 //{{{ 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 /// All values of `u8` can be split into 9 different character sets when
/// determining which encoding to use. This enum represents these groupings for /// determining which encoding to use. This enum represents these groupings for
/// parsing purpose. /// parsing purpose.
enum ExclusiveCharacterSet { enum ExclCharSet {
/// The end of string. /// The end of string.
EEnd = 0, End = 0,
/// All symbols supported by the Alphanumeric encoding, i.e. space, `$`, `%`, /// All symbols supported by the Alphanumeric encoding, i.e. space, `$`, `%`,
/// `*`, `+`, `-`, `.`, `/` and `:`. /// `*`, `+`, `-`, `.`, `/` and `:`.
ESymbol = 1, Symbol = 1,
/// All numbers (09). /// All numbers (09).
ENumeric = 2, Numeric = 2,
/// All uppercase letters (AZ). These characters may also appear in the /// All uppercase letters (AZ). These characters may also appear in the
/// second byte of a Shift JIS 2-byte encoding. /// 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 0x810x9f. /// The first byte of a Shift JIS 2-byte encoding, in the range 0x810x9f.
EKanjiHi1 = 4, KanjiHi1 = 4,
/// The first byte of a Shift JIS 2-byte encoding, in the range 0xe00xea. /// The first byte of a Shift JIS 2-byte encoding, in the range 0xe00xea.
EKanjiHi2 = 5, KanjiHi2 = 5,
/// The first byte of a Shift JIS 2-byte encoding, of value 0xeb. This is /// 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 /// different from the other two range that the second byte has a smaller
/// range. /// range.
EKanjiHi3 = 6, KanjiHi3 = 6,
/// The second byte of a Shift JIS 2-byte encoding, in the range 0x400xbf, /// The second byte of a Shift JIS 2-byte encoding, in the range 0x400xbf,
/// excluding letters (covered by `Alpha`), 0x810x9f (covered by `KanjiHi1`), /// excluding letters (covered by `Alpha`), 0x810x9f (covered by `KanjiHi1`),
/// and the invalid byte 0x7f. /// and the invalid byte 0x7f.
EKanjiLo1 = 7, KanjiLo1 = 7,
/// The second byte of a Shift JIS 2-byte encoding, in the range 0xc00xfc, /// The second byte of a Shift JIS 2-byte encoding, in the range 0xc00xfc,
/// excluding the range 0xe00xeb (covered by `KanjiHi2` and `KanjiHi3`). /// excluding the range 0xe00xeb (covered by `KanjiHi2` and `KanjiHi3`).
/// This half of byte-pair cannot appear as the second byte leaded by /// This half of byte-pair cannot appear as the second byte leaded by
/// `KanjiHi3`. /// `KanjiHi3`.
EKanjiLo2 = 8, KanjiLo2 = 8,
/// Any other values not covered by the above character sets. /// 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. /// Determines which character set a byte is in.
fn from_u8(c: u8) -> ExclusiveCharacterSet { fn from_u8(c: u8) -> ExclCharSet {
match c { match c {
0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ESymbol, 0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ExclCharSet::Symbol,
0x30 ... 0x39 => ENumeric, 0x30 ... 0x39 => ExclCharSet::Numeric,
0x41 ... 0x5a => EAlpha, 0x41 ... 0x5a => ExclCharSet::Alpha,
0x81 ... 0x9f => EKanjiHi1, 0x81 ... 0x9f => ExclCharSet::KanjiHi1,
0xe0 ... 0xea => EKanjiHi2, 0xe0 ... 0xea => ExclCharSet::KanjiHi2,
0xeb => EKanjiHi3, 0xeb => ExclCharSet::KanjiHi3,
0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => EKanjiLo1, 0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => ExclCharSet::KanjiLo1,
0xc0 ... 0xdf | 0xec ... 0xfc => EKanjiLo2, 0xc0 ... 0xdf | 0xec ... 0xfc => ExclCharSet::KanjiLo2,
_ => EByte _ => ExclCharSet::Byte
} }
} }
} }
/// The current parsing state. /// The current parsing state.
enum SegmentParseState { enum State {
/// Just initialized. /// Just initialized.
SInit = 0, Init = 0,
/// Inside a string that can be exclusively encoded as Numeric. /// Inside a string that can be exclusively encoded as Numeric.
SNumeric = 10, Numeric = 10,
/// Inside a string that can be exclusively encoded as Alphanumeric. /// 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. /// 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 /// Just encountered the first byte of a Shift JIS 2-byte sequence of the
/// set `KanjiHi1` or `KanjiHi2`. /// set `KanjiHi1` or `KanjiHi2`.
SKanjiHi12 = 40, KanjiHi12 = 40,
/// Just encountered the first byte of a Shift JIS 2-byte sequence of the /// Just encountered the first byte of a Shift JIS 2-byte sequence of the
/// set `KanjiHi3`. /// set `KanjiHi3`.
SKanjiHi3 = 50, KanjiHi3 = 50,
/// Inside a string that can be exclusively encoded as Kanji. /// Inside a string that can be exclusively encoded as Kanji.
SKanji = 60, Kanji = 60,
} }
/// What should the parser do after a state transition. /// What should the parser do after a state transition.
enum ParserAction { enum Action {
/// The parser should do nothing. /// The parser should do nothing.
AIdle, Idle,
/// Push the current segment as a Numeric string, and reset the marks. /// 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. /// 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. /// 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. /// 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 current segment excluding the last byte as a Kanji string, then
/// push the remaining single byte as a Byte string, and reset the marks. /// 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) // STATE_TRANSITION[current_state + next_character] == (next_state, what_to_do)
// Init state: // Init state:
(SInit, AIdle), // End (State::Init, Action::Idle), // End
(SAlpha, AIdle), // Symbol (State::Alpha, Action::Idle), // Symbol
(SNumeric, AIdle), // Numeric (State::Numeric, Action::Idle), // Numeric
(SAlpha, AIdle), // Alpha (State::Alpha, Action::Idle), // Alpha
(SKanjiHi12, AIdle), // KanjiHi1 (State::KanjiHi12, Action::Idle), // KanjiHi1
(SKanjiHi12, AIdle), // KanjiHi2 (State::KanjiHi12, Action::Idle), // KanjiHi2
(SKanjiHi3, AIdle), // KanjiHi3 (State::KanjiHi3, Action::Idle), // KanjiHi3
(SByte, AIdle), // KanjiLo1 (State::Byte, Action::Idle), // KanjiLo1
(SByte, AIdle), // KanjiLo2 (State::Byte, Action::Idle), // KanjiLo2
(SByte, AIdle), // Byte (State::Byte, Action::Idle), // Byte
// Numeric state: // Numeric state:
(SInit, ANumeric), // End (State::Init, Action::Numeric), // End
(SAlpha, ANumeric), // Symbol (State::Alpha, Action::Numeric), // Symbol
(SNumeric, AIdle), // Numeric (State::Numeric, Action::Idle), // Numeric
(SAlpha, ANumeric), // Alpha (State::Alpha, Action::Numeric), // Alpha
(SKanjiHi12, ANumeric), // KanjiHi1 (State::KanjiHi12, Action::Numeric), // KanjiHi1
(SKanjiHi12, ANumeric), // KanjiHi2 (State::KanjiHi12, Action::Numeric), // KanjiHi2
(SKanjiHi3, ANumeric), // KanjiHi3 (State::KanjiHi3, Action::Numeric), // KanjiHi3
(SByte, ANumeric), // KanjiLo1 (State::Byte, Action::Numeric), // KanjiLo1
(SByte, ANumeric), // KanjiLo2 (State::Byte, Action::Numeric), // KanjiLo2
(SByte, ANumeric), // Byte (State::Byte, Action::Numeric), // Byte
// Alpha state: // Alpha state:
(SInit, AAlpha), // End (State::Init, Action::Alpha), // End
(SAlpha, AIdle), // Symbol (State::Alpha, Action::Idle), // Symbol
(SNumeric, AAlpha), // Numeric (State::Numeric, Action::Alpha), // Numeric
(SAlpha, AIdle), // Alpha (State::Alpha, Action::Idle), // Alpha
(SKanjiHi12, AAlpha), // KanjiHi1 (State::KanjiHi12, Action::Alpha), // KanjiHi1
(SKanjiHi12, AAlpha), // KanjiHi2 (State::KanjiHi12, Action::Alpha), // KanjiHi2
(SKanjiHi3, AAlpha), // KanjiHi3 (State::KanjiHi3, Action::Alpha), // KanjiHi3
(SByte, AAlpha), // KanjiLo1 (State::Byte, Action::Alpha), // KanjiLo1
(SByte, AAlpha), // KanjiLo2 (State::Byte, Action::Alpha), // KanjiLo2
(SByte, AAlpha), // Byte (State::Byte, Action::Alpha), // Byte
// Byte state: // Byte state:
(SInit, AByte), // End (State::Init, Action::Byte), // End
(SAlpha, AByte), // Symbol (State::Alpha, Action::Byte), // Symbol
(SNumeric, AByte), // Numeric (State::Numeric, Action::Byte), // Numeric
(SAlpha, AByte), // Alpha (State::Alpha, Action::Byte), // Alpha
(SKanjiHi12, AByte), // KanjiHi1 (State::KanjiHi12, Action::Byte), // KanjiHi1
(SKanjiHi12, AByte), // KanjiHi2 (State::KanjiHi12, Action::Byte), // KanjiHi2
(SKanjiHi3, AByte), // KanjiHi3 (State::KanjiHi3, Action::Byte), // KanjiHi3
(SByte, AIdle), // KanjiLo1 (State::Byte, Action::Idle), // KanjiLo1
(SByte, AIdle), // KanjiLo2 (State::Byte, Action::Idle), // KanjiLo2
(SByte, AIdle), // Byte (State::Byte, Action::Idle), // Byte
// KanjiHi12 state: // KanjiHi12 state:
(SInit, AKanjiAndSingleByte), // End (State::Init, Action::KanjiAndSingleByte), // End
(SAlpha, AKanjiAndSingleByte), // Symbol (State::Alpha, Action::KanjiAndSingleByte), // Symbol
(SNumeric, AKanjiAndSingleByte), // Numeric (State::Numeric, Action::KanjiAndSingleByte), // Numeric
(SKanji, AIdle), // Alpha (State::Kanji, Action::Idle), // Alpha
(SKanji, AIdle), // KanjiHi1 (State::Kanji, Action::Idle), // KanjiHi1
(SKanji, AIdle), // KanjiHi2 (State::Kanji, Action::Idle), // KanjiHi2
(SKanji, AIdle), // KanjiHi3 (State::Kanji, Action::Idle), // KanjiHi3
(SKanji, AIdle), // KanjiLo1 (State::Kanji, Action::Idle), // KanjiLo1
(SKanji, AIdle), // KanjiLo2 (State::Kanji, Action::Idle), // KanjiLo2
(SByte, AKanjiAndSingleByte), // Byte (State::Byte, Action::KanjiAndSingleByte), // Byte
// KanjiHi3 state: // KanjiHi3 state:
(SInit, AKanjiAndSingleByte), // End (State::Init, Action::KanjiAndSingleByte), // End
(SAlpha, AKanjiAndSingleByte), // Symbol (State::Alpha, Action::KanjiAndSingleByte), // Symbol
(SNumeric, AKanjiAndSingleByte), // Numeric (State::Numeric, Action::KanjiAndSingleByte), // Numeric
(SKanji, AIdle), // Alpha (State::Kanji, Action::Idle), // Alpha
(SKanji, AIdle), // KanjiHi1 (State::Kanji, Action::Idle), // KanjiHi1
(SKanjiHi12, AKanjiAndSingleByte), // KanjiHi2 (State::KanjiHi12, Action::KanjiAndSingleByte), // KanjiHi2
(SKanjiHi3, AKanjiAndSingleByte), // KanjiHi3 (State::KanjiHi3, Action::KanjiAndSingleByte), // KanjiHi3
(SKanji, AIdle), // KanjiLo1 (State::Kanji, Action::Idle), // KanjiLo1
(SByte, AKanjiAndSingleByte), // KanjiLo2 (State::Byte, Action::KanjiAndSingleByte), // KanjiLo2
(SByte, AKanjiAndSingleByte), // Byte (State::Byte, Action::KanjiAndSingleByte), // Byte
// Kanji state: // Kanji state:
(SInit, AKanji), // End (State::Init, Action::Kanji), // End
(SAlpha, AKanji), // Symbol (State::Alpha, Action::Kanji), // Symbol
(SNumeric, AKanji), // Numeric (State::Numeric, Action::Kanji), // Numeric
(SAlpha, AKanji), // Alpha (State::Alpha, Action::Kanji), // Alpha
(SKanjiHi12, AIdle), // KanjiHi1 (State::KanjiHi12, Action::Idle), // KanjiHi1
(SKanjiHi12, AIdle), // KanjiHi2 (State::KanjiHi12, Action::Idle), // KanjiHi2
(SKanjiHi3, AIdle), // KanjiHi3 (State::KanjiHi3, Action::Idle), // KanjiHi3
(SByte, AKanji), // KanjiLo1 (State::Byte, Action::Kanji), // KanjiLo1
(SByte, AKanji), // KanjiLo2 (State::Byte, Action::Kanji), // KanjiLo2
(SByte, AKanji), // Byte (State::Byte, Action::Kanji), // Byte
]; ];
//}}} //}}}

View file

@ -39,7 +39,7 @@ pub type QrResult<T> = Result<T, QrError>;
/// even if parts of the code is damaged. /// even if parts of the code is damaged.
#[deriving(Show, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)] #[deriving(Show, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
#[unstable] #[unstable]
pub enum ErrorCorrectionLevel { pub enum EcLevel {
/// Low error correction. Allows up to 7% of wrong blocks. /// Low error correction. Allows up to 7% of wrong blocks.
L = 0, L = 0,
@ -61,27 +61,26 @@ pub enum ErrorCorrectionLevel {
/// Larger version means the size of code is larger, and therefore can carry /// Larger version means the size of code is larger, and therefore can carry
/// more information. /// more information.
/// ///
/// The smallest version is `Version(1)` of size 21×21, and the largest is /// The smallest version is `Version::Normal(1)` of size 21×21, and the largest
/// `Version(40)` of size 177×177. /// is `Version::Normal(40)` of size 177×177.
#[unstable] #[unstable]
#[deriving(Show, PartialEq, Eq, Copy, Clone)] #[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. /// A normal QR code version. The parameter should be between 1 and 40.
#[unstable] Normal(i16),
Version(i16),
/// A Micro QR code version. The parameter should be between 1 and 4. /// 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 /// Get the number of "modules" on each size of the QR code, i.e. the width
/// and height of the code. /// and height of the code.
#[unstable] #[unstable]
pub fn width(&self) -> i16 { pub fn width(&self) -> i16 {
match *self { match *self {
Version(v) => v * 4 + 17, Version::Normal(v) => v * 4 + 17,
MicroVersion(v) => v * 2 + 9, Version::Micro(v) => v * 2 + 9,
} }
} }
@ -94,21 +93,21 @@ impl QrVersion {
/// the order [L, M, Q, H]. /// the order [L, M, Q, H].
/// ///
/// If the entry compares equal to the default value of T, this method /// If the entry compares equal to the default value of T, this method
/// returns `Err(InvalidVersion)`. /// returns `Err(QrError::InvalidVersion)`.
pub fn fetch<T>(&self, ec_level: ErrorCorrectionLevel, table: &[[T, ..4]]) -> QrResult<T> pub fn fetch<T>(&self, ec_level: EcLevel, table: &[[T, ..4]]) -> QrResult<T>
where T: PartialEq + Default + Copy where T: PartialEq + Default + Copy
{ {
match *self { match *self {
Version(v @ 1...40) => Ok(table[v as uint - 1][ec_level as uint]), Version::Normal(v @ 1...40) => Ok(table[v as uint - 1][ec_level as uint]),
MicroVersion(v @ 1...4) => { Version::Micro(v @ 1...4) => {
let obj = table[v as uint + 39][ec_level as uint]; let obj = table[v as uint + 39][ec_level as uint];
if obj != Default::default() { if obj != Default::default() {
Ok(obj) Ok(obj)
} else { } else {
Err(InvalidVersion) Err(QrError::InvalidVersion)
} }
} }
_ => Err(InvalidVersion) _ => Err(QrError::InvalidVersion)
} }
} }
@ -116,7 +115,7 @@ impl QrVersion {
#[unstable] #[unstable]
pub fn mode_bits_count(&self) -> uint { pub fn mode_bits_count(&self) -> uint {
match *self { match *self {
MicroVersion(a) => (a - 1) as uint, Version::Micro(a) => (a - 1) as uint,
_ => 4, _ => 4,
} }
} }
@ -125,8 +124,8 @@ impl QrVersion {
#[unstable] #[unstable]
pub fn is_micro(&self) -> bool { pub fn is_micro(&self) -> bool {
match *self { match *self {
Version(_) => false, Version::Normal(_) => false,
MicroVersion(_) => true, Version::Micro(_) => true,
} }
} }
} }
@ -156,68 +155,68 @@ pub enum Mode {
impl Mode { impl Mode {
/// Computes the number of bits needed to encode the data length. /// 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 /// This method will return `Err(QrError::UnsupportedCharacterSet)` if the
/// supported in the given version. /// mode is not supported in the given version.
#[unstable] #[unstable]
pub fn length_bits_count(&self, version: QrVersion) -> uint { pub fn length_bits_count(&self, version: Version) -> uint {
match version { match version {
MicroVersion(a) => { Version::Micro(a) => {
let a = a as uint; let a = a as uint;
match *self { match *self {
Numeric => 2 + a, Mode::Numeric => 2 + a,
Alphanumeric | Byte => 1 + a, Mode::Alphanumeric | Mode::Byte => 1 + a,
Kanji => a, Mode::Kanji => a,
} }
} }
Version(1...9) => match *self { Version::Normal(1...9) => match *self {
Numeric => 10, Mode::Numeric => 10,
Alphanumeric => 9, Mode::Alphanumeric => 9,
Byte => 8, Mode::Byte => 8,
Kanji => 8, Mode::Kanji => 8,
}, },
Version(10...26) => match *self { Version::Normal(10...26) => match *self {
Numeric => 12, Mode::Numeric => 12,
Alphanumeric => 11, Mode::Alphanumeric => 11,
Byte => 16, Mode::Byte => 16,
Kanji => 10, Mode::Kanji => 10,
}, },
Version(_) => match *self { Version::Normal(_) => match *self {
Numeric => 14, Mode::Numeric => 14,
Alphanumeric => 13, Mode::Alphanumeric => 13,
Byte => 16, Mode::Byte => 16,
Kanji => 12, Mode::Kanji => 12,
}, },
} }
} }
/// Computes the number of bits needed to some data of a given raw length. /// 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, /// Note that in Kanji mode, the `raw_data_len` is the number of Kanjis,
/// i.e. half the total size of bytes. /// i.e. half the total size of bytes.
#[unstable] #[unstable]
pub fn data_bits_count(&self, raw_data_len: uint) -> uint { pub fn data_bits_count(&self, raw_data_len: uint) -> uint {
match *self { match *self {
Numeric => (raw_data_len * 10 + 2) / 3, Mode::Numeric => (raw_data_len * 10 + 2) / 3,
Alphanumeric => (raw_data_len * 11 + 1) / 2, Mode::Alphanumeric => (raw_data_len * 11 + 1) / 2,
Byte => raw_data_len * 8, Mode::Byte => raw_data_len * 8,
Kanji => raw_data_len * 13, Mode::Kanji => raw_data_len * 13,
} }
} }
/// Find the lowest common mode which both modes are compatible with. /// Find the lowest common mode which both modes are compatible with.
/// ///
/// use qrcode::types::{Numeric, Kanji}; /// use qrcode::types::Mode;
/// ///
/// let a = Numeric; /// let a = Mode::Numeric;
/// let b = Kanji; /// let b = Mode::Kanji;
/// let c = a.max(b); /// let c = a.max(b);
/// assert!(a <= c); /// assert!(a <= c);
/// assert!(b <= c); /// assert!(b <= c);
@ -226,7 +225,7 @@ impl Mode {
match self.partial_cmp(&other) { match self.partial_cmp(&other) {
Some(Less) | Some(Equal) => other, Some(Less) | Some(Equal) => other,
Some(Greater) => *self, Some(Greater) => *self,
None => Byte, None => Mode::Byte,
} }
} }
} }
@ -236,14 +235,14 @@ impl PartialOrd for Mode {
/// a superset of all characters supported by `a`. /// a superset of all characters supported by `a`.
fn partial_cmp(&self, other: &Mode) -> Option<Ordering> { fn partial_cmp(&self, other: &Mode) -> Option<Ordering> {
match (*self, *other) { match (*self, *other) {
(Numeric, Alphanumeric) => Some(Less), (Mode::Numeric, Mode::Alphanumeric) => Some(Less),
(Alphanumeric, Numeric) => Some(Greater), (Mode::Alphanumeric, Mode::Numeric) => Some(Greater),
(Numeric, Byte) => Some(Less), (Mode::Numeric, Mode::Byte) => Some(Less),
(Byte, Numeric) => Some(Greater), (Mode::Byte, Mode::Numeric) => Some(Greater),
(Alphanumeric, Byte) => Some(Less), (Mode::Alphanumeric, Mode::Byte) => Some(Less),
(Byte, Alphanumeric) => Some(Greater), (Mode::Byte, Mode::Alphanumeric) => Some(Greater),
(Kanji, Byte) => Some(Less), (Mode::Kanji, Mode::Byte) => Some(Less),
(Byte, Kanji) => Some(Greater), (Mode::Byte, Mode::Kanji) => Some(Greater),
(a, b) if a == b => Some(Equal), (a, b) if a == b => Some(Equal),
_ => None, _ => None,
} }
@ -252,7 +251,7 @@ impl PartialOrd for Mode {
#[cfg(test)] #[cfg(test)]
mod mode_tests { mod mode_tests {
use types::{Numeric, Alphanumeric, Byte, Kanji}; use types::Mode::{Numeric, Alphanumeric, Byte, Kanji};
#[test] #[test]
fn test_mode_order() { fn test_mode_order() {