Apply clippy fixes

This commit is contained in:
Josh Holmer 2018-07-28 16:51:54 -04:00
parent 868fd502b9
commit f862a0df24
10 changed files with 99 additions and 93 deletions

View file

@ -25,7 +25,8 @@ impl AtomicMin {
let mut current_val = self.val.load(Relaxed); let mut current_val = self.val.load(Relaxed);
loop { loop {
if new_val < current_val { if new_val < current_val {
if let Err(v) = self.val if let Err(v) = self
.val
.compare_exchange(current_val, new_val, SeqCst, Relaxed) .compare_exchange(current_val, new_val, SeqCst, Relaxed)
{ {
current_val = v; current_val = v;

View file

@ -35,8 +35,8 @@ impl fmt::Display for ColorType {
impl ColorType { impl ColorType {
/// Get the code used by the PNG specification to denote this color type /// Get the code used by the PNG specification to denote this color type
#[inline] #[inline]
pub fn png_header_code(&self) -> u8 { pub fn png_header_code(self) -> u8 {
match *self { match self {
ColorType::Grayscale => 0, ColorType::Grayscale => 0,
ColorType::RGB => 2, ColorType::RGB => 2,
ColorType::Indexed => 3, ColorType::Indexed => 3,
@ -46,8 +46,8 @@ impl ColorType {
} }
#[inline] #[inline]
pub fn channels_per_pixel(&self) -> u8 { pub fn channels_per_pixel(self) -> u8 {
match *self { match self {
ColorType::Grayscale | ColorType::Indexed => 1, ColorType::Grayscale | ColorType::Indexed => 1,
ColorType::GrayscaleAlpha => 2, ColorType::GrayscaleAlpha => 2,
ColorType::RGB => 3, ColorType::RGB => 3,
@ -91,8 +91,8 @@ impl fmt::Display for BitDepth {
impl BitDepth { impl BitDepth {
/// Retrieve the number of bits per channel per pixel as a `u8` /// Retrieve the number of bits per channel per pixel as a `u8`
#[inline] #[inline]
pub fn as_u8(&self) -> u8 { pub fn as_u8(self) -> u8 {
match *self { match self {
BitDepth::One => 1, BitDepth::One => 1,
BitDepth::Two => 2, BitDepth::Two => 2,
BitDepth::Four => 4, BitDepth::Four => 4,

View file

@ -1,6 +1,7 @@
use atomicmin::AtomicMin; use atomicmin::AtomicMin;
use error::PngError; use error::PngError;
use miniz_oxide::deflate::core::*; use miniz_oxide::deflate::core::*;
use PngResult;
pub fn compress_to_vec_oxipng( pub fn compress_to_vec_oxipng(
input: &[u8], input: &[u8],
@ -8,7 +9,7 @@ pub fn compress_to_vec_oxipng(
window_bits: i32, window_bits: i32,
strategy: i32, strategy: i32,
max_size: &AtomicMin, max_size: &AtomicMin,
) -> Result<Vec<u8>, PngError> { ) -> PngResult<Vec<u8>> {
// The comp flags function sets the zlib flag if the window_bits parameter is > 0. // The comp flags function sets the zlib flag if the window_bits parameter is > 0.
let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy); let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy);
let mut compressor = CompressorOxide::new(flags); let mut compressor = CompressorOxide::new(flags);

View file

@ -3,24 +3,19 @@ use error::PngError;
use miniz_oxide; use miniz_oxide;
use std::cmp::max; use std::cmp::max;
use zopfli; use zopfli;
use PngResult;
#[doc(hidden)] #[doc(hidden)]
pub mod miniz_stream; pub mod miniz_stream;
/// Decompress a data stream using the DEFLATE algorithm /// Decompress a data stream using the DEFLATE algorithm
pub fn inflate(data: &[u8]) -> Result<Vec<u8>, PngError> { pub fn inflate(data: &[u8]) -> PngResult<Vec<u8>> {
miniz_oxide::inflate::decompress_to_vec_zlib(data) miniz_oxide::inflate::decompress_to_vec_zlib(data)
.map_err(|e| PngError::new(&format!("Error on decompress: {:?}", e))) .map_err(|e| PngError::new(&format!("Error on decompress: {:?}", e)))
} }
/// Compress a data stream using the DEFLATE algorithm /// Compress a data stream using the DEFLATE algorithm
pub fn deflate( pub fn deflate(data: &[u8], zc: u8, zs: u8, zw: u8, max_size: &AtomicMin) -> PngResult<Vec<u8>> {
data: &[u8],
zc: u8,
zs: u8,
zw: u8,
max_size: &AtomicMin,
) -> Result<Vec<u8>, PngError> {
#[cfg(feature = "cfzlib")] #[cfg(feature = "cfzlib")]
{ {
if is_cfzlib_supported() { if is_cfzlib_supported() {
@ -55,7 +50,7 @@ pub fn cfzlib_deflate(
strategy: u8, strategy: u8,
window_bits: u8, window_bits: u8,
max_size: &AtomicMin, max_size: &AtomicMin,
) -> Result<Vec<u8>, PngError> { ) -> PngResult<Vec<u8>> {
use cloudflare_zlib_sys::*; use cloudflare_zlib_sys::*;
use std::mem; use std::mem;
@ -98,7 +93,7 @@ pub fn cfzlib_deflate(
} }
} }
pub fn zopfli_deflate(data: &[u8]) -> Result<Vec<u8>, PngError> { pub fn zopfli_deflate(data: &[u8]) -> PngResult<Vec<u8>> {
let mut output = Vec::with_capacity(max(1024, data.len() / 20)); let mut output = Vec::with_capacity(max(1024, data.len() / 20));
let options = zopfli::Options::default(); let options = zopfli::Options::default();
match zopfli::compress(&options, &zopfli::Format::Zlib, data, &mut output) { match zopfli::compress(&options, &zopfli::Format::Zlib, data, &mut output) {

View file

@ -32,9 +32,8 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> Vec
}); });
} else { } else {
filtered.push(match i.checked_sub(bpp) { filtered.push(match i.checked_sub(bpp) {
Some(x) => byte.wrapping_sub( Some(x) => byte
((u16::from(data[x]) + u16::from(last_line[i])) >> 1) as u8, .wrapping_sub(((u16::from(data[x]) + u16::from(last_line[i])) >> 1) as u8),
),
None => byte.wrapping_sub(last_line[i] >> 1), None => byte.wrapping_sub(last_line[i] >> 1),
}); });
}; };
@ -87,31 +86,33 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V
); );
}; };
} }
3 => for (i, byte) in data.iter().enumerate() { 3 => {
if last_line.is_empty() { for (i, byte) in data.iter().enumerate() {
match i.checked_sub(bpp) { if last_line.is_empty() {
Some(x) => { match i.checked_sub(bpp) {
let b = unfiltered[x]; Some(x) => {
unfiltered.push(byte.wrapping_add(b >> 1)); let b = unfiltered[x];
} unfiltered.push(byte.wrapping_add(b >> 1));
None => { }
unfiltered.push(*byte); None => {
} unfiltered.push(*byte);
}
};
} else {
match i.checked_sub(bpp) {
Some(x) => {
let b = unfiltered[x];
unfiltered.push(byte.wrapping_add(
((u16::from(b) + u16::from(last_line[i])) >> 1) as u8,
));
}
None => {
unfiltered.push(byte.wrapping_add(last_line[i] >> 1));
}
};
}; };
} else { }
match i.checked_sub(bpp) { }
Some(x) => {
let b = unfiltered[x];
unfiltered.push(byte.wrapping_add(
((u16::from(b) + u16::from(last_line[i])) >> 1) as u8,
));
}
None => {
unfiltered.push(byte.wrapping_add(last_line[i] >> 1));
}
};
};
},
4 => for (i, byte) in data.iter().enumerate() { 4 => for (i, byte) in data.iter().enumerate() {
if last_line.is_empty() { if last_line.is_empty() {
match i.checked_sub(bpp) { match i.checked_sub(bpp) {

View file

@ -4,6 +4,7 @@ use crc::crc32;
use error::PngError; use error::PngError;
use std::collections::HashSet; use std::collections::HashSet;
use std::io::Cursor; use std::io::Cursor;
use PngResult;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
/// Headers from the IHDR chunk of the image /// Headers from the IHDR chunk of the image
@ -46,14 +47,22 @@ pub fn file_header_is_valid(bytes: &[u8]) -> bool {
*bytes == expected_header *bytes == expected_header
} }
#[derive(Debug, Clone, Copy)]
pub struct RawHeader<'a> {
pub name: &'a [u8],
pub data: &'a [u8],
}
pub fn parse_next_header<'a>( pub fn parse_next_header<'a>(
byte_data: &'a [u8], byte_data: &'a [u8],
byte_offset: &mut usize, byte_offset: &mut usize,
fix_errors: bool, fix_errors: bool,
) -> Result<Option<(&'a [u8], &'a [u8])>, PngError> { ) -> PngResult<Option<RawHeader<'a>>> {
let mut rdr = Cursor::new(byte_data let mut rdr = Cursor::new(
.get(*byte_offset..*byte_offset + 4) byte_data
.ok_or(PngError::TruncatedData)?); .get(*byte_offset..*byte_offset + 4)
.ok_or(PngError::TruncatedData)?,
);
let length = rdr.read_u32::<BigEndian>().unwrap(); let length = rdr.read_u32::<BigEndian>().unwrap();
*byte_offset += 4; *byte_offset += 4;
@ -71,9 +80,11 @@ pub fn parse_next_header<'a>(
.get(*byte_offset..*byte_offset + length as usize) .get(*byte_offset..*byte_offset + length as usize)
.ok_or(PngError::TruncatedData)?; .ok_or(PngError::TruncatedData)?;
*byte_offset += length as usize; *byte_offset += length as usize;
let mut rdr = Cursor::new(byte_data let mut rdr = Cursor::new(
.get(*byte_offset..*byte_offset + 4) byte_data
.ok_or(PngError::TruncatedData)?); .get(*byte_offset..*byte_offset + 4)
.ok_or(PngError::TruncatedData)?,
);
let crc = rdr.read_u32::<BigEndian>().unwrap(); let crc = rdr.read_u32::<BigEndian>().unwrap();
*byte_offset += 4; *byte_offset += 4;
@ -87,10 +98,13 @@ pub fn parse_next_header<'a>(
))); )));
} }
Ok(Some((chunk_name, data))) Ok(Some(RawHeader {
name: chunk_name,
data,
}))
} }
pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, PngError> { pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult<IhdrData> {
let mut rdr = Cursor::new(&byte_data[0..8]); let mut rdr = Cursor::new(&byte_data[0..8]);
Ok(IhdrData { Ok(IhdrData {
color_type: match byte_data[9] { color_type: match byte_data[9] {

View file

@ -21,7 +21,7 @@ use std::fmt;
use std::fs::{copy, File}; use std::fs::{copy, File};
use std::io::{stdin, stdout, BufWriter, Read, Write}; use std::io::{stdin, stdout, BufWriter, Read, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Mutex; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
pub use colors::AlphaOptim; pub use colors::AlphaOptim;
@ -96,6 +96,8 @@ impl<T: Into<PathBuf>> From<T> for InFile {
} }
} }
pub type PngResult<T> = Result<T, PngError>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Options controlling the output of the `optimize` function /// Options controlling the output of the `optimize` function
pub struct Options { pub struct Options {
@ -321,7 +323,7 @@ impl Default for Options {
} }
/// Perform optimization on the input file using the options provided /// Perform optimization on the input file using the options provided
pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> Result<(), PngError> { pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<()> {
// Initialize the thread pool with correct number of threads // Initialize the thread pool with correct number of threads
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
let thread_count = opts.threads; let thread_count = opts.threads;
@ -418,7 +420,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> Result<(),
/// Perform optimization on the input file using the options provided, where the file is already /// Perform optimization on the input file using the options provided, where the file is already
/// loaded in-memory /// loaded in-memory
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngError> { pub fn optimize_from_memory(data: &[u8], opts: &Options) -> PngResult<Vec<u8>> {
// Initialize the thread pool with correct number of threads // Initialize the thread pool with correct number of threads
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
let thread_count = opts.threads; let thread_count = opts.threads;
@ -454,11 +456,7 @@ struct TrialOptions {
} }
/// Perform optimization on the input PNG object using the options provided /// Perform optimization on the input PNG object using the options provided
fn optimize_png( fn optimize_png(png: &mut PngData, original_data: &[u8], opts: &Options) -> PngResult<Vec<u8>> {
png: &mut PngData,
original_data: &[u8],
opts: &Options,
) -> Result<Vec<u8>, PngError> {
type TrialWithData = (TrialOptions, Vec<u8>); type TrialWithData = (TrialOptions, Vec<u8>);
let deadline = Deadline::new(opts); let deadline = Deadline::new(opts);
@ -771,7 +769,7 @@ fn perform_reductions(png: &mut PngData, opts: &Options, deadline: &Deadline) ->
struct Deadline { struct Deadline {
start: Instant, start: Instant,
timeout: Option<Duration>, timeout: Option<Duration>,
print_message: Mutex<bool>, print_message: AtomicBool,
} }
impl Deadline { impl Deadline {
@ -779,7 +777,7 @@ impl Deadline {
Self { Self {
start: Instant::now(), start: Instant::now(),
timeout: opts.timeout, timeout: opts.timeout,
print_message: Mutex::new(opts.verbosity.is_some()), print_message: AtomicBool::new(opts.verbosity.is_some()),
} }
} }
@ -789,9 +787,8 @@ impl Deadline {
pub fn passed(&self) -> bool { pub fn passed(&self) -> bool {
if let Some(timeout) = self.timeout { if let Some(timeout) = self.timeout {
if self.start.elapsed() > timeout { if self.start.elapsed() > timeout {
let mut print_message = self.print_message.lock().unwrap(); if self.print_message.load(Ordering::Relaxed) {
if *print_message { self.print_message.store(false, Ordering::Relaxed);
*print_message = false;
eprintln!("Timed out after {} second(s)", timeout.as_secs()); eprintln!("Timed out after {} second(s)", timeout.as_secs());
} }
return true; return true;
@ -852,7 +849,7 @@ fn is_fully_optimized(original_size: usize, optimized_size: usize, opts: &Option
original_size <= optimized_size && !opts.force && opts.interlace.is_none() original_size <= optimized_size && !opts.force && opts.interlace.is_none()
} }
fn perform_backup(input_path: &Path) -> Result<(), PngError> { fn perform_backup(input_path: &Path) -> PngResult<()> {
let backup_file = input_path.with_extension(format!( let backup_file = input_path.with_extension(format!(
"bak.{}", "bak.{}",
input_path.extension().unwrap().to_str().unwrap() input_path.extension().unwrap().to_str().unwrap()

View file

@ -9,8 +9,9 @@ use clap::{App, AppSettings, Arg, ArgMatches};
use oxipng::AlphaOptim; use oxipng::AlphaOptim;
use oxipng::Deflaters; use oxipng::Deflaters;
use oxipng::Headers; use oxipng::Headers;
use oxipng::Options;
use oxipng::PngResult;
use oxipng::{InFile, OutFile}; use oxipng::{InFile, OutFile};
use oxipng::{Options, PngError};
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::DirBuilder; use std::fs::DirBuilder;
use std::path::PathBuf; use std::path::PathBuf;
@ -240,7 +241,7 @@ fn main() {
true, true,
); );
let res: Result<(), PngError> = files let res: PngResult<()> = files
.into_iter() .into_iter()
.map(|(input, output)| oxipng::optimize(&input, &output, &opts)) .map(|(input, output)| oxipng::optimize(&input, &output, &opts))
.collect(); .collect();
@ -321,7 +322,8 @@ fn parse_opts_into_struct(
} }
if let Some(x) = matches.value_of("timeout") { if let Some(x) = matches.value_of("timeout") {
let num = x.parse() let num = x
.parse()
.map_err(|_| "Timeout must be a number".to_owned())?; .map_err(|_| "Timeout must be a number".to_owned())?;
opts.timeout = Some(Duration::from_secs(num)); opts.timeout = Some(Duration::from_secs(num));
} }
@ -435,7 +437,8 @@ fn parse_opts_into_struct(
} }
if let Some(hdrs) = matches.value_of("strip") { if let Some(hdrs) = matches.value_of("strip") {
let hdrs = hdrs.split(',') let hdrs = hdrs
.split(',')
.map(|x| x.trim().to_owned()) .map(|x| x.trim().to_owned())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
if hdrs.contains(&"safe".to_owned()) || hdrs.contains(&"all".to_owned()) { if hdrs.contains(&"safe".to_owned()) || hdrs.contains(&"all".to_owned()) {
@ -525,5 +528,5 @@ fn parse_numeric_range_opts(
return Ok(items); return Ok(items);
} }
return Err(ERROR_MESSAGE.to_owned()); Err(ERROR_MESSAGE.to_owned())
} }

View file

@ -95,19 +95,14 @@ impl PngData {
// Read the data headers // Read the data headers
let mut aux_headers: HashMap<String, Vec<u8>> = HashMap::new(); let mut aux_headers: HashMap<String, Vec<u8>> = HashMap::new();
let mut idat_headers: Vec<u8> = Vec::new(); let mut idat_headers: Vec<u8> = Vec::new();
loop { while let Some(header) = parse_next_header(byte_data, &mut byte_offset, fix_errors)? {
let header = parse_next_header(byte_data, &mut byte_offset, fix_errors)?; match header.name {
let (name, data) = match header { b"IDAT" => idat_headers.extend(header.data),
Some(x) => x,
None => break,
};
match name {
b"IDAT" => idat_headers.extend(data),
b"acTL" => return Err(PngError::APNGNotSupported), b"acTL" => return Err(PngError::APNGNotSupported),
_ => { _ => {
let name = let name = String::from_utf8(header.name.to_owned())
String::from_utf8(name.to_owned()).map_err(|_| PngError::InvalidData)?; .map_err(|_| PngError::InvalidData)?;
aux_headers.insert(name, data.to_owned()); aux_headers.insert(name, header.data.to_owned());
} }
} }
} }
@ -184,7 +179,8 @@ impl PngData {
let _ = ihdr_data.write_u8(self.ihdr_data.interlaced); let _ = ihdr_data.write_u8(self.ihdr_data.interlaced);
write_png_block(b"IHDR", &ihdr_data, &mut output); write_png_block(b"IHDR", &ihdr_data, &mut output);
// Ancillary headers // Ancillary headers
for (key, header) in self.aux_headers for (key, header) in self
.aux_headers
.iter() .iter()
.filter(|&(key, _)| !(*key == "bKGD" || *key == "hIST" || *key == "tRNS")) .filter(|&(key, _)| !(*key == "bKGD" || *key == "hIST" || *key == "tRNS"))
{ {
@ -202,7 +198,8 @@ impl PngData {
write_png_block(b"tRNS", transparency_pixel, &mut output); write_png_block(b"tRNS", transparency_pixel, &mut output);
} }
// Special ancillary headers that need to come after PLTE but before IDAT // Special ancillary headers that need to come after PLTE but before IDAT
for (key, header) in self.aux_headers for (key, header) in self
.aux_headers
.iter() .iter()
.filter(|&(key, _)| *key == "bKGD" || *key == "hIST" || *key == "tRNS") .filter(|&(key, _)| *key == "bKGD" || *key == "hIST" || *key == "tRNS")
{ {
@ -713,12 +710,11 @@ impl PngData {
fn reduce_alpha_to_up(&self, bpc: usize, bpp: usize) -> Vec<u8> { fn reduce_alpha_to_up(&self, bpc: usize, bpp: usize) -> Vec<u8> {
let mut lines = Vec::new(); let mut lines = Vec::new();
let mut scan_lines = self.scan_lines() let mut scan_lines = self.scan_lines().collect::<Vec<ScanLine>>();
.collect::<Vec<ScanLine>>();
scan_lines.reverse(); scan_lines.reverse();
let mut last_line = vec![0; scan_lines[0].data.len()]; let mut last_line = vec![0; scan_lines[0].data.len()];
let mut current_line = Vec::with_capacity(last_line.len()); let mut current_line = Vec::with_capacity(last_line.len());
for line in scan_lines.into_iter() { for line in scan_lines {
current_line.push(line.filter); current_line.push(line.filter);
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) { for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 { if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {

View file

@ -8,10 +8,8 @@ pub fn reduce_alpha_channel(png: &mut PngData, channels: u8) -> Option<Vec<u8>>
let colored_bytes = bpp - byte_depth; let colored_bytes = bpp - byte_depth;
for line in png.scan_lines() { for line in png.scan_lines() {
for (i, &byte) in line.data.iter().enumerate() { for (i, &byte) in line.data.iter().enumerate() {
if i as u8 & bpp_mask >= colored_bytes { if i as u8 & bpp_mask >= colored_bytes && byte != 255 {
if byte != 255 { return None;
return None;
}
} }
} }
} }