arrow_schema/
error.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines `ArrowError` for representing failures in various Arrow operations.
19use std::fmt::{Debug, Display, Formatter};
20use std::io::Write;
21
22use std::error::Error;
23
24/// Many different operations in the `arrow` crate return this error type.
25#[derive(Debug)]
26pub enum ArrowError {
27    /// Returned when functionality is not yet available.
28    NotYetImplemented(String),
29    /// Wraps an external error.
30    ExternalError(Box<dyn Error + Send + Sync>),
31    /// Error during casting from one type to another.
32    CastError(String),
33    /// Memory or buffer error.
34    MemoryError(String),
35    /// Error during parsing from a string.
36    ParseError(String),
37    /// Error during schema-related operations.
38    SchemaError(String),
39    /// Error during computation.
40    ComputeError(String),
41    /// Error during division by zero.
42    DivideByZero,
43    /// Error when an arithmetic operation overflows.
44    ArithmeticOverflow(String),
45    /// Error during CSV-related operations.
46    CsvError(String),
47    /// Error during JSON-related operations.
48    JsonError(String),
49    /// Error during IO operations.
50    IoError(String, std::io::Error),
51    /// Error during IPC operations in `arrow-ipc` or `arrow-flight`.
52    IpcError(String),
53    /// Error indicating that an unexpected or bad argument was passed to a function.
54    InvalidArgumentError(String),
55    /// Error during Parquet operations.
56    ParquetError(String),
57    /// Error during import or export to/from the C Data Interface
58    CDataInterface(String),
59    /// Error when a dictionary key is bigger than the key type
60    DictionaryKeyOverflowError,
61    /// Error when the run end index in a REE array is bigger than the array length
62    RunEndIndexOverflowError,
63    /// Error when the offset overflows.
64    OffsetOverflowError(usize),
65}
66
67impl ArrowError {
68    /// Wraps an external error in an `ArrowError`.
69    pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
70        Self::ExternalError(error)
71    }
72}
73
74impl From<std::io::Error> for ArrowError {
75    fn from(error: std::io::Error) -> Self {
76        ArrowError::IoError(error.to_string(), error)
77    }
78}
79
80impl From<std::str::Utf8Error> for ArrowError {
81    fn from(error: std::str::Utf8Error) -> Self {
82        ArrowError::ParseError(error.to_string())
83    }
84}
85
86impl From<std::string::FromUtf8Error> for ArrowError {
87    fn from(error: std::string::FromUtf8Error) -> Self {
88        ArrowError::ParseError(error.to_string())
89    }
90}
91
92impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError {
93    fn from(error: std::io::IntoInnerError<W>) -> Self {
94        ArrowError::IoError(error.to_string(), error.into())
95    }
96}
97
98impl Display for ArrowError {
99    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100        match self {
101            ArrowError::NotYetImplemented(source) => {
102                write!(f, "Not yet implemented: {}", &source)
103            }
104            ArrowError::ExternalError(source) => write!(f, "External error: {}", &source),
105            ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"),
106            ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"),
107            ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"),
108            ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"),
109            ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"),
110            ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"),
111            ArrowError::DivideByZero => write!(f, "Divide by zero error"),
112            ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"),
113            ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"),
114            ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"),
115            ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"),
116            ArrowError::InvalidArgumentError(desc) => {
117                write!(f, "Invalid argument error: {desc}")
118            }
119            ArrowError::ParquetError(desc) => {
120                write!(f, "Parquet argument error: {desc}")
121            }
122            ArrowError::CDataInterface(desc) => {
123                write!(f, "C Data interface error: {desc}")
124            }
125            ArrowError::DictionaryKeyOverflowError => {
126                write!(f, "Dictionary key bigger than the key type")
127            }
128            ArrowError::RunEndIndexOverflowError => {
129                write!(f, "Run end encoded array index overflow error")
130            }
131            ArrowError::OffsetOverflowError(offset) => {
132                write!(f, "Offset overflow error: {offset}")
133            }
134        }
135    }
136}
137
138impl Error for ArrowError {
139    fn source(&self) -> Option<&(dyn Error + 'static)> {
140        match self {
141            ArrowError::ExternalError(source) => Some(source.as_ref()),
142            ArrowError::IoError(_, source) => Some(source),
143            _ => None,
144        }
145    }
146}
147
148#[cfg(test)]
149mod test {
150    use super::*;
151
152    #[test]
153    fn error_source() {
154        let e1 = ArrowError::DivideByZero;
155        assert!(e1.source().is_none());
156
157        // one level of wrapping
158        let e2 = ArrowError::ExternalError(Box::new(e1));
159        let source = e2.source().unwrap().downcast_ref::<ArrowError>().unwrap();
160        assert!(matches!(source, ArrowError::DivideByZero));
161
162        // two levels of wrapping
163        let e3 = ArrowError::ExternalError(Box::new(e2));
164        let source = e3
165            .source()
166            .unwrap()
167            .downcast_ref::<ArrowError>()
168            .unwrap()
169            .source()
170            .unwrap()
171            .downcast_ref::<ArrowError>()
172            .unwrap();
173
174        assert!(matches!(source, ArrowError::DivideByZero));
175    }
176}