1use std::fmt;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, Clone, PartialEq)]
10#[non_exhaustive]
11pub enum Error {
12 InvalidDimensions {
14 width: u32,
16 height: u32,
18 reason: &'static str,
20 },
21 InvalidQuality {
23 value: f32,
25 valid_range: &'static str,
27 },
28 InvalidColorFormat {
30 reason: &'static str,
32 },
33 InvalidBufferSize {
35 expected: usize,
37 actual: usize,
39 },
40 InvalidJpegData {
42 reason: &'static str,
44 },
45 UnexpectedEof {
47 context: &'static str,
49 },
50 InvalidMarker {
52 marker: u8,
54 context: &'static str,
56 },
57 InvalidHuffmanTable {
59 table_idx: u8,
61 reason: &'static str,
63 },
64 InvalidQuantTable {
66 table_idx: u8,
68 reason: &'static str,
70 },
71 UnsupportedFeature {
73 feature: &'static str,
75 },
76 InternalError {
78 reason: &'static str,
80 },
81 IoError {
83 reason: String,
85 },
86 IccError(String),
88 DecodeError(String),
90 InvalidScanScript(String),
92 AllocationFailed {
94 bytes: usize,
96 context: &'static str,
98 },
99 SizeOverflow {
101 context: &'static str,
103 },
104 ImageTooLarge {
106 pixels: u64,
108 limit: u64,
110 },
111 TooManyScans {
113 count: usize,
115 limit: usize,
117 },
118}
119
120impl fmt::Display for Error {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 match self {
123 Self::InvalidDimensions {
124 width,
125 height,
126 reason,
127 } => {
128 write!(f, "invalid dimensions {}x{}: {}", width, height, reason)
129 }
130 Self::InvalidQuality { value, valid_range } => {
131 write!(f, "invalid quality {}: must be in {}", value, valid_range)
132 }
133 Self::InvalidColorFormat { reason } => {
134 write!(f, "invalid color format: {}", reason)
135 }
136 Self::InvalidBufferSize { expected, actual } => {
137 write!(
138 f,
139 "invalid buffer size: expected {} bytes, got {}",
140 expected, actual
141 )
142 }
143 Self::InvalidJpegData { reason } => {
144 write!(f, "invalid JPEG data: {}", reason)
145 }
146 Self::UnexpectedEof { context } => {
147 write!(f, "unexpected end of data while {}", context)
148 }
149 Self::InvalidMarker { marker, context } => {
150 write!(f, "invalid marker 0x{:02X} while {}", marker, context)
151 }
152 Self::InvalidHuffmanTable { table_idx, reason } => {
153 write!(f, "invalid Huffman table {}: {}", table_idx, reason)
154 }
155 Self::InvalidQuantTable { table_idx, reason } => {
156 write!(f, "invalid quantization table {}: {}", table_idx, reason)
157 }
158 Self::UnsupportedFeature { feature } => {
159 write!(f, "unsupported feature: {}", feature)
160 }
161 Self::InternalError { reason } => {
162 write!(f, "internal error: {}", reason)
163 }
164 Self::IoError { reason } => {
165 write!(f, "I/O error: {}", reason)
166 }
167 Self::IccError(reason) => {
168 write!(f, "ICC error: {}", reason)
169 }
170 Self::DecodeError(reason) => {
171 write!(f, "decode error: {}", reason)
172 }
173 Self::InvalidScanScript(reason) => {
174 write!(f, "invalid scan script: {}", reason)
175 }
176 Self::AllocationFailed { bytes, context } => {
177 write!(f, "allocation of {} bytes failed while {}", bytes, context)
178 }
179 Self::SizeOverflow { context } => {
180 write!(f, "size calculation overflow while {}", context)
181 }
182 Self::ImageTooLarge { pixels, limit } => {
183 write!(
184 f,
185 "image too large: {} pixels exceeds limit of {}",
186 pixels, limit
187 )
188 }
189 Self::TooManyScans { count, limit } => {
190 write!(f, "too many scans: {} exceeds limit of {}", count, limit)
191 }
192 }
193 }
194}
195
196impl std::error::Error for Error {}
197
198impl From<std::io::Error> for Error {
199 fn from(err: std::io::Error) -> Self {
200 Self::IoError {
201 reason: err.to_string(),
202 }
203 }
204}
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209
210 #[test]
211 fn test_error_display() {
212 let err = Error::InvalidDimensions {
213 width: 0,
214 height: 100,
215 reason: "width cannot be zero",
216 };
217 assert!(err.to_string().contains("width cannot be zero"));
218 }
219
220 #[test]
221 fn test_io_error_conversion() {
222 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
223 let err: Error = io_err.into();
224 assert!(matches!(err, Error::IoError { .. }));
225 }
226}