Skip to main content

structured_zstd/decoding/
errors.rs

1//! Errors that might occur while decoding zstd formatted data
2
3use crate::bit_io::GetBitsError;
4use crate::blocks::block::BlockType;
5use crate::blocks::literals_section::LiteralsSectionType;
6use crate::io::Error;
7use alloc::vec::Vec;
8use core::fmt;
9#[cfg(feature = "std")]
10use std::error::Error as StdError;
11
12#[derive(Debug)]
13#[non_exhaustive]
14pub enum FrameDescriptorError {
15    InvalidFrameContentSizeFlag { got: u8 },
16}
17
18impl fmt::Display for FrameDescriptorError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        match self {
21            Self::InvalidFrameContentSizeFlag { got } => write!(
22                f,
23                "Invalid Frame_Content_Size_Flag; Is: {got}, Should be one of: 0, 1, 2, 3"
24            ),
25        }
26    }
27}
28
29#[cfg(feature = "std")]
30impl StdError for FrameDescriptorError {}
31
32#[derive(Debug)]
33#[non_exhaustive]
34pub enum FrameHeaderError {
35    WindowTooBig { got: u64 },
36    WindowTooSmall { got: u64 },
37    FrameDescriptorError(FrameDescriptorError),
38    DictIdTooSmall { got: usize, expected: usize },
39    MismatchedFrameSize { got: usize, expected: u8 },
40    FrameSizeIsZero,
41    InvalidFrameSize { got: u8 },
42}
43
44impl fmt::Display for FrameHeaderError {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Self::WindowTooBig { got } => write!(
48                f,
49                "window_size bigger than allowed maximum. Is: {}, Should be lower than: {}",
50                got,
51                crate::common::MAX_WINDOW_SIZE
52            ),
53            Self::WindowTooSmall { got } => write!(
54                f,
55                "window_size smaller than allowed minimum. Is: {}, Should be greater than: {}",
56                got,
57                crate::common::MIN_WINDOW_SIZE
58            ),
59            Self::FrameDescriptorError(e) => write!(f, "{e:?}"),
60            Self::DictIdTooSmall { got, expected } => write!(
61                f,
62                "Not enough bytes in dict_id. Is: {got}, Should be: {expected}"
63            ),
64            Self::MismatchedFrameSize { got, expected } => write!(
65                f,
66                "frame_content_size does not have the right length. Is: {got}, Should be: {expected}"
67            ),
68            Self::FrameSizeIsZero => write!(f, "frame_content_size was zero"),
69            Self::InvalidFrameSize { got } => write!(
70                f,
71                "Invalid frame_content_size. Is: {got}, Should be one of 1, 2, 4, 8 bytes"
72            ),
73        }
74    }
75}
76
77#[cfg(feature = "std")]
78impl StdError for FrameHeaderError {
79    fn source(&self) -> Option<&(dyn StdError + 'static)> {
80        match self {
81            FrameHeaderError::FrameDescriptorError(source) => Some(source),
82            _ => None,
83        }
84    }
85}
86
87impl From<FrameDescriptorError> for FrameHeaderError {
88    fn from(error: FrameDescriptorError) -> Self {
89        Self::FrameDescriptorError(error)
90    }
91}
92
93#[derive(Debug)]
94#[non_exhaustive]
95pub enum ReadFrameHeaderError {
96    MagicNumberReadError(Error),
97    BadMagicNumber(u32),
98    FrameDescriptorReadError(Error),
99    InvalidFrameDescriptor(FrameDescriptorError),
100    WindowDescriptorReadError(Error),
101    DictionaryIdReadError(Error),
102    FrameContentSizeReadError(Error),
103    SkipFrame { magic_number: u32, length: u32 },
104}
105
106impl fmt::Display for ReadFrameHeaderError {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        match self {
109            Self::MagicNumberReadError(e) => write!(f, "Error while reading magic number: {e}"),
110            Self::BadMagicNumber(e) => write!(f, "Read wrong magic number: 0x{e:X}"),
111            Self::FrameDescriptorReadError(e) => {
112                write!(f, "Error while reading frame descriptor: {e}")
113            }
114            Self::InvalidFrameDescriptor(e) => write!(f, "{e:?}"),
115            Self::WindowDescriptorReadError(e) => {
116                write!(f, "Error while reading window descriptor: {e}")
117            }
118            Self::DictionaryIdReadError(e) => write!(f, "Error while reading dictionary id: {e}"),
119            Self::FrameContentSizeReadError(e) => {
120                write!(f, "Error while reading frame content size: {e}")
121            }
122            Self::SkipFrame {
123                magic_number,
124                length,
125            } => write!(
126                f,
127                "SkippableFrame encountered with MagicNumber 0x{magic_number:X} and length {length} bytes"
128            ),
129        }
130    }
131}
132
133#[cfg(feature = "std")]
134impl StdError for ReadFrameHeaderError {
135    fn source(&self) -> Option<&(dyn StdError + 'static)> {
136        match self {
137            ReadFrameHeaderError::MagicNumberReadError(source) => Some(source),
138            ReadFrameHeaderError::FrameDescriptorReadError(source) => Some(source),
139            ReadFrameHeaderError::InvalidFrameDescriptor(source) => Some(source),
140            ReadFrameHeaderError::WindowDescriptorReadError(source) => Some(source),
141            ReadFrameHeaderError::DictionaryIdReadError(source) => Some(source),
142            ReadFrameHeaderError::FrameContentSizeReadError(source) => Some(source),
143            _ => None,
144        }
145    }
146}
147
148impl From<FrameDescriptorError> for ReadFrameHeaderError {
149    fn from(error: FrameDescriptorError) -> Self {
150        Self::InvalidFrameDescriptor(error)
151    }
152}
153
154#[derive(Debug)]
155#[non_exhaustive]
156pub enum BlockHeaderReadError {
157    ReadError(Error),
158    FoundReservedBlock,
159    BlockTypeError(BlockTypeError),
160    BlockSizeError(BlockSizeError),
161}
162
163#[cfg(feature = "std")]
164impl std::error::Error for BlockHeaderReadError {
165    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
166        match self {
167            BlockHeaderReadError::ReadError(source) => Some(source),
168            BlockHeaderReadError::BlockTypeError(source) => Some(source),
169            BlockHeaderReadError::BlockSizeError(source) => Some(source),
170            BlockHeaderReadError::FoundReservedBlock => None,
171        }
172    }
173}
174
175impl ::core::fmt::Display for BlockHeaderReadError {
176    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
177        match self {
178            BlockHeaderReadError::ReadError(_) => write!(f, "Error while reading the block header"),
179            BlockHeaderReadError::FoundReservedBlock => write!(
180                f,
181                "Reserved block occured. This is considered corruption by the documentation"
182            ),
183            BlockHeaderReadError::BlockTypeError(e) => write!(f, "Error getting block type: {e}"),
184            BlockHeaderReadError::BlockSizeError(e) => {
185                write!(f, "Error getting block content size: {e}")
186            }
187        }
188    }
189}
190
191impl From<Error> for BlockHeaderReadError {
192    fn from(val: Error) -> Self {
193        Self::ReadError(val)
194    }
195}
196
197impl From<BlockTypeError> for BlockHeaderReadError {
198    fn from(val: BlockTypeError) -> Self {
199        Self::BlockTypeError(val)
200    }
201}
202
203impl From<BlockSizeError> for BlockHeaderReadError {
204    fn from(val: BlockSizeError) -> Self {
205        Self::BlockSizeError(val)
206    }
207}
208
209#[derive(Debug)]
210#[non_exhaustive]
211pub enum BlockTypeError {
212    InvalidBlocktypeNumber { num: u8 },
213}
214
215#[cfg(feature = "std")]
216impl std::error::Error for BlockTypeError {}
217
218impl core::fmt::Display for BlockTypeError {
219    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
220        match self {
221            BlockTypeError::InvalidBlocktypeNumber { num } => {
222                write!(
223                    f,
224                    "Invalid Blocktype number. Is: {num}. Should be one of: 0, 1, 2, 3 (3 is reserved).",
225                )
226            }
227        }
228    }
229}
230
231#[derive(Debug)]
232#[non_exhaustive]
233pub enum BlockSizeError {
234    BlockSizeTooLarge { size: u32 },
235}
236
237#[cfg(feature = "std")]
238impl std::error::Error for BlockSizeError {}
239
240impl core::fmt::Display for BlockSizeError {
241    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
242        match self {
243            BlockSizeError::BlockSizeTooLarge { size } => {
244                write!(
245                    f,
246                    "Blocksize was bigger than the absolute maximum {} (128kb). Is: {}",
247                    crate::common::MAX_BLOCK_SIZE,
248                    size,
249                )
250            }
251        }
252    }
253}
254
255#[derive(Debug)]
256#[non_exhaustive]
257pub enum DecompressBlockError {
258    BlockContentReadError(Error),
259    MalformedSectionHeader {
260        expected_len: usize,
261        remaining_bytes: usize,
262    },
263    DecompressLiteralsError(DecompressLiteralsError),
264    LiteralsSectionParseError(LiteralsSectionParseError),
265    SequencesHeaderParseError(SequencesHeaderParseError),
266    DecodeSequenceError(DecodeSequenceError),
267    ExecuteSequencesError(ExecuteSequencesError),
268}
269
270#[cfg(feature = "std")]
271impl std::error::Error for DecompressBlockError {
272    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
273        match self {
274            DecompressBlockError::BlockContentReadError(source) => Some(source),
275            DecompressBlockError::DecompressLiteralsError(source) => Some(source),
276            DecompressBlockError::LiteralsSectionParseError(source) => Some(source),
277            DecompressBlockError::SequencesHeaderParseError(source) => Some(source),
278            DecompressBlockError::DecodeSequenceError(source) => Some(source),
279            DecompressBlockError::ExecuteSequencesError(source) => Some(source),
280            _ => None,
281        }
282    }
283}
284
285impl core::fmt::Display for DecompressBlockError {
286    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
287        match self {
288            DecompressBlockError::BlockContentReadError(e) => {
289                write!(f, "Error while reading the block content: {e}")
290            }
291            DecompressBlockError::MalformedSectionHeader {
292                expected_len,
293                remaining_bytes,
294            } => {
295                write!(
296                    f,
297                    "Malformed section header. Says literals would be this long: {expected_len} but there are only {remaining_bytes} bytes left",
298                )
299            }
300            DecompressBlockError::DecompressLiteralsError(e) => write!(f, "{e:?}"),
301            DecompressBlockError::LiteralsSectionParseError(e) => write!(f, "{e:?}"),
302            DecompressBlockError::SequencesHeaderParseError(e) => write!(f, "{e:?}"),
303            DecompressBlockError::DecodeSequenceError(e) => write!(f, "{e:?}"),
304            DecompressBlockError::ExecuteSequencesError(e) => write!(f, "{e:?}"),
305        }
306    }
307}
308
309impl From<Error> for DecompressBlockError {
310    fn from(val: Error) -> Self {
311        Self::BlockContentReadError(val)
312    }
313}
314
315impl From<DecompressLiteralsError> for DecompressBlockError {
316    fn from(val: DecompressLiteralsError) -> Self {
317        Self::DecompressLiteralsError(val)
318    }
319}
320
321impl From<LiteralsSectionParseError> for DecompressBlockError {
322    fn from(val: LiteralsSectionParseError) -> Self {
323        Self::LiteralsSectionParseError(val)
324    }
325}
326
327impl From<SequencesHeaderParseError> for DecompressBlockError {
328    fn from(val: SequencesHeaderParseError) -> Self {
329        Self::SequencesHeaderParseError(val)
330    }
331}
332
333impl From<DecodeSequenceError> for DecompressBlockError {
334    fn from(val: DecodeSequenceError) -> Self {
335        Self::DecodeSequenceError(val)
336    }
337}
338
339impl From<ExecuteSequencesError> for DecompressBlockError {
340    fn from(val: ExecuteSequencesError) -> Self {
341        Self::ExecuteSequencesError(val)
342    }
343}
344
345#[derive(Debug)]
346#[non_exhaustive]
347pub enum DecodeBlockContentError {
348    DecoderStateIsFailed,
349    ExpectedHeaderOfPreviousBlock,
350    ReadError { step: BlockType, source: Error },
351    DecompressBlockError(DecompressBlockError),
352}
353
354#[cfg(feature = "std")]
355impl std::error::Error for DecodeBlockContentError {
356    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
357        match self {
358            DecodeBlockContentError::ReadError { step: _, source } => Some(source),
359            DecodeBlockContentError::DecompressBlockError(source) => Some(source),
360            _ => None,
361        }
362    }
363}
364
365impl core::fmt::Display for DecodeBlockContentError {
366    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
367        match self {
368            DecodeBlockContentError::DecoderStateIsFailed => {
369                write!(
370                    f,
371                    "Can't decode next block if failed along the way. Results will be nonsense",
372                )
373            }
374            DecodeBlockContentError::ExpectedHeaderOfPreviousBlock => {
375                write!(
376                    f,
377                    "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense",
378                )
379            }
380            DecodeBlockContentError::ReadError { step, source } => {
381                write!(f, "Error while reading bytes for {step}: {source}",)
382            }
383            DecodeBlockContentError::DecompressBlockError(e) => write!(f, "{e:?}"),
384        }
385    }
386}
387
388impl From<DecompressBlockError> for DecodeBlockContentError {
389    fn from(val: DecompressBlockError) -> Self {
390        Self::DecompressBlockError(val)
391    }
392}
393
394#[derive(Debug)]
395#[non_exhaustive]
396pub enum DecodeBufferError {
397    NotEnoughBytesInDictionary { got: usize, need: usize },
398    OffsetTooBig { offset: usize, buf_len: usize },
399    ZeroOffset,
400}
401
402#[cfg(feature = "std")]
403impl std::error::Error for DecodeBufferError {}
404
405impl core::fmt::Display for DecodeBufferError {
406    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407        match self {
408            DecodeBufferError::NotEnoughBytesInDictionary { got, need } => {
409                write!(
410                    f,
411                    "Need {need} bytes from the dictionary but it is only {got} bytes long",
412                )
413            }
414            DecodeBufferError::OffsetTooBig { offset, buf_len } => {
415                write!(f, "offset: {offset} bigger than buffer: {buf_len}",)
416            }
417            DecodeBufferError::ZeroOffset => {
418                write!(f, "Illegal offset: 0 found")
419            }
420        }
421    }
422}
423
424#[derive(Debug)]
425#[non_exhaustive]
426pub enum DictionaryDecodeError {
427    BadMagicNum { got: [u8; 4] },
428    DictionaryTooSmall { got: usize, need: usize },
429    ZeroDictionaryId,
430    ZeroRepeatOffsetInDictionary { index: u8 },
431    FSETableError(FSETableError),
432    HuffmanTableError(HuffmanTableError),
433}
434
435#[cfg(feature = "std")]
436impl std::error::Error for DictionaryDecodeError {
437    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
438        match self {
439            DictionaryDecodeError::FSETableError(source) => Some(source),
440            DictionaryDecodeError::HuffmanTableError(source) => Some(source),
441            _ => None,
442        }
443    }
444}
445
446impl core::fmt::Display for DictionaryDecodeError {
447    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
448        match self {
449            DictionaryDecodeError::BadMagicNum { got } => {
450                write!(
451                    f,
452                    "Bad magic_num at start of the dictionary; Got: {:#04X?}, Expected: {:#04x?}",
453                    got,
454                    crate::decoding::dictionary::MAGIC_NUM,
455                )
456            }
457            DictionaryDecodeError::DictionaryTooSmall { got, need } => {
458                write!(
459                    f,
460                    "Dictionary is too small: got {got} bytes, need at least {need} bytes",
461                )
462            }
463            DictionaryDecodeError::ZeroDictionaryId => {
464                write!(f, "Dictionary id must be non-zero")
465            }
466            DictionaryDecodeError::ZeroRepeatOffsetInDictionary { index } => {
467                write!(f, "Dictionary repeat offset rep{index} must be non-zero")
468            }
469            DictionaryDecodeError::FSETableError(e) => write!(f, "{e:?}"),
470            DictionaryDecodeError::HuffmanTableError(e) => write!(f, "{e:?}"),
471        }
472    }
473}
474
475impl From<FSETableError> for DictionaryDecodeError {
476    fn from(val: FSETableError) -> Self {
477        Self::FSETableError(val)
478    }
479}
480
481impl From<HuffmanTableError> for DictionaryDecodeError {
482    fn from(val: HuffmanTableError) -> Self {
483        Self::HuffmanTableError(val)
484    }
485}
486
487#[derive(Debug)]
488#[non_exhaustive]
489pub enum FrameDecoderError {
490    ReadFrameHeaderError(ReadFrameHeaderError),
491    FrameHeaderError(FrameHeaderError),
492    WindowSizeTooBig { requested: u64 },
493    DictionaryDecodeError(DictionaryDecodeError),
494    FailedToReadBlockHeader(BlockHeaderReadError),
495    FailedToReadBlockBody(DecodeBlockContentError),
496    FailedToReadChecksum(Error),
497    NotYetInitialized,
498    FailedToInitialize(FrameHeaderError),
499    FailedToDrainDecodebuffer(Error),
500    FailedToSkipFrame,
501    TargetTooSmall,
502    DictNotProvided { dict_id: u32 },
503    DictIdMismatch { expected: u32, provided: u32 },
504    DictAlreadyRegistered { dict_id: u32 },
505}
506
507#[cfg(feature = "std")]
508impl StdError for FrameDecoderError {
509    fn source(&self) -> Option<&(dyn StdError + 'static)> {
510        match self {
511            FrameDecoderError::ReadFrameHeaderError(source) => Some(source),
512            FrameDecoderError::FrameHeaderError(source) => Some(source),
513            FrameDecoderError::DictionaryDecodeError(source) => Some(source),
514            FrameDecoderError::FailedToReadBlockHeader(source) => Some(source),
515            FrameDecoderError::FailedToReadBlockBody(source) => Some(source),
516            FrameDecoderError::FailedToReadChecksum(source) => Some(source),
517            FrameDecoderError::FailedToInitialize(source) => Some(source),
518            FrameDecoderError::FailedToDrainDecodebuffer(source) => Some(source),
519            _ => None,
520        }
521    }
522}
523
524impl core::fmt::Display for FrameDecoderError {
525    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
526        match self {
527            FrameDecoderError::ReadFrameHeaderError(e) => {
528                write!(f, "{e:?}")
529            }
530            FrameDecoderError::FrameHeaderError(e) => {
531                write!(f, "{e:?}")
532            }
533            FrameDecoderError::WindowSizeTooBig { requested } => {
534                write!(
535                    f,
536                    "Specified window_size is too big; Requested: {}, Allowed: {}",
537                    requested,
538                    crate::common::MAXIMUM_ALLOWED_WINDOW_SIZE,
539                )
540            }
541            FrameDecoderError::DictionaryDecodeError(e) => {
542                write!(f, "{e:?}")
543            }
544            FrameDecoderError::FailedToReadBlockHeader(e) => {
545                write!(f, "Failed to parse/decode block body: {e}")
546            }
547            FrameDecoderError::FailedToReadBlockBody(e) => {
548                write!(f, "Failed to parse block header: {e}")
549            }
550            FrameDecoderError::FailedToReadChecksum(e) => {
551                write!(f, "Failed to read checksum: {e}")
552            }
553            FrameDecoderError::NotYetInitialized => {
554                write!(f, "Decoder must initialized or reset before using it",)
555            }
556            FrameDecoderError::FailedToInitialize(e) => {
557                write!(f, "Decoder encountered error while initializing: {e}")
558            }
559            FrameDecoderError::FailedToDrainDecodebuffer(e) => {
560                write!(
561                    f,
562                    "Decoder encountered error while draining the decodebuffer: {e}",
563                )
564            }
565            FrameDecoderError::FailedToSkipFrame => {
566                write!(
567                    f,
568                    "Failed to skip bytes for the length given in the frame header"
569                )
570            }
571            FrameDecoderError::TargetTooSmall => {
572                write!(
573                    f,
574                    "Target must have at least as many bytes as the content size reported by the frame"
575                )
576            }
577            FrameDecoderError::DictNotProvided { dict_id } => {
578                write!(
579                    f,
580                    "Frame header specified dictionary id 0x{dict_id:X} that wasn't provided via add_dict()/add_dict_from_bytes() (or add_dict_handle() on atomic targets) or reset_with_dict_handle()/decode_all_with_dict_handle()/decode_all_with_dict_bytes()"
581                )
582            }
583            FrameDecoderError::DictIdMismatch { expected, provided } => {
584                write!(
585                    f,
586                    "Frame header dictionary id 0x{expected:X} does not match provided dictionary id 0x{provided:X}"
587                )
588            }
589            FrameDecoderError::DictAlreadyRegistered { dict_id } => {
590                write!(
591                    f,
592                    "Dictionary id 0x{dict_id:X} already registered in decoder"
593                )
594            }
595        }
596    }
597}
598
599impl From<DictionaryDecodeError> for FrameDecoderError {
600    fn from(val: DictionaryDecodeError) -> Self {
601        Self::DictionaryDecodeError(val)
602    }
603}
604
605impl From<BlockHeaderReadError> for FrameDecoderError {
606    fn from(val: BlockHeaderReadError) -> Self {
607        Self::FailedToReadBlockHeader(val)
608    }
609}
610
611impl From<FrameHeaderError> for FrameDecoderError {
612    fn from(val: FrameHeaderError) -> Self {
613        Self::FrameHeaderError(val)
614    }
615}
616
617impl From<ReadFrameHeaderError> for FrameDecoderError {
618    fn from(val: ReadFrameHeaderError) -> Self {
619        Self::ReadFrameHeaderError(val)
620    }
621}
622
623#[derive(Debug)]
624#[non_exhaustive]
625pub enum DecompressLiteralsError {
626    MissingCompressedSize,
627    MissingNumStreams,
628    GetBitsError(GetBitsError),
629    HuffmanTableError(HuffmanTableError),
630    HuffmanDecoderError(HuffmanDecoderError),
631    UninitializedHuffmanTable,
632    MissingBytesForJumpHeader { got: usize },
633    MissingBytesForLiterals { got: usize, needed: usize },
634    ExtraPadding { skipped_bits: i32 },
635    BitstreamReadMismatch { read_til: isize, expected: isize },
636    DecodedLiteralCountMismatch { decoded: usize, expected: usize },
637}
638
639#[cfg(feature = "std")]
640impl std::error::Error for DecompressLiteralsError {
641    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
642        match self {
643            DecompressLiteralsError::GetBitsError(source) => Some(source),
644            DecompressLiteralsError::HuffmanTableError(source) => Some(source),
645            DecompressLiteralsError::HuffmanDecoderError(source) => Some(source),
646            _ => None,
647        }
648    }
649}
650impl core::fmt::Display for DecompressLiteralsError {
651    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
652        match self {
653            DecompressLiteralsError::MissingCompressedSize => {
654                write!(
655                    f,
656                    "compressed size was none even though it must be set to something for compressed literals",
657                )
658            }
659            DecompressLiteralsError::MissingNumStreams => {
660                write!(
661                    f,
662                    "num_streams was none even though it must be set to something (1 or 4) for compressed literals",
663                )
664            }
665            DecompressLiteralsError::GetBitsError(e) => write!(f, "{e:?}"),
666            DecompressLiteralsError::HuffmanTableError(e) => write!(f, "{e:?}"),
667            DecompressLiteralsError::HuffmanDecoderError(e) => write!(f, "{e:?}"),
668            DecompressLiteralsError::UninitializedHuffmanTable => {
669                write!(
670                    f,
671                    "Tried to reuse huffman table but it was never initialized",
672                )
673            }
674            DecompressLiteralsError::MissingBytesForJumpHeader { got } => {
675                write!(f, "Need 6 bytes to decode jump header, got {got} bytes",)
676            }
677            DecompressLiteralsError::MissingBytesForLiterals { got, needed } => {
678                write!(
679                    f,
680                    "Need at least {needed} bytes to decode literals. Have: {got} bytes",
681                )
682            }
683            DecompressLiteralsError::ExtraPadding { skipped_bits } => {
684                write!(
685                    f,
686                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
687                )
688            }
689            DecompressLiteralsError::BitstreamReadMismatch { read_til, expected } => {
690                write!(
691                    f,
692                    "Bitstream was read till: {read_til}, should have been: {expected}",
693                )
694            }
695            DecompressLiteralsError::DecodedLiteralCountMismatch { decoded, expected } => {
696                write!(
697                    f,
698                    "Did not decode enough literals: {decoded}, Should have been: {expected}",
699                )
700            }
701        }
702    }
703}
704
705impl From<HuffmanDecoderError> for DecompressLiteralsError {
706    fn from(val: HuffmanDecoderError) -> Self {
707        Self::HuffmanDecoderError(val)
708    }
709}
710
711impl From<GetBitsError> for DecompressLiteralsError {
712    fn from(val: GetBitsError) -> Self {
713        Self::GetBitsError(val)
714    }
715}
716
717impl From<HuffmanTableError> for DecompressLiteralsError {
718    fn from(val: HuffmanTableError) -> Self {
719        Self::HuffmanTableError(val)
720    }
721}
722
723#[derive(Debug)]
724#[non_exhaustive]
725pub enum ExecuteSequencesError {
726    DecodebufferError(DecodeBufferError),
727    NotEnoughBytesForSequence { wanted: usize, have: usize },
728    ZeroOffset,
729}
730
731impl core::fmt::Display for ExecuteSequencesError {
732    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
733        match self {
734            ExecuteSequencesError::DecodebufferError(e) => {
735                write!(f, "{e:?}")
736            }
737            ExecuteSequencesError::NotEnoughBytesForSequence { wanted, have } => {
738                write!(
739                    f,
740                    "Sequence wants to copy up to byte {wanted}. Bytes in literalsbuffer: {have}"
741                )
742            }
743            ExecuteSequencesError::ZeroOffset => {
744                write!(f, "Illegal offset: 0 found")
745            }
746        }
747    }
748}
749
750#[cfg(feature = "std")]
751impl std::error::Error for ExecuteSequencesError {
752    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
753        match self {
754            ExecuteSequencesError::DecodebufferError(source) => Some(source),
755            _ => None,
756        }
757    }
758}
759
760impl From<DecodeBufferError> for ExecuteSequencesError {
761    fn from(val: DecodeBufferError) -> Self {
762        Self::DecodebufferError(val)
763    }
764}
765
766#[derive(Debug)]
767#[non_exhaustive]
768pub enum DecodeSequenceError {
769    GetBitsError(GetBitsError),
770    FSEDecoderError(FSEDecoderError),
771    FSETableError(FSETableError),
772    ExtraPadding { skipped_bits: i32 },
773    UnsupportedOffset { offset_code: u8 },
774    ZeroOffset,
775    NotEnoughBytesForNumSequences,
776    ExtraBits { bits_remaining: isize },
777    MissingCompressionMode,
778    MissingByteForRleLlTable,
779    MissingByteForRleOfTable,
780    MissingByteForRleMlTable,
781}
782
783#[cfg(feature = "std")]
784impl std::error::Error for DecodeSequenceError {
785    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
786        match self {
787            DecodeSequenceError::GetBitsError(source) => Some(source),
788            DecodeSequenceError::FSEDecoderError(source) => Some(source),
789            DecodeSequenceError::FSETableError(source) => Some(source),
790            _ => None,
791        }
792    }
793}
794
795impl core::fmt::Display for DecodeSequenceError {
796    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
797        match self {
798            DecodeSequenceError::GetBitsError(e) => write!(f, "{e:?}"),
799            DecodeSequenceError::FSEDecoderError(e) => write!(f, "{e:?}"),
800            DecodeSequenceError::FSETableError(e) => write!(f, "{e:?}"),
801            DecodeSequenceError::ExtraPadding { skipped_bits } => {
802                write!(
803                    f,
804                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
805                )
806            }
807            DecodeSequenceError::UnsupportedOffset { offset_code } => {
808                write!(
809                    f,
810                    "Do not support offsets bigger than 1<<32; got: {offset_code}",
811                )
812            }
813            DecodeSequenceError::ZeroOffset => write!(
814                f,
815                "Read an offset == 0. That is an illegal value for offsets"
816            ),
817            DecodeSequenceError::NotEnoughBytesForNumSequences => write!(
818                f,
819                "Bytestream did not contain enough bytes to decode num_sequences"
820            ),
821            DecodeSequenceError::ExtraBits { bits_remaining } => write!(f, "{bits_remaining}"),
822            DecodeSequenceError::MissingCompressionMode => write!(
823                f,
824                "compression modes are none but they must be set to something"
825            ),
826            DecodeSequenceError::MissingByteForRleLlTable => {
827                write!(f, "Need a byte to read for RLE ll table")
828            }
829            DecodeSequenceError::MissingByteForRleOfTable => {
830                write!(f, "Need a byte to read for RLE of table")
831            }
832            DecodeSequenceError::MissingByteForRleMlTable => {
833                write!(f, "Need a byte to read for RLE ml table")
834            }
835        }
836    }
837}
838
839impl From<GetBitsError> for DecodeSequenceError {
840    fn from(val: GetBitsError) -> Self {
841        Self::GetBitsError(val)
842    }
843}
844
845impl From<FSETableError> for DecodeSequenceError {
846    fn from(val: FSETableError) -> Self {
847        Self::FSETableError(val)
848    }
849}
850
851impl From<FSEDecoderError> for DecodeSequenceError {
852    fn from(val: FSEDecoderError) -> Self {
853        Self::FSEDecoderError(val)
854    }
855}
856
857#[derive(Debug)]
858#[non_exhaustive]
859pub enum LiteralsSectionParseError {
860    IllegalLiteralSectionType { got: u8 },
861    GetBitsError(GetBitsError),
862    NotEnoughBytes { have: usize, need: u8 },
863}
864
865#[cfg(feature = "std")]
866impl std::error::Error for LiteralsSectionParseError {
867    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
868        match self {
869            LiteralsSectionParseError::GetBitsError(source) => Some(source),
870            _ => None,
871        }
872    }
873}
874impl core::fmt::Display for LiteralsSectionParseError {
875    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
876        match self {
877            LiteralsSectionParseError::IllegalLiteralSectionType { got } => {
878                write!(
879                    f,
880                    "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3"
881                )
882            }
883            LiteralsSectionParseError::GetBitsError(e) => write!(f, "{e:?}"),
884            LiteralsSectionParseError::NotEnoughBytes { have, need } => {
885                write!(
886                    f,
887                    "Not enough byte to parse the literals section header. Have: {have}, Need: {need}",
888                )
889            }
890        }
891    }
892}
893
894impl From<GetBitsError> for LiteralsSectionParseError {
895    fn from(val: GetBitsError) -> Self {
896        Self::GetBitsError(val)
897    }
898}
899
900impl core::fmt::Display for LiteralsSectionType {
901    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
902        match self {
903            LiteralsSectionType::Compressed => write!(f, "Compressed"),
904            LiteralsSectionType::Raw => write!(f, "Raw"),
905            LiteralsSectionType::RLE => write!(f, "RLE"),
906            LiteralsSectionType::Treeless => write!(f, "Treeless"),
907        }
908    }
909}
910
911#[derive(Debug)]
912#[non_exhaustive]
913pub enum SequencesHeaderParseError {
914    NotEnoughBytes { need_at_least: u8, got: usize },
915}
916
917#[cfg(feature = "std")]
918impl std::error::Error for SequencesHeaderParseError {}
919
920impl core::fmt::Display for SequencesHeaderParseError {
921    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
922        match self {
923            SequencesHeaderParseError::NotEnoughBytes { need_at_least, got } => {
924                write!(
925                    f,
926                    "source must have at least {need_at_least} bytes to parse header; got {got} bytes",
927                )
928            }
929        }
930    }
931}
932
933#[derive(Debug)]
934#[non_exhaustive]
935pub enum FSETableError {
936    AccLogIsZero,
937    AccLogTooBig {
938        got: u8,
939        max: u8,
940    },
941    GetBitsError(GetBitsError),
942    ProbabilityCounterMismatch {
943        got: u32,
944        expected_sum: u32,
945        symbol_probabilities: Vec<i32>,
946    },
947    TooManySymbols {
948        got: usize,
949    },
950}
951
952#[cfg(feature = "std")]
953impl std::error::Error for FSETableError {
954    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
955        match self {
956            FSETableError::GetBitsError(source) => Some(source),
957            _ => None,
958        }
959    }
960}
961
962impl core::fmt::Display for FSETableError {
963    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
964        match self {
965            FSETableError::AccLogIsZero => write!(f, "Acclog must be at least 1"),
966            FSETableError::AccLogTooBig { got, max } => {
967                write!(
968                    f,
969                    "Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}"
970                )
971            }
972            FSETableError::GetBitsError(e) => write!(f, "{e:?}"),
973            FSETableError::ProbabilityCounterMismatch {
974                got,
975                expected_sum,
976                symbol_probabilities,
977            } => {
978                write!(
979                    f,
980                    "The counter ({got}) exceeded the expected sum: {expected_sum}. This means an error or corrupted data \n {symbol_probabilities:?}",
981                )
982            }
983            FSETableError::TooManySymbols { got } => {
984                write!(
985                    f,
986                    "There are too many symbols in this distribution: {got}. Max: 256",
987                )
988            }
989        }
990    }
991}
992
993impl From<GetBitsError> for FSETableError {
994    fn from(val: GetBitsError) -> Self {
995        Self::GetBitsError(val)
996    }
997}
998
999#[derive(Debug)]
1000#[non_exhaustive]
1001pub enum FSEDecoderError {
1002    GetBitsError(GetBitsError),
1003    TableIsUninitialized,
1004}
1005
1006#[cfg(feature = "std")]
1007impl std::error::Error for FSEDecoderError {
1008    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1009        match self {
1010            FSEDecoderError::GetBitsError(source) => Some(source),
1011            _ => None,
1012        }
1013    }
1014}
1015
1016impl core::fmt::Display for FSEDecoderError {
1017    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1018        match self {
1019            FSEDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
1020            FSEDecoderError::TableIsUninitialized => {
1021                write!(f, "Tried to use an uninitialized table!")
1022            }
1023        }
1024    }
1025}
1026
1027impl From<GetBitsError> for FSEDecoderError {
1028    fn from(val: GetBitsError) -> Self {
1029        Self::GetBitsError(val)
1030    }
1031}
1032
1033#[derive(Debug)]
1034#[non_exhaustive]
1035pub enum HuffmanTableError {
1036    GetBitsError(GetBitsError),
1037    FSEDecoderError(FSEDecoderError),
1038    FSETableError(FSETableError),
1039    SourceIsEmpty,
1040    NotEnoughBytesForWeights {
1041        got_bytes: usize,
1042        expected_bytes: u8,
1043    },
1044    ExtraPadding {
1045        skipped_bits: i32,
1046    },
1047    TooManyWeights {
1048        got: usize,
1049    },
1050    MissingWeights,
1051    LeftoverIsNotAPowerOf2 {
1052        got: u32,
1053    },
1054    NotEnoughBytesToDecompressWeights {
1055        have: usize,
1056        need: usize,
1057    },
1058    FSETableUsedTooManyBytes {
1059        used: usize,
1060        available_bytes: u8,
1061    },
1062    NotEnoughBytesInSource {
1063        got: usize,
1064        need: usize,
1065    },
1066    WeightBiggerThanMaxNumBits {
1067        got: u8,
1068    },
1069    MaxBitsTooHigh {
1070        got: u8,
1071    },
1072}
1073
1074#[cfg(feature = "std")]
1075impl StdError for HuffmanTableError {
1076    fn source(&self) -> Option<&(dyn StdError + 'static)> {
1077        match self {
1078            HuffmanTableError::GetBitsError(source) => Some(source),
1079            HuffmanTableError::FSEDecoderError(source) => Some(source),
1080            HuffmanTableError::FSETableError(source) => Some(source),
1081            _ => None,
1082        }
1083    }
1084}
1085
1086impl core::fmt::Display for HuffmanTableError {
1087    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1088        match self {
1089            HuffmanTableError::GetBitsError(e) => write!(f, "{e:?}"),
1090            HuffmanTableError::FSEDecoderError(e) => write!(f, "{e:?}"),
1091            HuffmanTableError::FSETableError(e) => write!(f, "{e:?}"),
1092            HuffmanTableError::SourceIsEmpty => write!(f, "Source needs to have at least one byte"),
1093            HuffmanTableError::NotEnoughBytesForWeights {
1094                got_bytes,
1095                expected_bytes,
1096            } => {
1097                write!(
1098                    f,
1099                    "Header says there should be {expected_bytes} bytes for the weights but there are only {got_bytes} bytes in the stream"
1100                )
1101            }
1102            HuffmanTableError::ExtraPadding { skipped_bits } => {
1103                write!(
1104                    f,
1105                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
1106                )
1107            }
1108            HuffmanTableError::TooManyWeights { got } => {
1109                write!(
1110                    f,
1111                    "More than 255 weights decoded (got {got} weights). Stream is probably corrupted",
1112                )
1113            }
1114            HuffmanTableError::MissingWeights => {
1115                write!(f, "Can\'t build huffman table without any weights")
1116            }
1117            HuffmanTableError::LeftoverIsNotAPowerOf2 { got } => {
1118                write!(f, "Leftover must be power of two but is: {got}")
1119            }
1120            HuffmanTableError::NotEnoughBytesToDecompressWeights { have, need } => {
1121                write!(
1122                    f,
1123                    "Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}",
1124                )
1125            }
1126            HuffmanTableError::FSETableUsedTooManyBytes {
1127                used,
1128                available_bytes,
1129            } => {
1130                write!(
1131                    f,
1132                    "FSE table used more bytes: {used} than were meant to be used for the whole stream of huffman weights ({available_bytes})",
1133                )
1134            }
1135            HuffmanTableError::NotEnoughBytesInSource { got, need } => {
1136                write!(f, "Source needs to have at least {need} bytes, got: {got}",)
1137            }
1138            HuffmanTableError::WeightBiggerThanMaxNumBits { got } => {
1139                write!(
1140                    f,
1141                    "Cant have weight: {} bigger than max_num_bits: {}",
1142                    got,
1143                    crate::huff0::MAX_MAX_NUM_BITS,
1144                )
1145            }
1146            HuffmanTableError::MaxBitsTooHigh { got } => {
1147                write!(
1148                    f,
1149                    "max_bits derived from weights is: {} should be lower than: {}",
1150                    got,
1151                    crate::huff0::MAX_MAX_NUM_BITS,
1152                )
1153            }
1154        }
1155    }
1156}
1157
1158impl From<GetBitsError> for HuffmanTableError {
1159    fn from(val: GetBitsError) -> Self {
1160        Self::GetBitsError(val)
1161    }
1162}
1163
1164impl From<FSEDecoderError> for HuffmanTableError {
1165    fn from(val: FSEDecoderError) -> Self {
1166        Self::FSEDecoderError(val)
1167    }
1168}
1169
1170impl From<FSETableError> for HuffmanTableError {
1171    fn from(val: FSETableError) -> Self {
1172        Self::FSETableError(val)
1173    }
1174}
1175
1176#[derive(Debug)]
1177#[non_exhaustive]
1178pub enum HuffmanDecoderError {
1179    GetBitsError(GetBitsError),
1180}
1181
1182impl core::fmt::Display for HuffmanDecoderError {
1183    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1184        match self {
1185            HuffmanDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
1186        }
1187    }
1188}
1189
1190#[cfg(feature = "std")]
1191impl StdError for HuffmanDecoderError {
1192    fn source(&self) -> Option<&(dyn StdError + 'static)> {
1193        match self {
1194            HuffmanDecoderError::GetBitsError(source) => Some(source),
1195        }
1196    }
1197}
1198
1199impl From<GetBitsError> for HuffmanDecoderError {
1200    fn from(val: GetBitsError) -> Self {
1201        Self::GetBitsError(val)
1202    }
1203}
1204
1205#[cfg(test)]
1206mod tests {
1207    use alloc::{string::ToString, vec};
1208
1209    use super::{
1210        BlockTypeError, DecodeBlockContentError, DecodeSequenceError, DecompressBlockError,
1211        DecompressLiteralsError, FSETableError, FrameDecoderError, HuffmanTableError,
1212    };
1213
1214    #[test]
1215    fn block_and_sequence_display_messages_are_specific() {
1216        assert_eq!(
1217            BlockTypeError::InvalidBlocktypeNumber { num: 7 }.to_string(),
1218            "Invalid Blocktype number. Is: 7. Should be one of: 0, 1, 2, 3 (3 is reserved)."
1219        );
1220        assert_eq!(
1221            DecompressBlockError::MalformedSectionHeader {
1222                expected_len: 12,
1223                remaining_bytes: 3,
1224            }
1225            .to_string(),
1226            "Malformed section header. Says literals would be this long: 12 but there are only 3 bytes left"
1227        );
1228        assert_eq!(
1229            DecodeBlockContentError::ExpectedHeaderOfPreviousBlock.to_string(),
1230            "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense"
1231        );
1232        assert_eq!(
1233            DecodeSequenceError::ExtraPadding { skipped_bits: 11 }.to_string(),
1234            "Padding at the end of the sequence_section was more than a byte long: 11 bits. Probably caused by data corruption"
1235        );
1236    }
1237
1238    #[test]
1239    fn frame_decoder_display_messages_are_specific() {
1240        assert_eq!(
1241            FrameDecoderError::TargetTooSmall.to_string(),
1242            "Target must have at least as many bytes as the content size reported by the frame"
1243        );
1244        assert_eq!(
1245            FrameDecoderError::DictNotProvided { dict_id: 0xABCD }.to_string(),
1246            "Frame header specified dictionary id 0xABCD that wasn't provided via add_dict()/add_dict_from_bytes() (or add_dict_handle() on atomic targets) or reset_with_dict_handle()/decode_all_with_dict_handle()/decode_all_with_dict_bytes()"
1247        );
1248        assert_eq!(
1249            FrameDecoderError::DictIdMismatch {
1250                expected: 0xABCD,
1251                provided: 0x1234
1252            }
1253            .to_string(),
1254            "Frame header dictionary id 0xABCD does not match provided dictionary id 0x1234"
1255        );
1256        assert_eq!(
1257            FrameDecoderError::DictAlreadyRegistered { dict_id: 0xABCD }.to_string(),
1258            "Dictionary id 0xABCD already registered in decoder"
1259        );
1260    }
1261
1262    #[test]
1263    fn literal_display_messages_are_specific() {
1264        assert_eq!(
1265            DecompressLiteralsError::MissingCompressedSize.to_string(),
1266            "compressed size was none even though it must be set to something for compressed literals"
1267        );
1268        assert_eq!(
1269            DecompressLiteralsError::MissingNumStreams.to_string(),
1270            "num_streams was none even though it must be set to something (1 or 4) for compressed literals"
1271        );
1272        assert_eq!(
1273            DecompressLiteralsError::ExtraPadding { skipped_bits: 9 }.to_string(),
1274            "Padding at the end of the sequence_section was more than a byte long: 9 bits. Probably caused by data corruption"
1275        );
1276    }
1277
1278    #[test]
1279    fn fse_and_huffman_display_messages_are_specific() {
1280        assert_eq!(
1281            FSETableError::ProbabilityCounterMismatch {
1282                got: 4,
1283                expected_sum: 3,
1284                symbol_probabilities: vec![1, -1],
1285            }
1286            .to_string(),
1287            "The counter (4) exceeded the expected sum: 3. This means an error or corrupted data \n [1, -1]"
1288        );
1289        assert_eq!(
1290            HuffmanTableError::NotEnoughBytesForWeights {
1291                got_bytes: 2,
1292                expected_bytes: 5,
1293            }
1294            .to_string(),
1295            "Header says there should be 5 bytes for the weights but there are only 2 bytes in the stream"
1296        );
1297        assert_eq!(
1298            HuffmanTableError::ExtraPadding { skipped_bits: 13 }.to_string(),
1299            "Padding at the end of the sequence_section was more than a byte long: 13 bits. Probably caused by data corruption"
1300        );
1301        assert_eq!(
1302            HuffmanTableError::FSETableUsedTooManyBytes {
1303                used: 7,
1304                available_bytes: 6,
1305            }
1306            .to_string(),
1307            "FSE table used more bytes: 7 than were meant to be used for the whole stream of huffman weights (6)"
1308        );
1309    }
1310}