From 19e478faa4bc2ad4459922d8cf1e5ecf7c604aab Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 21 Apr 2024 14:32:50 -0700 Subject: [PATCH] Switch to quick-error (#67) --- Cargo.toml | 2 +- src/decoder.rs | 259 +++++++++++++++++++++++++++---------------------- src/encoder.rs | 30 +++--- src/lib.rs | 2 + 4 files changed, 166 insertions(+), 127 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bae0af4..18e46c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ include = ["/src", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] [dependencies] byteorder-lite = "0.1.0" -thiserror = "1.0.47" +quick-error = "2.0.1" [dev-dependencies] paste = "1.0.14" diff --git a/src/decoder.rs b/src/decoder.rs index 7c1d8a3..e95e777 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -1,132 +1,163 @@ use byteorder_lite::{LittleEndian, ReadBytesExt}; -use std::collections::HashMap; +use quick_error::quick_error; +use std::collections::HashMap; use std::io::{self, BufReader, Cursor, Read, Seek}; - use std::num::NonZeroU16; use std::ops::Range; -use thiserror::Error; use crate::extended::{self, get_alpha_predictor, read_alpha_chunk, WebPExtendedInfo}; use super::lossless::LosslessDecoder; use super::vp8::Vp8Decoder; -/// Errors that can occur when attempting to decode a WebP image -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum DecodingError { - /// An IO error occurred while reading the file - #[error("IO Error: {0}")] - IoError(#[from] io::Error), +quick_error! { + /// Errors that can occur when attempting to decode a WebP image + #[derive(Debug)] + #[non_exhaustive] + pub enum DecodingError { + /// An IO error occurred while reading the file + IoError(err: io::Error) { + from() + display("IO Error: {}", err) + source(err) + } + + /// RIFF's "RIFF" signature not found or invalid + RiffSignatureInvalid(err: [u8; 4]) { + display("Invalid RIFF signature: {err:x?}") + } + + /// WebP's "WEBP" signature not found or invalid + WebpSignatureInvalid(err: [u8; 4]) { + display("Invalid WebP signature: {err:x?}") + } + + /// An expected chunk was missing + ChunkMissing { + display("An expected chunk was missing") + } + + /// Chunk Header was incorrect or invalid in its usage + ChunkHeaderInvalid(err: [u8; 4]) { + display("Invalid Chunk header: {err:x?}") + } + + /// Some bits were invalid + ReservedBitSet { + display("Reserved bits set") + } + + /// Invalid compression method + InvalidCompressionMethod { + display("Invalid compression method") + } + + /// Alpha chunk doesn't match the frame's size + AlphaChunkSizeMismatch { + display("Alpha chunk size mismatch") + } + + /// Image is too large, either for the platform's pointer size or generally + ImageTooLarge { + display("Image too large") + } + + /// Frame would go out of the canvas + FrameOutsideImage { + display("Frame outside image") + } - /// RIFF's "RIFF" signature not found or invalid - #[error("Invalid RIFF signature: {0:x?}")] - RiffSignatureInvalid([u8; 4]), + /// Signature of 0x2f not found + LosslessSignatureInvalid(err: u8) { + display("Invalid lossless signature: {err:x?}") + } - /// WebP's "WEBP" signature not found or invalid - #[error("Invalid WebP signature: {0:x?}")] - WebpSignatureInvalid([u8; 4]), - - /// An expected chunk was missing - #[error("An expected chunk was missing")] - ChunkMissing, - - /// Chunk Header was incorrect or invalid in its usage - #[error("Invalid Chunk header: {0:?}")] - ChunkHeaderInvalid([u8; 4]), - - /// Some bits were invalid - #[error("Reserved bits set")] - ReservedBitSet, - - /// Invalid compression method - #[error("Invalid compression method")] - InvalidCompressionMethod, - - /// Alpha chunk doesn't match the frame's size - #[error("Alpha chunk size mismatch")] - AlphaChunkSizeMismatch, - - /// Image is too large, either for the platform's pointer size or generally - #[error("Image too large")] - ImageTooLarge, - - /// Frame would go out of the canvas - #[error("Frame outside image")] - FrameOutsideImage, - - /// Signature of 0x2f not found - #[error("Invalid lossless signature: {0:x?}")] - LosslessSignatureInvalid(u8), - - /// Version Number was not zero - #[error("Invalid lossless version number: {0}")] - VersionNumberInvalid(u8), - - /// Invalid color cache bits - #[error("Invalid color cache bits: {0}")] - InvalidColorCacheBits(u8), - - /// An invalid Huffman code was encountered - #[error("Invalid Huffman code")] - HuffmanError, - - /// The bitstream was somehow corrupt - #[error("Corrupt bitstream")] - BitStreamError, - - /// The transforms specified were invalid - #[error("Invalid transform")] - TransformError, - - /// VP8's `[0x9D, 0x01, 0x2A]` magic not found or invalid - #[error("Invalid VP8 magic: {0:x?}")] - Vp8MagicInvalid([u8; 3]), - - /// VP8 Decoder initialisation wasn't provided with enough data - #[error("Not enough VP8 init data")] - NotEnoughInitData, - - /// At time of writing, only the YUV colour-space encoded as `0` is specified - #[error("Invalid VP8 color space: {0}")] - ColorSpaceInvalid(u8), - - /// LUMA prediction mode was not recognised - #[error("Invalid VP8 luma prediction mode: {0}")] - LumaPredictionModeInvalid(i8), - - /// Intra-prediction mode was not recognised - #[error("Invalid VP8 intra prediction mode: {0}")] - IntraPredictionModeInvalid(i8), - - /// Chroma prediction mode was not recognised - #[error("Invalid VP8 chroma prediction mode: {0}")] - ChromaPredictionModeInvalid(i8), - - /// Inconsistent image sizes - #[error("Inconsistent image sizes")] - InconsistentImageSizes, - - /// The file may be valid, but this crate doesn't support decoding it. - #[error("Unsupported feature: {0}")] - UnsupportedFeature(String), - - /// Invalid function call or parameter - #[error("Invalid parameter: {0}")] - InvalidParameter(String), - - /// Memory limit exceeded - #[error("Memory limit exceeded")] - MemoryLimitExceeded, + /// Version Number was not zero + VersionNumberInvalid(err: u8) { + display("Invalid lossless version number: {err}") + } - /// Invalid chunk size - #[error("Invalid chunk size")] - InvalidChunkSize, + /// Invalid color cache bits + InvalidColorCacheBits(err: u8) { + display("Invalid color cache bits: {err}") + } - /// No more frames in image - #[error("No more frames")] - NoMoreFrames, + /// An invalid Huffman code was encountered + HuffmanError { + display("Invalid Huffman code") + } + + /// The bitstream was somehow corrupt + BitStreamError { + display("Corrupt bitstream") + } + + /// The transforms specified were invalid + TransformError { + display("Invalid transform") + } + + /// VP8's `[0x9D, 0x01, 0x2A]` magic not found or invalid + Vp8MagicInvalid(err: [u8; 3]) { + display("Invalid VP8 magic: {err:x?}") + } + + /// VP8 Decoder initialisation wasn't provided with enough data + NotEnoughInitData { + display("Not enough VP8 init data") + } + + /// At time of writing, only the YUV colour-space encoded as `0` is specified + ColorSpaceInvalid(err: u8) { + display("Invalid VP8 color space: {err}") + } + + /// LUMA prediction mode was not recognised + LumaPredictionModeInvalid(err: i8) { + display("Invalid VP8 luma prediction mode: {err}") + } + + /// Intra-prediction mode was not recognised + IntraPredictionModeInvalid(err: i8) { + display("Invalid VP8 intra prediction mode: {err}") + } + + /// Chroma prediction mode was not recognised + ChromaPredictionModeInvalid(err: i8) { + display("Invalid VP8 chroma prediction mode: {err}") + } + + /// Inconsistent image sizes + InconsistentImageSizes { + display("Inconsistent image sizes") + } + + /// The file may be valid, but this crate doesn't support decoding it. + UnsupportedFeature(err: String) { + display("Unsupported feature: {err}") + } + + /// Invalid function call or parameter + InvalidParameter(err: String) { + display("Invalid parameter: {err}") + } + + /// Memory limit exceeded + MemoryLimitExceeded { + display("Memory limit exceeded") + } + + /// Invalid chunk size + InvalidChunkSize { + display("Invalid chunk size") + } + + /// No more frames in image + NoMoreFrames { + display("No more frames") + } + } } /// All possible RIFF chunks in a WebP image file diff --git a/src/encoder.rs b/src/encoder.rs index 2c241e6..cec3f0a 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -3,7 +3,7 @@ use std::collections::BinaryHeap; use std::io::{self, Write}; use std::slice::ChunksExact; -use thiserror::Error; +use quick_error::quick_error; /// Color type of the image. /// @@ -22,17 +22,23 @@ pub enum ColorType { Rgba8, } -/// Error that can occur during encoding. -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum EncodingError { - /// An IO error occurred. - #[error("IO error: {0}")] - IoError(#[from] io::Error), - - /// The image dimensions are not allowed by the WebP format. - #[error("Invalid dimensions")] - InvalidDimensions, +quick_error! { + /// Error that can occur during encoding. + #[derive(Debug)] + #[non_exhaustive] + pub enum EncodingError { + /// An IO error occurred. + IoError(err: io::Error) { + from() + display("IO error: {}", err) + source(err) + } + + /// The image dimensions are not allowed by the WebP format. + InvalidDimensions { + display("Invalid dimensions") + } + } } struct BitWriter { diff --git a/src/lib.rs b/src/lib.rs index bf44941..4c60479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ #![forbid(unsafe_code)] #![deny(missing_docs)] +// Increase recursion limit for the `quick_error!` macro. +#![recursion_limit = "256"] pub use self::decoder::{DecodingError, LoopCount, WebPDecoder}; pub use self::encoder::{ColorType, EncodingError, WebPEncoder};