diff --git a/Cargo.toml b/Cargo.toml index c90b8e0c..fbb48675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruzstd" -version = "0.4.0" +version = "0.5.0" authors = ["Moritz Borcherding "] edition = "2018" license = "MIT" @@ -11,9 +11,9 @@ exclude = ["decodecorpus_files/*", "dict_tests/*", "fuzz_decodecorpus/*"] readme = "Readme.md" [dependencies] -byteorder = { version = "1.4", default-features = false } +byteorder = { version = "1.5", default-features = false } twox-hash = { version = "1.6", default-features = false } -thiserror = { package = "thiserror-core", version = "1.0.38", default-features = false } +derive_more = { version = "0.99", default-features = false, features = ["display", "from"] } [dev-dependencies] criterion = "0.3" @@ -21,7 +21,7 @@ rand = {version = "0.8.5", features = ["small_rng"]} [features] default = ["std"] -std = ["thiserror/std"] +std = ["derive_more/error"] [[bench]] name = "reversedbitreader_bench" diff --git a/src/blocks/literals_section.rs b/src/blocks/literals_section.rs index 8f2aa51d..50d821c1 100644 --- a/src/blocks/literals_section.rs +++ b/src/blocks/literals_section.rs @@ -14,14 +14,18 @@ pub enum LiteralsSectionType { Treeless, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum LiteralsSectionParseError { - #[error("Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3")] + #[display(fmt = "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3")] IllegalLiteralSectionType { got: u8 }, - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error("Not enough byte to parse the literals section header. Have: {have}, Need: {need}")] + #[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 }, } diff --git a/src/blocks/sequence_section.rs b/src/blocks/sequence_section.rs index 544755e0..47b18d72 100644 --- a/src/blocks/sequence_section.rs +++ b/src/blocks/sequence_section.rs @@ -55,10 +55,13 @@ impl Default for SequencesHeader { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum SequencesHeaderParseError { - #[error("source must have at least {need_at_least} bytes to parse header; got {got} bytes")] + #[display( + fmt = "source must have at least {need_at_least} bytes to parse header; got {got} bytes" + )] NotEnoughBytes { need_at_least: u8, got: usize }, } diff --git a/src/decoding/bit_reader.rs b/src/decoding/bit_reader.rs index e07ac45c..55fb3064 100644 --- a/src/decoding/bit_reader.rs +++ b/src/decoding/bit_reader.rs @@ -3,15 +3,18 @@ pub struct BitReader<'s> { source: &'s [u8], } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum GetBitsError { - #[error("Cant serve this request. The reader is limited to {limit} bits, requested {num_requested_bits} bits")] + #[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, }, - #[error("Can't read {requested} bits, only have {remaining} bits left")] + #[display(fmt = "Can't read {requested} bits, only have {remaining} bits left")] NotEnoughRemainingBits { requested: usize, remaining: usize }, } diff --git a/src/decoding/block_decoder.rs b/src/decoding/block_decoder.rs index 0fbce8f4..18307b09 100644 --- a/src/decoding/block_decoder.rs +++ b/src/decoding/block_decoder.rs @@ -25,72 +25,89 @@ enum DecoderState { Failed, //TODO put "self.internal_state = DecoderState::Failed;" everywhere an unresolvable error occurs } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockHeaderReadError { - #[error("Error while reading the block header")] - ReadError(#[from] io::Error), - #[error("Reserved block occured. This is considered corruption by the documentation")] + #[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, - #[error("Error getting block type: {0}")] - BlockTypeError(#[from] BlockTypeError), - #[error("Error getting block content size: {0}")] - BlockSizeError(#[from] BlockSizeError), + #[display(fmt = "Error getting block type: {_0}")] + #[from] + BlockTypeError(BlockTypeError), + #[display(fmt = "Error getting block content size: {_0}")] + #[from] + BlockSizeError(BlockSizeError), } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockTypeError { - #[error( - "Invalid Blocktype number. Is: {num} Should be one of: 0, 1, 2, 3 (3 is reserved though" + #[display( + fmt = "Invalid Blocktype number. Is: {num} Should be one of: 0, 1, 2, 3 (3 is reserved though" )] InvalidBlocktypeNumber { num: u8 }, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum BlockSizeError { - #[error("Blocksize was bigger than the absolute maximum {ABSOLUTE_MAXIMUM_BLOCK_SIZE} (128kb). Is: {size}")] + #[display( + fmt = "Blocksize was bigger than the absolute maximum {ABSOLUTE_MAXIMUM_BLOCK_SIZE} (128kb). Is: {size}" + )] BlockSizeTooLarge { size: u32 }, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecompressBlockError { - #[error("Error while reading the block content: {0}")] - BlockContentReadError(#[from] io::Error), - #[error("Malformed section header. Says literals would be this long: {expected_len} but there are only {remaining_bytes} bytes left")] + #[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, }, - #[error(transparent)] - DecompressLiteralsError(#[from] DecompressLiteralsError), - #[error(transparent)] - LiteralsSectionParseError(#[from] LiteralsSectionParseError), - #[error(transparent)] - SequencesHeaderParseError(#[from] SequencesHeaderParseError), - #[error(transparent)] - DecodeSequenceError(#[from] DecodeSequenceError), - #[error(transparent)] - ExecuteSequencesError(#[from] ExecuteSequencesError), + #[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), } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodeBlockContentError { - #[error("Can't decode next block if failed along the way. Results will be nonsense")] + #[display(fmt = "Can't decode next block if failed along the way. Results will be nonsense")] DecoderStateIsFailed, - #[error("Cant decode next block body, while expecting to decode the header of the previous block. Results will be nonsense")] + #[display( + fmt = "Cant decode next block body, while expecting to decode the header of the previous block. Results will be nonsense" + )] ExpectedHeaderOfPreviousBlock, - #[error("Error while reading bytes for {step}: {source}")] - ReadError { - step: BlockType, - #[source] - source: io::Error, - }, - #[error(transparent)] - DecompressBlockError(#[from] DecompressBlockError), + #[display(fmt = "Error while reading bytes for {step}: {source}")] + ReadError { step: BlockType, source: io::Error }, + #[display(fmt = "{_0:?}")] + #[from] + DecompressBlockError(DecompressBlockError), } pub fn new() -> BlockDecoder { diff --git a/src/decoding/decodebuffer.rs b/src/decoding/decodebuffer.rs index 15f43e2a..34dc691e 100644 --- a/src/decoding/decodebuffer.rs +++ b/src/decoding/decodebuffer.rs @@ -15,12 +15,13 @@ pub struct Decodebuffer { pub hash: XxHash64, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodebufferError { - #[error("Need {need} bytes from the dictionary but it is only {got} bytes long")] + #[display(fmt = "Need {need} bytes from the dictionary but it is only {got} bytes long")] NotEnoughBytesInDictionary { got: usize, need: usize }, - #[error("offset: {offset} bigger than buffer: {buf_len}")] + #[display(fmt = "offset: {offset} bigger than buffer: {buf_len}")] OffsetTooBig { offset: usize, buf_len: usize }, } diff --git a/src/decoding/dictionary.rs b/src/decoding/dictionary.rs index aa676937..b86678e1 100644 --- a/src/decoding/dictionary.rs +++ b/src/decoding/dictionary.rs @@ -14,17 +14,20 @@ pub struct Dictionary { pub offset_hist: [u32; 3], } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DictionaryDecodeError { - #[error( - "Bad magic_num at start of the dictionary; Got: {got:#04X?}, Expected: {MAGIC_NUM:#04x?}" + #[display( + fmt = "Bad magic_num at start of the dictionary; Got: {got:#04X?}, Expected: {MAGIC_NUM:#04x?}" )] BadMagicNum { got: [u8; 4] }, - #[error(transparent)] - FSETableError(#[from] FSETableError), - #[error(transparent)] - HuffmanTableError(#[from] HuffmanTableError), + #[display(fmt = "{_0:?}")] + #[from] + FSETableError(FSETableError), + #[display(fmt = "{_0:?}")] + #[from] + HuffmanTableError(HuffmanTableError), } 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 bd7fb18e..50e0c941 100644 --- a/src/decoding/literals_section_decoder.rs +++ b/src/decoding/literals_section_decoder.rs @@ -4,32 +4,40 @@ use super::scratch::HuffmanScratch; use crate::huff0::{HuffmanDecoder, HuffmanDecoderError, HuffmanTableError}; use alloc::vec::Vec; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecompressLiteralsError { - #[error( - "compressed size was none even though it must be set to something for compressed literals" + #[display( + fmt = "compressed size was none even though it must be set to something for compressed literals" )] MissingCompressedSize, - #[error("num_streams was none even though it must be set to something (1 or 4) for compressed literals")] + #[display( + fmt = "num_streams was none even though it must be set to something (1 or 4) for compressed literals" + )] MissingNumStreams, - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error(transparent)] - HuffmanTableError(#[from] HuffmanTableError), - #[error(transparent)] - HuffmanDecoderError(#[from] HuffmanDecoderError), - #[error("Tried to reuse huffman table but it was never initialized")] + #[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, - #[error("Need 6 bytes to decode jump header, got {got} bytes")] + #[display(fmt = "Need 6 bytes to decode jump header, got {got} bytes")] MissingBytesForJumpHeader { got: usize }, - #[error("Need at least {needed} bytes to decode literals. Have: {got} bytes")] + #[display(fmt = "Need at least {needed} bytes to decode literals. Have: {got} bytes")] MissingBytesForLiterals { got: usize, needed: usize }, - #[error("Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption")] + #[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 }, - #[error("Bitstream was read till: {read_til}, should have been: {expected}")] + #[display(fmt = "Bitstream was read till: {read_til}, should have been: {expected}")] BitstreamReadMismatch { read_til: isize, expected: isize }, - #[error("Did not decode enough literals: {decoded}, Should have been: {expected}")] + #[display(fmt = "Did not decode enough literals: {decoded}, Should have been: {expected}")] DecodedLiteralCountMismatch { decoded: usize, expected: usize }, } diff --git a/src/decoding/ringbuffer.rs b/src/decoding/ringbuffer.rs index a9da2ed1..041fec55 100644 --- a/src/decoding/ringbuffer.rs +++ b/src/decoding/ringbuffer.rs @@ -268,8 +268,6 @@ impl RingBuffer { /// 2. More then len reserved space so we do not write out-of-bounds #[warn(unsafe_op_in_unsafe_fn)] pub unsafe fn extend_from_within_unchecked(&mut self, start: usize, len: usize) { - debug_assert!(!self.buf.as_ptr().is_null()); - if self.head < self.tail { // continous data slice |____HDDDDDDDT_____| let after_tail = usize::min(len, self.cap - self.tail); diff --git a/src/decoding/sequence_execution.rs b/src/decoding/sequence_execution.rs index 5946df18..cc03c6ec 100644 --- a/src/decoding/sequence_execution.rs +++ b/src/decoding/sequence_execution.rs @@ -1,13 +1,15 @@ use super::{decodebuffer::DecodebufferError, scratch::DecoderScratch}; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum ExecuteSequencesError { - #[error(transparent)] - DecodebufferError(#[from] DecodebufferError), - #[error("Sequence wants to copy up to byte {wanted}. Bytes in literalsbuffer: {have}")] + #[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 }, - #[error("Illegal offset: 0 found")] + #[display(fmt = "Illegal offset: 0 found")] ZeroOffset, } diff --git a/src/decoding/sequence_section_decoder.rs b/src/decoding/sequence_section_decoder.rs index 27ad4b25..e95e9e60 100644 --- a/src/decoding/sequence_section_decoder.rs +++ b/src/decoding/sequence_section_decoder.rs @@ -6,32 +6,38 @@ use super::scratch::FSEScratch; use crate::fse::{FSEDecoder, FSEDecoderError, FSETableError}; use alloc::vec::Vec; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum DecodeSequenceError { - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error(transparent)] - FSEDecoderError(#[from] FSEDecoderError), - #[error(transparent)] - FSETableError(#[from] FSETableError), - #[error("Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption")] + #[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 }, - #[error("Do not support offsets bigger than 1<<32; got: {offset_code}")] + #[display(fmt = "Do not support offsets bigger than 1<<32; got: {offset_code}")] UnsupportedOffset { offset_code: u8 }, - #[error("Read an offset == 0. That is an illegal value for offsets")] + #[display(fmt = "Read an offset == 0. That is an illegal value for offsets")] ZeroOffset, - #[error("Bytestream did not contain enough bytes to decode num_sequences")] + #[display(fmt = "Bytestream did not contain enough bytes to decode num_sequences")] NotEnoughBytesForNumSequences, - #[error("Did not use full bitstream. Bits left: {bits_remaining} ({} bytes)", bits_remaining / 8)] + #[display(fmt = "Did not use full bitstream. Bits left: {bits_remaining} ({} bytes)", bits_remaining / 8)] ExtraBits { bits_remaining: isize }, - #[error("compression modes are none but they must be set to something")] + #[display(fmt = "compression modes are none but they must be set to something")] MissingCompressionMode, - #[error("Need a byte to read for RLE ll table")] + #[display(fmt = "Need a byte to read for RLE ll table")] MissingByteForRleLlTable, - #[error("Need a byte to read for RLE of table")] + #[display(fmt = "Need a byte to read for RLE of table")] MissingByteForRleOfTable, - #[error("Need a byte to read for RLE ml table")] + #[display(fmt = "Need a byte to read for RLE ml table")] MissingByteForRleMlTable, } diff --git a/src/frame.rs b/src/frame.rs index 3810e4bc..0f771765 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -16,10 +16,11 @@ pub struct FrameHeader { pub struct FrameDescriptor(u8); -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameDescriptorError { - #[error("Invalid Frame_Content_Size_Flag; Is: {got}, Should be one of: 0, 1, 2, 3")] + #[display(fmt = "Invalid Frame_Content_Size_Flag; Is: {got}, Should be one of: 0, 1, 2, 3")] InvalidFrameContentSizeFlag { got: u8 }, } @@ -72,22 +73,30 @@ impl FrameDescriptor { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameHeaderError { - #[error("window_size bigger than allowed maximum. Is: {got}, Should be lower than: {MAX_WINDOW_SIZE}")] + #[display( + fmt = "window_size bigger than allowed maximum. Is: {got}, Should be lower than: {MAX_WINDOW_SIZE}" + )] WindowTooBig { got: u64 }, - #[error("window_size smaller than allowed minimum. Is: {got}, Should be greater than: {MIN_WINDOW_SIZE}")] + #[display( + fmt = "window_size smaller than allowed minimum. Is: {got}, Should be greater than: {MIN_WINDOW_SIZE}" + )] WindowTooSmall { got: u64 }, - #[error(transparent)] - FrameDescriptorError(#[from] FrameDescriptorError), - #[error("Not enough bytes in dict_id. Is: {got}, Should be: {expected}")] + #[display(fmt = "{_0:?}")] + #[from] + FrameDescriptorError(FrameDescriptorError), + #[display(fmt = "Not enough bytes in dict_id. Is: {got}, Should be: {expected}")] DictIdTooSmall { got: usize, expected: usize }, - #[error("frame_content_size does not have the right length. Is: {got}, Should be: {expected}")] + #[display( + fmt = "frame_content_size does not have the right length. Is: {got}, Should be: {expected}" + )] MismatchedFrameSize { got: usize, expected: u8 }, - #[error("frame_content_size was zero")] + #[display(fmt = "frame_content_size was zero")] FrameSizeIsZero, - #[error("Invalid frame_content_size. Is: {got}, Should be one of 1, 2, 4, 8 bytes")] + #[display(fmt = "Invalid frame_content_size. Is: {got}, Should be one of 1, 2, 4, 8 bytes")] InvalidFrameSize { got: u8 }, } @@ -126,24 +135,26 @@ impl FrameHeader { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum ReadFrameHeaderError { - #[error("Error while reading magic number: {0}")] - MagicNumberReadError(#[source] Error), - #[error("Read wrong magic number: 0x{0:X}")] - BadMagicNumber(u32), - #[error("Error while reading frame descriptor: {0}")] - FrameDescriptorReadError(#[source] Error), - #[error(transparent)] - InvalidFrameDescriptor(#[from] FrameDescriptorError), - #[error("Error while reading window descriptor: {0}")] - WindowDescriptorReadError(#[source] Error), - #[error("Error while reading dictionary id: {0}")] - DictionaryIdReadError(#[source] Error), - #[error("Error while reading frame content size: {0}")] - FrameContentSizeReadError(#[source] Error), - #[error("SkippableFrame encountered with MagicNumber 0x{0:X} and length {1} bytes")] + #[display(fmt = "Error while reading magic number: {_0}")] + MagicNumberReadError(Error), + #[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{_0:X} and length {_1} bytes")] SkipFrame(u32, u32), } diff --git a/src/frame_decoder.rs b/src/frame_decoder.rs index b871fe4e..2144bd22 100644 --- a/src/frame_decoder.rs +++ b/src/frame_decoder.rs @@ -80,32 +80,43 @@ pub enum BlockDecodingStrategy { UptoBytes(usize), } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FrameDecoderError { - #[error(transparent)] - ReadFrameHeaderError(#[from] frame::ReadFrameHeaderError), - #[error(transparent)] - FrameHeaderError(#[from] frame::FrameHeaderError), - #[error("Specified window_size is too big; Requested: {requested}, Max: {MAX_WINDOW_SIZE}")] + #[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 }, - #[error(transparent)] - DictionaryDecodeError(#[from] dictionary::DictionaryDecodeError), - #[error("Failed to parse/decode block body: {0}")] - FailedToReadBlockHeader(#[from] decoding::block_decoder::BlockHeaderReadError), - #[error("Failed to parse block header: {0}")] + #[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), - #[error("Failed to read checksum: {0}")] - FailedToReadChecksum(#[source] Error), - #[error("Decoder must initialized or reset before using it")] + #[display(fmt = "Failed to read checksum: {_0}")] + FailedToReadChecksum(Error), + #[display(fmt = "Decoder must initialized or reset before using it")] NotYetInitialized, - #[error("Decoder encountered error while initializing: {0}")] + #[display(fmt = "Decoder encountered error while initializing: {_0}")] FailedToInitialize(frame::FrameHeaderError), - #[error("Decoder encountered error while draining the decodebuffer: {0}")] - FailedToDrainDecodebuffer(#[source] Error), - #[error("Target must have at least as many bytes as the contentsize of the frame reports")] + #[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, - #[error("Frame header specified dictionary id 0x{dict_id:X} that wasnt provided by add_dict() or reset_with_dict()")] + #[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 }, } diff --git a/src/fse/fse_decoder.rs b/src/fse/fse_decoder.rs index 21868ff8..969768f1 100644 --- a/src/fse/fse_decoder.rs +++ b/src/fse/fse_decoder.rs @@ -16,22 +16,26 @@ impl Default for FSETable { } } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FSETableError { - #[error("Acclog must be at least 1")] + #[display(fmt = "Acclog must be at least 1")] AccLogIsZero, - #[error("Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}")] + #[display(fmt = "Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}")] AccLogTooBig { got: u8, max: u8 }, - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error("The counter ({got}) exceeded the expected sum: {expected_sum}. This means an error or corrupted data \n {symbol_probabilities:?}")] + #[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, }, - #[error("There are too many symbols in this distribution: {got}. Max: 256")] + #[display(fmt = "There are too many symbols in this distribution: {got}. Max: 256")] TooManySymbols { got: usize }, } @@ -40,12 +44,14 @@ pub struct FSEDecoder<'table> { table: &'table FSETable, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum FSEDecoderError { - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error("Tried to use an uninitialized table!")] + #[display(fmt = "{_0:?}")] + #[from] + GetBitsError(GetBitsError), + #[display(fmt = "Tried to use an uninitialized table!")] TableIsUninitialized, } @@ -66,7 +72,7 @@ fn highest_bit_set(x: u32) -> u32 { impl<'t> FSEDecoder<'t> { pub fn new(table: &'t FSETable) -> FSEDecoder<'_> { FSEDecoder { - state: table.decode.get(0).copied().unwrap_or(Entry { + state: table.decode.first().copied().unwrap_or(Entry { base_line: 0, num_bits: 0, symbol: 0, diff --git a/src/huff0/huff0_decoder.rs b/src/huff0/huff0_decoder.rs index a8aa7456..cc12476a 100644 --- a/src/huff0/huff0_decoder.rs +++ b/src/huff0/huff0_decoder.rs @@ -14,39 +14,55 @@ pub struct HuffmanTable { fse_table: FSETable, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum HuffmanTableError { - #[error(transparent)] - GetBitsError(#[from] GetBitsError), - #[error(transparent)] - FSEDecoderError(#[from] FSEDecoderError), - #[error(transparent)] - FSETableError(#[from] FSETableError), - #[error("Source needs to have at least one byte")] + #[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, - #[error("Header says there should be {expected_bytes} bytes for the weights but there are only {got_bytes} bytes in the stream")] + #[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, }, - #[error("Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption")] + #[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 }, - #[error("More than 255 weights decoded (got {got} weights). Stream is probably corrupted")] + #[display( + fmt = "More than 255 weights decoded (got {got} weights). Stream is probably corrupted" + )] TooManyWeights { got: usize }, - #[error("Can't build huffman table without any weights")] + #[display(fmt = "Can't build huffman table without any weights")] MissingWeights, - #[error("Leftover must be power of two but is: {got}")] + #[display(fmt = "Leftover must be power of two but is: {got}")] LeftoverIsNotAPowerOf2 { got: u32 }, - #[error("Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}")] + #[display( + fmt = "Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}" + )] NotEnoughBytesToDecompressWeights { have: usize, need: usize }, - #[error("FSE table used more bytes: {used} than were meant to be used for the whole stream of huffman weights ({available_bytes})")] + #[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 }, - #[error("Source needs to have at least {need} bytes, got: {got}")] + #[display(fmt = "Source needs to have at least {need} bytes, got: {got}")] NotEnoughBytesInSource { got: usize, need: usize }, - #[error("Cant have weight: {got} bigger than max_num_bits: {MAX_MAX_NUM_BITS}")] + #[display(fmt = "Cant have weight: {got} bigger than max_num_bits: {MAX_MAX_NUM_BITS}")] WeightBiggerThanMaxNumBits { got: u8 }, - #[error("max_bits derived from weights is: {got} should be lower than: {MAX_MAX_NUM_BITS}")] + #[display( + fmt = "max_bits derived from weights is: {got} should be lower than: {MAX_MAX_NUM_BITS}" + )] MaxBitsTooHigh { got: u8 }, } @@ -55,11 +71,13 @@ pub struct HuffmanDecoder<'table> { pub state: u64, } -#[derive(Debug, thiserror::Error)] +#[derive(Debug, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "std", derive(derive_more::Error))] #[non_exhaustive] pub enum HuffmanDecoderError { - #[error(transparent)] - GetBitsError(#[from] GetBitsError), + #[display(fmt = "{_0:?}")] + #[from] + GetBitsError(GetBitsError), } #[derive(Copy, Clone)] diff --git a/src/io_nostd.rs b/src/io_nostd.rs index 1e5d1416..0fc76e90 100644 --- a/src/io_nostd.rs +++ b/src/io_nostd.rs @@ -27,20 +27,27 @@ impl core::fmt::Display for ErrorKind { } } -#[derive(Debug)] pub struct Error { kind: ErrorKind, - err: Option>, + err: Option>, +} + +impl alloc::fmt::Debug for Error { + fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> Result<(), alloc::fmt::Error> { + let mut s = f.debug_struct("Error"); + s.field("kind", &self.kind); + if let Some(err) = self.err.as_ref() { + s.field("err", &alloc::format!("{err}")); + } + s.finish() + } } impl Error { - pub fn new(kind: ErrorKind, err: E) -> Self - where - E: Into>, - { + pub fn new(kind: ErrorKind, err: Box) -> Self { Self { kind, - err: Some(err.into()), + err: Some(err), } } @@ -52,15 +59,11 @@ impl Error { self.kind } - pub fn get_ref(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> { + pub fn get_ref(&self) -> Option<&(dyn core::fmt::Display + Send + Sync)> { self.err.as_ref().map(|e| e.as_ref()) } - pub fn get_mut(&mut self) -> Option<&mut (dyn core::error::Error + Send + Sync + 'static)> { - self.err.as_mut().map(|e| e.as_mut()) - } - - pub fn into_inner(self) -> Option> { + pub fn into_inner(self) -> Option> { self.err } } @@ -77,8 +80,6 @@ impl core::fmt::Display for Error { } } -impl core::error::Error for Error {} - impl From for Error { fn from(value: ErrorKind) -> Self { Self::from(value) diff --git a/src/lib.rs b/src/lib.rs index aecef623..03616c44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] #![deny(trivial_casts, trivial_numeric_casts, rust_2018_idioms)] -#![cfg_attr(not(feature = "std"), feature(error_in_core))] #[cfg(feature = "std")] extern crate std; diff --git a/src/streaming_decoder.rs b/src/streaming_decoder.rs index f345a897..52aa10c4 100644 --- a/src/streaming_decoder.rs +++ b/src/streaming_decoder.rs @@ -59,10 +59,15 @@ impl> Read for StreamingDecoder { /*Nothing to do*/ } Err(e) => { - let err = Error::new( - ErrorKind::Other, - alloc::format!("Error in the zstd decoder: {:?}", e), - ); + let err; + #[cfg(feature = "std")] + { + err = Error::new(ErrorKind::Other, e); + } + #[cfg(not(feature = "std"))] + { + err = Error::new(ErrorKind::Other, alloc::boxed::Box::new(e)); + } return Err(err); } } diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 0f25073e..32f55a4d 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -16,13 +16,22 @@ impl crate::io_nostd::Read for std::fs::File { } else { crate::io_nostd::Error::new( crate::io_nostd::ErrorKind::Other, - e.into_inner().unwrap(), + alloc::boxed::Box::new(e.into_inner().unwrap()), ) } }) } } +#[cfg(all(test, feature = "std"))] +#[allow(dead_code)] +fn assure_error_impl() { + // not a real test just there to throw an compiler error if Error is not derived correctly + + use crate::frame_decoder::FrameDecoderError; + let _err: &dyn std::error::Error = &FrameDecoderError::NotYetInitialized; +} + #[test] fn skippable_frame() { use crate::frame;