1 |
|
2 | //! Error type definitions.
|
3 |
|
4 | use std::borrow::Cow;
|
5 | use std::io::ErrorKind;
|
6 | pub use std::io::Error as IoError;
|
7 | pub use std::io::Result as IoResult;
|
8 | use std::convert::TryFrom;
|
9 | use std::error;
|
10 | use std::fmt;
|
11 | use std::num::TryFromIntError;
|
12 |
|
13 |
|
14 | // Export types
|
15 |
|
16 | /// A result that may contain an exr error.
|
17 | pub type Result<T> = std::result::Result<T, Error>;
|
18 |
|
19 | /// A result that, if ok, contains nothing, and otherwise contains an exr error.
|
20 | pub type UnitResult = Result<()>;
|
21 |
|
22 |
|
23 | /// An error that may happen while reading or writing an exr file.
|
24 | /// Distinguishes between three types of errors:
|
25 | /// unsupported features, invalid data, and file system errors.
|
26 | #[derive (Debug)]
|
27 | pub enum Error {
|
28 |
|
29 | /// Reading or Writing the file has been aborted by the caller.
|
30 | /// This error will never be triggered by this crate itself,
|
31 | /// only by users of this library.
|
32 | /// It exists to be returned from a progress callback.
|
33 | Aborted, // FIXME remove?? is not used really?
|
34 |
|
35 | /// The contents of the file are not supported by
|
36 | /// this specific implementation of open exr,
|
37 | /// even though the data may be valid.
|
38 | NotSupported(Cow<'static, str>),
|
39 |
|
40 | /// The contents of the image are contradicting or insufficient.
|
41 | /// Also returned for `ErrorKind::UnexpectedEof` errors.
|
42 | Invalid(Cow<'static, str>),
|
43 |
|
44 | /// The underlying byte stream could not be read successfully,
|
45 | /// probably due to file system related errors.
|
46 | Io(IoError),
|
47 | }
|
48 |
|
49 |
|
50 | impl Error {
|
51 |
|
52 | /// Create an error of the variant `Invalid`.
|
53 | pub(crate) fn invalid(message: impl Into<Cow<'static, str>>) -> Self {
|
54 | Error::Invalid(message.into())
|
55 | }
|
56 |
|
57 | /// Create an error of the variant `NotSupported`.
|
58 | pub(crate) fn unsupported(message: impl Into<Cow<'static, str>>) -> Self {
|
59 | Error::NotSupported(message.into())
|
60 | }
|
61 | }
|
62 |
|
63 | /// Enable using the `?` operator on `std::io::Result`.
|
64 | impl From<IoError> for Error {
|
65 | fn from(error: IoError) -> Self {
|
66 | if error.kind() == ErrorKind::UnexpectedEof {
|
67 | Error::invalid(message:"reference to missing bytes" )
|
68 | }
|
69 | else {
|
70 | Error::Io(error)
|
71 | }
|
72 | }
|
73 | }
|
74 |
|
75 | // TODO use `usize::try_from(x)?` everywhere
|
76 | impl From<TryFromIntError> for Error {
|
77 | fn from(_: TryFromIntError) -> Self {
|
78 | Error::invalid(message:"invalid size" )
|
79 | }
|
80 | }
|
81 |
|
82 | impl error::Error for Error {
|
83 | fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
84 | match *self {
|
85 | Error::Io(ref err: &Error) => Some(err),
|
86 | _ => None,
|
87 | }
|
88 | }
|
89 | }
|
90 |
|
91 | impl fmt::Display for Error {
|
92 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
93 | match self {
|
94 | Error::Io(err: &Error) => err.fmt(formatter),
|
95 | Error::NotSupported(message: &Cow<'_, str>) => write!(formatter, "not supported: {}" , message),
|
96 | Error::Invalid(message: &Cow<'_, str>) => write!(formatter, "invalid: {}" , message),
|
97 | Error::Aborted => write!(formatter, "cancelled" ),
|
98 | }
|
99 | }
|
100 | }
|
101 |
|
102 | /// Return error on invalid range.
|
103 | #[inline ]
|
104 | pub(crate) fn i32_to_usize(value: i32, error_message: &'static str) -> Result<usize> {
|
105 | usize::try_from(value).map_err(|_| Error::invalid(error_message))
|
106 | }
|
107 |
|
108 | /// Return error on invalid range.
|
109 | #[inline ]
|
110 | pub(crate) fn usize_to_u16(value: usize) -> Result<u16> {
|
111 | Ok(u16::try_from(value)?)
|
112 | }
|
113 |
|
114 | /// Panic on overflow.
|
115 | #[inline ]
|
116 | pub(crate) fn u64_to_usize(value: u64) -> usize {
|
117 | usize::try_from(value).expect(msg:"(u64 as usize) overflowed" )
|
118 | }
|
119 |
|
120 | /// Panic on overflow.
|
121 | #[inline ]
|
122 | pub(crate) fn u32_to_usize(value: u32) -> usize {
|
123 | usize::try_from(value).expect(msg:"(u32 as usize) overflowed" )
|
124 | }
|
125 |
|
126 | /// Panic on overflow.
|
127 | #[inline ]
|
128 | pub(crate) fn usize_to_i32(value: usize) -> i32 {
|
129 | i32::try_from(value).expect(msg:"(usize as i32) overflowed" )
|
130 | }
|
131 |
|
132 | /// Panic on overflow.
|
133 | #[inline ]
|
134 | pub(crate) fn usize_to_u64(value: usize) -> u64 {
|
135 | u64::try_from(value).expect(msg:"(usize as u64) overflowed" )
|
136 | }
|
137 | |