1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Error types for Snappy compression/decompression.
use std::fmt;
use std::io;
/// Error type for Snappy operations.
#[derive(Debug)]
pub enum SnappyError {
/// The input data is too short or truncated.
UnexpectedEof {
/// Description of what was expected.
context: &'static str,
},
/// The decompressed length header is invalid or too large.
InvalidLength {
/// The decoded length value.
length: usize,
/// Maximum allowed length.
max_length: usize,
},
/// An invalid tag byte was encountered during decompression.
InvalidTag {
/// The tag byte value.
tag: u8,
/// Byte offset in the compressed stream.
offset: usize,
},
/// A copy operation references data before the start of the output.
InvalidOffset {
/// The back-reference offset.
offset: usize,
/// Current output position.
position: usize,
},
/// The decompressed output does not match the expected length.
OutputLengthMismatch {
/// Expected output length from the header.
expected: usize,
/// Actual decompressed length.
actual: usize,
},
/// CRC32C checksum mismatch in framed format.
ChecksumMismatch {
/// Expected checksum from the frame.
expected: u32,
/// Computed checksum from the data.
computed: u32,
},
/// Invalid or unrecognized chunk type in framed format.
InvalidChunkType {
/// The chunk type byte.
chunk_type: u8,
},
/// The stream identifier is missing or invalid.
InvalidStreamIdentifier,
/// The compressed data is corrupted.
CorruptedData {
/// Description of the corruption.
message: String,
},
/// An I/O error occurred.
Io(io::Error),
}
impl fmt::Display for SnappyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnexpectedEof { context } => {
write!(f, "unexpected end of input: {context}")
}
Self::InvalidLength { length, max_length } => {
write!(f, "invalid decompressed length {length} (max {max_length})")
}
Self::InvalidTag { tag, offset } => {
write!(f, "invalid tag byte {tag:#04x} at offset {offset}")
}
Self::InvalidOffset { offset, position } => {
write!(
f,
"invalid back-reference offset {offset} at output position {position}"
)
}
Self::OutputLengthMismatch { expected, actual } => {
write!(
f,
"output length mismatch: expected {expected}, got {actual}"
)
}
Self::ChecksumMismatch { expected, computed } => {
write!(
f,
"CRC32C checksum mismatch: expected {expected:#010x}, computed {computed:#010x}"
)
}
Self::InvalidChunkType { chunk_type } => {
write!(f, "invalid chunk type: {chunk_type:#04x}")
}
Self::InvalidStreamIdentifier => {
write!(f, "missing or invalid stream identifier")
}
Self::CorruptedData { message } => {
write!(f, "corrupted data: {message}")
}
Self::Io(err) => write!(f, "I/O error: {err}"),
}
}
}
impl std::error::Error for SnappyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(err) => Some(err),
_ => None,
}
}
}
impl From<io::Error> for SnappyError {
fn from(err: io::Error) -> Self {
Self::Io(err)
}
}
impl From<SnappyError> for io::Error {
fn from(err: SnappyError) -> Self {
match err {
SnappyError::Io(e) => e,
other => io::Error::new(io::ErrorKind::InvalidData, other.to_string()),
}
}
}
impl From<SnappyError> for oxiarc_core::error::OxiArcError {
fn from(err: SnappyError) -> Self {
match err {
SnappyError::Io(e) => Self::Io(e),
SnappyError::ChecksumMismatch { expected, computed } => {
Self::CrcMismatch { expected, computed }
}
SnappyError::UnexpectedEof { .. } => Self::UnexpectedEof { expected: 0 },
other => Self::CorruptedData {
offset: 0,
message: other.to_string(),
},
}
}
}