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}