1 use std::error::Error;
2 use std::fmt;
3 use std::io;
4 use std::string;
5 
6 use decoder::ifd::{Value};
7 use tags::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Tag};
8 use miniz_oxide::inflate::TINFLStatus;
9 use ColorType;
10 
11 /// Tiff error kinds.
12 #[derive(Debug)]
13 pub enum TiffError {
14     /// The Image is not formatted properly.
15     FormatError(TiffFormatError),
16 
17     /// The Decoder does not support features required by the image.
18     UnsupportedError(TiffUnsupportedError),
19 
20     /// An I/O Error occurred while decoding the image.
21     IoError(io::Error),
22 
23     /// The Limits of the Decoder is exceeded.
24     LimitsExceeded,
25 
26     /// An integer conversion to or from a platform size failed, either due to
27     /// limits of the platform size or limits of the format.
28     IntSizeError,
29 }
30 
31 /// The image is not formatted properly.
32 ///
33 /// This indicates that the encoder producing the image might behave incorrectly or that the input
34 /// file has been corrupted.
35 ///
36 /// The list of variants may grow to incorporate errors of future features. Matching against this
37 /// exhaustively is not covered by interface stability guarantees.
38 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
39 pub enum TiffFormatError {
40     TiffSignatureNotFound,
41     TiffSignatureInvalid,
42     ImageFileDirectoryNotFound,
43     InconsistentSizesEncountered,
44     InvalidTag,
45     InvalidTagValueType(Tag),
46     RequiredTagNotFound(Tag),
47     UnknownPredictor(u16),
48     UnsignedIntegerExpected(Value),
49     SignedIntegerExpected(Value),
50     InflateError(InflateError),
51     #[doc(hidden)]
52     /// Do not match against this variant. It may get removed.
53     __NonExhaustive,
54 }
55 
56 impl fmt::Display for TiffFormatError {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>57     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
58         use self::TiffFormatError::*;
59         match *self {
60             TiffSignatureNotFound => write!(fmt, "TIFF signature not found."),
61             TiffSignatureInvalid => write!(fmt, "TIFF signature invalid."),
62             ImageFileDirectoryNotFound => write!(fmt, "Image file directory not found."),
63             InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."),
64             InvalidTag => write!(fmt, "Image contains invalid tag."),
65             InvalidTagValueType(ref tag) =>
66                 write!(fmt, "Tag `{:?}` did not have the expected value type.", tag),
67             RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag),
68             UnknownPredictor(ref predictor) => {
69                 write!(fmt, "Unknown predictor “{}” encountered", predictor)
70             }
71             UnsignedIntegerExpected(ref val) => {
72                 write!(fmt, "Expected unsigned integer, {:?} found.", val)
73             }
74             SignedIntegerExpected(ref val) => {
75                 write!(fmt, "Expected signed integer, {:?} found.", val)
76             }
77             InflateError(_) => write!(fmt, "Failed to decode inflate data."),
78             __NonExhaustive => unreachable!(),
79         }
80     }
81 }
82 
83 /// Decompression failed due to faulty compressed data.
84 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
85 pub struct InflateError {
86     status: TINFLStatus,
87 }
88 
89 impl InflateError {
new(status: TINFLStatus) -> Self90     pub(crate) fn new(status: TINFLStatus) -> Self {
91         Self { status }
92     }
93 }
94 
95 impl TiffError {
from_inflate_status(status: TINFLStatus) -> Self96     pub(crate) fn from_inflate_status(status: TINFLStatus) -> Self {
97         TiffError::FormatError(TiffFormatError::InflateError(InflateError::new(status)))
98     }
99 }
100 
101 /// The Decoder does not support features required by the image.
102 ///
103 /// This only captures known failures for which the standard either does not require support or an
104 /// implementation has been planned but not yet completed. Some variants may become unused over
105 /// time and will then get deprecated before being removed.
106 ///
107 /// The list of variants may grow. Matching against this exhaustively is not covered by interface
108 /// stability guarantees.
109 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
110 pub enum TiffUnsupportedError {
111     HorizontalPredictor(ColorType),
112     InterpretationWithBits(PhotometricInterpretation, Vec<u8>),
113     UnknownInterpretation,
114     UnknownCompressionMethod,
115     UnsupportedCompressionMethod(CompressionMethod),
116     UnsupportedSampleDepth(u8),
117     UnsupportedColorType(ColorType),
118     UnsupportedBitsPerChannel(u8),
119     UnsupportedPlanarConfig(Option<PlanarConfiguration>),
120     UnsupportedDataType,
121     #[doc(hidden)]
122     /// Do not match against this variant. It may get removed.
123     __NonExhaustive,
124 }
125 
126 impl fmt::Display for TiffUnsupportedError {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>127     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
128         use self::TiffUnsupportedError::*;
129         match *self {
130             HorizontalPredictor(color_type) => write!(
131                 fmt,
132                 "Horizontal predictor for {:?} is unsupported.",
133                 color_type
134             ),
135             InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => write!(
136                 fmt,
137                 "{:?} with {:?} bits per sample is unsupported",
138                 photometric_interpretation, bits_per_sample
139             ),
140             UnknownInterpretation => write!(
141                 fmt,
142                 "The image is using an unknown photometric interpretation."
143             ),
144             UnknownCompressionMethod => write!(fmt, "Unknown compression method."),
145             UnsupportedCompressionMethod(method) => {
146                 write!(fmt, "Compression method {:?} is unsupported", method)
147             }
148             UnsupportedSampleDepth(samples) => {
149                 write!(fmt, "{} samples per pixel is unsupported.", samples)
150             }
151             UnsupportedColorType(color_type) => {
152                 write!(fmt, "Color type {:?} is unsupported", color_type)
153             }
154             UnsupportedBitsPerChannel(bits) => {
155                 write!(fmt, "{} bits per channel not supported", bits)
156             }
157             UnsupportedPlanarConfig(config) => {
158                 write!(fmt, "Unsupported planar configuration “{:?}”.", config)
159             }
160             UnsupportedDataType => write!(fmt, "Unsupported data type."),
161             __NonExhaustive => unreachable!(),
162         }
163     }
164 }
165 
166 impl fmt::Display for TiffError {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>167     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
168         match *self {
169             TiffError::FormatError(ref e) => write!(fmt, "Format error: {}", e),
170             TiffError::UnsupportedError(ref f) => write!(
171                 fmt,
172                 "The Decoder does not support the \
173                  image format `{}`",
174                 f
175             ),
176             TiffError::IoError(ref e) => e.fmt(fmt),
177             TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"),
178             TiffError::IntSizeError => write!(fmt, "Platform or format size limits exceeded"),
179         }
180     }
181 }
182 
183 impl Error for TiffError {
description(&self) -> &str184     fn description(&self) -> &str {
185         match *self {
186             TiffError::FormatError(..) => "Format error",
187             TiffError::UnsupportedError(..) => "Unsupported error",
188             TiffError::IoError(..) => "IO error",
189             TiffError::LimitsExceeded => "Decoder limits exceeded",
190             TiffError::IntSizeError => "Platform or format size limits exceeded",
191         }
192     }
193 
cause(&self) -> Option<&dyn Error>194     fn cause(&self) -> Option<&dyn Error> {
195         match *self {
196             TiffError::IoError(ref e) => Some(e),
197             _ => None,
198         }
199     }
200 }
201 
202 impl From<io::Error> for TiffError {
from(err: io::Error) -> TiffError203     fn from(err: io::Error) -> TiffError {
204         TiffError::IoError(err)
205     }
206 }
207 
208 impl From<string::FromUtf8Error> for TiffError {
from(_err: string::FromUtf8Error) -> TiffError209     fn from(_err: string::FromUtf8Error) -> TiffError {
210         TiffError::FormatError(TiffFormatError::InvalidTag)
211     }
212 }
213 
214 impl From<TiffFormatError> for TiffError {
from(err: TiffFormatError) -> TiffError215     fn from(err: TiffFormatError) -> TiffError {
216         TiffError::FormatError(err)
217     }
218 }
219 
220 impl From<TiffUnsupportedError> for TiffError {
from(err: TiffUnsupportedError) -> TiffError221     fn from(err: TiffUnsupportedError) -> TiffError {
222         TiffError::UnsupportedError(err)
223     }
224 }
225 
226 impl From<std::num::TryFromIntError> for TiffError {
from(_err: std::num::TryFromIntError) -> TiffError227     fn from(_err: std::num::TryFromIntError) -> TiffError {
228         TiffError::IntSizeError
229     }
230 }
231 
232 /// Result of an image decoding/encoding process
233 pub type TiffResult<T> = Result<T, TiffError>;
234