| 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<'static, str>) => write!(formatter, "not supported: {}" , message),
|
| 96 | Error::Invalid(message: &Cow<'static, 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 | |