#![unstable]
#![feature(slicing_syntax)]
#![feature(while_let)]
extern crate test;
pub use types::{QrResult, EcLevel, Version};
pub mod types;
pub mod bits;
pub mod optimize;
pub mod ec;
pub mod canvas;
#[deriving(Clone)]
pub struct QrCode {
content: Vec<bool>,
version: Version,
ec_level: EcLevel,
width: uint,
}
impl QrCode {
pub fn new(data: &[u8]) -> QrResult<QrCode> {
QrCode::with_error_correction_level(data, EcLevel::M)
}
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)
}
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));
QrCode::with_bits(bits, ec_level)
}
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);
let canvas = canvas.apply_best_mask();
Ok(QrCode {
content: canvas.to_bools(),
version: version,
ec_level: ec_level,
width: version.width() as uint,
})
}
pub fn version(&self) -> Version {
self.version
}
pub fn error_correction_level(&self) -> EcLevel {
self.ec_level
}
pub fn width(&self) -> uint {
self.width
}
pub fn to_debug_str(&self, on_char: char, off_char: char) -> String {
let width = self.width;
let mut k = 0;
let mut res = String::with_capacity(width * (width + 1));
for _ in range(0, width) {
res.push('\n');
for _ in range(0, width) {
res.push(if self.content[k] { on_char } else { off_char });
k += 1;
}
}
res
}
pub fn to_vec(&self) -> Vec<bool> {
self.content.clone()
}
pub fn into_vec(self) -> Vec<bool> {
self.content.clone()
}
}
impl Index<(uint, uint), bool> for QrCode {
fn index(&self, &(x, y): &(uint, uint)) -> &bool {
let index = y * self.width + x;
self.content.index(&index)
}
}
#[cfg(test)]
mod tests {
use {QrCode, Version, EcLevel};
#[test]
fn test_annex_i_qr() {
let code = QrCode::with_version(b"01234567", Version::Normal(1), EcLevel::M).unwrap();
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######..#.##.#######\n\
#.....#..####.#.....#\n\
#.###.#.#.....#.###.#\n\
#.###.#.##....#.###.#\n\
#.###.#.#.###.#.###.#\n\
#.....#.#...#.#.....#\n\
#######.#.#.#.#######\n\
........#..##........\n\
#.#####..#..#.#####..\n\
...#.#.##.#.#..#.##..\n\
..#...##.#.#.#..#####\n\
....#....#.....####..\n\
...######..#.#..#....\n\
........#.#####..##..\n\
#######..##.#.##.....\n\
#.....#.#.#####...#.#\n\
#.###.#.#...#..#.##..\n\
#.###.#.##..#..#.....\n\
#.###.#.#.##.#..#.#..\n\
#.....#........##.##.\n\
#######.####.#..#.#..");
}
#[test]
fn test_annex_i_micro_qr() {
let code = QrCode::with_version(b"01234567", Version::Micro(2), EcLevel::L).unwrap();
assert_eq!(&*code.to_debug_str('#', '.'), "\n\
#######.#.#.#\n\
#.....#.###.#\n\
#.###.#..##.#\n\
#.###.#..####\n\
#.###.#.###..\n\
#.....#.#...#\n\
#######..####\n\
.........##..\n\
##.#....#...#\n\
.##.#.#.#.#.#\n\
###..#######.\n\
...#.#....##.\n\
###.#..##.###");
}
}