Skip to main content

zstd_zero/
error.rs

1use core::fmt;
2
3#[derive(Clone, Copy, Debug, Eq, PartialEq)]
4#[non_exhaustive]
5pub enum DecodeError {
6    DecoderPoisoned,
7    InvalidMagic,
8    InvalidFrameHeader,
9    UnsupportedDictionary { id: u32 },
10    WindowTooLarge,
11    HistoryTooSmall { required: usize, provided: usize },
12    BlockScratchTooSmall { required: usize, provided: usize },
13    LiteralScratchTooSmall { required: usize, provided: usize },
14    InvalidBlock,
15    InvalidEntropyTable,
16    InvalidBitstream,
17    InvalidOffset,
18    ChecksumMismatch { expected: u32, actual: u32 },
19    ContentSizeMismatch { expected: u64, actual: u64 },
20    UnexpectedEof,
21    ArithmeticOverflow,
22}
23
24impl fmt::Display for DecodeError {
25    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
26        match self {
27            Self::DecoderPoisoned => formatter.write_str("decoder is poisoned"),
28            Self::InvalidMagic => formatter.write_str("invalid zstd frame magic"),
29            Self::InvalidFrameHeader => formatter.write_str("invalid zstd frame header"),
30            Self::UnsupportedDictionary { id } => {
31                write!(formatter, "zstd dictionary {id} is not supported")
32            }
33            Self::WindowTooLarge => formatter.write_str("zstd window does not fit this platform"),
34            Self::HistoryTooSmall { required, provided } => write!(
35                formatter,
36                "history buffer is too small: need {required} bytes, have {provided}"
37            ),
38            Self::BlockScratchTooSmall { required, provided } => write!(
39                formatter,
40                "block scratch is too small: need {required} bytes, have {provided}"
41            ),
42            Self::LiteralScratchTooSmall { required, provided } => write!(
43                formatter,
44                "literal scratch is too small: need {required} bytes, have {provided}"
45            ),
46            Self::InvalidBlock => formatter.write_str("invalid zstd block"),
47            Self::InvalidEntropyTable => formatter.write_str("invalid zstd entropy table"),
48            Self::InvalidBitstream => formatter.write_str("invalid zstd bitstream"),
49            Self::InvalidOffset => formatter.write_str("invalid zstd match offset"),
50            Self::ChecksumMismatch { expected, actual } => write!(
51                formatter,
52                "zstd checksum mismatch: expected {expected:08x}, got {actual:08x}"
53            ),
54            Self::ContentSizeMismatch { expected, actual } => write!(
55                formatter,
56                "zstd content-size mismatch: expected {expected}, got {actual}"
57            ),
58            Self::UnexpectedEof => formatter.write_str("unexpected end of zstd stream"),
59            Self::ArithmeticOverflow => formatter.write_str("zstd size arithmetic overflow"),
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use std::string::ToString;
67
68    use super::DecodeError;
69
70    #[test]
71    fn formats_every_decode_error() {
72        let cases = [
73            (DecodeError::DecoderPoisoned, "decoder is poisoned"),
74            (DecodeError::InvalidMagic, "invalid zstd frame magic"),
75            (DecodeError::InvalidFrameHeader, "invalid zstd frame header"),
76            (
77                DecodeError::UnsupportedDictionary { id: 42 },
78                "zstd dictionary 42 is not supported",
79            ),
80            (
81                DecodeError::WindowTooLarge,
82                "zstd window does not fit this platform",
83            ),
84            (
85                DecodeError::HistoryTooSmall {
86                    required: 8,
87                    provided: 3,
88                },
89                "history buffer is too small: need 8 bytes, have 3",
90            ),
91            (
92                DecodeError::BlockScratchTooSmall {
93                    required: 8,
94                    provided: 3,
95                },
96                "block scratch is too small: need 8 bytes, have 3",
97            ),
98            (
99                DecodeError::LiteralScratchTooSmall {
100                    required: 8,
101                    provided: 3,
102                },
103                "literal scratch is too small: need 8 bytes, have 3",
104            ),
105            (DecodeError::InvalidBlock, "invalid zstd block"),
106            (
107                DecodeError::InvalidEntropyTable,
108                "invalid zstd entropy table",
109            ),
110            (DecodeError::InvalidBitstream, "invalid zstd bitstream"),
111            (DecodeError::InvalidOffset, "invalid zstd match offset"),
112            (
113                DecodeError::ChecksumMismatch {
114                    expected: 0x1234,
115                    actual: 0xabcd,
116                },
117                "zstd checksum mismatch: expected 00001234, got 0000abcd",
118            ),
119            (
120                DecodeError::ContentSizeMismatch {
121                    expected: 12,
122                    actual: 34,
123                },
124                "zstd content-size mismatch: expected 12, got 34",
125            ),
126            (DecodeError::UnexpectedEof, "unexpected end of zstd stream"),
127            (
128                DecodeError::ArithmeticOverflow,
129                "zstd size arithmetic overflow",
130            ),
131        ];
132
133        for (error, expected) in cases {
134            assert_eq!(error.to_string(), expected);
135        }
136    }
137}