Start using quickcheck and add inline hints
This commit is contained in:
parent
c950a68bfe
commit
64edc9110e
10 changed files with 69 additions and 1 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue