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}
400
401#[cfg(feature = "std")]
402impl std::error::Error for DecodeBufferError {}
403
404impl core::fmt::Display for DecodeBufferError {
405    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
406        match self {
407            DecodeBufferError::NotEnoughBytesInDictionary { got, need } => {
408                write!(
409                    f,
410                    "Need {need} bytes from the dictionary but it is only {got} bytes long",
411                )
412            }
413            DecodeBufferError::OffsetTooBig { offset, buf_len } => {
414                write!(f, "offset: {offset} bigger than buffer: {buf_len}",)
415            }
416        }
417    }
418}
419
420#[derive(Debug)]
421#[non_exhaustive]
422pub enum DictionaryDecodeError {
423    BadMagicNum { got: [u8; 4] },
424    FSETableError(FSETableError),
425    HuffmanTableError(HuffmanTableError),
426}
427
428#[cfg(feature = "std")]
429impl std::error::Error for DictionaryDecodeError {
430    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
431        match self {
432            DictionaryDecodeError::FSETableError(source) => Some(source),
433            DictionaryDecodeError::HuffmanTableError(source) => Some(source),
434            _ => None,
435        }
436    }
437}
438
439impl core::fmt::Display for DictionaryDecodeError {
440    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
441        match self {
442            DictionaryDecodeError::BadMagicNum { got } => {
443                write!(
444                    f,
445                    "Bad magic_num at start of the dictionary; Got: {:#04X?}, Expected: {:#04x?}",
446                    got,
447                    crate::decoding::dictionary::MAGIC_NUM,
448                )
449            }
450            DictionaryDecodeError::FSETableError(e) => write!(f, "{e:?}"),
451            DictionaryDecodeError::HuffmanTableError(e) => write!(f, "{e:?}"),
452        }
453    }
454}
455
456impl From<FSETableError> for DictionaryDecodeError {
457    fn from(val: FSETableError) -> Self {
458        Self::FSETableError(val)
459    }
460}
461
462impl From<HuffmanTableError> for DictionaryDecodeError {
463    fn from(val: HuffmanTableError) -> Self {
464        Self::HuffmanTableError(val)
465    }
466}
467
468#[derive(Debug)]
469#[non_exhaustive]
470pub enum FrameDecoderError {
471    ReadFrameHeaderError(ReadFrameHeaderError),
472    FrameHeaderError(FrameHeaderError),
473    WindowSizeTooBig { requested: u64 },
474    DictionaryDecodeError(DictionaryDecodeError),
475    FailedToReadBlockHeader(BlockHeaderReadError),
476    FailedToReadBlockBody(DecodeBlockContentError),
477    FailedToReadChecksum(Error),
478    NotYetInitialized,
479    FailedToInitialize(FrameHeaderError),
480    FailedToDrainDecodebuffer(Error),
481    FailedToSkipFrame,
482    TargetTooSmall,
483    DictNotProvided { dict_id: u32 },
484}
485
486#[cfg(feature = "std")]
487impl StdError for FrameDecoderError {
488    fn source(&self) -> Option<&(dyn StdError + 'static)> {
489        match self {
490            FrameDecoderError::ReadFrameHeaderError(source) => Some(source),
491            FrameDecoderError::FrameHeaderError(source) => Some(source),
492            FrameDecoderError::DictionaryDecodeError(source) => Some(source),
493            FrameDecoderError::FailedToReadBlockHeader(source) => Some(source),
494            FrameDecoderError::FailedToReadBlockBody(source) => Some(source),
495            FrameDecoderError::FailedToReadChecksum(source) => Some(source),
496            FrameDecoderError::FailedToInitialize(source) => Some(source),
497            FrameDecoderError::FailedToDrainDecodebuffer(source) => Some(source),
498            _ => None,
499        }
500    }
501}
502
503impl core::fmt::Display for FrameDecoderError {
504    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
505        match self {
506            FrameDecoderError::ReadFrameHeaderError(e) => {
507                write!(f, "{e:?}")
508            }
509            FrameDecoderError::FrameHeaderError(e) => {
510                write!(f, "{e:?}")
511            }
512            FrameDecoderError::WindowSizeTooBig { requested } => {
513                write!(
514                    f,
515                    "Specified window_size is too big; Requested: {}, Max: {}",
516                    requested,
517                    crate::common::MAX_WINDOW_SIZE,
518                )
519            }
520            FrameDecoderError::DictionaryDecodeError(e) => {
521                write!(f, "{e:?}")
522            }
523            FrameDecoderError::FailedToReadBlockHeader(e) => {
524                write!(f, "Failed to parse/decode block body: {e}")
525            }
526            FrameDecoderError::FailedToReadBlockBody(e) => {
527                write!(f, "Failed to parse block header: {e}")
528            }
529            FrameDecoderError::FailedToReadChecksum(e) => {
530                write!(f, "Failed to read checksum: {e}")
531            }
532            FrameDecoderError::NotYetInitialized => {
533                write!(f, "Decoder must initialized or reset before using it",)
534            }
535            FrameDecoderError::FailedToInitialize(e) => {
536                write!(f, "Decoder encountered error while initializing: {e}")
537            }
538            FrameDecoderError::FailedToDrainDecodebuffer(e) => {
539                write!(
540                    f,
541                    "Decoder encountered error while draining the decodebuffer: {e}",
542                )
543            }
544            FrameDecoderError::FailedToSkipFrame => {
545                write!(
546                    f,
547                    "Failed to skip bytes for the length given in the frame header"
548                )
549            }
550            FrameDecoderError::TargetTooSmall => {
551                write!(
552                    f,
553                    "Target must have at least as many bytes as the content size reported by the frame"
554                )
555            }
556            FrameDecoderError::DictNotProvided { dict_id } => {
557                write!(
558                    f,
559                    "Frame header specified dictionary id 0x{dict_id:X} that wasn't provided via add_dict() or reset_with_dict()"
560                )
561            }
562        }
563    }
564}
565
566impl From<DictionaryDecodeError> for FrameDecoderError {
567    fn from(val: DictionaryDecodeError) -> Self {
568        Self::DictionaryDecodeError(val)
569    }
570}
571
572impl From<BlockHeaderReadError> for FrameDecoderError {
573    fn from(val: BlockHeaderReadError) -> Self {
574        Self::FailedToReadBlockHeader(val)
575    }
576}
577
578impl From<FrameHeaderError> for FrameDecoderError {
579    fn from(val: FrameHeaderError) -> Self {
580        Self::FrameHeaderError(val)
581    }
582}
583
584impl From<ReadFrameHeaderError> for FrameDecoderError {
585    fn from(val: ReadFrameHeaderError) -> Self {
586        Self::ReadFrameHeaderError(val)
587    }
588}
589
590#[derive(Debug)]
591#[non_exhaustive]
592pub enum DecompressLiteralsError {
593    MissingCompressedSize,
594    MissingNumStreams,
595    GetBitsError(GetBitsError),
596    HuffmanTableError(HuffmanTableError),
597    HuffmanDecoderError(HuffmanDecoderError),
598    UninitializedHuffmanTable,
599    MissingBytesForJumpHeader { got: usize },
600    MissingBytesForLiterals { got: usize, needed: usize },
601    ExtraPadding { skipped_bits: i32 },
602    BitstreamReadMismatch { read_til: isize, expected: isize },
603    DecodedLiteralCountMismatch { decoded: usize, expected: usize },
604}
605
606#[cfg(feature = "std")]
607impl std::error::Error for DecompressLiteralsError {
608    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
609        match self {
610            DecompressLiteralsError::GetBitsError(source) => Some(source),
611            DecompressLiteralsError::HuffmanTableError(source) => Some(source),
612            DecompressLiteralsError::HuffmanDecoderError(source) => Some(source),
613            _ => None,
614        }
615    }
616}
617impl core::fmt::Display for DecompressLiteralsError {
618    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
619        match self {
620            DecompressLiteralsError::MissingCompressedSize => {
621                write!(
622                    f,
623                    "compressed size was none even though it must be set to something for compressed literals",
624                )
625            }
626            DecompressLiteralsError::MissingNumStreams => {
627                write!(
628                    f,
629                    "num_streams was none even though it must be set to something (1 or 4) for compressed literals",
630                )
631            }
632            DecompressLiteralsError::GetBitsError(e) => write!(f, "{e:?}"),
633            DecompressLiteralsError::HuffmanTableError(e) => write!(f, "{e:?}"),
634            DecompressLiteralsError::HuffmanDecoderError(e) => write!(f, "{e:?}"),
635            DecompressLiteralsError::UninitializedHuffmanTable => {
636                write!(
637                    f,
638                    "Tried to reuse huffman table but it was never initialized",
639                )
640            }
641            DecompressLiteralsError::MissingBytesForJumpHeader { got } => {
642                write!(f, "Need 6 bytes to decode jump header, got {got} bytes",)
643            }
644            DecompressLiteralsError::MissingBytesForLiterals { got, needed } => {
645                write!(
646                    f,
647                    "Need at least {needed} bytes to decode literals. Have: {got} bytes",
648                )
649            }
650            DecompressLiteralsError::ExtraPadding { skipped_bits } => {
651                write!(
652                    f,
653                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
654                )
655            }
656            DecompressLiteralsError::BitstreamReadMismatch { read_til, expected } => {
657                write!(
658                    f,
659                    "Bitstream was read till: {read_til}, should have been: {expected}",
660                )
661            }
662            DecompressLiteralsError::DecodedLiteralCountMismatch { decoded, expected } => {
663                write!(
664                    f,
665                    "Did not decode enough literals: {decoded}, Should have been: {expected}",
666                )
667            }
668        }
669    }
670}
671
672impl From<HuffmanDecoderError> for DecompressLiteralsError {
673    fn from(val: HuffmanDecoderError) -> Self {
674        Self::HuffmanDecoderError(val)
675    }
676}
677
678impl From<GetBitsError> for DecompressLiteralsError {
679    fn from(val: GetBitsError) -> Self {
680        Self::GetBitsError(val)
681    }
682}
683
684impl From<HuffmanTableError> for DecompressLiteralsError {
685    fn from(val: HuffmanTableError) -> Self {
686        Self::HuffmanTableError(val)
687    }
688}
689
690#[derive(Debug)]
691#[non_exhaustive]
692pub enum ExecuteSequencesError {
693    DecodebufferError(DecodeBufferError),
694    NotEnoughBytesForSequence { wanted: usize, have: usize },
695    ZeroOffset,
696}
697
698impl core::fmt::Display for ExecuteSequencesError {
699    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
700        match self {
701            ExecuteSequencesError::DecodebufferError(e) => {
702                write!(f, "{e:?}")
703            }
704            ExecuteSequencesError::NotEnoughBytesForSequence { wanted, have } => {
705                write!(
706                    f,
707                    "Sequence wants to copy up to byte {wanted}. Bytes in literalsbuffer: {have}"
708                )
709            }
710            ExecuteSequencesError::ZeroOffset => {
711                write!(f, "Illegal offset: 0 found")
712            }
713        }
714    }
715}
716
717#[cfg(feature = "std")]
718impl std::error::Error for ExecuteSequencesError {
719    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
720        match self {
721            ExecuteSequencesError::DecodebufferError(source) => Some(source),
722            _ => None,
723        }
724    }
725}
726
727impl From<DecodeBufferError> for ExecuteSequencesError {
728    fn from(val: DecodeBufferError) -> Self {
729        Self::DecodebufferError(val)
730    }
731}
732
733#[derive(Debug)]
734#[non_exhaustive]
735pub enum DecodeSequenceError {
736    GetBitsError(GetBitsError),
737    FSEDecoderError(FSEDecoderError),
738    FSETableError(FSETableError),
739    ExtraPadding { skipped_bits: i32 },
740    UnsupportedOffset { offset_code: u8 },
741    ZeroOffset,
742    NotEnoughBytesForNumSequences,
743    ExtraBits { bits_remaining: isize },
744    MissingCompressionMode,
745    MissingByteForRleLlTable,
746    MissingByteForRleOfTable,
747    MissingByteForRleMlTable,
748}
749
750#[cfg(feature = "std")]
751impl std::error::Error for DecodeSequenceError {
752    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
753        match self {
754            DecodeSequenceError::GetBitsError(source) => Some(source),
755            DecodeSequenceError::FSEDecoderError(source) => Some(source),
756            DecodeSequenceError::FSETableError(source) => Some(source),
757            _ => None,
758        }
759    }
760}
761
762impl core::fmt::Display for DecodeSequenceError {
763    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
764        match self {
765            DecodeSequenceError::GetBitsError(e) => write!(f, "{e:?}"),
766            DecodeSequenceError::FSEDecoderError(e) => write!(f, "{e:?}"),
767            DecodeSequenceError::FSETableError(e) => write!(f, "{e:?}"),
768            DecodeSequenceError::ExtraPadding { skipped_bits } => {
769                write!(
770                    f,
771                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
772                )
773            }
774            DecodeSequenceError::UnsupportedOffset { offset_code } => {
775                write!(
776                    f,
777                    "Do not support offsets bigger than 1<<32; got: {offset_code}",
778                )
779            }
780            DecodeSequenceError::ZeroOffset => write!(
781                f,
782                "Read an offset == 0. That is an illegal value for offsets"
783            ),
784            DecodeSequenceError::NotEnoughBytesForNumSequences => write!(
785                f,
786                "Bytestream did not contain enough bytes to decode num_sequences"
787            ),
788            DecodeSequenceError::ExtraBits { bits_remaining } => write!(f, "{bits_remaining}"),
789            DecodeSequenceError::MissingCompressionMode => write!(
790                f,
791                "compression modes are none but they must be set to something"
792            ),
793            DecodeSequenceError::MissingByteForRleLlTable => {
794                write!(f, "Need a byte to read for RLE ll table")
795            }
796            DecodeSequenceError::MissingByteForRleOfTable => {
797                write!(f, "Need a byte to read for RLE of table")
798            }
799            DecodeSequenceError::MissingByteForRleMlTable => {
800                write!(f, "Need a byte to read for RLE ml table")
801            }
802        }
803    }
804}
805
806impl From<GetBitsError> for DecodeSequenceError {
807    fn from(val: GetBitsError) -> Self {
808        Self::GetBitsError(val)
809    }
810}
811
812impl From<FSETableError> for DecodeSequenceError {
813    fn from(val: FSETableError) -> Self {
814        Self::FSETableError(val)
815    }
816}
817
818impl From<FSEDecoderError> for DecodeSequenceError {
819    fn from(val: FSEDecoderError) -> Self {
820        Self::FSEDecoderError(val)
821    }
822}
823
824#[derive(Debug)]
825#[non_exhaustive]
826pub enum LiteralsSectionParseError {
827    IllegalLiteralSectionType { got: u8 },
828    GetBitsError(GetBitsError),
829    NotEnoughBytes { have: usize, need: u8 },
830}
831
832#[cfg(feature = "std")]
833impl std::error::Error for LiteralsSectionParseError {
834    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
835        match self {
836            LiteralsSectionParseError::GetBitsError(source) => Some(source),
837            _ => None,
838        }
839    }
840}
841impl core::fmt::Display for LiteralsSectionParseError {
842    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
843        match self {
844            LiteralsSectionParseError::IllegalLiteralSectionType { got } => {
845                write!(
846                    f,
847                    "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3"
848                )
849            }
850            LiteralsSectionParseError::GetBitsError(e) => write!(f, "{e:?}"),
851            LiteralsSectionParseError::NotEnoughBytes { have, need } => {
852                write!(
853                    f,
854                    "Not enough byte to parse the literals section header. Have: {have}, Need: {need}",
855                )
856            }
857        }
858    }
859}
860
861impl From<GetBitsError> for LiteralsSectionParseError {
862    fn from(val: GetBitsError) -> Self {
863        Self::GetBitsError(val)
864    }
865}
866
867impl core::fmt::Display for LiteralsSectionType {
868    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
869        match self {
870            LiteralsSectionType::Compressed => write!(f, "Compressed"),
871            LiteralsSectionType::Raw => write!(f, "Raw"),
872            LiteralsSectionType::RLE => write!(f, "RLE"),
873            LiteralsSectionType::Treeless => write!(f, "Treeless"),
874        }
875    }
876}
877
878#[derive(Debug)]
879#[non_exhaustive]
880pub enum SequencesHeaderParseError {
881    NotEnoughBytes { need_at_least: u8, got: usize },
882}
883
884#[cfg(feature = "std")]
885impl std::error::Error for SequencesHeaderParseError {}
886
887impl core::fmt::Display for SequencesHeaderParseError {
888    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
889        match self {
890            SequencesHeaderParseError::NotEnoughBytes { need_at_least, got } => {
891                write!(
892                    f,
893                    "source must have at least {need_at_least} bytes to parse header; got {got} bytes",
894                )
895            }
896        }
897    }
898}
899
900#[derive(Debug)]
901#[non_exhaustive]
902pub enum FSETableError {
903    AccLogIsZero,
904    AccLogTooBig {
905        got: u8,
906        max: u8,
907    },
908    GetBitsError(GetBitsError),
909    ProbabilityCounterMismatch {
910        got: u32,
911        expected_sum: u32,
912        symbol_probabilities: Vec<i32>,
913    },
914    TooManySymbols {
915        got: usize,
916    },
917}
918
919#[cfg(feature = "std")]
920impl std::error::Error for FSETableError {
921    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
922        match self {
923            FSETableError::GetBitsError(source) => Some(source),
924            _ => None,
925        }
926    }
927}
928
929impl core::fmt::Display for FSETableError {
930    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
931        match self {
932            FSETableError::AccLogIsZero => write!(f, "Acclog must be at least 1"),
933            FSETableError::AccLogTooBig { got, max } => {
934                write!(
935                    f,
936                    "Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}"
937                )
938            }
939            FSETableError::GetBitsError(e) => write!(f, "{e:?}"),
940            FSETableError::ProbabilityCounterMismatch {
941                got,
942                expected_sum,
943                symbol_probabilities,
944            } => {
945                write!(
946                    f,
947                    "The counter ({got}) exceeded the expected sum: {expected_sum}. This means an error or corrupted data \n {symbol_probabilities:?}",
948                )
949            }
950            FSETableError::TooManySymbols { got } => {
951                write!(
952                    f,
953                    "There are too many symbols in this distribution: {got}. Max: 256",
954                )
955            }
956        }
957    }
958}
959
960impl From<GetBitsError> for FSETableError {
961    fn from(val: GetBitsError) -> Self {
962        Self::GetBitsError(val)
963    }
964}
965
966#[derive(Debug)]
967#[non_exhaustive]
968pub enum FSEDecoderError {
969    GetBitsError(GetBitsError),
970    TableIsUninitialized,
971}
972
973#[cfg(feature = "std")]
974impl std::error::Error for FSEDecoderError {
975    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
976        match self {
977            FSEDecoderError::GetBitsError(source) => Some(source),
978            _ => None,
979        }
980    }
981}
982
983impl core::fmt::Display for FSEDecoderError {
984    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
985        match self {
986            FSEDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
987            FSEDecoderError::TableIsUninitialized => {
988                write!(f, "Tried to use an uninitialized table!")
989            }
990        }
991    }
992}
993
994impl From<GetBitsError> for FSEDecoderError {
995    fn from(val: GetBitsError) -> Self {
996        Self::GetBitsError(val)
997    }
998}
999
1000#[derive(Debug)]
1001#[non_exhaustive]
1002pub enum HuffmanTableError {
1003    GetBitsError(GetBitsError),
1004    FSEDecoderError(FSEDecoderError),
1005    FSETableError(FSETableError),
1006    SourceIsEmpty,
1007    NotEnoughBytesForWeights {
1008        got_bytes: usize,
1009        expected_bytes: u8,
1010    },
1011    ExtraPadding {
1012        skipped_bits: i32,
1013    },
1014    TooManyWeights {
1015        got: usize,
1016    },
1017    MissingWeights,
1018    LeftoverIsNotAPowerOf2 {
1019        got: u32,
1020    },
1021    NotEnoughBytesToDecompressWeights {
1022        have: usize,
1023        need: usize,
1024    },
1025    FSETableUsedTooManyBytes {
1026        used: usize,
1027        available_bytes: u8,
1028    },
1029    NotEnoughBytesInSource {
1030        got: usize,
1031        need: usize,
1032    },
1033    WeightBiggerThanMaxNumBits {
1034        got: u8,
1035    },
1036    MaxBitsTooHigh {
1037        got: u8,
1038    },
1039}
1040
1041#[cfg(feature = "std")]
1042impl StdError for HuffmanTableError {
1043    fn source(&self) -> Option<&(dyn StdError + 'static)> {
1044        match self {
1045            HuffmanTableError::GetBitsError(source) => Some(source),
1046            HuffmanTableError::FSEDecoderError(source) => Some(source),
1047            HuffmanTableError::FSETableError(source) => Some(source),
1048            _ => None,
1049        }
1050    }
1051}
1052
1053impl core::fmt::Display for HuffmanTableError {
1054    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1055        match self {
1056            HuffmanTableError::GetBitsError(e) => write!(f, "{e:?}"),
1057            HuffmanTableError::FSEDecoderError(e) => write!(f, "{e:?}"),
1058            HuffmanTableError::FSETableError(e) => write!(f, "{e:?}"),
1059            HuffmanTableError::SourceIsEmpty => write!(f, "Source needs to have at least one byte"),
1060            HuffmanTableError::NotEnoughBytesForWeights {
1061                got_bytes,
1062                expected_bytes,
1063            } => {
1064                write!(
1065                    f,
1066                    "Header says there should be {expected_bytes} bytes for the weights but there are only {got_bytes} bytes in the stream"
1067                )
1068            }
1069            HuffmanTableError::ExtraPadding { skipped_bits } => {
1070                write!(
1071                    f,
1072                    "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
1073                )
1074            }
1075            HuffmanTableError::TooManyWeights { got } => {
1076                write!(
1077                    f,
1078                    "More than 255 weights decoded (got {got} weights). Stream is probably corrupted",
1079                )
1080            }
1081            HuffmanTableError::MissingWeights => {
1082                write!(f, "Can\'t build huffman table without any weights")
1083            }
1084            HuffmanTableError::LeftoverIsNotAPowerOf2 { got } => {
1085                write!(f, "Leftover must be power of two but is: {got}")
1086            }
1087            HuffmanTableError::NotEnoughBytesToDecompressWeights { have, need } => {
1088                write!(
1089                    f,
1090                    "Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}",
1091                )
1092            }
1093            HuffmanTableError::FSETableUsedTooManyBytes {
1094                used,
1095                available_bytes,
1096            } => {
1097                write!(
1098                    f,
1099                    "FSE table used more bytes: {used} than were meant to be used for the whole stream of huffman weights ({available_bytes})",
1100                )
1101            }
1102            HuffmanTableError::NotEnoughBytesInSource { got, need } => {
1103                write!(f, "Source needs to have at least {need} bytes, got: {got}",)
1104            }
1105            HuffmanTableError::WeightBiggerThanMaxNumBits { got } => {
1106                write!(
1107                    f,
1108                    "Cant have weight: {} bigger than max_num_bits: {}",
1109                    got,
1110                    crate::huff0::MAX_MAX_NUM_BITS,
1111                )
1112            }
1113            HuffmanTableError::MaxBitsTooHigh { got } => {
1114                write!(
1115                    f,
1116                    "max_bits derived from weights is: {} should be lower than: {}",
1117                    got,
1118                    crate::huff0::MAX_MAX_NUM_BITS,
1119                )
1120            }
1121        }
1122    }
1123}
1124
1125impl From<GetBitsError> for HuffmanTableError {
1126    fn from(val: GetBitsError) -> Self {
1127        Self::GetBitsError(val)
1128    }
1129}
1130
1131impl From<FSEDecoderError> for HuffmanTableError {
1132    fn from(val: FSEDecoderError) -> Self {
1133        Self::FSEDecoderError(val)
1134    }
1135}
1136
1137impl From<FSETableError> for HuffmanTableError {
1138    fn from(val: FSETableError) -> Self {
1139        Self::FSETableError(val)
1140    }
1141}
1142
1143#[derive(Debug)]
1144#[non_exhaustive]
1145pub enum HuffmanDecoderError {
1146    GetBitsError(GetBitsError),
1147}
1148
1149impl core::fmt::Display for HuffmanDecoderError {
1150    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1151        match self {
1152            HuffmanDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
1153        }
1154    }
1155}
1156
1157#[cfg(feature = "std")]
1158impl StdError for HuffmanDecoderError {
1159    fn source(&self) -> Option<&(dyn StdError + 'static)> {
1160        match self {
1161            HuffmanDecoderError::GetBitsError(source) => Some(source),
1162        }
1163    }
1164}
1165
1166impl From<GetBitsError> for HuffmanDecoderError {
1167    fn from(val: GetBitsError) -> Self {
1168        Self::GetBitsError(val)
1169    }
1170}
1171
1172#[cfg(test)]
1173mod tests {
1174    use alloc::{string::ToString, vec};
1175
1176    use super::{
1177        BlockTypeError, DecodeBlockContentError, DecodeSequenceError, DecompressBlockError,
1178        DecompressLiteralsError, FSETableError, FrameDecoderError, HuffmanTableError,
1179    };
1180
1181    #[test]
1182    fn block_and_sequence_display_messages_are_specific() {
1183        assert_eq!(
1184            BlockTypeError::InvalidBlocktypeNumber { num: 7 }.to_string(),
1185            "Invalid Blocktype number. Is: 7. Should be one of: 0, 1, 2, 3 (3 is reserved)."
1186        );
1187        assert_eq!(
1188            DecompressBlockError::MalformedSectionHeader {
1189                expected_len: 12,
1190                remaining_bytes: 3,
1191            }
1192            .to_string(),
1193            "Malformed section header. Says literals would be this long: 12 but there are only 3 bytes left"
1194        );
1195        assert_eq!(
1196            DecodeBlockContentError::ExpectedHeaderOfPreviousBlock.to_string(),
1197            "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense"
1198        );
1199        assert_eq!(
1200            DecodeSequenceError::ExtraPadding { skipped_bits: 11 }.to_string(),
1201            "Padding at the end of the sequence_section was more than a byte long: 11 bits. Probably caused by data corruption"
1202        );
1203    }
1204
1205    #[test]
1206    fn frame_decoder_display_messages_are_specific() {
1207        assert_eq!(
1208            FrameDecoderError::TargetTooSmall.to_string(),
1209            "Target must have at least as many bytes as the content size reported by the frame"
1210        );
1211        assert_eq!(
1212            FrameDecoderError::DictNotProvided { dict_id: 0xABCD }.to_string(),
1213            "Frame header specified dictionary id 0xABCD that wasn't provided via add_dict() or reset_with_dict()"
1214        );
1215    }
1216
1217    #[test]
1218    fn literal_display_messages_are_specific() {
1219        assert_eq!(
1220            DecompressLiteralsError::MissingCompressedSize.to_string(),
1221            "compressed size was none even though it must be set to something for compressed literals"
1222        );
1223        assert_eq!(
1224            DecompressLiteralsError::MissingNumStreams.to_string(),
1225            "num_streams was none even though it must be set to something (1 or 4) for compressed literals"
1226        );
1227        assert_eq!(
1228            DecompressLiteralsError::ExtraPadding { skipped_bits: 9 }.to_string(),
1229            "Padding at the end of the sequence_section was more than a byte long: 9 bits. Probably caused by data corruption"
1230        );
1231    }
1232
1233    #[test]
1234    fn fse_and_huffman_display_messages_are_specific() {
1235        assert_eq!(
1236            FSETableError::ProbabilityCounterMismatch {
1237                got: 4,
1238                expected_sum: 3,
1239                symbol_probabilities: vec![1, -1],
1240            }
1241            .to_string(),
1242            "The counter (4) exceeded the expected sum: 3. This means an error or corrupted data \n [1, -1]"
1243        );
1244        assert_eq!(
1245            HuffmanTableError::NotEnoughBytesForWeights {
1246                got_bytes: 2,
1247                expected_bytes: 5,
1248            }
1249            .to_string(),
1250            "Header says there should be 5 bytes for the weights but there are only 2 bytes in the stream"
1251        );
1252        assert_eq!(
1253            HuffmanTableError::ExtraPadding { skipped_bits: 13 }.to_string(),
1254            "Padding at the end of the sequence_section was more than a byte long: 13 bits. Probably caused by data corruption"
1255        );
1256        assert_eq!(
1257            HuffmanTableError::FSETableUsedTooManyBytes {
1258                used: 7,
1259                available_bytes: 6,
1260            }
1261            .to_string(),
1262            "FSE table used more bytes: 7 than were meant to be used for the whole stream of huffman weights (6)"
1263        );
1264    }
1265}