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

View file

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

View file

@ -1,6 +1,6 @@
//! The `ec` module applies the Reed-Solomon error correction codes.
use types::{QrResult, QrVersion, ErrorCorrectionLevel};
use types::{QrResult, Version, EcLevel};
//------------------------------------------------------------------------------
//{{{ Error correction primitive
@ -96,8 +96,8 @@ fn test_interleave() {
/// Constructs data and error correction codewords ready to be put in the QR
/// code matrix.
pub fn construct_codewords(rawbits: &[u8],
version: QrVersion,
ec_level: ErrorCorrectionLevel) -> QrResult<(Vec<u8>, Vec<u8>)> {
version: Version,
ec_level: EcLevel) -> QrResult<(Vec<u8>, Vec<u8>)> {
let (block_1_size, block_1_count, block_2_size, block_2_count) =
try!(version.fetch(ec_level, &DATA_BYTES_PER_BLOCK));
@ -129,12 +129,12 @@ pub fn construct_codewords(rawbits: &[u8],
#[cfg(test)]
mod construct_codewords_test {
use ec::construct_codewords;
use types::{Version, M, Q};
use types::{Version, EcLevel};
#[test]
fn test_add_ec_simple() {
let msg = b" [\x0bx\xd1r\xdcMC@\xec\x11\xec\x11\xec\x11";
let (blocks_vec, ec_vec) = construct_codewords(msg, Version(1), M).unwrap();
let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(1), EcLevel::M).unwrap();
assert_eq!(&*blocks_vec, msg);
assert_eq!(&*ec_vec, b"\xc4#'w\xeb\xd7\xe7\xe2]\x17");
}
@ -142,7 +142,7 @@ mod construct_codewords_test {
#[test]
fn test_add_ec_complex() {
let msg = b"CUF\x86W&U\xc2w2\x06\x12\x06g&\xf6\xf6B\x07v\x86\xf2\x07&V\x16\xc6\xc7\x92\x06\xb6\xe6\xf7w2\x07v\x86W&R\x06\x86\x972\x07F\xf7vV\xc2\x06\x972\x10\xec\x11\xec\x11\xec\x11\xec";
let (blocks_vec, ec_vec) = construct_codewords(msg, Version(5), Q).unwrap();
let (blocks_vec, ec_vec) = construct_codewords(msg, Version::Normal(5), EcLevel::Q).unwrap();
assert_eq!(&*blocks_vec,
b"C\xf6\xb6FU\xf6\xe6\xf7FB\xf7v\x86\x07wVWv2\xc2&\x86\x07\x06U\xf2v\x97\xc2\x07\x862w&W\x102V&\xec\x06\x16R\x11\x12\xc6\x06\xec\x06\xc7\x86\x11g\x92\x97\xec&\x062\x11\x07\xec");
assert_eq!(&*ec_vec,

View file

@ -24,8 +24,7 @@
extern crate test;
pub use types::{QrResult, ErrorCorrectionLevel, L, M, Q, H,
QrVersion, Version, MicroVersion};
pub use types::{QrResult, EcLevel, Version};
pub mod types;
pub mod bits;
@ -37,8 +36,8 @@ pub mod canvas;
#[deriving(Clone)]
pub struct QrCode {
content: Vec<bool>,
version: QrVersion,
ec_level: ErrorCorrectionLevel,
version: Version,
ec_level: EcLevel,
width: uint,
}
@ -53,7 +52,7 @@ impl QrCode {
/// let code = QrCode::new(b"Some data").unwrap();
///
pub fn new(data: &[u8]) -> QrResult<QrCode> {
QrCode::with_error_correction_level(data, M)
QrCode::with_error_correction_level(data, EcLevel::M)
}
/// Constructs a new QR code which automatically encodes the given data at a
@ -61,11 +60,11 @@ impl QrCode {
///
/// This method automatically chooses the smallest QR code.
///
/// use qrcode::{QrCode, H};
/// use qrcode::{QrCode, EcLevel};
///
/// let code = QrCode::with_error_correction_level(b"Some data", H).unwrap();
/// let code = QrCode::with_error_correction_level(b"Some data", EcLevel::H).unwrap();
///
pub fn with_error_correction_level(data: &[u8], ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
pub fn with_error_correction_level(data: &[u8], ec_level: EcLevel) -> QrResult<QrCode> {
let bits = try!(bits::encode_auto(data, ec_level));
QrCode::with_bits(bits, ec_level)
}
@ -73,19 +72,17 @@ impl QrCode {
/// Constructs a new QR code for the given version and error correction
/// level.
///
/// use qrcode::{QrCode, Version, M};
/// use qrcode::{QrCode, Version, EcLevel};
///
/// let code = QrCode::with_version(b"Some data", Version(5), M).unwrap();
/// let code = QrCode::with_version(b"Some data", Version::Normal(5), EcLevel::M).unwrap();
///
/// This method can also be used to generate Micro QR code.
///
/// use qrcode::{QrCode, MicroVersion, L};
/// use qrcode::{QrCode, Version, EcLevel};
///
/// let micro_code = QrCode::with_version(b"123", MicroVersion(1), L).unwrap();
/// let micro_code = QrCode::with_version(b"123", Version::Micro(1), EcLevel::L).unwrap();
///
pub fn with_version(data: &[u8],
version: QrVersion,
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
pub fn with_version(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<QrCode> {
let mut bits = bits::Bits::new(version);
try!(bits.push_optimal_data(data));
try!(bits.push_terminator(ec_level));
@ -103,25 +100,24 @@ impl QrCode {
///
/// See the `Bits` structure for detail.
///
/// #![allow(unused_must_use)];
/// #![allow(unused_must_use)]
///
/// use qrcode::{QrCode, Version, L};
/// use qrcode::{QrCode, Version, EcLevel};
/// use qrcode::bits::Bits;
///
/// let mut bits = Bits::new(Version(1));
/// let mut bits = Bits::new(Version::Normal(1));
/// bits.push_eci_designator(9);
/// bits.push_byte_data(b"\xca\xfe\xe4\xe9\xea\xe1\xf2 QR");
/// bits.push_terminator(L);
/// let qrcode = QrCode::with_bits(bits, L);
/// bits.push_terminator(EcLevel::L);
/// let qrcode = QrCode::with_bits(bits, EcLevel::L);
///
pub fn with_bits(bits: bits::Bits,
ec_level: ErrorCorrectionLevel) -> QrResult<QrCode> {
pub fn with_bits(bits: bits::Bits, ec_level: EcLevel) -> QrResult<QrCode> {
let version = bits.version();
let data = bits.into_bytes();
let (encoded_data, ec_data) = try!(ec::construct_codewords(data[], version, ec_level));
let mut canvas = canvas::Canvas::new(version, ec_level);
canvas.draw_all_functional_patterns();
canvas.draw_data(encoded_data[], ec_data[]);
canvas.draw_data(&*encoded_data, &*ec_data);
let canvas = canvas.apply_best_mask();
Ok(QrCode {
content: canvas.to_bools(),
@ -132,12 +128,12 @@ impl QrCode {
}
/// Gets the version of this QR code.
pub fn version(&self) -> QrVersion {
pub fn version(&self) -> Version {
self.version
}
/// Gets the error correction level of this QR code.
pub fn error_correction_level(&self) -> ErrorCorrectionLevel {
pub fn error_correction_level(&self) -> EcLevel {
self.ec_level
}
@ -186,12 +182,12 @@ impl Index<(uint, uint), bool> for QrCode {
#[cfg(test)]
mod tests {
use {QrCode, Version, MicroVersion, L, M};
use {QrCode, Version, EcLevel};
#[test]
fn test_annex_i_qr() {
// This uses the ISO Annex I as test vector.
let code = QrCode::with_version(b"01234567", Version(1), M).unwrap();
let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap();
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######..#.##.#######\n\
#.....#..####.#.....#\n\
@ -218,7 +214,7 @@ mod tests {
#[test]
fn test_annex_i_micro_qr() {
let code = QrCode::with_version(b"01234567", MicroVersion(2), L).unwrap();
let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap();
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######.#.#.#\n\
#.....#.###.#\n\

View file

@ -7,7 +7,7 @@ use std::slice::Items;
#[cfg(test)]
use test::Bencher;
use types::{Mode, QrVersion, Numeric, Alphanumeric, Byte, Kanji};
use types::{Mode, Version};
//------------------------------------------------------------------------------
//{{{ Segment
@ -28,9 +28,9 @@ pub struct Segment {
impl Segment {
/// Compute the number of bits (including the size of the mode indicator and
/// length bits) when this segment is encoded.
pub fn encoded_len(&self, version: QrVersion) -> uint {
pub fn encoded_len(&self, version: Version) -> uint {
let byte_size = self.end - self.begin;
let chars_count = if self.mode == Kanji { byte_size / 2 } else { byte_size };
let chars_count = if self.mode == Mode::Kanji { byte_size / 2 } else { byte_size };
let mode_bits_count = version.mode_bits_count();
let length_bits_count = self.mode.length_bits_count(version);
@ -47,7 +47,9 @@ impl Segment {
/// This iterator is basically equivalent to
///
/// ```ignore
/// data.map(|c| ExclusiveCharacterSet::from_u8(*c)).chain(Some(EEnd).move_iter()).enumerate()
/// data.map(|c| ExclCharSet::from_u8(*c))
/// .chain(Some(ExclCharSet::End).move_iter())
/// .enumerate()
/// ```
///
/// But the type is too hard to write, thus the new type.
@ -58,8 +60,8 @@ struct EcsIter<I> {
ended: bool,
}
impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIter<I> {
fn next(&mut self) -> Option<(uint, ExclusiveCharacterSet)> {
impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclCharSet)> for EcsIter<I> {
fn next(&mut self) -> Option<(uint, ExclCharSet)> {
if self.ended {
return None;
}
@ -67,12 +69,12 @@ impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIte
match self.base.next() {
None => {
self.ended = true;
Some((self.index, EEnd))
Some((self.index, ExclCharSet::End))
}
Some(c) => {
let old_index = self.index;
self.index += 1;
Some((old_index, ExclusiveCharacterSet::from_u8(*c)))
Some((old_index, ExclCharSet::from_u8(*c)))
}
}
}
@ -81,7 +83,7 @@ impl<'a, I: Iterator<&'a u8>> Iterator<(uint, ExclusiveCharacterSet)> for EcsIte
/// QR code data parser to classify the input into distinct segments.
pub struct Parser<'a> {
ecs_iter: EcsIter<Items<'a, u8>>,
state: SegmentParseState,
state: State,
begin: uint,
pending_single_byte: bool,
}
@ -101,7 +103,7 @@ impl<'a> Parser<'a> {
pub fn new(data: &[u8]) -> Parser {
Parser {
ecs_iter: EcsIter { base: data.iter(), index: 0, ended: false },
state: SInit,
state: State::Init,
begin: 0,
pending_single_byte: false,
}
@ -113,7 +115,11 @@ impl<'a> Iterator<Segment> for Parser<'a> {
if self.pending_single_byte {
self.pending_single_byte = false;
self.begin += 1;
return Some(Segment { mode: Byte, begin: self.begin-1, end: self.begin });
return Some(Segment {
mode: Mode::Byte,
begin: self.begin-1,
end: self.begin,
});
}
loop {
@ -126,25 +132,33 @@ impl<'a> Iterator<Segment> for Parser<'a> {
let old_begin = self.begin;
let push_mode = match action {
AIdle => { continue; }
ANumeric => Numeric,
AAlpha => Alphanumeric,
AByte => Byte,
AKanji => Kanji,
AKanjiAndSingleByte => {
Action::Idle => { continue; }
Action::Numeric => Mode::Numeric,
Action::Alpha => Mode::Alphanumeric,
Action::Byte => Mode::Byte,
Action::Kanji => Mode::Kanji,
Action::KanjiAndSingleByte => {
let next_begin = i - 1;
if self.begin == next_begin {
Byte
Mode::Byte
} else {
self.pending_single_byte = true;
self.begin = next_begin;
return Some(Segment { mode: Kanji, begin: old_begin, end: next_begin });
return Some(Segment {
mode: Mode::Kanji,
begin: old_begin,
end: next_begin,
});
}
}
};
self.begin = i;
return Some(Segment { mode: push_mode, begin: old_begin, end: i });
return Some(Segment {
mode: push_mode,
begin: old_begin,
end: i,
});
}
}
}
@ -152,7 +166,7 @@ impl<'a> Iterator<Segment> for Parser<'a> {
#[cfg(test)]
mod parse_tests {
use optimize::{Parser, Segment};
use types::{Numeric, Alphanumeric, Byte, Kanji};
use types::Mode;
fn parse(data: &[u8]) -> Vec<Segment> {
Parser::new(data).collect()
@ -161,39 +175,39 @@ mod parse_tests {
#[test]
fn test_parse_1() {
let segs = parse(b"01049123451234591597033130128%10ABC123");
assert_eq!(segs, vec![Segment { mode: Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 30 },
Segment { mode: Numeric, begin: 30, end: 32 },
Segment { mode: Alphanumeric, begin: 32, end: 35 },
Segment { mode: Numeric, begin: 35, end: 38 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 },
Segment { mode: Mode::Numeric, begin: 30, end: 32 },
Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 },
Segment { mode: Mode::Numeric, begin: 35, end: 38 }]);
}
#[test]
fn test_parse_shift_jis_example_1() {
let segs = parse(b"\x82\xa0\x81\x41\x41\xb1\x81\xf0"); // "あ、AアÅ"
assert_eq!(segs, vec![Segment { mode: Kanji, begin: 0, end: 4 },
Segment { mode: Alphanumeric, begin: 4, end: 5 },
Segment { mode: Byte, begin: 5, end: 6 },
Segment { mode: Kanji, begin: 6, end: 8 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 },
Segment { mode: Mode::Byte, begin: 5, end: 6 },
Segment { mode: Mode::Kanji, begin: 6, end: 8 }]);
}
#[test]
fn test_parse_utf_8() {
// Mojibake?
let segs = parse(b"\xe3\x81\x82\xe3\x80\x81A\xef\xbd\xb1\xe2\x84\xab");
assert_eq!(segs, vec![Segment { mode: Kanji, begin: 0, end: 4 },
Segment { mode: Byte, begin: 4, end: 5 },
Segment { mode: Kanji, begin: 5, end: 7 },
Segment { mode: Byte, begin: 7, end: 10 },
Segment { mode: Kanji, begin: 10, end: 12 },
Segment { mode: Byte, begin: 12, end: 13 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Mode::Byte, begin: 4, end: 5 },
Segment { mode: Mode::Kanji, begin: 5, end: 7 },
Segment { mode: Mode::Byte, begin: 7, end: 10 },
Segment { mode: Mode::Kanji, begin: 10, end: 12 },
Segment { mode: Mode::Byte, begin: 12, end: 13 }]);
}
#[test]
fn test_not_kanji_1() {
let segs = parse(b"\x81\x30");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 },
Segment { mode: Numeric, begin: 1, end: 2 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Mode::Numeric, begin: 1, end: 2 }]);
}
#[test]
@ -201,22 +215,22 @@ mod parse_tests {
// Note that it's implementation detail that the byte seq is split into
// two. Perhaps adjust the test to check for this.
let segs = parse(b"\xeb\xc0");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 },
Segment { mode: Byte, begin: 1, end: 2 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Mode::Byte, begin: 1, end: 2 }]);
}
#[test]
fn test_not_kanji_3() {
let segs = parse(b"\x81\x7f");
assert_eq!(segs, vec![Segment { mode: Byte, begin: 0, end: 1 },
Segment { mode: Byte, begin: 1, end: 2 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Byte, begin: 0, end: 1 },
Segment { mode: Mode::Byte, begin: 1, end: 2 }]);
}
#[test]
fn test_not_kanji_4() {
let segs = parse(b"\x81\x40\x81");
assert_eq!(segs, vec![Segment { mode: Kanji, begin: 0, end: 2 },
Segment { mode: Byte, begin: 2, end: 3 }]);
assert_eq!(segs, vec![Segment { mode: Mode::Kanji, begin: 0, end: 2 },
Segment { mode: Mode::Byte, begin: 2, end: 3 }]);
}
}
@ -228,7 +242,7 @@ pub struct Optimizer<I> {
parser: I,
last_segment: Segment,
last_segment_size: uint,
version: QrVersion,
version: Version,
ended: bool,
}
@ -239,11 +253,11 @@ impl<I: Iterator<Segment>> Optimizer<I> {
/// left to right until the new segment is longer than before. This method
/// does *not* use Annex J from the ISO standard.
///
pub fn new(mut segments: I, version: QrVersion) -> Optimizer<I> {
pub fn new(mut segments: I, version: Version) -> Optimizer<I> {
match segments.next() {
None => Optimizer {
parser: segments,
last_segment: Segment { mode: Numeric, begin: 0, end: 0 },
last_segment: Segment { mode: Mode::Numeric, begin: 0, end: 0 },
last_segment_size: 0,
version: version,
ended: true,
@ -260,7 +274,7 @@ impl<I: Iterator<Segment>> Optimizer<I> {
}
impl<'a> Parser<'a> {
pub fn optimize(self, version: QrVersion) -> Optimizer<Parser<'a>> {
pub fn optimize(self, version: Version) -> Optimizer<Parser<'a>> {
Optimizer::new(self, version)
}
}
@ -303,7 +317,7 @@ impl<I: Iterator<Segment>> Iterator<Segment> for Optimizer<I> {
}
/// Computes the total encoded length of all segments.
pub fn total_encoded_len(segments: &[Segment], version: QrVersion) -> uint {
pub fn total_encoded_len(segments: &[Segment], version: Version) -> uint {
use std::iter::AdditiveIterator;
segments.iter().map(|seg| seg.encoded_len(version)).sum()
}
@ -311,11 +325,11 @@ pub fn total_encoded_len(segments: &[Segment], version: QrVersion) -> uint {
#[cfg(test)]
mod optimize_tests {
use optimize::{Optimizer, total_encoded_len, Segment};
use types::{Numeric, Alphanumeric, Byte, Kanji, QrVersion, Version, MicroVersion};
use types::{Mode, Version};
fn test_optimization_result(given: Vec<Segment>, expected: Vec<Segment>, version: QrVersion) {
fn test_optimization_result(given: Vec<Segment>, expected: Vec<Segment>, version: Version) {
let prev_len = total_encoded_len(&*given, version);
let opt_segs = Optimizer::new(given.iter().map(|seg| *seg), version).collect::<Vec<Segment>>();
let opt_segs = Optimizer::new(given.iter().map(|seg| *seg), version).collect::<Vec<_>>();
let new_len = total_encoded_len(&*opt_segs, version);
if given != opt_segs {
assert!(prev_len > new_len, "{} > {}", prev_len, new_len);
@ -329,14 +343,14 @@ mod optimize_tests {
fn test_example_1() {
test_optimization_result(
vec![Segment { mode: Alphanumeric, begin: 0, end: 3 },
Segment { mode: Numeric, begin: 3, end: 6 },
Segment { mode: Byte, begin: 6, end: 10 }],
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 3 },
Segment { mode: Mode::Numeric, begin: 3, end: 6 },
Segment { mode: Mode::Byte, begin: 6, end: 10 }],
vec![Segment { mode: Alphanumeric, begin: 0, end: 6 },
Segment { mode: Byte, begin: 6, end: 10 }],
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 6 },
Segment { mode: Mode::Byte, begin: 6, end: 10 }],
Version(1)
Version::Normal(1)
);
}
@ -345,16 +359,16 @@ mod optimize_tests {
fn test_example_2() {
test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 30 },
Segment { mode: Numeric, begin: 30, end: 32 },
Segment { mode: Alphanumeric, begin: 32, end: 35 },
Segment { mode: Numeric, begin: 35, end: 38 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Mode::Alphanumeric, begin: 29, end: 30 },
Segment { mode: Mode::Numeric, begin: 30, end: 32 },
Segment { mode: Mode::Alphanumeric, begin: 32, end: 35 },
Segment { mode: Mode::Numeric, begin: 35, end: 38 }],
vec![Segment { mode: Numeric, begin: 0, end: 29 },
Segment { mode: Alphanumeric, begin: 29, end: 38 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 29 },
Segment { mode: Mode::Alphanumeric, begin: 29, end: 38 }],
Version(9)
Version::Normal(9)
);
}
@ -363,14 +377,14 @@ mod optimize_tests {
fn test_example_3() {
test_optimization_result(
vec![Segment { mode: Kanji, begin: 0, end: 4 },
Segment { mode: Alphanumeric, begin: 4, end: 5 },
Segment { mode: Byte, begin: 5, end: 6 },
Segment { mode: Kanji, begin: 6, end: 8 }],
vec![Segment { mode: Mode::Kanji, begin: 0, end: 4 },
Segment { mode: Mode::Alphanumeric, begin: 4, end: 5 },
Segment { mode: Mode::Byte, begin: 5, end: 6 },
Segment { mode: Mode::Kanji, begin: 6, end: 8 }],
vec![Segment { mode: Byte, begin: 0, end: 8 }],
vec![Segment { mode: Mode::Byte, begin: 0, end: 8 }],
Version(1)
Version::Normal(1)
);
}
@ -379,13 +393,13 @@ mod optimize_tests {
fn test_example_4() {
test_optimization_result(
vec![Segment { mode: Kanji, begin: 0, end: 10 },
Segment { mode: Byte, begin: 10, end: 11 }],
vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
Segment { mode: Mode::Byte, begin: 10, end: 11 }],
vec![Segment { mode: Kanji, begin: 0, end: 10 },
Segment { mode: Byte, begin: 10, end: 11 }],
vec![Segment { mode: Mode::Kanji, begin: 0, end: 10 },
Segment { mode: Mode::Byte, begin: 10, end: 11 }],
Version(1)
Version::Normal(1)
);
}
@ -394,13 +408,13 @@ mod optimize_tests {
fn test_annex_j_guideline_1a() {
test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }],
MicroVersion(2)
Version::Micro(2)
);
}
@ -409,12 +423,12 @@ mod optimize_tests {
fn test_annex_j_guideline_1b() {
test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 2 },
Segment { mode: Alphanumeric, begin: 2, end: 4 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 2 },
Segment { mode: Mode::Alphanumeric, begin: 2, end: 4 }],
vec![Segment { mode: Alphanumeric, begin: 0, end: 4 }],
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }],
MicroVersion(2)
Version::Micro(2)
);
}
@ -423,12 +437,12 @@ mod optimize_tests {
fn test_annex_j_guideline_1c() {
test_optimization_result(
vec![Segment { mode: Numeric, begin: 0, end: 3 },
Segment { mode: Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Mode::Numeric, begin: 0, end: 3 },
Segment { mode: Mode::Alphanumeric, begin: 3, end: 4 }],
vec![Segment { mode: Alphanumeric, begin: 0, end: 4 }],
vec![Segment { mode: Mode::Alphanumeric, begin: 0, end: 4 }],
MicroVersion(3)
Version::Micro(3)
);
}
@ -441,7 +455,7 @@ fn bench_optimize(bencher: &mut Bencher) {
let data = b"QR\x83R\x81[\x83h\x81i\x83L\x83\x85\x81[\x83A\x81[\x83\x8b\x83R\x81[\x83h\x81j\x82\xc6\x82\xcd\x81A1994\x94N\x82\xc9\x83f\x83\x93\x83\\\x81[\x82\xcc\x8aJ\x94\xad\x95\x94\x96\xe5\x81i\x8c\xbb\x8d\xdd\x82\xcd\x95\xaa\x97\xa3\x82\xb5\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x81j\x82\xaa\x8aJ\x94\xad\x82\xb5\x82\xbd\x83}\x83g\x83\x8a\x83b\x83N\x83X\x8c^\x93\xf1\x8e\x9f\x8c\xb3\x83R\x81[\x83h\x82\xc5\x82\xa0\x82\xe9\x81B\x82\xc8\x82\xa8\x81AQR\x83R\x81[\x83h\x82\xc6\x82\xa2\x82\xa4\x96\xbc\x8f\xcc\x81i\x82\xa8\x82\xe6\x82\xd1\x92P\x8c\xea\x81j\x82\xcd\x83f\x83\x93\x83\\\x81[\x83E\x83F\x81[\x83u\x82\xcc\x93o\x98^\x8f\xa4\x95W\x81i\x91\xe64075066\x8d\x86\x81j\x82\xc5\x82\xa0\x82\xe9\x81BQR\x82\xcdQuick Response\x82\xc9\x97R\x97\x88\x82\xb5\x81A\x8d\x82\x91\xac\x93\xc7\x82\xdd\x8e\xe6\x82\xe8\x82\xaa\x82\xc5\x82\xab\x82\xe9\x82\xe6\x82\xa4\x82\xc9\x8aJ\x94\xad\x82\xb3\x82\xea\x82\xbd\x81B\x93\x96\x8f\x89\x82\xcd\x8e\xa9\x93\xae\x8e\xd4\x95\x94\x95i\x8dH\x8f\xea\x82\xe2\x94z\x91\x97\x83Z\x83\x93\x83^\x81[\x82\xc8\x82\xc7\x82\xc5\x82\xcc\x8eg\x97p\x82\xf0\x94O\x93\xaa\x82\xc9\x8aJ\x94\xad\x82\xb3\x82\xea\x82\xbd\x82\xaa\x81A\x8c\xbb\x8d\xdd\x82\xc5\x82\xcd\x83X\x83}\x81[\x83g\x83t\x83H\x83\x93\x82\xcc\x95\x81\x8by\x82\xc8\x82\xc7\x82\xc9\x82\xe6\x82\xe8\x93\xfa\x96{\x82\xc9\x8c\xc0\x82\xe7\x82\xb8\x90\xa2\x8aE\x93I\x82\xc9\x95\x81\x8by\x82\xb5\x82\xc4\x82\xa2\x82\xe9\x81B";
bencher.iter(|| {
Parser::new(data).optimize(Version(15))
Parser::new(data).optimize(Version::Normal(15))
});
}
@ -450,210 +464,208 @@ fn bench_optimize(bencher: &mut Bencher) {
//------------------------------------------------------------------------------
//{{{ Internal types and data for parsing
// All the silly prefixes are to avoid name collision with each other.
/// All values of `u8` can be split into 9 different character sets when
/// determining which encoding to use. This enum represents these groupings for
/// parsing purpose.
enum ExclusiveCharacterSet {
enum ExclCharSet {
/// The end of string.
EEnd = 0,
End = 0,
/// All symbols supported by the Alphanumeric encoding, i.e. space, `$`, `%`,
/// `*`, `+`, `-`, `.`, `/` and `:`.
ESymbol = 1,
Symbol = 1,
/// All numbers (09).
ENumeric = 2,
Numeric = 2,
/// All uppercase letters (AZ). These characters may also appear in the
/// second byte of a Shift JIS 2-byte encoding.
EAlpha = 3,
Alpha = 3,
/// The first byte of a Shift JIS 2-byte encoding, in the range 0x810x9f.
EKanjiHi1 = 4,
KanjiHi1 = 4,
/// 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
/// different from the other two range that the second byte has a smaller
/// range.
EKanjiHi3 = 6,
KanjiHi3 = 6,
/// The second byte of a Shift JIS 2-byte encoding, in the range 0x400xbf,
/// excluding letters (covered by `Alpha`), 0x810x9f (covered by `KanjiHi1`),
/// and the invalid byte 0x7f.
EKanjiLo1 = 7,
KanjiLo1 = 7,
/// The second byte of a Shift JIS 2-byte encoding, in the range 0xc00xfc,
/// excluding the range 0xe00xeb (covered by `KanjiHi2` and `KanjiHi3`).
/// This half of byte-pair cannot appear as the second byte leaded by
/// `KanjiHi3`.
EKanjiLo2 = 8,
KanjiLo2 = 8,
/// Any other values not covered by the above character sets.
EByte = 9,
Byte = 9,
}
impl ExclusiveCharacterSet {
impl ExclCharSet {
/// Determines which character set a byte is in.
fn from_u8(c: u8) -> ExclusiveCharacterSet {
fn from_u8(c: u8) -> ExclCharSet {
match c {
0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ESymbol,
0x30 ... 0x39 => ENumeric,
0x41 ... 0x5a => EAlpha,
0x81 ... 0x9f => EKanjiHi1,
0xe0 ... 0xea => EKanjiHi2,
0xeb => EKanjiHi3,
0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => EKanjiLo1,
0xc0 ... 0xdf | 0xec ... 0xfc => EKanjiLo2,
_ => EByte
0x20 | 0x24 | 0x25 | 0x2a | 0x2b | 0x2d ... 0x2f | 0x3a => ExclCharSet::Symbol,
0x30 ... 0x39 => ExclCharSet::Numeric,
0x41 ... 0x5a => ExclCharSet::Alpha,
0x81 ... 0x9f => ExclCharSet::KanjiHi1,
0xe0 ... 0xea => ExclCharSet::KanjiHi2,
0xeb => ExclCharSet::KanjiHi3,
0x40 | 0x5b ... 0x7e | 0x80 | 0xa0 ... 0xbf => ExclCharSet::KanjiLo1,
0xc0 ... 0xdf | 0xec ... 0xfc => ExclCharSet::KanjiLo2,
_ => ExclCharSet::Byte
}
}
}
/// The current parsing state.
enum SegmentParseState {
enum State {
/// Just initialized.
SInit = 0,
Init = 0,
/// Inside a string that can be exclusively encoded as Numeric.
SNumeric = 10,
Numeric = 10,
/// Inside a string that can be exclusively encoded as Alphanumeric.
SAlpha = 20,
Alpha = 20,
/// Inside a string that can be exclusively encoded as 8-Bit Byte.
SByte = 30,
Byte = 30,
/// Just encountered the first byte of a Shift JIS 2-byte sequence of the
/// set `KanjiHi1` or `KanjiHi2`.
SKanjiHi12 = 40,
KanjiHi12 = 40,
/// Just encountered the first byte of a Shift JIS 2-byte sequence of the
/// set `KanjiHi3`.
SKanjiHi3 = 50,
KanjiHi3 = 50,
/// Inside a string that can be exclusively encoded as Kanji.
SKanji = 60,
Kanji = 60,
}
/// What should the parser do after a state transition.
enum ParserAction {
enum Action {
/// The parser should do nothing.
AIdle,
Idle,
/// Push the current segment as a Numeric string, and reset the marks.
ANumeric,
Numeric,
/// Push the current segment as an Alphanumeric string, and reset the marks.
AAlpha,
Alpha,
/// Push the current segment as a 8-Bit Byte string, and reset the marks.
AByte,
Byte,
/// Push the current segment as a Kanji string, and reset the marks.
AKanji,
Kanji,
/// Push the current segment excluding the last byte as a Kanji string, then
/// push the remaining single byte as a Byte string, and reset the marks.
AKanjiAndSingleByte,
KanjiAndSingleByte,
}
static STATE_TRANSITION: [(SegmentParseState, ParserAction), ..70] = [
static STATE_TRANSITION: [(State, Action), ..70] = [
// STATE_TRANSITION[current_state + next_character] == (next_state, what_to_do)
// Init state:
(SInit, AIdle), // End
(SAlpha, AIdle), // Symbol
(SNumeric, AIdle), // Numeric
(SAlpha, AIdle), // Alpha
(SKanjiHi12, AIdle), // KanjiHi1
(SKanjiHi12, AIdle), // KanjiHi2
(SKanjiHi3, AIdle), // KanjiHi3
(SByte, AIdle), // KanjiLo1
(SByte, AIdle), // KanjiLo2
(SByte, AIdle), // Byte
(State::Init, Action::Idle), // End
(State::Alpha, Action::Idle), // Symbol
(State::Numeric, Action::Idle), // Numeric
(State::Alpha, Action::Idle), // Alpha
(State::KanjiHi12, Action::Idle), // KanjiHi1
(State::KanjiHi12, Action::Idle), // KanjiHi2
(State::KanjiHi3, Action::Idle), // KanjiHi3
(State::Byte, Action::Idle), // KanjiLo1
(State::Byte, Action::Idle), // KanjiLo2
(State::Byte, Action::Idle), // Byte
// Numeric state:
(SInit, ANumeric), // End
(SAlpha, ANumeric), // Symbol
(SNumeric, AIdle), // Numeric
(SAlpha, ANumeric), // Alpha
(SKanjiHi12, ANumeric), // KanjiHi1
(SKanjiHi12, ANumeric), // KanjiHi2
(SKanjiHi3, ANumeric), // KanjiHi3
(SByte, ANumeric), // KanjiLo1
(SByte, ANumeric), // KanjiLo2
(SByte, ANumeric), // Byte
(State::Init, Action::Numeric), // End
(State::Alpha, Action::Numeric), // Symbol
(State::Numeric, Action::Idle), // Numeric
(State::Alpha, Action::Numeric), // Alpha
(State::KanjiHi12, Action::Numeric), // KanjiHi1
(State::KanjiHi12, Action::Numeric), // KanjiHi2
(State::KanjiHi3, Action::Numeric), // KanjiHi3
(State::Byte, Action::Numeric), // KanjiLo1
(State::Byte, Action::Numeric), // KanjiLo2
(State::Byte, Action::Numeric), // Byte
// Alpha state:
(SInit, AAlpha), // End
(SAlpha, AIdle), // Symbol
(SNumeric, AAlpha), // Numeric
(SAlpha, AIdle), // Alpha
(SKanjiHi12, AAlpha), // KanjiHi1
(SKanjiHi12, AAlpha), // KanjiHi2
(SKanjiHi3, AAlpha), // KanjiHi3
(SByte, AAlpha), // KanjiLo1
(SByte, AAlpha), // KanjiLo2
(SByte, AAlpha), // Byte
(State::Init, Action::Alpha), // End
(State::Alpha, Action::Idle), // Symbol
(State::Numeric, Action::Alpha), // Numeric
(State::Alpha, Action::Idle), // Alpha
(State::KanjiHi12, Action::Alpha), // KanjiHi1
(State::KanjiHi12, Action::Alpha), // KanjiHi2
(State::KanjiHi3, Action::Alpha), // KanjiHi3
(State::Byte, Action::Alpha), // KanjiLo1
(State::Byte, Action::Alpha), // KanjiLo2
(State::Byte, Action::Alpha), // Byte
// Byte state:
(SInit, AByte), // End
(SAlpha, AByte), // Symbol
(SNumeric, AByte), // Numeric
(SAlpha, AByte), // Alpha
(SKanjiHi12, AByte), // KanjiHi1
(SKanjiHi12, AByte), // KanjiHi2
(SKanjiHi3, AByte), // KanjiHi3
(SByte, AIdle), // KanjiLo1
(SByte, AIdle), // KanjiLo2
(SByte, AIdle), // Byte
(State::Init, Action::Byte), // End
(State::Alpha, Action::Byte), // Symbol
(State::Numeric, Action::Byte), // Numeric
(State::Alpha, Action::Byte), // Alpha
(State::KanjiHi12, Action::Byte), // KanjiHi1
(State::KanjiHi12, Action::Byte), // KanjiHi2
(State::KanjiHi3, Action::Byte), // KanjiHi3
(State::Byte, Action::Idle), // KanjiLo1
(State::Byte, Action::Idle), // KanjiLo2
(State::Byte, Action::Idle), // Byte
// KanjiHi12 state:
(SInit, AKanjiAndSingleByte), // End
(SAlpha, AKanjiAndSingleByte), // Symbol
(SNumeric, AKanjiAndSingleByte), // Numeric
(SKanji, AIdle), // Alpha
(SKanji, AIdle), // KanjiHi1
(SKanji, AIdle), // KanjiHi2
(SKanji, AIdle), // KanjiHi3
(SKanji, AIdle), // KanjiLo1
(SKanji, AIdle), // KanjiLo2
(SByte, AKanjiAndSingleByte), // Byte
(State::Init, Action::KanjiAndSingleByte), // End
(State::Alpha, Action::KanjiAndSingleByte), // Symbol
(State::Numeric, Action::KanjiAndSingleByte), // Numeric
(State::Kanji, Action::Idle), // Alpha
(State::Kanji, Action::Idle), // KanjiHi1
(State::Kanji, Action::Idle), // KanjiHi2
(State::Kanji, Action::Idle), // KanjiHi3
(State::Kanji, Action::Idle), // KanjiLo1
(State::Kanji, Action::Idle), // KanjiLo2
(State::Byte, Action::KanjiAndSingleByte), // Byte
// KanjiHi3 state:
(SInit, AKanjiAndSingleByte), // End
(SAlpha, AKanjiAndSingleByte), // Symbol
(SNumeric, AKanjiAndSingleByte), // Numeric
(SKanji, AIdle), // Alpha
(SKanji, AIdle), // KanjiHi1
(SKanjiHi12, AKanjiAndSingleByte), // KanjiHi2
(SKanjiHi3, AKanjiAndSingleByte), // KanjiHi3
(SKanji, AIdle), // KanjiLo1
(SByte, AKanjiAndSingleByte), // KanjiLo2
(SByte, AKanjiAndSingleByte), // Byte
(State::Init, Action::KanjiAndSingleByte), // End
(State::Alpha, Action::KanjiAndSingleByte), // Symbol
(State::Numeric, Action::KanjiAndSingleByte), // Numeric
(State::Kanji, Action::Idle), // Alpha
(State::Kanji, Action::Idle), // KanjiHi1
(State::KanjiHi12, Action::KanjiAndSingleByte), // KanjiHi2
(State::KanjiHi3, Action::KanjiAndSingleByte), // KanjiHi3
(State::Kanji, Action::Idle), // KanjiLo1
(State::Byte, Action::KanjiAndSingleByte), // KanjiLo2
(State::Byte, Action::KanjiAndSingleByte), // Byte
// Kanji state:
(SInit, AKanji), // End
(SAlpha, AKanji), // Symbol
(SNumeric, AKanji), // Numeric
(SAlpha, AKanji), // Alpha
(SKanjiHi12, AIdle), // KanjiHi1
(SKanjiHi12, AIdle), // KanjiHi2
(SKanjiHi3, AIdle), // KanjiHi3
(SByte, AKanji), // KanjiLo1
(SByte, AKanji), // KanjiLo2
(SByte, AKanji), // Byte
(State::Init, Action::Kanji), // End
(State::Alpha, Action::Kanji), // Symbol
(State::Numeric, Action::Kanji), // Numeric
(State::Alpha, Action::Kanji), // Alpha
(State::KanjiHi12, Action::Idle), // KanjiHi1
(State::KanjiHi12, Action::Idle), // KanjiHi2
(State::KanjiHi3, Action::Idle), // KanjiHi3
(State::Byte, Action::Kanji), // KanjiLo1
(State::Byte, Action::Kanji), // KanjiLo2
(State::Byte, Action::Kanji), // Byte
];
//}}}

View file

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