Start using quickcheck and add inline hints

This commit is contained in:
Josh Holmer 2016-07-30 23:14:36 -04:00
parent c950a68bfe
commit 64edc9110e
10 changed files with 69 additions and 1 deletions

25
Cargo.lock generated
View file

@ -13,6 +13,7 @@ dependencies = [
"libz-sys 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quickcheck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-pool 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -112,6 +113,15 @@ dependencies = [
"num 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "flate2"
version = "0.2.14"
@ -182,6 +192,11 @@ dependencies = [
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matches"
version = "0.1.2"
@ -300,6 +315,16 @@ dependencies = [
"num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quickcheck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quine-mc_cluskey"
version = "0.2.2"

View file

@ -44,6 +44,9 @@ version = "^0.0.79"
optional = true
version = "^0.1.63"
[dev-dependencies]
quickcheck = "^0.3.0"
[dev-dependencies.image]
version = "^0.8.0"
default-features = false

View file

@ -16,6 +16,7 @@ pub enum ColorType {
}
impl fmt::Display for ColorType {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
@ -31,6 +32,7 @@ impl fmt::Display for ColorType {
impl ColorType {
/// Get the code used by the PNG specification to denote this color type
#[inline]
pub fn png_header_code(&self) -> u8 {
match *self {
ColorType::Grayscale => 0,
@ -58,6 +60,7 @@ pub enum BitDepth {
}
impl fmt::Display for BitDepth {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
@ -73,6 +76,7 @@ impl fmt::Display for BitDepth {
impl BitDepth {
/// Retrieve the number of bits per channel per pixel as a `u8`
#[inline]
pub fn as_u8(&self) -> u8 {
match *self {
BitDepth::One => 1,
@ -83,6 +87,7 @@ impl BitDepth {
}
}
/// Parse a number of bits per channel per pixel into a `BitDepth`
#[inline]
pub fn from_u8(depth: u8) -> BitDepth {
match depth {
1 => BitDepth::One,

View file

@ -2,6 +2,8 @@ use libz_sys;
use miniz_sys;
use libc::c_int;
use std::cmp::max;
#[cfg(test)]
use quickcheck::TestResult;
/// Decompress a data stream using the DEFLATE algorithm
pub fn inflate(data: &[u8]) -> Result<Vec<u8>, String> {
@ -58,3 +60,13 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result<Vec<u8>, S
Ok(output)
}
#[cfg(test)]
quickcheck! {
fn quickcheck(data: Vec<u8>, zc: u8, zm: u8, zs: u8, zw: u8) -> TestResult {
if data.is_empty() || zc > 9 || zm == 0 || zm > 9 || zs > 3 || zw > 15 || zw < 8 {
return TestResult::discard();
}
TestResult::from_bool(data == inflate(&deflate(&data, zc, zm, zs, zw).unwrap()).unwrap())
}
}

View file

@ -62,10 +62,12 @@ impl Stream<Compress> {
}
impl<T: Direction> Stream<T> {
#[inline]
pub fn total_in(&self) -> usize {
self.raw.total_in as usize
}
#[inline]
pub fn total_out(&self) -> usize {
self.raw.total_out as usize
}
@ -105,23 +107,27 @@ impl Stream<Compress> {
}
}
#[inline]
pub fn reset(&mut self) -> c_int {
unsafe { libz_sys::deflateReset(&mut self.raw) }
}
}
impl Direction for Compress {
#[inline]
unsafe fn destroy(stream: *mut libz_sys::z_stream) -> c_int {
libz_sys::deflateEnd(stream)
}
}
impl Direction for Decompress {
#[inline]
unsafe fn destroy(stream: *mut libz_sys::z_stream) -> c_int {
libz_sys::inflateEnd(stream)
}
}
impl<D: Direction> Drop for Stream<D> {
#[inline]
fn drop(&mut self) {
unsafe {
let _ = <D as Direction>::destroy(&mut self.raw);

View file

@ -57,10 +57,12 @@ impl Stream<Compress> {
}
impl<T: Direction> Stream<T> {
#[inline]
pub fn total_in(&self) -> usize {
self.raw.total_in as usize
}
#[inline]
pub fn total_out(&self) -> usize {
self.raw.total_out as usize
}
@ -100,23 +102,27 @@ impl Stream<Compress> {
}
}
#[inline]
pub fn reset(&mut self) -> c_int {
unsafe { miniz_sys::mz_deflateReset(&mut self.raw) }
}
}
impl Direction for Compress {
#[inline]
unsafe fn destroy(stream: *mut miniz_sys::mz_stream) -> c_int {
miniz_sys::mz_deflateEnd(stream)
}
}
impl Direction for Decompress {
#[inline]
unsafe fn destroy(stream: *mut miniz_sys::mz_stream) -> c_int {
miniz_sys::mz_inflateEnd(stream)
}
}
impl<D: Direction> Drop for Stream<D> {
#[inline]
fn drop(&mut self) {
unsafe {
let _ = <D as Direction>::destroy(&mut self.raw);

View file

@ -147,6 +147,7 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V
unfiltered
}
#[inline]
fn paeth_predictor(a: u8, b: u8, c: u8) -> u8 {
let p = a as i32 + b as i32 - c as i32;
let pa = (p - a as i32).abs();

View file

@ -35,10 +35,11 @@ pub enum Headers {
All,
}
#[inline]
pub fn file_header_is_valid(bytes: &[u8]) -> bool {
let expected_header: [u8; 8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
bytes.iter().zip(expected_header.iter()).all(|x| x.0 == x.1)
*bytes == expected_header
}
pub fn parse_next_header(byte_data: &[u8],

View file

@ -8,6 +8,10 @@ extern crate miniz_sys;
extern crate num_cpus;
extern crate scoped_pool;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
use headers::Headers;
use scoped_pool::Pool;
use std::collections::{HashMap, HashSet};
@ -536,6 +540,7 @@ fn perform_reductions(png: &mut png::PngData, opts: &Options) -> bool {
}
/// Display the status of the image data after a reduction has taken place
#[inline]
fn report_reduction(png: &png::PngData) {
if let Some(palette) = png.palette.clone() {
writeln!(&mut stderr(),
@ -581,6 +586,7 @@ fn perform_strip(png: &mut png::PngData, opts: &Options) {
}
/// Check if an image was already optimized prior to oxipng's operations
#[inline]
fn is_fully_optimized(original_size: usize, optimized_size: usize, opts: &Options) -> bool {
original_size <= optimized_size && !opts.force && opts.interlace.is_none()
}

View file

@ -272,6 +272,7 @@ impl PngData {
}
/// Return the number of channels in the image, based on color type
#[inline]
pub fn channels_per_pixel(&self) -> u8 {
match self.ihdr_data.color_type {
ColorType::Grayscale | ColorType::Indexed => 1,
@ -733,6 +734,7 @@ impl PngData {
/// Returns true if the interlacing was changed, false otherwise
/// The `interlace` parameter specifies the *new* interlacing mode
/// Assumes that the data has already been de-filtered
#[inline]
pub fn change_interlacing(&mut self, interlace: u8) -> bool {
if interlace == self.ihdr_data.interlaced {
return false;
@ -749,6 +751,7 @@ impl PngData {
}
}
#[inline]
fn write_png_block(key: &[u8], header: &[u8], output: &mut Vec<u8>) {
let mut header_data = Vec::with_capacity(header.len() + 4);
header_data.extend_from_slice(key);