libzstd_bitexact_rs/error.rs
1use std::fmt;
2
3/// Errors produced while decoding a Zstandard stream.
4///
5/// The taxonomy intentionally mirrors the error conditions of the C libzstd
6/// (`ZSTD_ErrorCode`) so that accept/reject behavior can be compared in
7/// differential tests.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum Error {
11 /// The input ended before a complete frame could be decoded
12 /// (`ZSTD_error_srcSize_wrong`).
13 SrcSizeWrong,
14 /// The first four bytes of a frame are neither the Zstandard magic
15 /// number nor a skippable-frame magic (`ZSTD_error_prefix_unknown`).
16 UnknownMagic(u32),
17 /// The frame header violates the specification
18 /// (`ZSTD_error_frameParameter_unsupported`).
19 FrameHeaderInvalid(&'static str),
20 /// The declared window size exceeds what this decoder supports
21 /// (`ZSTD_error_frameParameter_windowTooLarge`).
22 WindowTooLarge,
23 /// A block used the reserved block type (`ZSTD_error_corruption_detected`).
24 BlockTypeInvalid,
25 /// The compressed data is malformed (`ZSTD_error_corruption_detected`).
26 Corrupted(&'static str),
27 /// The frame's XXH64 content checksum did not match
28 /// (`ZSTD_error_checksum_wrong`).
29 ChecksumMismatch { expected: u32, actual: u32 },
30 /// The frame was compressed with a dictionary, but none was supplied to
31 /// the decoder (`ZSTD_error_dictionary_wrong`). The payload is the
32 /// dictionary ID the frame asks for.
33 DictionaryRequired(u32),
34 /// A dictionary was supplied, but its ID does not match the one the frame
35 /// requires (`ZSTD_error_dictionary_wrong`).
36 DictionaryWrong { expected: u32, actual: u32 },
37 /// A supplied dictionary buffer began with the `ZDICT` magic but could not
38 /// be parsed (`ZSTD_error_dictionary_corrupted`).
39 DictionaryCorrupted,
40 /// The frame declared a content size that does not match the number of
41 /// bytes actually regenerated (`ZSTD_error_corruption_detected`).
42 FrameContentSizeMismatch,
43 /// Decoding would exceed the output limit given to
44 /// [`decompress_with_limit`](crate::decompress_with_limit).
45 OutputTooLarge,
46 /// An internal invariant was violated while encoding — e.g. a table log
47 /// out of range, or a distribution that does not normalize
48 /// (`ZSTD_error_GENERIC` on the compression path). Reserved for the
49 /// in-progress compressor.
50 Encode(&'static str),
51}
52
53impl fmt::Display for Error {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 Error::SrcSizeWrong => write!(f, "input is truncated or has trailing garbage"),
57 Error::UnknownMagic(m) => write!(f, "unknown frame magic number {m:#010x}"),
58 Error::FrameHeaderInvalid(why) => write!(f, "invalid frame header: {why}"),
59 Error::WindowTooLarge => write!(f, "frame window size is too large"),
60 Error::BlockTypeInvalid => write!(f, "reserved block type"),
61 Error::Corrupted(why) => write!(f, "corrupted compressed data: {why}"),
62 Error::ChecksumMismatch { expected, actual } => write!(
63 f,
64 "content checksum mismatch: stored {expected:#010x}, computed {actual:#010x}"
65 ),
66 Error::DictionaryRequired(id) => {
67 write!(f, "frame requires dictionary {id}, but none was supplied")
68 }
69 Error::DictionaryWrong { expected, actual } => write!(
70 f,
71 "wrong dictionary: frame requires ID {expected}, supplied dictionary has ID {actual}"
72 ),
73 Error::DictionaryCorrupted => write!(f, "supplied dictionary is malformed"),
74 Error::FrameContentSizeMismatch => {
75 write!(
76 f,
77 "regenerated size does not match the declared frame content size"
78 )
79 }
80 Error::OutputTooLarge => write!(f, "decompressed output exceeds the configured limit"),
81 Error::Encode(why) => write!(f, "encoding error: {why}"),
82 }
83 }
84}
85
86impl std::error::Error for Error {}