diff --git a/src/colors.rs b/src/colors.rs index a5365d2c..e1c49724 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -116,7 +116,7 @@ impl TryFrom for BitDepth { 4 => Ok(Self::Four), 8 => Ok(Self::Eight), 16 => Ok(Self::Sixteen), - _ => Err(PngError::new("Unexpected bit depth")), + _ => Err(PngError::InvalidData), } } } diff --git a/src/deflate/deflater.rs b/src/deflate/deflater.rs index 9ba19f59..1133a44c 100644 --- a/src/deflate/deflater.rs +++ b/src/deflate/deflater.rs @@ -22,7 +22,7 @@ pub fn inflate(data: &[u8], out_size: usize) -> PngResult> { .zlib_decompress(data, &mut dest) .map_err(|err| match err { DecompressionError::BadData => PngError::InvalidData, - DecompressionError::InsufficientSpace => PngError::new("inflated data too long"), + DecompressionError::InsufficientSpace => PngError::InflatedDataTooLong(out_size), })?; dest.truncate(len); Ok(dest) diff --git a/src/error.rs b/src/error.rs index 2c7d88a9..95c22a18 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,17 +5,17 @@ use crate::colors::{BitDepth, ColorType}; #[derive(Debug, Clone)] #[non_exhaustive] pub enum PngError { - DeflatedDataTooLong(usize), - TimedOut, - NotPNG, - APNGNotSupported, APNGOutOfOrder, - InvalidData, - TruncatedData, - ChunkMissing(&'static str), - InvalidDepthForType(BitDepth, ColorType), - IncorrectDataLength(usize, usize), C2PAMetadataPreventsChanges, + ChunkMissing(&'static str), + CRCMismatch([u8; 4]), + DeflatedDataTooLong(usize), + IncorrectDataLength(usize, usize), + InflatedDataTooLong(usize), + InvalidData, + InvalidDepthForType(BitDepth, ColorType), + NotPNG, + TruncatedData, Other(Box), } @@ -26,26 +26,30 @@ impl fmt::Display for PngError { #[cold] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - PngError::DeflatedDataTooLong(_) => f.write_str("deflated data too long"), - PngError::TimedOut => f.write_str("timed out"), - PngError::NotPNG => f.write_str("Invalid header detected; Not a PNG file"), - PngError::InvalidData => f.write_str("Invalid data found; unable to read PNG file"), - PngError::TruncatedData => { - f.write_str("Missing data in the file; the file is truncated") - } - PngError::APNGNotSupported => f.write_str("APNG files are not (yet) supported"), PngError::APNGOutOfOrder => f.write_str("APNG chunks are out of order"), + PngError::C2PAMetadataPreventsChanges => f.write_str( + "The image contains C2PA manifest that would be invalidated by any file changes", + ), PngError::ChunkMissing(s) => write!(f, "Chunk {s} missing or empty"), - PngError::InvalidDepthForType(d, ref c) => { - write!(f, "Invalid bit depth {d} for color type {c}") - } + PngError::CRCMismatch(ref c) => write!( + f, + "CRC mismatch in {} chunk; May be recoverable by using --fix", + String::from_utf8_lossy(c) + ), + PngError::DeflatedDataTooLong(_) => f.write_str("Deflated data too long"), PngError::IncorrectDataLength(l1, l2) => write!( f, "Data length {l1} does not match the expected length {l2}" ), - PngError::C2PAMetadataPreventsChanges => f.write_str( - "The image contains C2PA manifest that would be invalidated by any file changes", - ), + PngError::InflatedDataTooLong(_) => f.write_str("Inflated data too long"), + PngError::InvalidData => f.write_str("Invalid data found; unable to read PNG file"), + PngError::InvalidDepthForType(d, ref c) => { + write!(f, "Invalid bit depth {d} for color type {c}") + } + PngError::NotPNG => f.write_str("Invalid header detected; Not a PNG file"), + PngError::TruncatedData => { + f.write_str("Missing data in the file; the file is truncated") + } PngError::Other(ref s) => f.write_str(s), } } diff --git a/src/headers.rs b/src/headers.rs index 96379f44..3e3f6a99 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -172,10 +172,7 @@ pub fn parse_next_chunk<'a>( let chunk_bytes = &byte_data[chunk_start..chunk_start + 4 + length as usize]; if !fix_errors && crc32(chunk_bytes) != crc { - return Err(PngError::new(&format!( - "CRC Mismatch in {} chunk; May be recoverable by using --fix", - String::from_utf8_lossy(chunk_name) - ))); + return Err(PngError::CRCMismatch(chunk_name.try_into().unwrap())); } let name: [u8; 4] = chunk_name.try_into().unwrap(); @@ -208,7 +205,7 @@ pub fn parse_ihdr_chunk( }, 4 => ColorType::GrayscaleAlpha, 6 => ColorType::RGBA, - _ => return Err(PngError::new("Unexpected color type in header")), + _ => return Err(PngError::InvalidData), }, bit_depth: byte_data[8].try_into()?, width: read_be_u32(&byte_data[0..4]), @@ -216,7 +213,7 @@ pub fn parse_ihdr_chunk( interlaced: match interlaced { 0 => false, 1 => true, - _ => return Err(PngError::new("Unexpected interlacing in header")), + _ => return Err(PngError::InvalidData), }, }) } @@ -226,7 +223,7 @@ fn palette_to_rgba( palette_data: Option>, trns_data: Option>, ) -> Result, PngError> { - let palette_data = palette_data.ok_or_else(|| PngError::new("no palette in indexed image"))?; + let palette_data = palette_data.ok_or(PngError::ChunkMissing("PLTE"))?; let mut palette: Vec<_> = palette_data .chunks_exact(3) .map(|color| RGBA8::new(color[0], color[1], color[2], 255)) diff --git a/src/lib.rs b/src/lib.rs index 0f43631d..db8d7a49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -679,7 +679,7 @@ fn copy_permissions(metadata_input: &Metadata, out_file: &File) -> PngResult<()> .set_permissions(metadata_input.permissions()) .map_err(|err_io| { PngError::new(&format!( - "unable to set permissions for output file: {err_io}" + "Unable to set permissions for output file: {err_io}" )) }) } @@ -695,7 +695,7 @@ fn copy_times(input_path_meta: &Metadata, out_path: &Path) -> PngResult<()> { trace!("attempting to set file modification time: {mtime:?}"); filetime::set_file_mtime(out_path, mtime).map_err(|err_io| { PngError::new(&format!( - "unable to set file times on {out_path:?}: {err_io}" + "Unable to set file times on {out_path:?}: {err_io}" )) }) }