diff --git a/.travis.yml b/.travis.yml index ee3eab5b..b07956f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ matrix: env: TARGET=x86_64-apple-darwin cache: cargo - os: linux - rust: 1.8.0 + rust: 1.9.0 env: TARGET=x86_64-unknown-linux-gnu cache: cargo - os: linux diff --git a/CHANGELOG.md b/CHANGELOG.md index de7c81f3..3cc2ae22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ **Version 0.11.0 (unreleased)** - - [SEMVER_MAJOR] Bump minimum rustc version to 1.8.0, required by dependencies + - [SEMVER_MAJOR] Bump minimum rustc version to 1.9.0, required by dependencies - [SEMVER_MINOR] Allow calling optimization presets via crate using `Options::from_preset` + - [SEMVER_MAJOR] Return proper `PngError` type which implements `std::error::Error` from `Result`s **Version 0.10.0** - [SEMVER_MINOR] Make clap and regex dependencies optional diff --git a/Cargo.lock b/Cargo.lock index aea22eb9..dfb936bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,9 @@ dependencies = [ "clap 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -52,7 +52,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,7 +73,7 @@ version = "0.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -107,7 +107,7 @@ name = "flate2" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -123,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "image" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -142,7 +142,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -161,7 +161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -170,7 +170,7 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -184,7 +184,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,7 +193,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -260,7 +260,7 @@ name = "num_cpus" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -281,7 +281,7 @@ dependencies = [ [[package]] name = "quine-mc_cluskey" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -289,7 +289,7 @@ name = "rand" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -320,7 +320,7 @@ name = "scoped-pool" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "variance 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -353,7 +353,7 @@ name = "term_size" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -362,7 +362,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -426,17 +426,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum clippy 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "4eb4e734b771514b74b44e0d04e176e572d6e0637e32fe112331a0063a22ef39" "checksum clippy_lints 0.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "cd863204278a2011c4bf82417e7e8b869afd949410ce8d0dab14da2c79b96af9" "checksum crc 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a3f9159e74024e2cdb6f574e9117cdc2e91523a890930a022823d17abedc90a" -"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc" +"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79eff5be92a4d7d5bddf7daa7d650717ea71628634efe6ca7bcda85b2183c23" "checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" "checksum gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb000abd6df9df4c637f75190297ebe56c1d7e66b56bbf3b4aa7aece15f61a2" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum image 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7cd7efa3558b1acd537f2a6f9bcf15c4ae4842da38d2e2ea7c9ad023f36239b" +"checksum image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "559d5ebbe9ec73111799e49c07717944b244f8accf5de33a8a8128bc3ecd2e00" "checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb" -"checksum itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7ddb83e0e9730d830afba4e6839077948b4efa22075f7cd80a3867ec286c610f" +"checksum itertools 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f15d694e7f7d46ef7a6951db981b33f132472f91d11b5a0f44d3980b87ccbc3" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" -"checksum libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "39dfaaa0f4da0f1a06876c5d94329d739ad0150868069cc235f1ddf80a0480e7" +"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2" "checksum libz-sys 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab80d82d16acfbf5c0e731297db302378896c0cffbc428dddc61d995a82e15cf" "checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" @@ -451,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a859041cbf7a70ea1ece4b87d1a2c6ef364dcb68749c88db1f97304b9ec09d5f" "checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa" "checksum png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06208e2ee243e3118a55dda9318f821f206d8563fb8d4df258767f8e62bb0997" -"checksum quine-mc_cluskey 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f9a75e9319beed349f32bb252bcd7cafe4cce6c57a9ddcc9a8ffd3c49c3659" +"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2" "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199" diff --git a/README.md b/README.md index 79c08199..20267817 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ cp target/release/oxipng /usr/local/bin Please note that zlib is a required build dependency. Oxipng should work with any 1.x version of zlib, but you are advised to use the latest version (currently 1.2.8) for security and bug fixes. -The current minimum supported Rust version is **1.8.0**. Oxipng may compile on earlier versions of Rust, +The current minimum supported Rust version is **1.9.0**. Oxipng may compile on earlier versions of Rust, but there is no guarantee. Oxipng follows Semantic Versioning. diff --git a/src/deflate/deflate.rs b/src/deflate/deflate.rs index 7452d7e8..2cf54a15 100644 --- a/src/deflate/deflate.rs +++ b/src/deflate/deflate.rs @@ -1,10 +1,11 @@ +use error::PngError; use libz_sys; use miniz_sys; use libc::c_int; use std::cmp::max; /// Decompress a data stream using the DEFLATE algorithm -pub fn inflate(data: &[u8]) -> Result, String> { +pub fn inflate(data: &[u8]) -> Result, PngError> { let mut input = data.to_owned(); let mut stream = super::libz_stream::Stream::new_decompress(); let mut output = Vec::with_capacity(data.len()); @@ -12,7 +13,7 @@ pub fn inflate(data: &[u8]) -> Result, String> { match stream.decompress_vec(input.as_mut(), output.as_mut()) { libz_sys::Z_OK => output.reserve(data.len()), libz_sys::Z_STREAM_END => break, - c => return Err(format!("Error code on decompress: {}", c)), + c => return Err(PngError::new(&format!("Error code on decompress: {}", c))), } } output.shrink_to_fit(); @@ -21,7 +22,7 @@ pub fn inflate(data: &[u8]) -> Result, String> { } /// Compress a data stream using the zlib implementation of the DEFLATE algorithm -pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result, String> { +pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result, PngError> { let mut input = data.to_owned(); // Compressed input should be smaller than decompressed, so allocate less than data.len() // However, it needs a minimum capacity in order to handle very small images @@ -36,7 +37,7 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result, S match stream.compress_vec(input.as_mut(), output.as_mut()) { miniz_sys::MZ_OK => output.reserve(max(1024, data.len() / 20)), miniz_sys::MZ_STREAM_END => break, - c => return Err(format!("Error code on compress: {}", c)), + c => return Err(PngError::new(&format!("Error code on compress: {}", c))), } } } else { @@ -49,7 +50,7 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result, S match stream.compress_vec(input.as_mut(), output.as_mut()) { libz_sys::Z_OK => output.reserve(max(1024, data.len() / 20)), libz_sys::Z_STREAM_END => break, - c => return Err(format!("Error code on compress: {}", c)), + c => return Err(PngError::new(&format!("Error code on compress: {}", c))), } } } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..2bcf4d55 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,25 @@ +use std::error::Error; +use std::fmt; + +#[derive(Debug)] +pub struct PngError { + description: String, +} + +impl Error for PngError { + fn description(&self) -> &str { + &self.description + } +} + +impl fmt::Display for PngError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.description) + } +} + +impl PngError { + pub fn new(description: &str) -> PngError { + PngError { description: description.to_owned() } + } +} diff --git a/src/headers.rs b/src/headers.rs index 9f01de5e..2b8e5f0e 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -1,6 +1,7 @@ use byteorder::{BigEndian, ReadBytesExt}; use colors::{BitDepth, ColorType}; use crc::crc32; +use error::PngError; use std::io::Cursor; #[derive(Debug, Clone, Copy)] @@ -45,7 +46,7 @@ pub fn file_header_is_valid(bytes: &[u8]) -> bool { pub fn parse_next_header(byte_data: &[u8], byte_offset: &mut usize, fix_errors: bool) - -> Result)>, String> { + -> Result)>, PngError> { let mut rdr = Cursor::new(byte_data.iter() .skip(*byte_offset) .take(4) @@ -53,14 +54,14 @@ pub fn parse_next_header(byte_data: &[u8], .collect::>()); let length: u32 = match rdr.read_u32::() { Ok(x) => x, - Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()), + Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")), }; *byte_offset += 4; let mut header_bytes: Vec = byte_data.iter().skip(*byte_offset).take(4).cloned().collect(); let header = match String::from_utf8(header_bytes.clone()) { Ok(x) => x, - Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()), + Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")), }; if header == "IEND" { // End of data @@ -81,19 +82,19 @@ pub fn parse_next_header(byte_data: &[u8], .collect::>()); let crc: u32 = match rdr.read_u32::() { Ok(x) => x, - Err(_) => return Err("Invalid data found--unable to read PNG file".to_owned()), + Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")), }; *byte_offset += 4; header_bytes.extend(data.clone()); if !fix_errors && crc32::checksum_ieee(header_bytes.as_ref()) != crc { - return Err(format!("Corrupt data chunk found--CRC Mismatch in {}\nThis may be recoverable by using --fix", - header)); + return Err(PngError::new(&format!("CRC Mismatch in {} header; May be recoverable by using --fix", + header))); } Ok(Some((header, data))) } -pub fn parse_ihdr_header(byte_data: &[u8]) -> Result { +pub fn parse_ihdr_header(byte_data: &[u8]) -> Result { let mut rdr = Cursor::new(&byte_data[0..8]); Ok(IhdrData { color_type: match byte_data[9] { @@ -102,7 +103,7 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> Result { 3 => ColorType::Indexed, 4 => ColorType::GrayscaleAlpha, 6 => ColorType::RGBA, - _ => return Err("Unexpected color type in header".to_owned()), + _ => return Err(PngError::new("Unexpected color type in header")), }, bit_depth: match byte_data[8] { 1 => BitDepth::One, @@ -110,7 +111,7 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> Result { 4 => BitDepth::Four, 8 => BitDepth::Eight, 16 => BitDepth::Sixteen, - _ => return Err("Unexpected bit depth in header".to_owned()), + _ => return Err(PngError::new("Unexpected bit depth in header")), }, width: rdr.read_u32::().unwrap(), height: rdr.read_u32::().unwrap(), diff --git a/src/lib.rs b/src/lib.rs index 49a89581..d62082cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ extern crate miniz_sys; extern crate num_cpus; extern crate scoped_pool; +use error::PngError; use headers::Headers; use scoped_pool::Pool; use std::collections::{HashMap, HashSet}; @@ -22,6 +23,7 @@ pub mod deflate { pub mod libz_stream; pub mod miniz_stream; } +mod error; mod filters; pub mod headers; mod interlace; @@ -270,7 +272,7 @@ impl Default for Options { } /// Perform optimization on the input file using the options provided -pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> { +pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> { // Read in the file and try to decode as PNG. if opts.verbosity.is_some() { writeln!(&mut stderr(), "Processing: {}", filepath.to_str().unwrap()).ok(); @@ -305,8 +307,8 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> { .unwrap()))) { Ok(x) => x, Err(_) => { - return Err(format!("Unable to write to backup file at {}", - opts.out_file.display())) + return Err(PngError::new(&format!("Unable to write to backup file at {}", + opts.out_file.display()))) } }; } @@ -315,13 +317,14 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> { let mut buffer = BufWriter::new(stdout()); match buffer.write_all(&optimized_output) { Ok(_) => (), - Err(_) => return Err("Unable to write to stdout".to_owned()), + Err(_) => return Err(PngError::new("Unable to write to stdout")), } } else { let out_file = match File::create(&opts.out_file) { Ok(x) => x, Err(_) => { - return Err(format!("Unable to write to file {}", opts.out_file.display())) + return Err(PngError::new(&format!("Unable to write to file {}", + opts.out_file.display()))) } }; @@ -377,7 +380,8 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> { } } Err(_) => { - return Err(format!("Unable to write to file {}", opts.out_file.display())) + return Err(PngError::new(&format!("Unable to write to file {}", + opts.out_file.display()))) } } } @@ -387,7 +391,7 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), String> { /// Perform optimization on the input file using the options provided, where the file is already /// loaded in-memory -pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result, String> { +pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result, PngError> { // Read in the file and try to decode as PNG. if opts.verbosity.is_some() { writeln!(&mut stderr(), "Processing from memory").ok(); diff --git a/src/png.rs b/src/png.rs index 6acb207e..e51a7f33 100644 --- a/src/png.rs +++ b/src/png.rs @@ -2,6 +2,7 @@ use bit_vec::BitVec; use byteorder::{BigEndian, WriteBytesExt}; use colors::{BitDepth, ColorType}; use crc::crc32; +use error::PngError; use filters::*; use headers::*; use interlace::{interlace_image, deinterlace_image}; @@ -181,28 +182,28 @@ pub struct PngData { impl PngData { /// Create a new `PngData` struct by opening a file - pub fn new(filepath: &Path, fix_errors: bool) -> Result { + pub fn new(filepath: &Path, fix_errors: bool) -> Result { let mut file = match File::open(filepath) { Ok(f) => f, - Err(_) => return Err("Failed to open file for reading".to_owned()), + Err(_) => return Err(PngError::new("Failed to open file for reading")), }; let mut byte_data: Vec = Vec::new(); // Read raw png data into memory match file.read_to_end(&mut byte_data) { Ok(_) => (), - Err(_) => return Err("Failed to read from file".to_owned()), + Err(_) => return Err(PngError::new("Failed to read from file")), } PngData::from_slice(&byte_data, fix_errors) } /// Create a new `PngData` struct by reading a slice - pub fn from_slice(byte_data: &[u8], fix_errors: bool) -> Result { + pub fn from_slice(byte_data: &[u8], fix_errors: bool) -> Result { let mut byte_offset: usize = 0; // Test that png header is valid let header: Vec = byte_data.iter().take(8).cloned().collect(); if !file_header_is_valid(header.as_ref()) { - return Err("Invalid PNG header detected".to_owned()); + return Err(PngError::new("Invalid PNG header detected")); } byte_offset += 8; // Read the data headers @@ -226,10 +227,10 @@ impl PngData { } // Parse the headers into our PngData if idat_headers.is_empty() { - return Err("Image data was empty, skipping".to_owned()); + return Err(PngError::new("Image data was empty, skipping")); } if aux_headers.get("IHDR").is_none() { - return Err("Image header data was missing, skipping".to_owned()); + return Err(PngError::new("Image header data was missing, skipping")); } let ihdr_header = match parse_ihdr_header(aux_headers.remove("IHDR").unwrap().as_ref()) { Ok(x) => x, @@ -388,11 +389,7 @@ impl PngData { // http://www.libpng.org/pub/png/book/chapter09.html let mut trials: HashMap> = HashMap::with_capacity(5); // Avoid vertical filtering on first line of each interlacing pass - for filter in if last_pass == line.pass { - 0..5 - } else { - 0..2 - } { + for filter in if last_pass == line.pass { 0..5 } else { 0..2 } { trials.insert(filter, filter_line(filter, bpp, &line.data, &last_line)); } let (best_filter, best_line) = trials.iter() diff --git a/tests/filters.rs b/tests/filters.rs index dcc0ae38..f0dd9834 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -6,6 +6,7 @@ use image::Pixel; use oxipng::colors::{BitDepth, ColorType}; use oxipng::png; use std::collections::HashSet; +use std::error::Error; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -36,7 +37,7 @@ fn test_it_converts(input: &Path, match oxipng::optimize(input, opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -44,7 +45,7 @@ fn test_it_converts(input: &Path, Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; diff --git a/tests/flags.rs b/tests/flags.rs index 0d6d0c8e..3b0d4846 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -7,6 +7,7 @@ use oxipng::colors::{BitDepth, ColorType}; use oxipng::headers::Headers; use oxipng::png; use std::collections::HashSet; +use std::error::Error; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -37,7 +38,7 @@ fn test_it_converts(input: &Path, match oxipng::optimize(input, opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -45,7 +46,7 @@ fn test_it_converts(input: &Path, Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -93,7 +94,7 @@ fn strip_headers_list() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -101,7 +102,7 @@ fn strip_headers_list() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -134,7 +135,7 @@ fn strip_headers_safe() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -142,7 +143,7 @@ fn strip_headers_safe() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -175,7 +176,7 @@ fn strip_headers_all() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -183,7 +184,7 @@ fn strip_headers_all() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -216,7 +217,7 @@ fn strip_headers_none() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -224,7 +225,7 @@ fn strip_headers_none() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -255,7 +256,7 @@ fn interlacing_0_to_1() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -263,7 +264,7 @@ fn interlacing_0_to_1() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -292,7 +293,7 @@ fn interlacing_1_to_0() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -300,7 +301,7 @@ fn interlacing_1_to_0() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -331,7 +332,7 @@ fn interlacing_0_to_1_small_files() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -339,7 +340,7 @@ fn interlacing_0_to_1_small_files() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -372,7 +373,7 @@ fn interlacing_1_to_0_small_files() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -380,7 +381,7 @@ fn interlacing_1_to_0_small_files() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -414,7 +415,7 @@ fn interlaced_0_to_1_other_filter_mode() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -422,7 +423,7 @@ fn interlaced_0_to_1_other_filter_mode() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -470,7 +471,7 @@ fn fix_errors() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -478,7 +479,7 @@ fn fix_errors() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -504,7 +505,7 @@ fn issue_42() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -512,7 +513,7 @@ fn issue_42() { Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; diff --git a/tests/interlaced.rs b/tests/interlaced.rs index c675afcd..ed8677ba 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -6,6 +6,7 @@ use image::Pixel; use oxipng::colors::{BitDepth, ColorType}; use oxipng::png; use std::collections::HashSet; +use std::error::Error; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -37,7 +38,7 @@ fn test_it_converts(input: &Path, match oxipng::optimize(input, opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -45,7 +46,7 @@ fn test_it_converts(input: &Path, Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; diff --git a/tests/reduction.rs b/tests/reduction.rs index 08bc1f04..992c1e19 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -6,6 +6,7 @@ use image::Pixel; use oxipng::colors::{BitDepth, ColorType}; use oxipng::png; use std::collections::HashSet; +use std::error::Error; use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; @@ -37,7 +38,7 @@ fn test_it_converts(input: &Path, match oxipng::optimize(input, opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -45,7 +46,7 @@ fn test_it_converts(input: &Path, Ok(x) => x, Err(x) => { remove_file(output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -1247,7 +1248,7 @@ fn palette_should_be_reduced_with_dupes() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -1255,7 +1256,7 @@ fn palette_should_be_reduced_with_dupes() { Ok(x) => x, Err(x) => { remove_file(&output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -1287,7 +1288,7 @@ fn palette_should_be_reduced_with_unused() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -1295,7 +1296,7 @@ fn palette_should_be_reduced_with_unused() { Ok(x) => x, Err(x) => { remove_file(&output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } }; @@ -1327,7 +1328,7 @@ fn palette_should_be_reduced_with_both() { match oxipng::optimize(&input, &opts) { Ok(_) => (), - Err(x) => panic!(x.to_owned()), + Err(x) => panic!(x.description().to_owned()), }; assert!(output.exists()); @@ -1335,7 +1336,7 @@ fn palette_should_be_reduced_with_both() { Ok(x) => x, Err(x) => { remove_file(&output).ok(); - panic!(x.to_owned()) + panic!(x.description().to_owned()) } };