Skip to main content

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 {}