1use thiserror::Error;
4
5pub type Result<T> = core::result::Result<T, Error>;
7
8#[derive(Debug, Error)]
10pub enum Error {
11 #[error("corrupted data: {message}")]
13 CorruptedData {
14 message: String,
15 #[source]
16 source: Option<Box<dyn std::error::Error + Send + Sync>>,
17 },
18
19 #[error("buffer too small: need {required} bytes, got {provided}")]
21 BufferTooSmall { required: usize, provided: usize },
22
23 #[error("invalid compression level {level}: must be in range [{min}, {max}]")]
25 InvalidLevel { level: i32, min: i32, max: i32 },
26
27 #[error("invalid dictionary: {0}")]
29 InvalidDictionary(String),
30
31 #[error("checksum mismatch: expected 0x{expected:08x}, got 0x{actual:08x}")]
33 ChecksumMismatch { expected: u32, actual: u32 },
34
35 #[error("unexpected EOF after {bytes_read} bytes")]
37 UnexpectedEof { bytes_read: usize },
38
39 #[error("I/O error: {0}")]
41 Io(#[from] std::io::Error),
42
43 #[error("allocation failed: could not allocate {requested_bytes} bytes")]
45 AllocationFailed { requested_bytes: usize },
46
47 #[error("{algorithm} error: {message}")]
49 Algorithm {
50 algorithm: &'static str,
51 message: String,
52 },
53
54 #[error("invalid state: expected {expected}, got {actual}")]
56 InvalidState {
57 expected: &'static str,
58 actual: &'static str,
59 },
60
61 #[error("unsupported: {0}")]
63 Unsupported(String),
64}
65
66impl Error {
67 pub fn corrupted(message: impl Into<String>) -> Self {
69 Error::CorruptedData {
70 message: message.into(),
71 source: None,
72 }
73 }
74
75 pub fn corrupted_at(message: impl Into<String>, offset: usize) -> Self {
77 Error::CorruptedData {
78 message: format!("{} at offset {}", message.into(), offset),
79 source: None,
80 }
81 }
82
83 pub fn buffer_too_small(required: usize, provided: usize) -> Self {
85 Error::BufferTooSmall { required, provided }
86 }
87
88 pub fn checksum_mismatch(expected: u32, actual: u32) -> Self {
90 Error::ChecksumMismatch { expected, actual }
91 }
92
93 pub fn unexpected_eof(bytes_read: usize) -> Self {
95 Error::UnexpectedEof { bytes_read }
96 }
97
98 pub fn io(message: impl Into<String>) -> Self {
100 Error::Io(std::io::Error::other(message.into()))
101 }
102
103 pub fn algorithm(algorithm: &'static str, message: impl Into<String>) -> Self {
105 Error::Algorithm {
106 algorithm,
107 message: message.into(),
108 }
109 }
110
111 pub fn is_recoverable(&self) -> bool {
113 matches!(
114 self,
115 Error::UnexpectedEof { .. } | Error::BufferTooSmall { .. }
116 )
117 }
118
119 pub fn category(&self) -> &'static str {
121 match self {
122 Error::CorruptedData { .. } => "corrupted_data",
123 Error::BufferTooSmall { .. } => "buffer_too_small",
124 Error::InvalidLevel { .. } => "invalid_level",
125 Error::InvalidDictionary(_) => "invalid_dictionary",
126 Error::ChecksumMismatch { .. } => "checksum_mismatch",
127 Error::UnexpectedEof { .. } => "unexpected_eof",
128 Error::Io(_) => "io_error",
129 Error::AllocationFailed { .. } => "allocation_failed",
130 Error::Algorithm { .. } => "algorithm_error",
131 Error::InvalidState { .. } => "invalid_state",
132 Error::Unsupported(_) => "unsupported",
133 }
134 }
135}