1use std::fmt::{Debug, Display, Formatter};
7use std::io::Write;
8
9use std::error::Error;
10
11#[derive(Debug)]
13pub enum ArrowError {
14 NotYetImplemented(String),
16 ExternalError(Box<dyn Error + Send + Sync>),
18 CastError(String),
20 MemoryError(String),
22 ParseError(String),
24 SchemaError(String),
26 ComputeError(String),
28 DivideByZero,
30 ArithmeticOverflow(String),
32 CsvError(String),
34 JsonError(String),
36 AvroError(String),
38 IoError(String, std::io::Error),
40 IpcError(String),
42 InvalidArgumentError(String),
44 ParquetError(String),
46 CDataInterface(String),
48 DictionaryKeyOverflowError,
50 RunEndIndexOverflowError,
52 OffsetOverflowError(usize),
54}
55
56impl ArrowError {
57 pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
59 Self::ExternalError(error)
60 }
61}
62
63impl From<std::io::Error> for ArrowError {
64 fn from(error: std::io::Error) -> Self {
65 ArrowError::IoError(error.to_string(), error)
66 }
67}
68
69impl From<std::str::Utf8Error> for ArrowError {
70 fn from(error: std::str::Utf8Error) -> Self {
71 ArrowError::ParseError(error.to_string())
72 }
73}
74
75impl From<std::string::FromUtf8Error> for ArrowError {
76 fn from(error: std::string::FromUtf8Error) -> Self {
77 ArrowError::ParseError(error.to_string())
78 }
79}
80
81impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError {
82 fn from(error: std::io::IntoInnerError<W>) -> Self {
83 ArrowError::IoError(error.to_string(), error.into())
84 }
85}
86
87impl Display for ArrowError {
88 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
89 match self {
90 ArrowError::NotYetImplemented(source) => {
91 write!(f, "Not yet implemented: {source}")
92 }
93 ArrowError::ExternalError(source) => write!(f, "External error: {source}"),
94 ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"),
95 ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"),
96 ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"),
97 ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"),
98 ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"),
99 ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"),
100 ArrowError::DivideByZero => write!(f, "Divide by zero error"),
101 ArrowError::AvroError(desc) => write!(f, "Avro error: {desc}"),
102 ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"),
103 ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"),
104 ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"),
105 ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"),
106 ArrowError::InvalidArgumentError(desc) => {
107 write!(f, "Invalid argument error: {desc}")
108 }
109 ArrowError::ParquetError(desc) => {
110 write!(f, "Parquet argument error: {desc}")
111 }
112 ArrowError::CDataInterface(desc) => {
113 write!(f, "C Data interface error: {desc}")
114 }
115 ArrowError::DictionaryKeyOverflowError => {
116 write!(f, "Dictionary key bigger than the key type")
117 }
118 ArrowError::RunEndIndexOverflowError => {
119 write!(f, "Run end index bigger than the run-end type")
120 }
121 ArrowError::OffsetOverflowError(offset) => {
122 write!(f, "Offset overflow error: {offset}")
123 }
124 }
125 }
126}
127
128impl Error for ArrowError {
129 fn source(&self) -> Option<&(dyn Error + 'static)> {
130 match self {
131 ArrowError::ExternalError(source) => Some(source.as_ref()),
132 ArrowError::IoError(_, source) => Some(source),
133 _ => None,
134 }
135 }
136}
137
138#[cfg(test)]
139mod test {
140 use super::*;
141
142 #[test]
143 fn error_source() {
144 let e1 = ArrowError::DivideByZero;
145 assert!(e1.source().is_none());
146
147 let e2 = ArrowError::ExternalError(Box::new(e1));
149 let source = e2.source().unwrap().downcast_ref::<ArrowError>().unwrap();
150 assert!(matches!(source, ArrowError::DivideByZero));
151
152 let e3 = ArrowError::ExternalError(Box::new(e2));
154 let source = e3
155 .source()
156 .unwrap()
157 .downcast_ref::<ArrowError>()
158 .unwrap()
159 .source()
160 .unwrap()
161 .downcast_ref::<ArrowError>()
162 .unwrap();
163
164 assert!(matches!(source, ArrowError::DivideByZero));
165 }
166}