1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use crate::dataset::DataToken;
use dicom_core::error::Error as CoreError;
pub use dicom_core::error::{CastValueError, InvalidValueReadError};
use dicom_encoding::error::{Error as EncodingError, TextEncodingError};
use quick_error::quick_error;
use std::error::Error as BaseError;
use std::fmt;
use std::io;

/// Type alias for a result from this crate.
pub type Result<T> = ::std::result::Result<T, Error>;

quick_error! {
    /// The main data type for errors in the library.
    #[derive(Debug)]
    pub enum Error {
        /// Not valid DICOM content, typically raised when checking the magic code.
        InvalidFormat {
            description("Content is not DICOM or is corrupted")
        }
        /// Raised when the obtained data element was not the one expected.
        UnexpectedElement {
            description("Unexpected DICOM element in current reading position")
        }
        /// Raised when the obtained length is inconsistent.
        UnexpectedDataValueLength {
            description("Inconsistent data value length in data element")
        }
        /// Raised when a read was illegally attempted.
        IllegalDataRead {
            description("Illegal data value read")
        }
        /// Raised when the demanded transfer syntax is not supported.
        UnsupportedTransferSyntax {
            description("Unsupported transfer syntax")
        }
        /// Raised when the required character set is not supported.
        UnsupportedCharacterSet {
            description("Unsupported character set")
        }
        /// Raised when attempting to fetch an element by an unknown attribute name.
        NoSuchAttributeName {
            description("No such attribute name")
        }
        /// Raised when attempting to fetch an unexistent element.
        NoSuchDataElement {
            description("No such data element")
        }
        /// Raised when attempting to read pixel data out of bounds.
        PixelDataOutOfBounds {
            description("Pixel data access index out of bounds")
        }
        /// Raised when a data set parser couldn't fetch a value after a primitive
        /// data element's header.
        MissingElementValue {
            description("Expected value after data element header, but was missing")
        }
        /// Raised while parsing a DICOM data set and found an unexpected
        /// element header or value.
        DataSetSyntax(err: DataSetSyntaxError) {
            description("Data set syntax error")
            from()
            cause(err)
            display(self_) -> ("{}: {}", self_.description(), err.description())
        }
        /// Error related to an invalid value read.
        ReadValue(err: InvalidValueReadError) {
            description("Invalid value read")
            from()
            cause(err)
            display(self_) -> ("{}: {}", self_.description(), err.description())
        }
        /// Error related to a failed text encoding / decoding procedure.
        TextEncoding(err: TextEncodingError) {
            description("Failed text encoding/decoding")
            from()
            cause(err)
            display(self_) -> ("{}: {}", self_.description(), err.description())
        }
        /// A failed attempt to cast a value to an inappropriate format.
        CastValue(err: CastValueError) {
            description("Failed value cast")
            from()
            cause(err)
            display(self_) -> ("{}: {}", self_.description(), err.description())
        }
        /// Other I/O errors.
        Io(err: io::Error) {
            description("I/O error")
            from()
            cause(err)
            display(self_) -> ("{}: {}", self_.description(), err.description())
        }
    }
}

impl From<CoreError> for Error {
    fn from(e: CoreError) -> Self {
        match e {
            CoreError::UnexpectedDataValueLength => Error::UnexpectedDataValueLength,
            CoreError::UnexpectedElement => Error::UnexpectedElement,
            CoreError::ReadValue(e) => Error::ReadValue(e),
            CoreError::CastValue(e) => Error::CastValue(e),
        }
    }
}

impl From<EncodingError> for Error {
    fn from(e: EncodingError) -> Self {
        match e {
            EncodingError::UnexpectedElement => Error::UnexpectedElement,
            EncodingError::UnexpectedDataValueLength => Error::UnexpectedDataValueLength,
            EncodingError::ReadValue(e) => Error::ReadValue(e),
            EncodingError::TextEncoding(e) => Error::TextEncoding(e),
            EncodingError::CastValue(e) => Error::CastValue(e),
            EncodingError::Io(e) => Error::Io(e),
        }
    }
}

#[derive(Debug)]
pub enum DataSetSyntaxError {
    PrematureEnd,
    UnexpectedToken(DataToken),
}

impl fmt::Display for DataSetSyntaxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            DataSetSyntaxError::PrematureEnd => f.write_str(self.description()),
            DataSetSyntaxError::UnexpectedToken(ref token) => {
                write!(f, "{} {}", self.description(), token)
            }
        }
    }
}

impl ::std::error::Error for DataSetSyntaxError {
    fn description(&self) -> &str {
        match self {
            DataSetSyntaxError::PrematureEnd => "data set ended prematurely",
            DataSetSyntaxError::UnexpectedToken(_) => "unexpected data set token",
        }
    }
}