Line | Count | Source |
1 | | //! Contains detailed error representation. |
2 | | //! |
3 | | //! See the main [`ImageError`] which contains a variant for each specialized error type. The |
4 | | //! subtypes used in each variant are opaque by design. They can be roughly inspected through their |
5 | | //! respective `kind` methods which work similar to `std::io::Error::kind`. |
6 | | //! |
7 | | //! The error interface makes it possible to inspect the error of an underlying decoder or encoder, |
8 | | //! through the `Error::source` method. Note that this is not part of the stable interface and you |
9 | | //! may not rely on a particular error value for a particular operation. This means mainly that |
10 | | //! `image` does not promise to remain on a particular version of its underlying decoders but if |
11 | | //! you ensure to use the same version of the dependency (or at least of the error type) through |
12 | | //! external means then you could inspect the error type in slightly more detail. |
13 | | //! |
14 | | //! [`ImageError`]: enum.ImageError.html |
15 | | |
16 | | use std::collections::TryReserveError; |
17 | | use std::error::Error; |
18 | | use std::{fmt, io}; |
19 | | |
20 | | use crate::color::ExtendedColorType; |
21 | | use crate::{metadata::Cicp, ImageFormat}; |
22 | | |
23 | | /// The generic error type for image operations. |
24 | | /// |
25 | | /// This high level enum allows, by variant matching, a rough separation of concerns between |
26 | | /// underlying IO, the caller, format specifications, and the `image` implementation. |
27 | | #[derive(Debug)] |
28 | | pub enum ImageError { |
29 | | /// An error was encountered while decoding. |
30 | | /// |
31 | | /// This means that the input data did not conform to the specification of some image format, |
32 | | /// or that no format could be determined, or that it did not match format specific |
33 | | /// requirements set by the caller. |
34 | | Decoding(DecodingError), |
35 | | |
36 | | /// An error was encountered while encoding. |
37 | | /// |
38 | | /// The input image can not be encoded with the chosen format, for example because the |
39 | | /// specification has no representation for its color space or because a necessary conversion |
40 | | /// is ambiguous. In some cases it might also happen that the dimensions can not be used with |
41 | | /// the format. |
42 | | Encoding(EncodingError), |
43 | | |
44 | | /// An error was encountered in input arguments. |
45 | | /// |
46 | | /// This is a catch-all case for strictly internal operations such as scaling, conversions, |
47 | | /// etc. that involve no external format specifications. |
48 | | Parameter(ParameterError), |
49 | | |
50 | | /// Completing the operation would have required more resources than allowed. |
51 | | /// |
52 | | /// Errors of this type are limits set by the user or environment, *not* inherent in a specific |
53 | | /// format or operation that was executed. |
54 | | Limits(LimitError), |
55 | | |
56 | | /// An operation can not be completed by the chosen abstraction. |
57 | | /// |
58 | | /// This means that it might be possible for the operation to succeed in general but |
59 | | /// * it requires a disabled feature, |
60 | | /// * the implementation does not yet exist, or |
61 | | /// * no abstraction for a lower level could be found. |
62 | | Unsupported(UnsupportedError), |
63 | | |
64 | | /// An error occurred while interacting with the environment. |
65 | | IoError(io::Error), |
66 | | } |
67 | | |
68 | | /// The implementation for an operation was not provided. |
69 | | /// |
70 | | /// See the variant [`Unsupported`] for more documentation. |
71 | | /// |
72 | | /// [`Unsupported`]: enum.ImageError.html#variant.Unsupported |
73 | | #[derive(Debug)] |
74 | | pub struct UnsupportedError { |
75 | | format: ImageFormatHint, |
76 | | kind: UnsupportedErrorKind, |
77 | | } |
78 | | |
79 | | /// Details what feature is not supported. |
80 | | #[derive(Clone, Debug, Hash, PartialEq)] |
81 | | #[non_exhaustive] |
82 | | pub enum UnsupportedErrorKind { |
83 | | /// The required color type can not be handled. |
84 | | Color(ExtendedColorType), |
85 | | /// Dealing with an intricate layout is not implemented for an algorithm. |
86 | | ColorLayout(ExtendedColorType), |
87 | | /// The colors or transfer function of the CICP are not supported. |
88 | | ColorspaceCicp(Cicp), |
89 | | /// An image format is not supported. |
90 | | Format(ImageFormatHint), |
91 | | /// Some feature specified by string. |
92 | | /// This is discouraged and is likely to get deprecated (but not removed). |
93 | | GenericFeature(String), |
94 | | } |
95 | | |
96 | | /// An error was encountered while encoding an image. |
97 | | /// |
98 | | /// This is used as an opaque representation for the [`ImageError::Encoding`] variant. See its |
99 | | /// documentation for more information. |
100 | | /// |
101 | | /// [`ImageError::Encoding`]: enum.ImageError.html#variant.Encoding |
102 | | #[derive(Debug)] |
103 | | pub struct EncodingError { |
104 | | format: ImageFormatHint, |
105 | | underlying: Option<Box<dyn Error + Send + Sync>>, |
106 | | } |
107 | | |
108 | | /// An error was encountered in inputs arguments. |
109 | | /// |
110 | | /// This is used as an opaque representation for the [`ImageError::Parameter`] variant. See its |
111 | | /// documentation for more information. |
112 | | /// |
113 | | /// [`ImageError::Parameter`]: enum.ImageError.html#variant.Parameter |
114 | | #[derive(Debug)] |
115 | | pub struct ParameterError { |
116 | | kind: ParameterErrorKind, |
117 | | underlying: Option<Box<dyn Error + Send + Sync>>, |
118 | | } |
119 | | |
120 | | /// Details how a parameter is malformed. |
121 | | #[derive(Clone, Debug, Hash, PartialEq)] |
122 | | #[non_exhaustive] |
123 | | pub enum ParameterErrorKind { |
124 | | /// The dimensions passed are wrong. |
125 | | DimensionMismatch, |
126 | | /// Repeated an operation for which error that could not be cloned was emitted already. |
127 | | FailedAlready, |
128 | | /// The cicp is required to be RGB-like but had other matrix transforms or narrow range. |
129 | | RgbCicpRequired(Cicp), |
130 | | /// A string describing the parameter. |
131 | | /// This is discouraged and is likely to get deprecated (but not removed). |
132 | | Generic(String), |
133 | | /// The end of the image has been reached. |
134 | | NoMoreData, |
135 | | /// An operation expected a concrete color space but another was found. |
136 | | CicpMismatch { |
137 | | /// The cicp that was expected. |
138 | | expected: Cicp, |
139 | | /// The cicp that was found. |
140 | | found: Cicp, |
141 | | }, |
142 | | } |
143 | | |
144 | | /// An error was encountered while decoding an image. |
145 | | /// |
146 | | /// This is used as an opaque representation for the [`ImageError::Decoding`] variant. See its |
147 | | /// documentation for more information. |
148 | | /// |
149 | | /// [`ImageError::Decoding`]: enum.ImageError.html#variant.Decoding |
150 | | #[derive(Debug)] |
151 | | pub struct DecodingError { |
152 | | format: ImageFormatHint, |
153 | | underlying: Option<Box<dyn Error + Send + Sync>>, |
154 | | } |
155 | | |
156 | | /// Completing the operation would have required more resources than allowed. |
157 | | /// |
158 | | /// This is used as an opaque representation for the [`ImageError::Limits`] variant. See its |
159 | | /// documentation for more information. |
160 | | /// |
161 | | /// [`ImageError::Limits`]: enum.ImageError.html#variant.Limits |
162 | | #[derive(Debug)] |
163 | | pub struct LimitError { |
164 | | kind: LimitErrorKind, |
165 | | // do we need an underlying error? |
166 | | } |
167 | | |
168 | | /// Indicates the limit that prevented an operation from completing. |
169 | | /// |
170 | | /// Note that this enumeration is not exhaustive and may in the future be extended to provide more |
171 | | /// detailed information or to incorporate other resources types. |
172 | | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
173 | | #[non_exhaustive] |
174 | | #[allow(missing_copy_implementations)] // Might be non-Copy in the future. |
175 | | pub enum LimitErrorKind { |
176 | | /// The resulting image exceed dimension limits in either direction. |
177 | | DimensionError, |
178 | | /// The operation would have performed an allocation larger than allowed. |
179 | | InsufficientMemory, |
180 | | /// The specified strict limits are not supported for this operation |
181 | | Unsupported { |
182 | | /// The given limits |
183 | | limits: crate::Limits, |
184 | | /// The supported strict limits |
185 | | supported: crate::LimitSupport, |
186 | | }, |
187 | | } |
188 | | |
189 | | /// A best effort representation for image formats. |
190 | | #[derive(Clone, Debug, Hash, PartialEq)] |
191 | | #[non_exhaustive] |
192 | | pub enum ImageFormatHint { |
193 | | /// The format is known exactly. |
194 | | Exact(ImageFormat), |
195 | | |
196 | | /// The format can be identified by a name. |
197 | | Name(String), |
198 | | |
199 | | /// A common path extension for the format is known. |
200 | | PathExtension(std::path::PathBuf), |
201 | | |
202 | | /// The format is not known or could not be determined. |
203 | | Unknown, |
204 | | } |
205 | | |
206 | | impl UnsupportedError { |
207 | | /// Create an `UnsupportedError` for an image with details on the unsupported feature. |
208 | | /// |
209 | | /// If the operation was not connected to a particular image format then the hint may be |
210 | | /// `Unknown`. |
211 | | #[must_use] |
212 | 987 | pub fn from_format_and_kind(format: ImageFormatHint, kind: UnsupportedErrorKind) -> Self { |
213 | 987 | UnsupportedError { format, kind } |
214 | 987 | } |
215 | | |
216 | | /// Returns the corresponding `UnsupportedErrorKind` of the error. |
217 | | #[must_use] |
218 | 0 | pub fn kind(&self) -> UnsupportedErrorKind { |
219 | 0 | self.kind.clone() |
220 | 0 | } |
221 | | |
222 | | /// Returns the image format associated with this error. |
223 | | #[must_use] |
224 | 0 | pub fn format_hint(&self) -> ImageFormatHint { |
225 | 0 | self.format.clone() |
226 | 0 | } |
227 | | } |
228 | | |
229 | | impl DecodingError { |
230 | | /// Create a `DecodingError` that stems from an arbitrary error of an underlying decoder. |
231 | 37.2k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { |
232 | 37.2k | DecodingError { |
233 | 37.2k | format, |
234 | 37.2k | underlying: Some(err.into()), |
235 | 37.2k | } |
236 | 37.2k | } <image::error::DecodingError>::new::<qoi::error::Error> Line | Count | Source | 231 | 25 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 25 | DecodingError { | 233 | 25 | format, | 234 | 25 | underlying: Some(err.into()), | 235 | 25 | } | 236 | 25 | } |
<image::error::DecodingError>::new::<image_webp::decoder::DecodingError> Line | Count | Source | 231 | 1.89k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 1.89k | DecodingError { | 233 | 1.89k | format, | 234 | 1.89k | underlying: Some(err.into()), | 235 | 1.89k | } | 236 | 1.89k | } |
<image::error::DecodingError>::new::<tiff::error::TiffError> Line | Count | Source | 231 | 5.61k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 5.61k | DecodingError { | 233 | 5.61k | format, | 234 | 5.61k | underlying: Some(err.into()), | 235 | 5.61k | } | 236 | 5.61k | } |
<image::error::DecodingError>::new::<alloc::string::FromUtf8Error> Line | Count | Source | 231 | 30 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 30 | DecodingError { | 233 | 30 | format, | 234 | 30 | underlying: Some(err.into()), | 235 | 30 | } | 236 | 30 | } |
<image::error::DecodingError>::new::<alloc::string::String> Line | Count | Source | 231 | 5.95k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 5.95k | DecodingError { | 233 | 5.95k | format, | 234 | 5.95k | underlying: Some(err.into()), | 235 | 5.95k | } | 236 | 5.95k | } |
<image::error::DecodingError>::new::<zune_jpeg::errors::DecodeErrors> Line | Count | Source | 231 | 5.13k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 5.13k | DecodingError { | 233 | 5.13k | format, | 234 | 5.13k | underlying: Some(err.into()), | 235 | 5.13k | } | 236 | 5.13k | } |
<image::error::DecodingError>::new::<image::codecs::dds::DecoderError> Line | Count | Source | 231 | 18 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 18 | DecodingError { | 233 | 18 | format, | 234 | 18 | underlying: Some(err.into()), | 235 | 18 | } | 236 | 18 | } |
<image::error::DecodingError>::new::<png::decoder::stream::DecodingError> Line | Count | Source | 231 | 3.16k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 3.16k | DecodingError { | 233 | 3.16k | format, | 234 | 3.16k | underlying: Some(err.into()), | 235 | 3.16k | } | 236 | 3.16k | } |
<image::error::DecodingError>::new::<gif::reader::decoder::DecodingError> Line | Count | Source | 231 | 3.04k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 3.04k | DecodingError { | 233 | 3.04k | format, | 234 | 3.04k | underlying: Some(err.into()), | 235 | 3.04k | } | 236 | 3.04k | } |
Unexecuted instantiation: <image::error::DecodingError>::new::<std::io::error::Error> <image::error::DecodingError>::new::<image::codecs::bmp::decoder::DecoderError> Line | Count | Source | 231 | 968 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 968 | DecodingError { | 233 | 968 | format, | 234 | 968 | underlying: Some(err.into()), | 235 | 968 | } | 236 | 968 | } |
<image::error::DecodingError>::new::<image::codecs::hdr::decoder::DecoderError> Line | Count | Source | 231 | 1.86k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 1.86k | DecodingError { | 233 | 1.86k | format, | 234 | 1.86k | underlying: Some(err.into()), | 235 | 1.86k | } | 236 | 1.86k | } |
<image::error::DecodingError>::new::<image::codecs::ico::decoder::DecoderError> Line | Count | Source | 231 | 7.15k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 7.15k | DecodingError { | 233 | 7.15k | format, | 234 | 7.15k | underlying: Some(err.into()), | 235 | 7.15k | } | 236 | 7.15k | } |
<image::error::DecodingError>::new::<image::codecs::pnm::decoder::DecoderError> Line | Count | Source | 231 | 2.09k | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 2.09k | DecodingError { | 233 | 2.09k | format, | 234 | 2.09k | underlying: Some(err.into()), | 235 | 2.09k | } | 236 | 2.09k | } |
Unexecuted instantiation: <image::error::DecodingError>::new::<<image::error::ImageError as core::convert::From<image::images::flat::Error>>::from::NormalFormRequiredError> <image::error::DecodingError>::new::<&str> Line | Count | Source | 231 | 312 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { | 232 | 312 | DecodingError { | 233 | 312 | format, | 234 | 312 | underlying: Some(err.into()), | 235 | 312 | } | 236 | 312 | } |
|
237 | | |
238 | | /// Create a `DecodingError` for an image format. |
239 | | /// |
240 | | /// The error will not contain any further information but is very easy to create. |
241 | | #[must_use] |
242 | 0 | pub fn from_format_hint(format: ImageFormatHint) -> Self { |
243 | 0 | DecodingError { |
244 | 0 | format, |
245 | 0 | underlying: None, |
246 | 0 | } |
247 | 0 | } |
248 | | |
249 | | /// Returns the image format associated with this error. |
250 | | #[must_use] |
251 | 0 | pub fn format_hint(&self) -> ImageFormatHint { |
252 | 0 | self.format.clone() |
253 | 0 | } |
254 | | } |
255 | | |
256 | | impl EncodingError { |
257 | | /// Create an `EncodingError` that stems from an arbitrary error of an underlying encoder. |
258 | 0 | pub fn new(format: ImageFormatHint, err: impl Into<Box<dyn Error + Send + Sync>>) -> Self { |
259 | 0 | EncodingError { |
260 | 0 | format, |
261 | 0 | underlying: Some(err.into()), |
262 | 0 | } |
263 | 0 | } Unexecuted instantiation: <image::error::EncodingError>::new::<qoi::error::Error> Unexecuted instantiation: <image::error::EncodingError>::new::<image_webp::encoder::EncodingError> Unexecuted instantiation: <image::error::EncodingError>::new::<tiff::error::TiffError> Unexecuted instantiation: <image::error::EncodingError>::new::<gif::encoder::EncodingError> Unexecuted instantiation: <image::error::EncodingError>::new::<image::codecs::tga::encoder::EncoderError> Unexecuted instantiation: <image::error::EncodingError>::new::<image::codecs::jpeg::encoder::EncoderError> Unexecuted instantiation: <image::error::EncodingError>::new::<&str> Unexecuted instantiation: <image::error::EncodingError>::new::<ravif::error::Error> Unexecuted instantiation: <image::error::EncodingError>::new::<jpeg_encoder::error::EncodingError> |
264 | | |
265 | | /// Create an `EncodingError` for an image format. |
266 | | /// |
267 | | /// The error will not contain any further information but is very easy to create. |
268 | | #[must_use] |
269 | 0 | pub fn from_format_hint(format: ImageFormatHint) -> Self { |
270 | 0 | EncodingError { |
271 | 0 | format, |
272 | 0 | underlying: None, |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | | /// Return the image format associated with this error. |
277 | | #[must_use] |
278 | 0 | pub fn format_hint(&self) -> ImageFormatHint { |
279 | 0 | self.format.clone() |
280 | 0 | } |
281 | | } |
282 | | |
283 | | impl ParameterError { |
284 | | /// Construct a `ParameterError` directly from a corresponding kind. |
285 | | #[must_use] |
286 | 6 | pub fn from_kind(kind: ParameterErrorKind) -> Self { |
287 | 6 | ParameterError { |
288 | 6 | kind, |
289 | 6 | underlying: None, |
290 | 6 | } |
291 | 6 | } |
292 | | |
293 | | /// Returns the corresponding `ParameterErrorKind` of the error. |
294 | | #[must_use] |
295 | 0 | pub fn kind(&self) -> ParameterErrorKind { |
296 | 0 | self.kind.clone() |
297 | 0 | } |
298 | | } |
299 | | |
300 | | impl LimitError { |
301 | | /// Construct a generic `LimitError` directly from a corresponding kind. |
302 | | #[must_use] |
303 | 2.35k | pub fn from_kind(kind: LimitErrorKind) -> Self { |
304 | 2.35k | LimitError { kind } |
305 | 2.35k | } |
306 | | |
307 | | /// Returns the corresponding `LimitErrorKind` of the error. |
308 | | #[must_use] |
309 | 0 | pub fn kind(&self) -> LimitErrorKind { |
310 | 0 | self.kind.clone() |
311 | 0 | } |
312 | | } |
313 | | |
314 | | impl From<LimitErrorKind> for LimitError { |
315 | 0 | fn from(kind: LimitErrorKind) -> Self { |
316 | 0 | Self { kind } |
317 | 0 | } |
318 | | } |
319 | | |
320 | | impl From<io::Error> for ImageError { |
321 | 5.26k | fn from(err: io::Error) -> ImageError { |
322 | 5.26k | ImageError::IoError(err) |
323 | 5.26k | } |
324 | | } |
325 | | |
326 | | impl From<TryReserveError> for ImageError { |
327 | 0 | fn from(_: TryReserveError) -> ImageError { |
328 | 0 | ImageError::Limits(LimitErrorKind::InsufficientMemory.into()) |
329 | 0 | } |
330 | | } |
331 | | |
332 | | impl From<ImageFormat> for ImageFormatHint { |
333 | 32.2k | fn from(format: ImageFormat) -> Self { |
334 | 32.2k | ImageFormatHint::Exact(format) |
335 | 32.2k | } |
336 | | } |
337 | | |
338 | | impl From<&'_ std::path::Path> for ImageFormatHint { |
339 | 0 | fn from(path: &'_ std::path::Path) -> Self { |
340 | 0 | match path.extension() { |
341 | 0 | Some(ext) => ImageFormatHint::PathExtension(ext.into()), |
342 | 0 | None => ImageFormatHint::Unknown, |
343 | | } |
344 | 0 | } |
345 | | } |
346 | | |
347 | | impl From<ImageFormatHint> for UnsupportedError { |
348 | 0 | fn from(hint: ImageFormatHint) -> Self { |
349 | 0 | UnsupportedError { |
350 | 0 | format: hint.clone(), |
351 | 0 | kind: UnsupportedErrorKind::Format(hint), |
352 | 0 | } |
353 | 0 | } |
354 | | } |
355 | | |
356 | | /// Result of an image decoding/encoding process |
357 | | pub type ImageResult<T> = Result<T, ImageError>; |
358 | | |
359 | | impl fmt::Display for ImageError { |
360 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
361 | 0 | match self { |
362 | 0 | ImageError::IoError(err) => err.fmt(fmt), |
363 | 0 | ImageError::Decoding(err) => err.fmt(fmt), |
364 | 0 | ImageError::Encoding(err) => err.fmt(fmt), |
365 | 0 | ImageError::Parameter(err) => err.fmt(fmt), |
366 | 0 | ImageError::Limits(err) => err.fmt(fmt), |
367 | 0 | ImageError::Unsupported(err) => err.fmt(fmt), |
368 | | } |
369 | 0 | } |
370 | | } |
371 | | |
372 | | impl Error for ImageError { |
373 | 0 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
374 | 0 | match self { |
375 | 0 | ImageError::IoError(err) => err.source(), |
376 | 0 | ImageError::Decoding(err) => err.source(), |
377 | 0 | ImageError::Encoding(err) => err.source(), |
378 | 0 | ImageError::Parameter(err) => err.source(), |
379 | 0 | ImageError::Limits(err) => err.source(), |
380 | 0 | ImageError::Unsupported(err) => err.source(), |
381 | | } |
382 | 0 | } |
383 | | } |
384 | | |
385 | | impl fmt::Display for UnsupportedError { |
386 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
387 | 0 | match &self.kind { |
388 | | UnsupportedErrorKind::Format(ImageFormatHint::Unknown) => { |
389 | 0 | write!(fmt, "The image format could not be determined",) |
390 | | } |
391 | 0 | UnsupportedErrorKind::Format(format @ ImageFormatHint::PathExtension(_)) => write!( |
392 | 0 | fmt, |
393 | 0 | "The file extension {format} was not recognized as an image format", |
394 | | ), |
395 | 0 | UnsupportedErrorKind::Format(format) => { |
396 | 0 | write!(fmt, "The image format {format} is not supported",) |
397 | | } |
398 | 0 | UnsupportedErrorKind::Color(color) => write!( |
399 | 0 | fmt, |
400 | 0 | "The encoder or decoder for {} does not support the color type `{:?}`", |
401 | | self.format, color, |
402 | | ), |
403 | 0 | UnsupportedErrorKind::ColorLayout(layout) => write!( |
404 | 0 | fmt, |
405 | 0 | "Converting with the texel memory layout {layout:?} is not supported", |
406 | | ), |
407 | 0 | UnsupportedErrorKind::ColorspaceCicp(color) => write!( |
408 | 0 | fmt, |
409 | 0 | "The colorimetric interpretation of a CICP color space is not supported for `{color:?}`", |
410 | | ), |
411 | 0 | UnsupportedErrorKind::GenericFeature(message) => match &self.format { |
412 | 0 | ImageFormatHint::Unknown => write!( |
413 | 0 | fmt, |
414 | 0 | "The decoder does not support the format feature {message}", |
415 | | ), |
416 | 0 | other => write!( |
417 | 0 | fmt, |
418 | 0 | "The decoder for {other} does not support the format features {message}", |
419 | | ), |
420 | | }, |
421 | | } |
422 | 0 | } |
423 | | } |
424 | | |
425 | | impl Error for UnsupportedError {} |
426 | | |
427 | | impl fmt::Display for ParameterError { |
428 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
429 | 0 | match &self.kind { |
430 | 0 | ParameterErrorKind::DimensionMismatch => write!( |
431 | 0 | fmt, |
432 | 0 | "The Image's dimensions are either too \ |
433 | 0 | small or too large" |
434 | | ), |
435 | 0 | ParameterErrorKind::FailedAlready => write!( |
436 | 0 | fmt, |
437 | 0 | "The end the image stream has been reached due to a previous error" |
438 | | ), |
439 | 0 | ParameterErrorKind::RgbCicpRequired(cicp) => { |
440 | 0 | write!(fmt, "The CICP {cicp:?} can not be used for RGB images",) |
441 | | } |
442 | | |
443 | 0 | ParameterErrorKind::Generic(message) => { |
444 | 0 | write!(fmt, "The parameter is malformed: {message}",) |
445 | | } |
446 | 0 | ParameterErrorKind::NoMoreData => write!(fmt, "The end of the image has been reached",), |
447 | 0 | ParameterErrorKind::CicpMismatch { expected, found } => { |
448 | 0 | write!( |
449 | 0 | fmt, |
450 | 0 | "The color space {found:?} does not match the expected {expected:?}", |
451 | | ) |
452 | | } |
453 | 0 | }?; |
454 | | |
455 | 0 | if let Some(underlying) = &self.underlying { |
456 | 0 | write!(fmt, "\n{underlying}")?; |
457 | 0 | } |
458 | | |
459 | 0 | Ok(()) |
460 | 0 | } |
461 | | } |
462 | | |
463 | | impl Error for ParameterError { |
464 | 0 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
465 | 0 | match &self.underlying { |
466 | 0 | None => None, |
467 | 0 | Some(source) => Some(&**source), |
468 | | } |
469 | 0 | } |
470 | | } |
471 | | |
472 | | impl fmt::Display for EncodingError { |
473 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
474 | 0 | match &self.underlying { |
475 | 0 | Some(underlying) => write!( |
476 | 0 | fmt, |
477 | 0 | "Format error encoding {}:\n{}", |
478 | | self.format, underlying, |
479 | | ), |
480 | 0 | None => write!(fmt, "Format error encoding {}", self.format,), |
481 | | } |
482 | 0 | } |
483 | | } |
484 | | |
485 | | impl Error for EncodingError { |
486 | 0 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
487 | 0 | match &self.underlying { |
488 | 0 | None => None, |
489 | 0 | Some(source) => Some(&**source), |
490 | | } |
491 | 0 | } |
492 | | } |
493 | | |
494 | | impl fmt::Display for DecodingError { |
495 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
496 | 0 | match &self.underlying { |
497 | 0 | None => match self.format { |
498 | 0 | ImageFormatHint::Unknown => write!(fmt, "Format error"), |
499 | 0 | _ => write!(fmt, "Format error decoding {}", self.format), |
500 | | }, |
501 | 0 | Some(underlying) => { |
502 | 0 | write!(fmt, "Format error decoding {}: {}", self.format, underlying) |
503 | | } |
504 | | } |
505 | 0 | } |
506 | | } |
507 | | |
508 | | impl Error for DecodingError { |
509 | 0 | fn source(&self) -> Option<&(dyn Error + 'static)> { |
510 | 0 | match &self.underlying { |
511 | 0 | None => None, |
512 | 0 | Some(source) => Some(&**source), |
513 | | } |
514 | 0 | } |
515 | | } |
516 | | |
517 | | impl fmt::Display for LimitError { |
518 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
519 | 0 | match self.kind { |
520 | 0 | LimitErrorKind::InsufficientMemory => write!(fmt, "Memory limit exceeded"), |
521 | 0 | LimitErrorKind::DimensionError => write!(fmt, "Image size exceeds limit"), |
522 | | LimitErrorKind::Unsupported { .. } => { |
523 | 0 | write!(fmt, "The following strict limits are specified but not supported by the opertation: ")?; |
524 | 0 | Ok(()) |
525 | | } |
526 | | } |
527 | 0 | } |
528 | | } |
529 | | |
530 | | impl Error for LimitError {} |
531 | | |
532 | | impl fmt::Display for ImageFormatHint { |
533 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
534 | 0 | match self { |
535 | 0 | ImageFormatHint::Exact(format) => write!(fmt, "{format:?}"), |
536 | 0 | ImageFormatHint::Name(name) => write!(fmt, "`{name}`"), |
537 | 0 | ImageFormatHint::PathExtension(ext) => write!(fmt, "`.{ext:?}`"), |
538 | 0 | ImageFormatHint::Unknown => write!(fmt, "`Unknown`"), |
539 | | } |
540 | 0 | } |
541 | | } |
542 | | |
543 | | /// Converting [`ExtendedColorType`] to [`ColorType`][`crate::ColorType`] failed. |
544 | | /// |
545 | | /// This type is convertible to [`ImageError`] as [`ImageError::Unsupported`]. |
546 | | #[derive(Clone)] |
547 | | #[allow(missing_copy_implementations)] |
548 | | pub struct TryFromExtendedColorError { |
549 | | pub(crate) was: ExtendedColorType, |
550 | | } |
551 | | |
552 | | impl fmt::Debug for TryFromExtendedColorError { |
553 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
554 | 0 | write!(f, "{}", self) |
555 | 0 | } |
556 | | } |
557 | | |
558 | | impl fmt::Display for TryFromExtendedColorError { |
559 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
560 | 0 | write!( |
561 | 0 | f, |
562 | 0 | "The pixel layout {:?} is not supported as a buffer ColorType", |
563 | | self.was |
564 | | ) |
565 | 0 | } |
566 | | } |
567 | | |
568 | | impl Error for TryFromExtendedColorError {} |
569 | | |
570 | | impl From<TryFromExtendedColorError> for ImageError { |
571 | 0 | fn from(err: TryFromExtendedColorError) -> ImageError { |
572 | 0 | ImageError::Unsupported(UnsupportedError::from_format_and_kind( |
573 | 0 | ImageFormatHint::Unknown, |
574 | 0 | UnsupportedErrorKind::Color(err.was), |
575 | 0 | )) |
576 | 0 | } |
577 | | } |
578 | | |
579 | | #[cfg(test)] |
580 | | mod tests { |
581 | | use super::*; |
582 | | use std::mem::size_of; |
583 | | |
584 | | #[allow(dead_code)] |
585 | | // This will fail to compile if the size of this type is large. |
586 | | const ASSERT_SMALLISH: usize = [0][(size_of::<ImageError>() >= 200) as usize]; |
587 | | |
588 | | #[test] |
589 | | fn test_send_sync_stability() { |
590 | | fn assert_send_sync<T: Send + Sync>() {} |
591 | | |
592 | | assert_send_sync::<ImageError>(); |
593 | | } |
594 | | } |