1use std::fmt::{Debug, Display, Formatter};
20use std::io::Write;
21
22use std::error::Error;
23
24#[derive(Debug)]
26pub enum ArrowError {
27    NotYetImplemented(String),
29    ExternalError(Box<dyn Error + Send + Sync>),
31    CastError(String),
33    MemoryError(String),
35    ParseError(String),
37    SchemaError(String),
39    ComputeError(String),
41    DivideByZero,
43    ArithmeticOverflow(String),
45    CsvError(String),
47    JsonError(String),
49    AvroError(String),
51    IoError(String, std::io::Error),
53    IpcError(String),
55    InvalidArgumentError(String),
57    ParquetError(String),
59    CDataInterface(String),
61    DictionaryKeyOverflowError,
63    RunEndIndexOverflowError,
65    OffsetOverflowError(usize),
67}
68
69impl ArrowError {
70    pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
72        Self::ExternalError(error)
73    }
74}
75
76impl From<std::io::Error> for ArrowError {
77    fn from(error: std::io::Error) -> Self {
78        ArrowError::IoError(error.to_string(), error)
79    }
80}
81
82impl From<std::str::Utf8Error> for ArrowError {
83    fn from(error: std::str::Utf8Error) -> Self {
84        ArrowError::ParseError(error.to_string())
85    }
86}
87
88impl From<std::string::FromUtf8Error> for ArrowError {
89    fn from(error: std::string::FromUtf8Error) -> Self {
90        ArrowError::ParseError(error.to_string())
91    }
92}
93
94impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError {
95    fn from(error: std::io::IntoInnerError<W>) -> Self {
96        ArrowError::IoError(error.to_string(), error.into())
97    }
98}
99
100impl Display for ArrowError {
101    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102        match self {
103            ArrowError::NotYetImplemented(source) => {
104                write!(f, "Not yet implemented: {}", &source)
105            }
106            ArrowError::ExternalError(source) => write!(f, "External error: {}", &source),
107            ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"),
108            ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"),
109            ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"),
110            ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"),
111            ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"),
112            ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"),
113            ArrowError::DivideByZero => write!(f, "Divide by zero error"),
114            ArrowError::AvroError(desc) => write!(f, "Avro error: {desc}"),
115            ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"),
116            ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"),
117            ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"),
118            ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"),
119            ArrowError::InvalidArgumentError(desc) => {
120                write!(f, "Invalid argument error: {desc}")
121            }
122            ArrowError::ParquetError(desc) => {
123                write!(f, "Parquet argument error: {desc}")
124            }
125            ArrowError::CDataInterface(desc) => {
126                write!(f, "C Data interface error: {desc}")
127            }
128            ArrowError::DictionaryKeyOverflowError => {
129                write!(f, "Dictionary key bigger than the key type")
130            }
131            ArrowError::RunEndIndexOverflowError => {
132                write!(f, "Run end encoded array index overflow error")
133            }
134            ArrowError::OffsetOverflowError(offset) => {
135                write!(f, "Offset overflow error: {offset}")
136            }
137        }
138    }
139}
140
141impl Error for ArrowError {
142    fn source(&self) -> Option<&(dyn Error + 'static)> {
143        match self {
144            ArrowError::ExternalError(source) => Some(source.as_ref()),
145            ArrowError::IoError(_, source) => Some(source),
146            _ => None,
147        }
148    }
149}
150
151#[cfg(test)]
152mod test {
153    use super::*;
154
155    #[test]
156    fn error_source() {
157        let e1 = ArrowError::DivideByZero;
158        assert!(e1.source().is_none());
159
160        let e2 = ArrowError::ExternalError(Box::new(e1));
162        let source = e2.source().unwrap().downcast_ref::<ArrowError>().unwrap();
163        assert!(matches!(source, ArrowError::DivideByZero));
164
165        let e3 = ArrowError::ExternalError(Box::new(e2));
167        let source = e3
168            .source()
169            .unwrap()
170            .downcast_ref::<ArrowError>()
171            .unwrap()
172            .source()
173            .unwrap()
174            .downcast_ref::<ArrowError>()
175            .unwrap();
176
177        assert!(matches!(source, ArrowError::DivideByZero));
178    }
179}