1use 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 {
351 step: BlockType,
352 source: Error,
353 },
354 DecompressBlockError(DecompressBlockError),
355 BackendOverflow {
366 step: BlockType,
367 },
368}
369
370#[cfg(feature = "std")]
371impl std::error::Error for DecodeBlockContentError {
372 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
373 match self {
374 DecodeBlockContentError::ReadError { step: _, source } => Some(source),
375 DecodeBlockContentError::DecompressBlockError(source) => Some(source),
376 _ => None,
377 }
378 }
379}
380
381impl core::fmt::Display for DecodeBlockContentError {
382 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
383 match self {
384 DecodeBlockContentError::DecoderStateIsFailed => {
385 write!(
386 f,
387 "Can't decode next block if failed along the way. Results will be nonsense",
388 )
389 }
390 DecodeBlockContentError::ExpectedHeaderOfPreviousBlock => {
391 write!(
392 f,
393 "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense",
394 )
395 }
396 DecodeBlockContentError::ReadError { step, source } => {
397 write!(f, "Error while reading bytes for {step}: {source}",)
398 }
399 DecodeBlockContentError::DecompressBlockError(e) => write!(f, "{e:?}"),
400 DecodeBlockContentError::BackendOverflow { step } => write!(
401 f,
402 "{step} block's decompressed payload exceeds the caller-provided output buffer",
403 ),
404 }
405 }
406}
407
408impl From<DecompressBlockError> for DecodeBlockContentError {
409 fn from(val: DecompressBlockError) -> Self {
410 Self::DecompressBlockError(val)
411 }
412}
413
414#[derive(Debug)]
415#[non_exhaustive]
416pub enum DecodeBufferError {
417 NotEnoughBytesInDictionary {
418 got: usize,
419 need: usize,
420 },
421 OffsetTooBig {
422 offset: usize,
423 buf_len: usize,
424 },
425 ZeroOffset,
426 BackendOverflow,
438 OutputBufferOverflow {
448 tail: usize,
449 requested: usize,
450 capacity: usize,
451 },
452}
453
454#[cfg(feature = "std")]
455impl std::error::Error for DecodeBufferError {}
456
457impl core::fmt::Display for DecodeBufferError {
458 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
459 match self {
460 DecodeBufferError::NotEnoughBytesInDictionary { got, need } => {
461 write!(
462 f,
463 "Need {need} bytes from the dictionary but it is only {got} bytes long",
464 )
465 }
466 DecodeBufferError::OffsetTooBig { offset, buf_len } => {
467 write!(f, "offset: {offset} bigger than buffer: {buf_len}",)
468 }
469 DecodeBufferError::ZeroOffset => {
470 write!(f, "Illegal offset: 0 found")
471 }
472 DecodeBufferError::BackendOverflow => {
473 write!(
474 f,
475 "Match repeat would overflow the output buffer's fixed capacity"
476 )
477 }
478 DecodeBufferError::OutputBufferOverflow {
479 tail,
480 requested,
481 capacity,
482 } => {
483 write!(
484 f,
485 "Match repeat would write past fixed-capacity buffer: tail={tail}, requested={requested}, capacity={capacity}"
486 )
487 }
488 }
489 }
490}
491
492#[derive(Debug)]
493#[non_exhaustive]
494pub enum DictionaryDecodeError {
495 BadMagicNum { got: [u8; 4] },
496 DictionaryTooSmall { got: usize, need: usize },
497 ZeroDictionaryId,
498 ZeroRepeatOffsetInDictionary { index: u8 },
499 FSETableError(FSETableError),
500 HuffmanTableError(HuffmanTableError),
501}
502
503#[cfg(feature = "std")]
504impl std::error::Error for DictionaryDecodeError {
505 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
506 match self {
507 DictionaryDecodeError::FSETableError(source) => Some(source),
508 DictionaryDecodeError::HuffmanTableError(source) => Some(source),
509 _ => None,
510 }
511 }
512}
513
514impl core::fmt::Display for DictionaryDecodeError {
515 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
516 match self {
517 DictionaryDecodeError::BadMagicNum { got } => {
518 write!(
519 f,
520 "Bad magic_num at start of the dictionary; Got: {:#04X?}, Expected: {:#04x?}",
521 got,
522 crate::decoding::dictionary::MAGIC_NUM,
523 )
524 }
525 DictionaryDecodeError::DictionaryTooSmall { got, need } => {
526 write!(
527 f,
528 "Dictionary is too small: got {got} bytes, need at least {need} bytes",
529 )
530 }
531 DictionaryDecodeError::ZeroDictionaryId => {
532 write!(f, "Dictionary id must be non-zero")
533 }
534 DictionaryDecodeError::ZeroRepeatOffsetInDictionary { index } => {
535 write!(f, "Dictionary repeat offset rep{index} must be non-zero")
536 }
537 DictionaryDecodeError::FSETableError(e) => write!(f, "{e:?}"),
538 DictionaryDecodeError::HuffmanTableError(e) => write!(f, "{e:?}"),
539 }
540 }
541}
542
543impl From<FSETableError> for DictionaryDecodeError {
544 fn from(val: FSETableError) -> Self {
545 Self::FSETableError(val)
546 }
547}
548
549impl From<HuffmanTableError> for DictionaryDecodeError {
550 fn from(val: HuffmanTableError) -> Self {
551 Self::HuffmanTableError(val)
552 }
553}
554
555#[derive(Debug)]
556#[non_exhaustive]
557pub enum FrameDecoderError {
558 ReadFrameHeaderError(ReadFrameHeaderError),
559 FrameHeaderError(FrameHeaderError),
560 WindowSizeTooBig {
561 requested: u64,
562 },
563 DictionaryDecodeError(DictionaryDecodeError),
564 FailedToReadBlockHeader(BlockHeaderReadError),
565 FailedToReadBlockBody(DecodeBlockContentError),
566 FailedToReadChecksum(Error),
567 NotYetInitialized,
568 FailedToInitialize(FrameHeaderError),
569 FailedToDrainDecodebuffer(Error),
570 FailedToSkipFrame,
571 TargetTooSmall,
572 FrameContentSizeMismatch {
580 declared: u64,
581 produced: u64,
582 },
583 DictNotProvided {
584 dict_id: u32,
585 },
586 DictIdMismatch {
587 expected: u32,
588 provided: u32,
589 },
590 DictAlreadyRegistered {
591 dict_id: u32,
592 },
593 #[cfg(feature = "lsm")]
606 UnexpectedDictId {
607 expected: Option<u32>,
608 found: Option<u32>,
609 },
610 #[cfg(feature = "lsm")]
617 UnexpectedWindowDescriptor {
618 expected: u8,
619 found: Option<u8>,
620 },
621}
622
623#[cfg(feature = "std")]
624impl StdError for FrameDecoderError {
625 fn source(&self) -> Option<&(dyn StdError + 'static)> {
626 match self {
627 FrameDecoderError::ReadFrameHeaderError(source) => Some(source),
628 FrameDecoderError::FrameHeaderError(source) => Some(source),
629 FrameDecoderError::DictionaryDecodeError(source) => Some(source),
630 FrameDecoderError::FailedToReadBlockHeader(source) => Some(source),
631 FrameDecoderError::FailedToReadBlockBody(source) => Some(source),
632 FrameDecoderError::FailedToReadChecksum(source) => Some(source),
633 FrameDecoderError::FailedToInitialize(source) => Some(source),
634 FrameDecoderError::FailedToDrainDecodebuffer(source) => Some(source),
635 _ => None,
636 }
637 }
638}
639
640impl core::fmt::Display for FrameDecoderError {
641 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
642 match self {
643 FrameDecoderError::ReadFrameHeaderError(e) => {
644 write!(f, "{e:?}")
645 }
646 FrameDecoderError::FrameHeaderError(e) => {
647 write!(f, "{e:?}")
648 }
649 FrameDecoderError::WindowSizeTooBig { requested } => {
650 write!(
651 f,
652 "Specified window_size is too big; Requested: {}, Allowed: {}",
653 requested,
654 crate::common::MAXIMUM_ALLOWED_WINDOW_SIZE,
655 )
656 }
657 FrameDecoderError::DictionaryDecodeError(e) => {
658 write!(f, "{e:?}")
659 }
660 FrameDecoderError::FailedToReadBlockHeader(e) => {
661 write!(f, "Failed to parse/decode block body: {e}")
662 }
663 FrameDecoderError::FailedToReadBlockBody(e) => {
664 write!(f, "Failed to parse block header: {e}")
665 }
666 FrameDecoderError::FailedToReadChecksum(e) => {
667 write!(f, "Failed to read checksum: {e}")
668 }
669 FrameDecoderError::NotYetInitialized => {
670 write!(f, "Decoder must initialized or reset before using it",)
671 }
672 FrameDecoderError::FailedToInitialize(e) => {
673 write!(f, "Decoder encountered error while initializing: {e}")
674 }
675 FrameDecoderError::FailedToDrainDecodebuffer(e) => {
676 write!(
677 f,
678 "Decoder encountered error while draining the decodebuffer: {e}",
679 )
680 }
681 FrameDecoderError::FailedToSkipFrame => {
682 write!(
683 f,
684 "Failed to skip bytes for the length given in the frame header"
685 )
686 }
687 FrameDecoderError::TargetTooSmall => {
688 write!(
689 f,
690 "Target must have at least as many bytes as the content size reported by the frame"
691 )
692 }
693 FrameDecoderError::FrameContentSizeMismatch { declared, produced } => {
694 write!(
695 f,
696 "Frame content size mismatch (corrupt frame): declared {declared} bytes, blocks summed to {produced} bytes"
697 )
698 }
699 FrameDecoderError::DictNotProvided { dict_id } => {
700 write!(
701 f,
702 "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()"
703 )
704 }
705 FrameDecoderError::DictIdMismatch { expected, provided } => {
706 write!(
707 f,
708 "Frame header dictionary id 0x{expected:X} does not match provided dictionary id 0x{provided:X}"
709 )
710 }
711 FrameDecoderError::DictAlreadyRegistered { dict_id } => {
712 write!(
713 f,
714 "Dictionary id 0x{dict_id:X} already registered in decoder"
715 )
716 }
717 #[cfg(feature = "lsm")]
718 FrameDecoderError::UnexpectedDictId { expected, found } => {
719 write!(f, "Frame header dict_id mismatch: expected ")?;
720 match expected {
721 Some(id) => write!(f, "0x{id:X}")?,
722 None => write!(f, "<none>")?,
723 }
724 write!(f, ", found ")?;
725 match found {
726 Some(id) => write!(f, "0x{id:X}"),
727 None => write!(f, "<none>"),
728 }
729 }
730 #[cfg(feature = "lsm")]
731 FrameDecoderError::UnexpectedWindowDescriptor { expected, found } => {
732 write!(
733 f,
734 "Frame header window_descriptor mismatch: expected 0x{expected:02X}, found "
735 )?;
736 match found {
737 Some(byte) => write!(f, "0x{byte:02X}"),
738 None => write!(f, "<none> (single-segment frame omits window_descriptor)"),
739 }
740 }
741 }
742 }
743}
744
745impl From<DictionaryDecodeError> for FrameDecoderError {
746 fn from(val: DictionaryDecodeError) -> Self {
747 Self::DictionaryDecodeError(val)
748 }
749}
750
751impl From<BlockHeaderReadError> for FrameDecoderError {
752 fn from(val: BlockHeaderReadError) -> Self {
753 Self::FailedToReadBlockHeader(val)
754 }
755}
756
757impl From<FrameHeaderError> for FrameDecoderError {
758 fn from(val: FrameHeaderError) -> Self {
759 Self::FrameHeaderError(val)
760 }
761}
762
763impl From<ReadFrameHeaderError> for FrameDecoderError {
764 fn from(val: ReadFrameHeaderError) -> Self {
765 Self::ReadFrameHeaderError(val)
766 }
767}
768
769#[derive(Debug)]
770#[non_exhaustive]
771pub enum DecompressLiteralsError {
772 MissingCompressedSize,
773 MissingNumStreams,
774 GetBitsError(GetBitsError),
775 HuffmanTableError(HuffmanTableError),
776 HuffmanDecoderError(HuffmanDecoderError),
777 UninitializedHuffmanTable,
778 MissingBytesForJumpHeader { got: usize },
779 MissingBytesForLiterals { got: usize, needed: usize },
780 ExtraPadding { skipped_bits: i32 },
781 BitstreamReadMismatch { read_til: isize, expected: isize },
782 DecodedLiteralCountMismatch { decoded: usize, expected: usize },
783}
784
785#[cfg(feature = "std")]
786impl std::error::Error for DecompressLiteralsError {
787 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
788 match self {
789 DecompressLiteralsError::GetBitsError(source) => Some(source),
790 DecompressLiteralsError::HuffmanTableError(source) => Some(source),
791 DecompressLiteralsError::HuffmanDecoderError(source) => Some(source),
792 _ => None,
793 }
794 }
795}
796impl core::fmt::Display for DecompressLiteralsError {
797 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
798 match self {
799 DecompressLiteralsError::MissingCompressedSize => {
800 write!(
801 f,
802 "compressed size was none even though it must be set to something for compressed literals",
803 )
804 }
805 DecompressLiteralsError::MissingNumStreams => {
806 write!(
807 f,
808 "num_streams was none even though it must be set to something (1 or 4) for compressed literals",
809 )
810 }
811 DecompressLiteralsError::GetBitsError(e) => write!(f, "{e:?}"),
812 DecompressLiteralsError::HuffmanTableError(e) => write!(f, "{e:?}"),
813 DecompressLiteralsError::HuffmanDecoderError(e) => write!(f, "{e:?}"),
814 DecompressLiteralsError::UninitializedHuffmanTable => {
815 write!(
816 f,
817 "Tried to reuse huffman table but it was never initialized",
818 )
819 }
820 DecompressLiteralsError::MissingBytesForJumpHeader { got } => {
821 write!(f, "Need 6 bytes to decode jump header, got {got} bytes",)
822 }
823 DecompressLiteralsError::MissingBytesForLiterals { got, needed } => {
824 write!(
825 f,
826 "Need at least {needed} bytes to decode literals. Have: {got} bytes",
827 )
828 }
829 DecompressLiteralsError::ExtraPadding { skipped_bits } => {
830 write!(
831 f,
832 "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
833 )
834 }
835 DecompressLiteralsError::BitstreamReadMismatch { read_til, expected } => {
836 write!(
837 f,
838 "Bitstream was read till: {read_til}, should have been: {expected}",
839 )
840 }
841 DecompressLiteralsError::DecodedLiteralCountMismatch { decoded, expected } => {
842 write!(
843 f,
844 "Did not decode enough literals: {decoded}, Should have been: {expected}",
845 )
846 }
847 }
848 }
849}
850
851impl From<HuffmanDecoderError> for DecompressLiteralsError {
852 fn from(val: HuffmanDecoderError) -> Self {
853 Self::HuffmanDecoderError(val)
854 }
855}
856
857impl From<GetBitsError> for DecompressLiteralsError {
858 fn from(val: GetBitsError) -> Self {
859 Self::GetBitsError(val)
860 }
861}
862
863impl From<HuffmanTableError> for DecompressLiteralsError {
864 fn from(val: HuffmanTableError) -> Self {
865 Self::HuffmanTableError(val)
866 }
867}
868
869#[derive(Debug)]
870#[non_exhaustive]
871pub enum ExecuteSequencesError {
872 DecodebufferError(DecodeBufferError),
873 NotEnoughBytesForSequence {
874 wanted: usize,
875 have: usize,
876 },
877 ZeroOffset,
878 OutputBufferOverflow {
887 tail: usize,
888 requested: usize,
889 capacity: usize,
890 },
891}
892
893impl core::fmt::Display for ExecuteSequencesError {
894 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
895 match self {
896 ExecuteSequencesError::DecodebufferError(e) => {
897 write!(f, "{e:?}")
898 }
899 ExecuteSequencesError::NotEnoughBytesForSequence { wanted, have } => {
900 write!(
901 f,
902 "Sequence wants to copy up to byte {wanted}. Bytes in literalsbuffer: {have}"
903 )
904 }
905 ExecuteSequencesError::ZeroOffset => {
906 write!(f, "Illegal offset: 0 found")
907 }
908 ExecuteSequencesError::OutputBufferOverflow {
909 tail,
910 requested,
911 capacity,
912 } => {
913 write!(
914 f,
915 "Donor-path sequence would write past fixed-size buffer: tail={tail}, requested={requested}, capacity={capacity}"
916 )
917 }
918 }
919 }
920}
921
922#[cfg(feature = "std")]
923impl std::error::Error for ExecuteSequencesError {
924 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
925 match self {
926 ExecuteSequencesError::DecodebufferError(source) => Some(source),
927 _ => None,
928 }
929 }
930}
931
932impl From<DecodeBufferError> for ExecuteSequencesError {
933 fn from(val: DecodeBufferError) -> Self {
934 Self::DecodebufferError(val)
935 }
936}
937
938impl From<crate::decoding::buffer_backend::BackendOverflow> for ExecuteSequencesError {
939 fn from(val: crate::decoding::buffer_backend::BackendOverflow) -> Self {
940 Self::OutputBufferOverflow {
941 tail: val.tail,
942 requested: val.requested,
943 capacity: val.capacity,
944 }
945 }
946}
947
948#[derive(Debug)]
949#[non_exhaustive]
950pub enum DecodeSequenceError {
951 GetBitsError(GetBitsError),
952 FSEDecoderError(FSEDecoderError),
953 FSETableError(FSETableError),
954 ExtraPadding { skipped_bits: i32 },
955 UnsupportedOffset { offset_code: u8 },
956 ZeroOffset,
957 NotEnoughBytesForNumSequences,
958 ExtraBits { bits_remaining: isize },
959 MissingCompressionMode,
960 MissingByteForRleLlTable,
961 MissingByteForRleOfTable,
962 MissingByteForRleMlTable,
963}
964
965#[cfg(feature = "std")]
966impl std::error::Error for DecodeSequenceError {
967 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
968 match self {
969 DecodeSequenceError::GetBitsError(source) => Some(source),
970 DecodeSequenceError::FSEDecoderError(source) => Some(source),
971 DecodeSequenceError::FSETableError(source) => Some(source),
972 _ => None,
973 }
974 }
975}
976
977impl core::fmt::Display for DecodeSequenceError {
978 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
979 match self {
980 DecodeSequenceError::GetBitsError(e) => write!(f, "{e:?}"),
981 DecodeSequenceError::FSEDecoderError(e) => write!(f, "{e:?}"),
982 DecodeSequenceError::FSETableError(e) => write!(f, "{e:?}"),
983 DecodeSequenceError::ExtraPadding { skipped_bits } => {
984 write!(
985 f,
986 "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
987 )
988 }
989 DecodeSequenceError::UnsupportedOffset { offset_code } => {
990 write!(
991 f,
992 "Do not support offsets bigger than 1<<32; got: {offset_code}",
993 )
994 }
995 DecodeSequenceError::ZeroOffset => write!(
996 f,
997 "Read an offset == 0. That is an illegal value for offsets"
998 ),
999 DecodeSequenceError::NotEnoughBytesForNumSequences => write!(
1000 f,
1001 "Bytestream did not contain enough bytes to decode num_sequences"
1002 ),
1003 DecodeSequenceError::ExtraBits { bits_remaining } => write!(f, "{bits_remaining}"),
1004 DecodeSequenceError::MissingCompressionMode => write!(
1005 f,
1006 "compression modes are none but they must be set to something"
1007 ),
1008 DecodeSequenceError::MissingByteForRleLlTable => {
1009 write!(f, "Need a byte to read for RLE ll table")
1010 }
1011 DecodeSequenceError::MissingByteForRleOfTable => {
1012 write!(f, "Need a byte to read for RLE of table")
1013 }
1014 DecodeSequenceError::MissingByteForRleMlTable => {
1015 write!(f, "Need a byte to read for RLE ml table")
1016 }
1017 }
1018 }
1019}
1020
1021impl From<GetBitsError> for DecodeSequenceError {
1022 fn from(val: GetBitsError) -> Self {
1023 Self::GetBitsError(val)
1024 }
1025}
1026
1027impl From<FSETableError> for DecodeSequenceError {
1028 fn from(val: FSETableError) -> Self {
1029 Self::FSETableError(val)
1030 }
1031}
1032
1033impl From<FSEDecoderError> for DecodeSequenceError {
1034 fn from(val: FSEDecoderError) -> Self {
1035 Self::FSEDecoderError(val)
1036 }
1037}
1038
1039#[derive(Debug)]
1040#[non_exhaustive]
1041pub enum LiteralsSectionParseError {
1042 IllegalLiteralSectionType { got: u8 },
1043 GetBitsError(GetBitsError),
1044 NotEnoughBytes { have: usize, need: u8 },
1045}
1046
1047#[cfg(feature = "std")]
1048impl std::error::Error for LiteralsSectionParseError {
1049 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1050 match self {
1051 LiteralsSectionParseError::GetBitsError(source) => Some(source),
1052 _ => None,
1053 }
1054 }
1055}
1056impl core::fmt::Display for LiteralsSectionParseError {
1057 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1058 match self {
1059 LiteralsSectionParseError::IllegalLiteralSectionType { got } => {
1060 write!(
1061 f,
1062 "Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3"
1063 )
1064 }
1065 LiteralsSectionParseError::GetBitsError(e) => write!(f, "{e:?}"),
1066 LiteralsSectionParseError::NotEnoughBytes { have, need } => {
1067 write!(
1068 f,
1069 "Not enough byte to parse the literals section header. Have: {have}, Need: {need}",
1070 )
1071 }
1072 }
1073 }
1074}
1075
1076impl From<GetBitsError> for LiteralsSectionParseError {
1077 fn from(val: GetBitsError) -> Self {
1078 Self::GetBitsError(val)
1079 }
1080}
1081
1082impl core::fmt::Display for LiteralsSectionType {
1083 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
1084 match self {
1085 LiteralsSectionType::Compressed => write!(f, "Compressed"),
1086 LiteralsSectionType::Raw => write!(f, "Raw"),
1087 LiteralsSectionType::RLE => write!(f, "RLE"),
1088 LiteralsSectionType::Treeless => write!(f, "Treeless"),
1089 }
1090 }
1091}
1092
1093#[derive(Debug)]
1094#[non_exhaustive]
1095pub enum SequencesHeaderParseError {
1096 NotEnoughBytes { need_at_least: u8, got: usize },
1097}
1098
1099#[cfg(feature = "std")]
1100impl std::error::Error for SequencesHeaderParseError {}
1101
1102impl core::fmt::Display for SequencesHeaderParseError {
1103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1104 match self {
1105 SequencesHeaderParseError::NotEnoughBytes { need_at_least, got } => {
1106 write!(
1107 f,
1108 "source must have at least {need_at_least} bytes to parse header; got {got} bytes",
1109 )
1110 }
1111 }
1112 }
1113}
1114
1115#[derive(Debug)]
1116#[non_exhaustive]
1117pub enum FSETableError {
1118 AccLogIsZero,
1119 AccLogTooBig {
1120 got: u8,
1121 max: u8,
1122 },
1123 GetBitsError(GetBitsError),
1124 ProbabilityCounterMismatch {
1125 got: u32,
1126 expected_sum: u32,
1127 symbol_probabilities: Vec<i32>,
1128 },
1129 TooManySymbols {
1130 got: usize,
1131 },
1132 InvalidProbability {
1137 value: i32,
1138 table_size: u32,
1139 accuracy_log: u8,
1140 },
1141 TableInvariantViolation {
1149 prob: i32,
1150 symbol: u8,
1151 num_bits: u8,
1152 accuracy_log: u8,
1153 },
1154}
1155
1156#[cfg(feature = "std")]
1157impl std::error::Error for FSETableError {
1158 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1159 match self {
1160 FSETableError::GetBitsError(source) => Some(source),
1161 _ => None,
1162 }
1163 }
1164}
1165
1166impl core::fmt::Display for FSETableError {
1167 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1168 match self {
1169 FSETableError::AccLogIsZero => write!(f, "Acclog must be at least 1"),
1170 FSETableError::AccLogTooBig { got, max } => {
1171 write!(
1172 f,
1173 "Found FSE acc_log: {got} bigger than allowed maximum in this case: {max}"
1174 )
1175 }
1176 FSETableError::GetBitsError(e) => write!(f, "{e:?}"),
1177 FSETableError::ProbabilityCounterMismatch {
1178 got,
1179 expected_sum,
1180 symbol_probabilities,
1181 } => {
1182 write!(
1183 f,
1184 "FSE probability sum mismatch: got {got}, expected {expected_sum}. Indicates corrupted data or an invalid distribution\n {symbol_probabilities:?}",
1185 )
1186 }
1187 FSETableError::TooManySymbols { got } => {
1188 write!(
1189 f,
1190 "There are too many symbols in this distribution: {got}. Max: 256",
1191 )
1192 }
1193 FSETableError::InvalidProbability {
1194 value,
1195 table_size,
1196 accuracy_log,
1197 } => {
1198 write!(
1199 f,
1200 "FSE probability value {value} is outside the RFC 8878 allowed set (must be -1, 0, or in 1..={table_size}; accuracy_log={accuracy_log})",
1201 )
1202 }
1203 FSETableError::TableInvariantViolation {
1204 prob,
1205 symbol,
1206 num_bits,
1207 accuracy_log,
1208 } => {
1209 write!(
1210 f,
1211 "FSE table invariant violation: symbol {symbol} (prob {prob}) produced num_bits {num_bits} > accuracy_log {accuracy_log}",
1212 )
1213 }
1214 }
1215 }
1216}
1217
1218impl From<GetBitsError> for FSETableError {
1219 fn from(val: GetBitsError) -> Self {
1220 Self::GetBitsError(val)
1221 }
1222}
1223
1224#[derive(Debug)]
1225#[non_exhaustive]
1226pub enum FSEDecoderError {
1227 GetBitsError(GetBitsError),
1228 TableIsUninitialized,
1229 InvalidTableShape {
1235 decode_len: usize,
1236 accuracy_log: u8,
1237 },
1238}
1239
1240#[cfg(feature = "std")]
1241impl std::error::Error for FSEDecoderError {
1242 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1243 match self {
1244 FSEDecoderError::GetBitsError(source) => Some(source),
1245 _ => None,
1246 }
1247 }
1248}
1249
1250impl core::fmt::Display for FSEDecoderError {
1251 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1252 match self {
1253 FSEDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
1254 FSEDecoderError::TableIsUninitialized => {
1255 write!(f, "Tried to use an uninitialized table!")
1256 }
1257 FSEDecoderError::InvalidTableShape {
1258 decode_len,
1259 accuracy_log,
1260 } => match 1usize.checked_shl((*accuracy_log).into()) {
1261 Some(expected) => write!(
1262 f,
1263 "FSETable shape invariant violated: decode.len() = {decode_len}, expected 1 << accuracy_log = {expected} (accuracy_log = {accuracy_log})",
1264 ),
1265 None => write!(
1266 f,
1267 "FSETable shape invariant violated: decode.len() = {decode_len}, accuracy_log = {accuracy_log} overflows 1 << accuracy_log for usize",
1268 ),
1269 },
1270 }
1271 }
1272}
1273
1274impl From<GetBitsError> for FSEDecoderError {
1275 fn from(val: GetBitsError) -> Self {
1276 Self::GetBitsError(val)
1277 }
1278}
1279
1280#[derive(Debug)]
1281#[non_exhaustive]
1282pub enum HuffmanTableError {
1283 GetBitsError(GetBitsError),
1284 FSEDecoderError(FSEDecoderError),
1285 FSETableError(FSETableError),
1286 SourceIsEmpty,
1287 NotEnoughBytesForWeights {
1288 got_bytes: usize,
1289 expected_bytes: u8,
1290 },
1291 ExtraPadding {
1292 skipped_bits: i32,
1293 },
1294 TooManyWeights {
1295 got: usize,
1296 },
1297 MissingWeights,
1298 LeftoverIsNotAPowerOf2 {
1299 got: u32,
1300 },
1301 NotEnoughBytesToDecompressWeights {
1302 have: usize,
1303 need: usize,
1304 },
1305 FSETableUsedTooManyBytes {
1306 used: usize,
1307 available_bytes: u8,
1308 },
1309 NotEnoughBytesInSource {
1310 got: usize,
1311 need: usize,
1312 },
1313 WeightBiggerThanMaxNumBits {
1314 got: u8,
1315 },
1316 MaxBitsTooHigh {
1317 got: u8,
1318 },
1319}
1320
1321#[cfg(feature = "std")]
1322impl StdError for HuffmanTableError {
1323 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1324 match self {
1325 HuffmanTableError::GetBitsError(source) => Some(source),
1326 HuffmanTableError::FSEDecoderError(source) => Some(source),
1327 HuffmanTableError::FSETableError(source) => Some(source),
1328 _ => None,
1329 }
1330 }
1331}
1332
1333impl core::fmt::Display for HuffmanTableError {
1334 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1335 match self {
1336 HuffmanTableError::GetBitsError(e) => write!(f, "{e:?}"),
1337 HuffmanTableError::FSEDecoderError(e) => write!(f, "{e:?}"),
1338 HuffmanTableError::FSETableError(e) => write!(f, "{e:?}"),
1339 HuffmanTableError::SourceIsEmpty => write!(f, "Source needs to have at least one byte"),
1340 HuffmanTableError::NotEnoughBytesForWeights {
1341 got_bytes,
1342 expected_bytes,
1343 } => {
1344 write!(
1345 f,
1346 "Header says there should be {expected_bytes} bytes for the weights but there are only {got_bytes} bytes in the stream"
1347 )
1348 }
1349 HuffmanTableError::ExtraPadding { skipped_bits } => {
1350 write!(
1351 f,
1352 "Padding at the end of the sequence_section was more than a byte long: {skipped_bits} bits. Probably caused by data corruption",
1353 )
1354 }
1355 HuffmanTableError::TooManyWeights { got } => {
1356 write!(
1357 f,
1358 "More than 255 weights decoded (got {got} weights). Stream is probably corrupted",
1359 )
1360 }
1361 HuffmanTableError::MissingWeights => {
1362 write!(f, "Can\'t build huffman table without any weights")
1363 }
1364 HuffmanTableError::LeftoverIsNotAPowerOf2 { got } => {
1365 write!(f, "Leftover must be power of two but is: {got}")
1366 }
1367 HuffmanTableError::NotEnoughBytesToDecompressWeights { have, need } => {
1368 write!(
1369 f,
1370 "Not enough bytes in stream to decompress weights. Is: {have}, Should be: {need}",
1371 )
1372 }
1373 HuffmanTableError::FSETableUsedTooManyBytes {
1374 used,
1375 available_bytes,
1376 } => {
1377 write!(
1378 f,
1379 "FSE table used more bytes: {used} than were meant to be used for the whole stream of huffman weights ({available_bytes})",
1380 )
1381 }
1382 HuffmanTableError::NotEnoughBytesInSource { got, need } => {
1383 write!(f, "Source needs to have at least {need} bytes, got: {got}",)
1384 }
1385 HuffmanTableError::WeightBiggerThanMaxNumBits { got } => {
1386 write!(
1387 f,
1388 "Cant have weight: {} bigger than max_num_bits: {}",
1389 got,
1390 crate::huff0::MAX_MAX_NUM_BITS,
1391 )
1392 }
1393 HuffmanTableError::MaxBitsTooHigh { got } => {
1394 write!(
1395 f,
1396 "max_bits derived from weights is: {} should be lower than: {}",
1397 got,
1398 crate::huff0::MAX_MAX_NUM_BITS,
1399 )
1400 }
1401 }
1402 }
1403}
1404
1405impl From<GetBitsError> for HuffmanTableError {
1406 fn from(val: GetBitsError) -> Self {
1407 Self::GetBitsError(val)
1408 }
1409}
1410
1411impl From<FSEDecoderError> for HuffmanTableError {
1412 fn from(val: FSEDecoderError) -> Self {
1413 Self::FSEDecoderError(val)
1414 }
1415}
1416
1417impl From<FSETableError> for HuffmanTableError {
1418 fn from(val: FSETableError) -> Self {
1419 Self::FSETableError(val)
1420 }
1421}
1422
1423#[derive(Debug)]
1424#[non_exhaustive]
1425pub enum HuffmanDecoderError {
1426 GetBitsError(GetBitsError),
1427}
1428
1429impl core::fmt::Display for HuffmanDecoderError {
1430 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1431 match self {
1432 HuffmanDecoderError::GetBitsError(e) => write!(f, "{e:?}"),
1433 }
1434 }
1435}
1436
1437#[cfg(feature = "std")]
1438impl StdError for HuffmanDecoderError {
1439 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1440 match self {
1441 HuffmanDecoderError::GetBitsError(source) => Some(source),
1442 }
1443 }
1444}
1445
1446impl From<GetBitsError> for HuffmanDecoderError {
1447 fn from(val: GetBitsError) -> Self {
1448 Self::GetBitsError(val)
1449 }
1450}
1451
1452#[cfg(test)]
1453mod tests {
1454 use alloc::{string::ToString, vec};
1455
1456 use super::{
1457 BlockTypeError, DecodeBlockContentError, DecodeSequenceError, DecompressBlockError,
1458 DecompressLiteralsError, FSETableError, FrameDecoderError, HuffmanTableError,
1459 };
1460
1461 #[test]
1462 fn block_and_sequence_display_messages_are_specific() {
1463 assert_eq!(
1464 BlockTypeError::InvalidBlocktypeNumber { num: 7 }.to_string(),
1465 "Invalid Blocktype number. Is: 7. Should be one of: 0, 1, 2, 3 (3 is reserved)."
1466 );
1467 assert_eq!(
1468 DecompressBlockError::MalformedSectionHeader {
1469 expected_len: 12,
1470 remaining_bytes: 3,
1471 }
1472 .to_string(),
1473 "Malformed section header. Says literals would be this long: 12 but there are only 3 bytes left"
1474 );
1475 assert_eq!(
1476 DecodeBlockContentError::ExpectedHeaderOfPreviousBlock.to_string(),
1477 "Can't decode next block body, while expecting to decode the header of the previous block. Results will be nonsense"
1478 );
1479 assert_eq!(
1480 DecodeSequenceError::ExtraPadding { skipped_bits: 11 }.to_string(),
1481 "Padding at the end of the sequence_section was more than a byte long: 11 bits. Probably caused by data corruption"
1482 );
1483 }
1484
1485 #[test]
1486 fn frame_decoder_display_messages_are_specific() {
1487 assert_eq!(
1488 FrameDecoderError::TargetTooSmall.to_string(),
1489 "Target must have at least as many bytes as the content size reported by the frame"
1490 );
1491 assert_eq!(
1492 FrameDecoderError::DictNotProvided { dict_id: 0xABCD }.to_string(),
1493 "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()"
1494 );
1495 assert_eq!(
1496 FrameDecoderError::DictIdMismatch {
1497 expected: 0xABCD,
1498 provided: 0x1234
1499 }
1500 .to_string(),
1501 "Frame header dictionary id 0xABCD does not match provided dictionary id 0x1234"
1502 );
1503 assert_eq!(
1504 FrameDecoderError::DictAlreadyRegistered { dict_id: 0xABCD }.to_string(),
1505 "Dictionary id 0xABCD already registered in decoder"
1506 );
1507 assert_eq!(
1508 FrameDecoderError::FrameContentSizeMismatch {
1509 declared: 100,
1510 produced: 87,
1511 }
1512 .to_string(),
1513 "Frame content size mismatch (corrupt frame): declared 100 bytes, blocks summed to 87 bytes"
1514 );
1515 }
1516
1517 #[test]
1518 fn decode_block_content_backend_overflow_display_names_the_step() {
1519 use crate::blocks::block::BlockType;
1520 assert_eq!(
1521 DecodeBlockContentError::BackendOverflow {
1522 step: BlockType::RLE
1523 }
1524 .to_string(),
1525 "RLE block's decompressed payload exceeds the caller-provided output buffer"
1526 );
1527 assert_eq!(
1528 DecodeBlockContentError::BackendOverflow {
1529 step: BlockType::Raw
1530 }
1531 .to_string(),
1532 "Raw block's decompressed payload exceeds the caller-provided output buffer"
1533 );
1534 }
1535
1536 #[test]
1537 fn literal_display_messages_are_specific() {
1538 assert_eq!(
1539 DecompressLiteralsError::MissingCompressedSize.to_string(),
1540 "compressed size was none even though it must be set to something for compressed literals"
1541 );
1542 assert_eq!(
1543 DecompressLiteralsError::MissingNumStreams.to_string(),
1544 "num_streams was none even though it must be set to something (1 or 4) for compressed literals"
1545 );
1546 assert_eq!(
1547 DecompressLiteralsError::ExtraPadding { skipped_bits: 9 }.to_string(),
1548 "Padding at the end of the sequence_section was more than a byte long: 9 bits. Probably caused by data corruption"
1549 );
1550 }
1551
1552 #[test]
1553 fn fse_and_huffman_display_messages_are_specific() {
1554 assert_eq!(
1555 FSETableError::ProbabilityCounterMismatch {
1556 got: 4,
1557 expected_sum: 3,
1558 symbol_probabilities: vec![1, -1],
1559 }
1560 .to_string(),
1561 "FSE probability sum mismatch: got 4, expected 3. Indicates corrupted data or an invalid distribution\n [1, -1]"
1562 );
1563 assert_eq!(
1564 HuffmanTableError::NotEnoughBytesForWeights {
1565 got_bytes: 2,
1566 expected_bytes: 5,
1567 }
1568 .to_string(),
1569 "Header says there should be 5 bytes for the weights but there are only 2 bytes in the stream"
1570 );
1571 assert_eq!(
1572 HuffmanTableError::ExtraPadding { skipped_bits: 13 }.to_string(),
1573 "Padding at the end of the sequence_section was more than a byte long: 13 bits. Probably caused by data corruption"
1574 );
1575 assert_eq!(
1576 HuffmanTableError::FSETableUsedTooManyBytes {
1577 used: 7,
1578 available_bytes: 6,
1579 }
1580 .to_string(),
1581 "FSE table used more bytes: 7 than were meant to be used for the whole stream of huffman weights (6)"
1582 );
1583 }
1584}