From 42861a1ce27609c5c7d18affe6712089112fc9e5 Mon Sep 17 00:00:00 2001 From: Jelte Fennema Date: Sat, 15 Jun 2024 14:32:15 +0200 Subject: [PATCH] Revert "remove derive_more (#60)" This reverts commit 5265c12c8cdc03647b90ae89fd3b64015a1c2d8c. --- Cargo.toml | 3 +- src/blocks/literals_section.rs | 46 +---- src/blocks/sequence_section.rs | 23 +-- src/decoding/bit_reader.rs | 42 +--- src/decoding/block_decoder.rs | 244 +++++------------------ src/decoding/decodebuffer.rs | 25 +-- src/decoding/dictionary.rs | 49 +---- src/decoding/literals_section_decoder.rs | 107 ++-------- src/decoding/sequence_execution.rs | 42 +--- src/decoding/sequence_section_decoder.rs | 94 ++------- src/frame.rs | 154 +++----------- src/frame_decoder.rs | 119 +++-------- src/fse/fse_decoder.rs | 104 ++-------- src/huff0/huff0_decoder.rs | 203 ++++--------------- 14 files changed, 244 insertions(+), 1011 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bdd70fd4..80d7554a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ categories = ["compression"] [dependencies] byteorder = { version = "1.5", default-features = false } twox-hash = { version = "1.6", default-features = false, optional = true } +derive_more = { version = "0.99", default-features = false, features = ["display", "from"] } [dev-dependencies] criterion = "0.5" @@ -23,7 +24,7 @@ rand = { version = "0.8.5", features = ["small_rng"] } [features] default = ["hash", "std"] hash = ["dep:twox-hash"] -std = [] +std = ["derive_more/error"] [[bench]] name = "reversedbitreader_bench" diff --git a/src/blocks/literals_section.rs b/src/blocks/literals_section.rs index d7b908dd..5c70549f 100644 --- a/src/blocks/literals_section.rs +++ b/src/blocks/literals_section.rs @@ -42,51 +42,21 @@ pub enum LiteralsSectionType { Treeless, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum LiteralsSectionParseError { + #[display(fmt = "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3")] IllegalLiteralSectionType { got: u8 }, + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display( + fmt = "Not enough byte to parse the literals section header. Have: {have}, Need: {need}" + )] NotEnoughBytes { have: usize, need: u8 }, } -#[cfg(feature = "std")] -impl std::error::Error for LiteralsSectionParseError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - LiteralsSectionParseError::GetBitsError(source) => Some(source), - _ => None, - } - } -} -impl core::fmt::Display for LiteralsSectionParseError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - LiteralsSectionParseError::IllegalLiteralSectionType { got } => { - write!( - f, - "Illegal literalssectiontype. Is: {}, must be in: 0, 1, 2, 3", - got - ) - } - LiteralsSectionParseError::GetBitsError(e) => write!(f, "{:?}", e), - LiteralsSectionParseError::NotEnoughBytes { have, need } => { - write!( - f, - "Not enough byte to parse the literals section header. Have: {}, Need: {}", - have, need, - ) - } - } - } -} - -impl From for LiteralsSectionParseError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - impl core::fmt::Display for LiteralsSectionType { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { match self { diff --git a/src/blocks/sequence_section.rs b/src/blocks/sequence_section.rs index 9822f946..75e209a7 100644 --- a/src/blocks/sequence_section.rs +++ b/src/blocks/sequence_section.rs @@ -92,29 +92,16 @@ impl Default for SequencesHeader { } } -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum SequencesHeaderParseError { + #[display( + fmt = "source must have at least {need_at_least} bytes to parse header; got {got} bytes" + )] NotEnoughBytes { need_at_least: u8, got: usize }, } -#[cfg(feature = "std")] -impl std::error::Error for SequencesHeaderParseError {} - -impl core::fmt::Display for SequencesHeaderParseError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - SequencesHeaderParseError::NotEnoughBytes { need_at_least, got } => { - write!( - f, - "source must have at least {} bytes to parse header; got {} bytes", - need_at_least, got, - ) - } - } - } -} - impl SequencesHeader { /// Create a new [SequencesHeader]. pub fn new() -> SequencesHeader { diff --git a/src/decoding/bit_reader.rs b/src/decoding/bit_reader.rs index 85058211..5ae0a85e 100644 --- a/src/decoding/bit_reader.rs +++ b/src/decoding/bit_reader.rs @@ -4,47 +4,19 @@ pub struct BitReader<'s> { source: &'s [u8], } -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum GetBitsError { + #[display( + fmt = "Cant serve this request. The reader is limited to {limit} bits, requested {num_requested_bits} bits" + )] TooManyBits { num_requested_bits: usize, limit: u8, }, - NotEnoughRemainingBits { - requested: usize, - remaining: usize, - }, -} - -#[cfg(feature = "std")] -impl std::error::Error for GetBitsError {} - -impl core::fmt::Display for GetBitsError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - GetBitsError::TooManyBits { - num_requested_bits, - limit, - } => { - write!( - f, - "Cant serve this request. The reader is limited to {} bits, requested {} bits", - limit, num_requested_bits, - ) - } - GetBitsError::NotEnoughRemainingBits { - requested, - remaining, - } => { - write!( - f, - "Can\'t read {} bits, only have {} bits left", - requested, remaining, - ) - } - } - } + #[display(fmt = "Can't read {requested} bits, only have {remaining} bits left")] + NotEnoughRemainingBits { requested: usize, remaining: usize }, } impl<'s> BitReader<'s> { diff --git a/src/decoding/block_decoder.rs b/src/decoding/block_decoder.rs index 2d421fda..a2ecefea 100644 --- a/src/decoding/block_decoder.rs +++ b/src/decoding/block_decoder.rs @@ -25,245 +25,91 @@ enum DecoderState { Failed, //TODO put "self.internal_state = DecoderState::Failed;" everywhere an unresolvable error occurs } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockHeaderReadError { + #[display(fmt = "Error while reading the block header")] + #[from] ReadError(io::Error), + #[display(fmt = "Reserved block occured. This is considered corruption by the documentation")] FoundReservedBlock, + #[display(fmt = "Error getting block type: {_0}")] + #[from] BlockTypeError(BlockTypeError), + #[display(fmt = "Error getting block content size: {_0}")] + #[from] BlockSizeError(BlockSizeError), } -#[cfg(feature = "std")] -impl std::error::Error for BlockHeaderReadError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - BlockHeaderReadError::ReadError(source) => Some(source), - BlockHeaderReadError::BlockTypeError(source) => Some(source), - BlockHeaderReadError::BlockSizeError(source) => Some(source), - BlockHeaderReadError::FoundReservedBlock => None, - } - } -} - -impl ::core::fmt::Display for BlockHeaderReadError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - BlockHeaderReadError::ReadError(_) => write!(f, "Error while reading the block header"), - BlockHeaderReadError::FoundReservedBlock => write!( - f, - "Reserved block occured. This is considered corruption by the documentation" - ), - BlockHeaderReadError::BlockTypeError(e) => write!(f, "Error getting block type: {}", e), - BlockHeaderReadError::BlockSizeError(e) => { - write!(f, "Error getting block content size: {}", e) - } - } - } -} - -impl From for BlockHeaderReadError { - fn from(val: io::Error) -> Self { - Self::ReadError(val) - } -} - -impl From for BlockHeaderReadError { - fn from(val: BlockTypeError) -> Self { - Self::BlockTypeError(val) - } -} - -impl From for BlockHeaderReadError { - fn from(val: BlockSizeError) -> Self { - Self::BlockSizeError(val) - } -} - -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockTypeError { + #[display( + fmt = "Invalid Blocktype number. Is: {num} Should be one of: 0, 1, 2, 3 (3 is reserved though" + )] InvalidBlocktypeNumber { num: u8 }, } -#[cfg(feature = "std")] -impl std::error::Error for BlockTypeError {} - -impl core::fmt::Display for BlockTypeError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - BlockTypeError::InvalidBlocktypeNumber { num } => { - write!(f, - "Invalid Blocktype number. Is: {} Should be one of: 0, 1, 2, 3 (3 is reserved though", - num, - ) - } - } - } -} - -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockSizeError { + #[display( + fmt = "Blocksize was bigger than the absolute maximum {ABSOLUTE_MAXIMUM_BLOCK_SIZE} (128kb). Is: {size}" + )] BlockSizeTooLarge { size: u32 }, } -#[cfg(feature = "std")] -impl std::error::Error for BlockSizeError {} - -impl core::fmt::Display for BlockSizeError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - BlockSizeError::BlockSizeTooLarge { size } => { - write!( - f, - "Blocksize was bigger than the absolute maximum {} (128kb). Is: {}", - ABSOLUTE_MAXIMUM_BLOCK_SIZE, size, - ) - } - } - } -} - -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecompressBlockError { + #[display(fmt = "Error while reading the block content: {_0}")] + #[from] BlockContentReadError(io::Error), + #[display( + fmt = "Malformed section header. Says literals would be this long: {expected_len} but there are only {remaining_bytes} bytes left" + )] MalformedSectionHeader { expected_len: usize, remaining_bytes: usize, }, + #[display(fmt = "{_0:?}")] + #[from] DecompressLiteralsError(DecompressLiteralsError), + #[display(fmt = "{_0:?}")] + #[from] LiteralsSectionParseError(LiteralsSectionParseError), + #[display(fmt = "{_0:?}")] + #[from] SequencesHeaderParseError(SequencesHeaderParseError), + #[display(fmt = "{_0:?}")] + #[from] DecodeSequenceError(DecodeSequenceError), + #[display(fmt = "{_0:?}")] + #[from] ExecuteSequencesError(ExecuteSequencesError), } -#[cfg(feature = "std")] -impl std::error::Error for DecompressBlockError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - DecompressBlockError::BlockContentReadError(source) => Some(source), - DecompressBlockError::DecompressLiteralsError(source) => Some(source), - DecompressBlockError::LiteralsSectionParseError(source) => Some(source), - DecompressBlockError::SequencesHeaderParseError(source) => Some(source), - DecompressBlockError::DecodeSequenceError(source) => Some(source), - DecompressBlockError::ExecuteSequencesError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for DecompressBlockError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecompressBlockError::BlockContentReadError(e) => { - write!(f, "Error while reading the block content: {}", e) - } - DecompressBlockError::MalformedSectionHeader { - expected_len, - remaining_bytes, - } => { - write!(f, - "Malformed section header. Says literals would be this long: {} but there are only {} bytes left", - expected_len, - remaining_bytes, - ) - } - DecompressBlockError::DecompressLiteralsError(e) => write!(f, "{:?}", e), - DecompressBlockError::LiteralsSectionParseError(e) => write!(f, "{:?}", e), - DecompressBlockError::SequencesHeaderParseError(e) => write!(f, "{:?}", e), - DecompressBlockError::DecodeSequenceError(e) => write!(f, "{:?}", e), - DecompressBlockError::ExecuteSequencesError(e) => write!(f, "{:?}", e), - } - } -} - -impl From for DecompressBlockError { - fn from(val: io::Error) -> Self { - Self::BlockContentReadError(val) - } -} - -impl From for DecompressBlockError { - fn from(val: DecompressLiteralsError) -> Self { - Self::DecompressLiteralsError(val) - } -} - -impl From for DecompressBlockError { - fn from(val: LiteralsSectionParseError) -> Self { - Self::LiteralsSectionParseError(val) - } -} - -impl From for DecompressBlockError { - fn from(val: SequencesHeaderParseError) -> Self { - Self::SequencesHeaderParseError(val) - } -} - -impl From for DecompressBlockError { - fn from(val: DecodeSequenceError) -> Self { - Self::DecodeSequenceError(val) - } -} - -impl From for DecompressBlockError { - fn from(val: ExecuteSequencesError) -> Self { - Self::ExecuteSequencesError(val) - } -} - -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodeBlockContentError { + #[display(fmt = "Can't decode next block if failed along the way. Results will be nonsense")] DecoderStateIsFailed, + #[display( + fmt = "Cant decode next block body, while expecting to decode the header of the previous block. Results will be nonsense" + )] ExpectedHeaderOfPreviousBlock, + #[display(fmt = "Error while reading bytes for {step}: {source}")] ReadError { step: BlockType, source: io::Error }, + #[display(fmt = "{_0:?}")] + #[from] DecompressBlockError(DecompressBlockError), } -#[cfg(feature = "std")] -impl std::error::Error for DecodeBlockContentError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - DecodeBlockContentError::ReadError { step: _, source } => Some(source), - DecodeBlockContentError::DecompressBlockError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for DecodeBlockContentError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecodeBlockContentError::DecoderStateIsFailed => { - write!( - f, - "Can't decode next block if failed along the way. Results will be nonsense", - ) - } - DecodeBlockContentError::ExpectedHeaderOfPreviousBlock => { - write!(f, - "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense", - ) - } - DecodeBlockContentError::ReadError { step, source } => { - write!(f, "Error while reading bytes for {}: {}", step, source,) - } - DecodeBlockContentError::DecompressBlockError(e) => write!(f, "{:?}", e), - } - } -} - -impl From for DecodeBlockContentError { - fn from(val: DecompressBlockError) -> Self { - Self::DecompressBlockError(val) - } -} - /// Create a new [BlockDecoder]. pub fn new() -> BlockDecoder { BlockDecoder { diff --git a/src/decoding/decodebuffer.rs b/src/decoding/decodebuffer.rs index 04a43e8b..9cfb3652 100644 --- a/src/decoding/decodebuffer.rs +++ b/src/decoding/decodebuffer.rs @@ -15,33 +15,16 @@ pub struct DecodeBuffer { pub hash: twox_hash::XxHash64, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodeBufferError { + #[display(fmt = "Need {need} bytes from the dictionary but it is only {got} bytes long")] NotEnoughBytesInDictionary { got: usize, need: usize }, + #[display(fmt = "offset: {offset} bigger than buffer: {buf_len}")] OffsetTooBig { offset: usize, buf_len: usize }, } -#[cfg(feature = "std")] -impl std::error::Error for DecodeBufferError {} - -impl core::fmt::Display for DecodeBufferError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecodeBufferError::NotEnoughBytesInDictionary { got, need } => { - write!( - f, - "Need {} bytes from the dictionary but it is only {} bytes long", - need, got, - ) - } - DecodeBufferError::OffsetTooBig { offset, buf_len } => { - write!(f, "offset: {} bigger than buffer: {}", offset, buf_len,) - } - } - } -} - impl Read for DecodeBuffer { fn read(&mut self, target: &mut [u8]) -> Result { let max_amount = self.can_drain_to_window_size().unwrap_or(0); diff --git a/src/decoding/dictionary.rs b/src/decoding/dictionary.rs index 2d930c61..a17ebecc 100644 --- a/src/decoding/dictionary.rs +++ b/src/decoding/dictionary.rs @@ -37,53 +37,22 @@ pub struct Dictionary { pub offset_hist: [u32; 3], } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DictionaryDecodeError { + #[display( + fmt = "Bad magic_num at start of the dictionary; Got: {got:#04X?}, Expected: {MAGIC_NUM:#04x?}" + )] BadMagicNum { got: [u8; 4] }, + #[display(fmt = "{_0:?}")] + #[from] FSETableError(FSETableError), + #[display(fmt = "{_0:?}")] + #[from] HuffmanTableError(HuffmanTableError), } -#[cfg(feature = "std")] -impl std::error::Error for DictionaryDecodeError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - DictionaryDecodeError::FSETableError(source) => Some(source), - DictionaryDecodeError::HuffmanTableError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for DictionaryDecodeError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DictionaryDecodeError::BadMagicNum { got } => { - write!( - f, - "Bad magic_num at start of the dictionary; Got: {:#04X?}, Expected: {:#04x?}", - got, MAGIC_NUM, - ) - } - DictionaryDecodeError::FSETableError(e) => write!(f, "{:?}", e), - DictionaryDecodeError::HuffmanTableError(e) => write!(f, "{:?}", e), - } - } -} - -impl From for DictionaryDecodeError { - fn from(val: FSETableError) -> Self { - Self::FSETableError(val) - } -} - -impl From for DictionaryDecodeError { - fn from(val: HuffmanTableError) -> Self { - Self::HuffmanTableError(val) - } -} - /// This 4 byte (little endian) magic number refers to the start of a dictionary pub const MAGIC_NUM: [u8; 4] = [0x37, 0xA4, 0x30, 0xEC]; diff --git a/src/decoding/literals_section_decoder.rs b/src/decoding/literals_section_decoder.rs index 63301a66..253b2dc5 100644 --- a/src/decoding/literals_section_decoder.rs +++ b/src/decoding/literals_section_decoder.rs @@ -7,106 +7,43 @@ use super::scratch::HuffmanScratch; use crate::huff0::{HuffmanDecoder, HuffmanDecoderError, HuffmanTableError}; use alloc::vec::Vec; -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecompressLiteralsError { + #[display( + fmt = "compressed size was none even though it must be set to something for compressed literals" + )] MissingCompressedSize, + #[display( + fmt = "num_streams was none even though it must be set to something (1 or 4) for compressed literals" + )] MissingNumStreams, + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display(fmt = "{_0:?}")] + #[from] HuffmanTableError(HuffmanTableError), + #[display(fmt = "{_0:?}")] + #[from] HuffmanDecoderError(HuffmanDecoderError), + #[display(fmt = "Tried to reuse huffman table but it was never initialized")] UninitializedHuffmanTable, + #[display(fmt = "Need 6 bytes to decode jump header, got {got} bytes")] MissingBytesForJumpHeader { got: usize }, + #[display(fmt = "Need at least {needed} bytes to decode literals. Have: {got} bytes")] MissingBytesForLiterals { got: usize, needed: usize }, + #[display( + fmt = "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption" + )] ExtraPadding { skipped_bits: i32 }, + #[display(fmt = "Bitstream was read till: {read_til}, should have been: {expected}")] BitstreamReadMismatch { read_til: isize, expected: isize }, + #[display(fmt = "Did not decode enough literals: {decoded}, Should have been: {expected}")] DecodedLiteralCountMismatch { decoded: usize, expected: usize }, } -#[cfg(feature = "std")] -impl std::error::Error for DecompressLiteralsError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - DecompressLiteralsError::GetBitsError(source) => Some(source), - DecompressLiteralsError::HuffmanTableError(source) => Some(source), - DecompressLiteralsError::HuffmanDecoderError(source) => Some(source), - _ => None, - } - } -} -impl core::fmt::Display for DecompressLiteralsError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecompressLiteralsError::MissingCompressedSize => { - write!(f, - "compressed size was none even though it must be set to something for compressed literals", - ) - } - DecompressLiteralsError::MissingNumStreams => { - write!(f, - "num_streams was none even though it must be set to something (1 or 4) for compressed literals", - ) - } - DecompressLiteralsError::GetBitsError(e) => write!(f, "{:?}", e), - DecompressLiteralsError::HuffmanTableError(e) => write!(f, "{:?}", e), - DecompressLiteralsError::HuffmanDecoderError(e) => write!(f, "{:?}", e), - DecompressLiteralsError::UninitializedHuffmanTable => { - write!( - f, - "Tried to reuse huffman table but it was never initialized", - ) - } - DecompressLiteralsError::MissingBytesForJumpHeader { got } => { - write!(f, "Need 6 bytes to decode jump header, got {} bytes", got,) - } - DecompressLiteralsError::MissingBytesForLiterals { got, needed } => { - write!( - f, - "Need at least {} bytes to decode literals. Have: {} bytes", - needed, got, - ) - } - DecompressLiteralsError::ExtraPadding { skipped_bits } => { - write!(f, - "Padding at the end of the sequence_section was more than a byte long: {} bits. Probably caused by data corruption", - skipped_bits, - ) - } - DecompressLiteralsError::BitstreamReadMismatch { read_til, expected } => { - write!( - f, - "Bitstream was read till: {}, should have been: {}", - read_til, expected, - ) - } - DecompressLiteralsError::DecodedLiteralCountMismatch { decoded, expected } => { - write!( - f, - "Did not decode enough literals: {}, Should have been: {}", - decoded, expected, - ) - } - } - } -} - -impl From for DecompressLiteralsError { - fn from(val: HuffmanDecoderError) -> Self { - Self::HuffmanDecoderError(val) - } -} - -impl From for DecompressLiteralsError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - -impl From for DecompressLiteralsError { - fn from(val: HuffmanTableError) -> Self { - Self::HuffmanTableError(val) - } -} /// Decode and decompress the provided literals section into `target`, returning the number of bytes read. pub fn decode_literals( diff --git a/src/decoding/sequence_execution.rs b/src/decoding/sequence_execution.rs index 1a212284..e895caf2 100644 --- a/src/decoding/sequence_execution.rs +++ b/src/decoding/sequence_execution.rs @@ -1,48 +1,18 @@ use super::{decodebuffer::DecodeBufferError, scratch::DecoderScratch}; -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum ExecuteSequencesError { + #[display(fmt = "{_0:?}")] + #[from] DecodebufferError(DecodeBufferError), + #[display(fmt = "Sequence wants to copy up to byte {wanted}. Bytes in literalsbuffer: {have}")] NotEnoughBytesForSequence { wanted: usize, have: usize }, + #[display(fmt = "Illegal offset: 0 found")] ZeroOffset, } -impl core::fmt::Display for ExecuteSequencesError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - ExecuteSequencesError::DecodebufferError(e) => { - write!(f, "{:?}", e) - } - ExecuteSequencesError::NotEnoughBytesForSequence { wanted, have } => { - write!( - f, - "Sequence wants to copy up to byte {}. Bytes in literalsbuffer: {}", - wanted, have - ) - } - ExecuteSequencesError::ZeroOffset => { - write!(f, "Illegal offset: 0 found") - } - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for ExecuteSequencesError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - ExecuteSequencesError::DecodebufferError(source) => Some(source), - _ => None, - } - } -} - -impl From for ExecuteSequencesError { - fn from(val: DecodeBufferError) -> Self { - Self::DecodebufferError(val) - } -} /// Take the provided decoder and execute the sequences stored within pub fn execute_sequences(scratch: &mut DecoderScratch) -> Result<(), ExecuteSequencesError> { diff --git a/src/decoding/sequence_section_decoder.rs b/src/decoding/sequence_section_decoder.rs index e7cc1944..6f1dbaa2 100644 --- a/src/decoding/sequence_section_decoder.rs +++ b/src/decoding/sequence_section_decoder.rs @@ -9,97 +9,41 @@ use crate::blocks::sequence_section::{ use crate::fse::{FSEDecoder, FSEDecoderError, FSETableError}; use alloc::vec::Vec; -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodeSequenceError { + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display(fmt = "{_0:?}")] + #[from] FSEDecoderError(FSEDecoderError), + #[display(fmt = "{_0:?}")] + #[from] FSETableError(FSETableError), + #[display( + fmt = "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption" + )] ExtraPadding { skipped_bits: i32 }, + #[display(fmt = "Do not support offsets bigger than 1<<32; got: {offset_code}")] UnsupportedOffset { offset_code: u8 }, + #[display(fmt = "Read an offset == 0. That is an illegal value for offsets")] ZeroOffset, + #[display(fmt = "Bytestream did not contain enough bytes to decode num_sequences")] NotEnoughBytesForNumSequences, + #[display(fmt = "Did not use full bitstream. Bits left: {bits_remaining} ({} bytes)", bits_remaining / 8)] ExtraBits { bits_remaining: isize }, + #[display(fmt = "compression modes are none but they must be set to something")] MissingCompressionMode, + #[display(fmt = "Need a byte to read for RLE ll table")] MissingByteForRleLlTable, + #[display(fmt = "Need a byte to read for RLE of table")] MissingByteForRleOfTable, + #[display(fmt = "Need a byte to read for RLE ml table")] MissingByteForRleMlTable, } -#[cfg(feature = "std")] -impl std::error::Error for DecodeSequenceError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - DecodeSequenceError::GetBitsError(source) => Some(source), - DecodeSequenceError::FSEDecoderError(source) => Some(source), - DecodeSequenceError::FSETableError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for DecodeSequenceError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecodeSequenceError::GetBitsError(e) => write!(f, "{:?}", e), - DecodeSequenceError::FSEDecoderError(e) => write!(f, "{:?}", e), - DecodeSequenceError::FSETableError(e) => write!(f, "{:?}", e), - DecodeSequenceError::ExtraPadding { skipped_bits } => { - write!(f, - "Padding at the end of the sequence_section was more than a byte long: {} bits. Probably caused by data corruption", - skipped_bits, - ) - } - DecodeSequenceError::UnsupportedOffset { offset_code } => { - write!( - f, - "Do not support offsets bigger than 1<<32; got: {}", - offset_code, - ) - } - DecodeSequenceError::ZeroOffset => write!( - f, - "Read an offset == 0. That is an illegal value for offsets" - ), - DecodeSequenceError::NotEnoughBytesForNumSequences => write!( - f, - "Bytestream did not contain enough bytes to decode num_sequences" - ), - DecodeSequenceError::ExtraBits { bits_remaining } => write!(f, "{}", bits_remaining), - DecodeSequenceError::MissingCompressionMode => write!( - f, - "compression modes are none but they must be set to something" - ), - DecodeSequenceError::MissingByteForRleLlTable => { - write!(f, "Need a byte to read for RLE ll table") - } - DecodeSequenceError::MissingByteForRleOfTable => { - write!(f, "Need a byte to read for RLE of table") - } - DecodeSequenceError::MissingByteForRleMlTable => { - write!(f, "Need a byte to read for RLE ml table") - } - } - } -} - -impl From for DecodeSequenceError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - -impl From for DecodeSequenceError { - fn from(val: FSETableError) -> Self { - Self::FSETableError(val) - } -} - -impl From for DecodeSequenceError { - fn from(val: FSEDecoderError) -> Self { - Self::FSEDecoderError(val) - } -} /// Decode the provided source as a series of sequences into the supplied `target`. pub fn decode_sequences( diff --git a/src/frame.rs b/src/frame.rs index b7a23498..6ff7daac 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,7 +1,4 @@ use crate::io::{Error, Read}; -use core::fmt; -#[cfg(feature = "std")] -use std::error::Error as StdError; /// This magic number is included at the start of a single Zstandard frame pub const MAGIC_NUM: u32 = 0xFD2F_B528; @@ -53,27 +50,14 @@ pub struct FrameHeader { /// are present. pub struct FrameDescriptor(u8); -#[derive(Debug)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameDescriptorError { + #[display(fmt = "Invalid Frame_Content_Size_Flag; Is: {got}, Should be one of: 0, 1, 2, 3")] InvalidFrameContentSizeFlag { got: u8 }, } -impl fmt::Display for FrameDescriptorError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::InvalidFrameContentSizeFlag { got } => write!( - f, - "Invalid Frame_Content_Size_Flag; Is: {}, Should be one of: 0, 1, 2, 3", - got - ), - } - } -} - -#[cfg(feature = "std")] -impl StdError for FrameDescriptorError {} - impl FrameDescriptor { /// Read the `Frame_Content_Size_flag` from the frame header descriptor. /// @@ -160,68 +144,33 @@ impl FrameDescriptor { } } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameHeaderError { + #[display( + fmt = "window_size bigger than allowed maximum. Is: {got}, Should be lower than: {MAX_WINDOW_SIZE}" + )] WindowTooBig { got: u64 }, + #[display( + fmt = "window_size smaller than allowed minimum. Is: {got}, Should be greater than: {MIN_WINDOW_SIZE}" + )] WindowTooSmall { got: u64 }, + #[display(fmt = "{_0:?}")] + #[from] FrameDescriptorError(FrameDescriptorError), + #[display(fmt = "Not enough bytes in dict_id. Is: {got}, Should be: {expected}")] DictIdTooSmall { got: usize, expected: usize }, + #[display( + fmt = "frame_content_size does not have the right length. Is: {got}, Should be: {expected}" + )] MismatchedFrameSize { got: usize, expected: u8 }, + #[display(fmt = "frame_content_size was zero")] FrameSizeIsZero, + #[display(fmt = "Invalid frame_content_size. Is: {got}, Should be one of 1, 2, 4, 8 bytes")] InvalidFrameSize { got: u8 }, } -impl fmt::Display for FrameHeaderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::WindowTooBig { got } => write!( - f, - "window_size bigger than allowed maximum. Is: {}, Should be lower than: {}", - got, MAX_WINDOW_SIZE - ), - Self::WindowTooSmall { got } => write!( - f, - "window_size smaller than allowed minimum. Is: {}, Should be greater than: {}", - got, MIN_WINDOW_SIZE - ), - Self::FrameDescriptorError(e) => write!(f, "{:?}", e), - Self::DictIdTooSmall { got, expected } => write!( - f, - "Not enough bytes in dict_id. Is: {}, Should be: {}", - got, expected - ), - Self::MismatchedFrameSize { got, expected } => write!( - f, - "frame_content_size does not have the right length. Is: {}, Should be: {}", - got, expected - ), - Self::FrameSizeIsZero => write!(f, "frame_content_size was zero"), - Self::InvalidFrameSize { got } => write!( - f, - "Invalid frame_content_size. Is: {}, Should be one of 1, 2, 4, 8 bytes", - got - ), - } - } -} - -#[cfg(feature = "std")] -impl StdError for FrameHeaderError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - FrameHeaderError::FrameDescriptorError(source) => Some(source), - _ => None, - } - } -} - -impl From for FrameHeaderError { - fn from(error: FrameDescriptorError) -> Self { - Self::FrameDescriptorError(error) - } -} - impl FrameHeader { /// Read the size of the window from the header, returning the size in bytes. pub fn window_size(&self) -> Result { @@ -260,68 +209,31 @@ impl FrameHeader { } } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum ReadFrameHeaderError { + #[display(fmt = "Error while reading magic number: {_0}")] MagicNumberReadError(Error), - BadMagicNumber(u32), + #[display(fmt = "Read wrong magic number: 0x{_0:X}")] + BadMagicNumber(#[cfg_attr(feature = "std", error(ignore))] u32), + #[display(fmt = "Error while reading frame descriptor: {_0}")] FrameDescriptorReadError(Error), + #[display(fmt = "{_0:?}")] + #[from] InvalidFrameDescriptor(FrameDescriptorError), + #[display(fmt = "Error while reading window descriptor: {_0}")] WindowDescriptorReadError(Error), + #[display(fmt = "Error while reading dictionary id: {_0}")] DictionaryIdReadError(Error), + #[display(fmt = "Error while reading frame content size: {_0}")] FrameContentSizeReadError(Error), + #[display( + fmt = "SkippableFrame encountered with MagicNumber 0x{magic_number:X} and length {length} bytes" + )] SkipFrame { magic_number: u32, length: u32 }, } -impl fmt::Display for ReadFrameHeaderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::MagicNumberReadError(e) => write!(f, "Error while reading magic number: {}", e), - Self::BadMagicNumber(e) => write!(f, "Read wrong magic number: 0x{:X}", e), - Self::FrameDescriptorReadError(e) => { - write!(f, "Error while reading frame descriptor: {}", e) - } - Self::InvalidFrameDescriptor(e) => write!(f, "{:?}", e), - Self::WindowDescriptorReadError(e) => { - write!(f, "Error while reading window descriptor: {}", e) - } - Self::DictionaryIdReadError(e) => write!(f, "Error while reading dictionary id: {}", e), - Self::FrameContentSizeReadError(e) => { - write!(f, "Error while reading frame content size: {}", e) - } - Self::SkipFrame { - magic_number, - length, - } => write!( - f, - "SkippableFrame encountered with MagicNumber 0x{:X} and length {} bytes", - magic_number, length - ), - } - } -} - -#[cfg(feature = "std")] -impl StdError for ReadFrameHeaderError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - ReadFrameHeaderError::MagicNumberReadError(source) => Some(source), - ReadFrameHeaderError::FrameDescriptorReadError(source) => Some(source), - ReadFrameHeaderError::InvalidFrameDescriptor(source) => Some(source), - ReadFrameHeaderError::WindowDescriptorReadError(source) => Some(source), - ReadFrameHeaderError::DictionaryIdReadError(source) => Some(source), - ReadFrameHeaderError::FrameContentSizeReadError(source) => Some(source), - _ => None, - } - } -} - -impl From for ReadFrameHeaderError { - fn from(error: FrameDescriptorError) -> Self { - Self::InvalidFrameDescriptor(error) - } -} - /// Read a single serialized frame from the reader and return a tuple containing the parsed frame and the number of bytes read. pub fn read_frame_header(mut r: impl Read) -> Result<(Frame, u8), ReadFrameHeaderError> { use ReadFrameHeaderError as err; diff --git a/src/frame_decoder.rs b/src/frame_decoder.rs index 610ced4e..a4b8929a 100644 --- a/src/frame_decoder.rs +++ b/src/frame_decoder.rs @@ -10,8 +10,6 @@ use crate::io::{Error, Read, Write}; use alloc::collections::BTreeMap; use alloc::vec::Vec; use core::convert::TryInto; -#[cfg(feature = "std")] -use std::error::Error as StdError; /// This implements a decoder for zstd frames. This decoder is able to decode frames only partially and gives control /// over how many bytes/blocks will be decoded at a time (so you don't have to decode a 10GB file into memory all at once). @@ -85,115 +83,46 @@ pub enum BlockDecodingStrategy { UptoBytes(usize), } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameDecoderError { + #[display(fmt = "{_0:?}")] + #[from] ReadFrameHeaderError(frame::ReadFrameHeaderError), + #[display(fmt = "{_0:?}")] + #[from] FrameHeaderError(frame::FrameHeaderError), + #[display( + fmt = "Specified window_size is too big; Requested: {requested}, Max: {MAX_WINDOW_SIZE}" + )] WindowSizeTooBig { requested: u64 }, + #[display(fmt = "{_0:?}")] + #[from] DictionaryDecodeError(dictionary::DictionaryDecodeError), + #[display(fmt = "Failed to parse/decode block body: {_0}")] + #[from] FailedToReadBlockHeader(decoding::block_decoder::BlockHeaderReadError), + #[display(fmt = "Failed to parse block header: {_0}")] FailedToReadBlockBody(decoding::block_decoder::DecodeBlockContentError), + #[display(fmt = "Failed to read checksum: {_0}")] FailedToReadChecksum(Error), + #[display(fmt = "Decoder must initialized or reset before using it")] NotYetInitialized, + #[display(fmt = "Decoder encountered error while initializing: {_0}")] FailedToInitialize(frame::FrameHeaderError), + #[display(fmt = "Decoder encountered error while draining the decodebuffer: {_0}")] FailedToDrainDecodebuffer(Error), + #[display( + fmt = "Target must have at least as many bytes as the contentsize of the frame reports" + )] TargetTooSmall, + #[display( + fmt = "Frame header specified dictionary id 0x{dict_id:X} that wasnt provided by add_dict() or reset_with_dict()" + )] DictNotProvided { dict_id: u32 }, } -#[cfg(feature = "std")] -impl StdError for FrameDecoderError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - FrameDecoderError::ReadFrameHeaderError(source) => Some(source), - FrameDecoderError::FrameHeaderError(source) => Some(source), - FrameDecoderError::DictionaryDecodeError(source) => Some(source), - FrameDecoderError::FailedToReadBlockHeader(source) => Some(source), - FrameDecoderError::FailedToReadBlockBody(source) => Some(source), - FrameDecoderError::FailedToReadChecksum(source) => Some(source), - FrameDecoderError::FailedToInitialize(source) => Some(source), - FrameDecoderError::FailedToDrainDecodebuffer(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for FrameDecoderError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - FrameDecoderError::ReadFrameHeaderError(e) => { - write!(f, "{:?}", e) - } - FrameDecoderError::FrameHeaderError(e) => { - write!(f, "{:?}", e) - } - FrameDecoderError::WindowSizeTooBig { requested } => { - write!( - f, - "Specified window_size is too big; Requested: {}, Max: {}", - requested, MAX_WINDOW_SIZE, - ) - } - FrameDecoderError::DictionaryDecodeError(e) => { - write!(f, "{:?}", e) - } - FrameDecoderError::FailedToReadBlockHeader(e) => { - write!(f, "Failed to parse/decode block body: {}", e) - } - FrameDecoderError::FailedToReadBlockBody(e) => { - write!(f, "Failed to parse block header: {}", e) - } - FrameDecoderError::FailedToReadChecksum(e) => { - write!(f, "Failed to read checksum: {}", e) - } - FrameDecoderError::NotYetInitialized => { - write!(f, "Decoder must initialized or reset before using it",) - } - FrameDecoderError::FailedToInitialize(e) => { - write!(f, "Decoder encountered error while initializing: {}", e) - } - FrameDecoderError::FailedToDrainDecodebuffer(e) => { - write!( - f, - "Decoder encountered error while draining the decodebuffer: {}", - e, - ) - } - FrameDecoderError::TargetTooSmall => { - write!(f, "Target must have at least as many bytes as the contentsize of the frame reports") - } - FrameDecoderError::DictNotProvided { dict_id } => { - write!(f, "Frame header specified dictionary id 0x{:X} that wasnt provided by add_dict() or reset_with_dict()", dict_id) - } - } - } -} - -impl From for FrameDecoderError { - fn from(val: dictionary::DictionaryDecodeError) -> Self { - Self::DictionaryDecodeError(val) - } -} - -impl From for FrameDecoderError { - fn from(val: decoding::block_decoder::BlockHeaderReadError) -> Self { - Self::FailedToReadBlockHeader(val) - } -} - -impl From for FrameDecoderError { - fn from(val: frame::FrameHeaderError) -> Self { - Self::FrameHeaderError(val) - } -} - -impl From for FrameDecoderError { - fn from(val: frame::ReadFrameHeaderError) -> Self { - Self::ReadFrameHeaderError(val) - } -} - const MAX_WINDOW_SIZE: u64 = 1024 * 1024 * 100; impl FrameDecoderState { diff --git a/src/fse/fse_decoder.rs b/src/fse/fse_decoder.rs index c456fcab..be7923b4 100644 --- a/src/fse/fse_decoder.rs +++ b/src/fse/fse_decoder.rs @@ -32,74 +32,27 @@ pub struct FSETable { symbol_counter: Vec, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FSETableError { + #[display(fmt = "Acclog must be at least 1")] AccLogIsZero, - AccLogTooBig { - got: u8, - max: u8, - }, + #[display(fmt = "Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}")] + AccLogTooBig { got: u8, max: u8 }, + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display( + fmt = "The counter ({got}) exceeded the expected sum: {expected_sum}. This means an error or corrupted data \n {symbol_probabilities:?}" + )] ProbabilityCounterMismatch { got: u32, expected_sum: u32, symbol_probabilities: Vec, }, - TooManySymbols { - got: usize, - }, -} - -#[cfg(feature = "std")] -impl std::error::Error for FSETableError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - FSETableError::GetBitsError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for FSETableError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - FSETableError::AccLogIsZero => write!(f, "Acclog must be at least 1"), - FSETableError::AccLogTooBig { got, max } => { - write!( - f, - "Found FSE acc_log: {0} bigger than allowed maximum in this case: {1}", - got, max - ) - } - FSETableError::GetBitsError(e) => write!(f, "{:?}", e), - FSETableError::ProbabilityCounterMismatch { - got, - expected_sum, - symbol_probabilities, - } => { - write!(f, - "The counter ({}) exceeded the expected sum: {}. This means an error or corrupted data \n {:?}", - got, - expected_sum, - symbol_probabilities, - ) - } - FSETableError::TooManySymbols { got } => { - write!( - f, - "There are too many symbols in this distribution: {}. Max: 256", - got, - ) - } - } - } -} - -impl From for FSETableError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } + #[display(fmt = "There are too many symbols in this distribution: {got}. Max: 256")] + TooManySymbols { got: usize }, } pub struct FSEDecoder<'table> { @@ -109,40 +62,17 @@ pub struct FSEDecoder<'table> { table: &'table FSETable, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FSEDecoderError { + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display(fmt = "Tried to use an uninitialized table!")] TableIsUninitialized, } -#[cfg(feature = "std")] -impl std::error::Error for FSEDecoderError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - FSEDecoderError::GetBitsError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for FSEDecoderError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - FSEDecoderError::GetBitsError(e) => write!(f, "{:?}", e), - FSEDecoderError::TableIsUninitialized => { - write!(f, "Tried to use an uninitialized table!") - } - } - } -} - -impl From for FSEDecoderError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - /// A single entry in an FSE table. #[derive(Copy, Clone)] pub struct Entry { diff --git a/src/huff0/huff0_decoder.rs b/src/huff0/huff0_decoder.rs index 129cfc84..508b7c7f 100644 --- a/src/huff0/huff0_decoder.rs +++ b/src/huff0/huff0_decoder.rs @@ -3,8 +3,6 @@ use crate::decoding::bit_reader_reverse::{BitReaderReversed, GetBitsError}; use crate::fse::{FSEDecoder, FSEDecoderError, FSETable, FSETableError}; use alloc::vec::Vec; -#[cfg(feature = "std")] -use std::error::Error as StdError; pub struct HuffmanTable { decode: Vec, @@ -24,151 +22,56 @@ pub struct HuffmanTable { fse_table: FSETable, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum HuffmanTableError { + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), + #[display(fmt = "{_0:?}")] + #[from] FSEDecoderError(FSEDecoderError), + #[display(fmt = "{_0:?}")] + #[from] FSETableError(FSETableError), + #[display(fmt = "Source needs to have at least one byte")] SourceIsEmpty, + #[display( + fmt = "Header says there should be {expected_bytes} bytes for the weights but there are only {got_bytes} bytes in the stream" + )] NotEnoughBytesForWeights { got_bytes: usize, expected_bytes: u8, }, - ExtraPadding { - skipped_bits: i32, - }, - TooManyWeights { - got: usize, - }, + #[display( + fmt = "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption" + )] + ExtraPadding { skipped_bits: i32 }, + #[display( + fmt = "More than 255 weights decoded (got {got} weights). Stream is probably corrupted" + )] + TooManyWeights { got: usize }, + #[display(fmt = "Can't build huffman table without any weights")] MissingWeights, - LeftoverIsNotAPowerOf2 { - got: u32, - }, - NotEnoughBytesToDecompressWeights { - have: usize, - need: usize, - }, - FSETableUsedTooManyBytes { - used: usize, - available_bytes: u8, - }, - NotEnoughBytesInSource { - got: usize, - need: usize, - }, - WeightBiggerThanMaxNumBits { - got: u8, - }, - MaxBitsTooHigh { - got: u8, - }, -} - -#[cfg(feature = "std")] -impl StdError for HuffmanTableError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - HuffmanTableError::GetBitsError(source) => Some(source), - HuffmanTableError::FSEDecoderError(source) => Some(source), - HuffmanTableError::FSETableError(source) => Some(source), - _ => None, - } - } -} - -impl core::fmt::Display for HuffmanTableError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result { - match self { - HuffmanTableError::GetBitsError(e) => write!(f, "{:?}", e), - HuffmanTableError::FSEDecoderError(e) => write!(f, "{:?}", e), - HuffmanTableError::FSETableError(e) => write!(f, "{:?}", e), - HuffmanTableError::SourceIsEmpty => write!(f, "Source needs to have at least one byte"), - HuffmanTableError::NotEnoughBytesForWeights { - got_bytes, - expected_bytes, - } => { - write!(f, "Header says there should be {} bytes for the weights but there are only {} bytes in the stream", - expected_bytes, - got_bytes) - } - HuffmanTableError::ExtraPadding { skipped_bits } => { - write!(f, - "Padding at the end of the sequence_section was more than a byte long: {} bits. Probably caused by data corruption", - skipped_bits, - ) - } - HuffmanTableError::TooManyWeights { got } => { - write!( - f, - "More than 255 weights decoded (got {} weights). Stream is probably corrupted", - got, - ) - } - HuffmanTableError::MissingWeights => { - write!(f, "Can\'t build huffman table without any weights") - } - HuffmanTableError::LeftoverIsNotAPowerOf2 { got } => { - write!(f, "Leftover must be power of two but is: {}", got) - } - HuffmanTableError::NotEnoughBytesToDecompressWeights { have, need } => { - write!( - f, - "Not enough bytes in stream to decompress weights. Is: {}, Should be: {}", - have, need, - ) - } - HuffmanTableError::FSETableUsedTooManyBytes { - used, - available_bytes, - } => { - write!(f, - "FSE table used more bytes: {} than were meant to be used for the whole stream of huffman weights ({})", - used, - available_bytes, - ) - } - HuffmanTableError::NotEnoughBytesInSource { got, need } => { - write!( - f, - "Source needs to have at least {} bytes, got: {}", - need, got, - ) - } - HuffmanTableError::WeightBiggerThanMaxNumBits { got } => { - write!( - f, - "Cant have weight: {} bigger than max_num_bits: {}", - got, MAX_MAX_NUM_BITS, - ) - } - HuffmanTableError::MaxBitsTooHigh { got } => { - write!( - f, - "max_bits derived from weights is: {} should be lower than: {}", - got, MAX_MAX_NUM_BITS, - ) - } - } - } -} - -impl From for HuffmanTableError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - -impl From for HuffmanTableError { - fn from(val: FSEDecoderError) -> Self { - Self::FSEDecoderError(val) - } -} - -impl From for HuffmanTableError { - fn from(val: FSETableError) -> Self { - Self::FSETableError(val) - } + #[display(fmt = "Leftover must be power of two but is: {got}")] + LeftoverIsNotAPowerOf2 { got: u32 }, + #[display( + fmt = "Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}" + )] + NotEnoughBytesToDecompressWeights { have: usize, need: usize }, + #[display( + fmt = "FSE table used more bytes: {used} than were meant to be used for the whole stream of huffman weights ({available_bytes})" + )] + FSETableUsedTooManyBytes { used: usize, available_bytes: u8 }, + #[display(fmt = "Source needs to have at least {need} bytes, got: {got}")] + NotEnoughBytesInSource { got: usize, need: usize }, + #[display(fmt = "Cant have weight: {got} bigger than max_num_bits: {MAX_MAX_NUM_BITS}")] + WeightBiggerThanMaxNumBits { got: u8 }, + #[display( + fmt = "max_bits derived from weights is: {got} should be lower than: {MAX_MAX_NUM_BITS}" + )] + MaxBitsTooHigh { got: u8 }, } /// An interface around a huffman table used to decode data. @@ -178,35 +81,15 @@ pub struct HuffmanDecoder<'table> { pub state: u64, } -#[derive(Debug)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum HuffmanDecoderError { + #[display(fmt = "{_0:?}")] + #[from] GetBitsError(GetBitsError), } -impl core::fmt::Display for HuffmanDecoderError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - HuffmanDecoderError::GetBitsError(e) => write!(f, "{:?}", e), - } - } -} - -#[cfg(feature = "std")] -impl StdError for HuffmanDecoderError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - HuffmanDecoderError::GetBitsError(source) => Some(source), - } - } -} - -impl From for HuffmanDecoderError { - fn from(val: GetBitsError) -> Self { - Self::GetBitsError(val) - } -} - /// A single entry in the table contains the decoded symbol/literal and the /// size of the prefix code. #[derive(Copy, Clone)]