rustup for beta.

This commit is contained in:
kennytm 2015-04-05 16:18:28 +08:00
parent 9f2adaad82
commit 6ebf629ba4
5 changed files with 52 additions and 22 deletions

View file

@ -2,9 +2,13 @@
name = "qrcode" name = "qrcode"
description = "QR code encoder in Rust" description = "QR code encoder in Rust"
license = "Apache-2.0" license = "Apache-2.0"
version = "0.1.3" version = "0.1.4"
authors = ["kennytm <kennytm@gmail.com>"] authors = ["kennytm <kennytm@gmail.com>"]
keywords = ["qrcode"] keywords = ["qrcode"]
repository = "https://github.com/kennytm/qrcode-rust" repository = "https://github.com/kennytm/qrcode-rust"
readme = "README.md" readme = "README.md"
documentation = "http://www.rust-ci.org/kennytm/qrcode-rust/doc/qrcode/index.html" documentation = "http://www.rust-ci.org/kennytm/qrcode-rust/doc/qrcode/index.html"
[dependencies]
num = "*"

View file

@ -3,7 +3,6 @@
//! The `bits` module encodes binary data into raw bits used in a QR code. //! The `bits` module encodes binary data into raw bits used in a QR code.
use std::cmp::min; use std::cmp::min;
use std::iter::iterate;
#[cfg(test)] #[cfg(test)]
use test::Bencher; use test::Bencher;
@ -143,7 +142,7 @@ fn bench_push_splitted_bytes(bencher: &mut Bencher) {
/// An "extended" mode indicator, includes all indicators supported by QR code /// An "extended" mode indicator, includes all indicators supported by QR code
/// beyond those bearing data. /// beyond those bearing data.
#[derive(Copy)] #[derive(Copy, Clone)]
pub enum ExtendedMode { pub enum ExtendedMode {
/// ECI mode indicator, to introduce an ECI designator. /// ECI mode indicator, to introduce an ECI designator.
Eci, Eci,
@ -676,10 +675,12 @@ impl Bits {
} }
if self.len() < data_length { if self.len() < data_length {
const PADDING_BYTES: &'static [u8] = &[0b11101100, 0b00010001];
self.bit_offset = 0; self.bit_offset = 0;
let data_bytes_length = data_length / 8; let data_bytes_length = data_length / 8;
let padding_bytes_count = data_bytes_length - self.data.len(); let padding_bytes_count = data_bytes_length - self.data.len();
let padding = iterate(0b11101100, |a| a ^ 0b11111101).take(padding_bytes_count); let padding = PADDING_BYTES.iter().cloned().cycle().take(padding_bytes_count);
self.data.extend(padding); self.data.extend(padding);
} }

View file

@ -9,13 +9,19 @@
//! c.apply_mask(MaskPattern::Checkerboard); //! c.apply_mask(MaskPattern::Checkerboard);
//! let bools = c.to_bools(); //! let bools = c.to_bools();
use std::iter::{range_inclusive, repeat}; use std::iter::repeat;
use std::iter::order::equals;
use std::num::Int;
use std::cmp::max; use std::cmp::max;
use num::traits::PrimInt;
use std::ops::Range;
use types::{Version, EcLevel}; use types::{Version, EcLevel};
// TODO remove this after it is decided whether we want `p ... q` or
// `(p .. q).inclusive()`
fn range_inclusive<N: PrimInt>(from: N, to: N) -> Range<N> {
from .. (to + N::one())
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//{{{ Modules //{{{ Modules
@ -621,10 +627,10 @@ impl Canvas {
/// `off_color`. The coordinates will be extracted from the `coords` /// `off_color`. The coordinates will be extracted from the `coords`
/// iterator. It will start from the most significant bits first, so /// iterator. It will start from the most significant bits first, so
/// *trailing* zeros will be ignored. /// *trailing* zeros will be ignored.
fn draw_number<N: Int>(&mut self, number: N, fn draw_number<N: PrimInt>(&mut self, number: N,
on_color: Module, off_color: Module, on_color: Module, off_color: Module,
coords: &[(i16, i16)]) { coords: &[(i16, i16)]) {
let zero: N = Int::zero(); let zero: N = N::zero();
let mut mask: N = !(!zero >> 1); let mut mask: N = !(!zero >> 1);
for &(x, y) in coords { for &(x, y) in coords {
let color = if (mask & number) == zero { off_color } else { on_color }; let color = if (mask & number) == zero { off_color } else { on_color };
@ -887,8 +893,6 @@ impl Canvas {
/// Gets whether the module at the given coordinates represents a functional /// Gets whether the module at the given coordinates represents a functional
/// module. /// module.
pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool { pub fn is_functional(version: Version, width: i16, x: i16, y: i16) -> bool {
use std::num::SignedInt;
debug_assert!(width == version.width()); debug_assert!(width == version.width());
let x = if x < 0 { x + width } else { x }; let x = if x < 0 { x + width } else { x };
@ -1372,7 +1376,7 @@ mod draw_codewords_test {
/// The mask patterns. Since QR code and Micro QR code do not use the same /// The mask patterns. Since QR code and Micro QR code do not use the same
/// pattern number, we name them according to their shape instead of the number. /// pattern number, we name them according to their shape instead of the number.
#[derive(Debug, Copy)] #[derive(Debug, Copy, Clone)]
pub enum MaskPattern { pub enum MaskPattern {
/// QR code pattern 000: `(x + y) % 2 == 0`. /// QR code pattern 000: `(x + y) % 2 == 0`.
Checkerboard = 0b000, Checkerboard = 0b000,
@ -1649,6 +1653,13 @@ impl Canvas {
Module::Dark, Module::Light, Module::Dark, Module::Dark, Module::Light, Module::Dark,
]; ];
// TODO remove this after `equals()` is stable.
fn equals<T, U>(left: T, right: U) -> bool
where T: Iterator, U: Iterator, T::Item: PartialEq<U::Item>
{
left.zip(right).all(|(p, q)| p == q)
}
let mut total_score = 0; let mut total_score = 0;
for i in 0 .. self.width { for i in 0 .. self.width {
@ -1845,11 +1856,23 @@ impl Canvas {
Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(), Version::Micro(_) => ALL_PATTERNS_MICRO_QR.iter(),
}; };
patterns.map(|ptn| { let mut patterns = patterns.map(|ptn| {
let mut c = self.clone(); let mut c = self.clone();
c.apply_mask(*ptn); c.apply_mask(*ptn);
c c
}).min_by(|c| c.compute_total_penalty_scores()).unwrap() });
// TODO revert to `min_by` after it is stable.
let mut best_pattern = patterns.next().unwrap();
let mut best_pattern_score = best_pattern.compute_total_penalty_scores();
for c in patterns {
let score = c.compute_total_penalty_scores();
if score < best_pattern_score {
best_pattern = c;
best_pattern_score = score;
}
}
best_pattern
} }
/// Convert the modules into a vector of booleans. /// Convert the modules into a vector of booleans.

View file

@ -19,9 +19,11 @@
//! //!
#![unstable] #![unstable]
#![feature(test, core)] // Unstable libraries #![cfg_attr(test, feature(test))] // Unstable libraries
#[cfg(test)]
extern crate test; extern crate test;
extern crate num;
use std::ops::Index; use std::ops::Index;

View file

@ -322,8 +322,8 @@ impl<I: Iterator<Item=Segment>> Iterator 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: Version) -> usize { pub fn total_encoded_len(segments: &[Segment], version: Version) -> usize {
use std::iter::AdditiveIterator; // TODO revert to `.map().sum()` after `sum()` is stable.
segments.iter().map(|seg| seg.encoded_len(version)).sum() segments.iter().fold(0, |acc, seg| acc + seg.encoded_len(version))
} }
#[cfg(test)] #[cfg(test)]
@ -471,7 +471,7 @@ fn bench_optimize(bencher: &mut Bencher) {
/// 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.
#[derive(Copy)] #[derive(Copy, Clone)]
enum ExclCharSet { enum ExclCharSet {
/// The end of string. /// The end of string.
End = 0, End = 0,
@ -531,7 +531,7 @@ impl ExclCharSet {
} }
/// The current parsing state. /// The current parsing state.
#[derive(Copy)] #[derive(Copy, Clone)]
enum State { enum State {
/// Just initialized. /// Just initialized.
Init = 0, Init = 0,
@ -558,7 +558,7 @@ enum State {
} }
/// What should the parser do after a state transition. /// What should the parser do after a state transition.
#[derive(Copy)] #[derive(Copy, Clone)]
enum Action { enum Action {
/// The parser should do nothing. /// The parser should do nothing.
Idle, Idle,