| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| //! Defines `ArrowError` for representing failures in various Arrow operations. |
| use std::fmt::{Debug, Display, Formatter}; |
| use std::io::Write; |
| |
| use std::error::Error; |
| |
| /// Many different operations in the `arrow` crate return this error type. |
| #[derive(Debug)] |
| pub enum ArrowError { |
| /// Returned when functionality is not yet available. |
| NotYetImplemented(String), |
| /// Wraps an external error. |
| ExternalError(Box<dyn Error + Send + Sync>), |
| /// Error during casting from one type to another. |
| CastError(String), |
| /// Memory or buffer error. |
| MemoryError(String), |
| /// Error during parsing from a string. |
| ParseError(String), |
| /// Error during schema-related operations. |
| SchemaError(String), |
| /// Error during computation. |
| ComputeError(String), |
| /// Error during division by zero. |
| DivideByZero, |
| /// Error when an arithmetic operation overflows. |
| ArithmeticOverflow(String), |
| /// Error during CSV-related operations. |
| CsvError(String), |
| /// Error during JSON-related operations. |
| JsonError(String), |
| /// Error during IO operations. |
| IoError(String, std::io::Error), |
| /// Error during IPC operations in `arrow-ipc` or `arrow-flight`. |
| IpcError(String), |
| /// Error indicating that an unexpected or bad argument was passed to a function. |
| InvalidArgumentError(String), |
| /// Error during Parquet operations. |
| ParquetError(String), |
| /// Error during import or export to/from the C Data Interface |
| CDataInterface(String), |
| /// Error when a dictionary key is bigger than the key type |
| DictionaryKeyOverflowError, |
| /// Error when the run end index in a REE array is bigger than the array length |
| RunEndIndexOverflowError, |
| /// Error when the offset overflows. |
| OffsetOverflowError(usize), |
| } |
| |
| impl ArrowError { |
| /// Wraps an external error in an `ArrowError`. |
| pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self { |
| Self::ExternalError(error) |
| } |
| } |
| |
| impl From<std::io::Error> for ArrowError { |
| fn from(error: std::io::Error) -> Self { |
| ArrowError::IoError(error.to_string(), error) |
| } |
| } |
| |
| impl From<std::str::Utf8Error> for ArrowError { |
| fn from(error: std::str::Utf8Error) -> Self { |
| ArrowError::ParseError(error.to_string()) |
| } |
| } |
| |
| impl From<std::string::FromUtf8Error> for ArrowError { |
| fn from(error: std::string::FromUtf8Error) -> Self { |
| ArrowError::ParseError(error.to_string()) |
| } |
| } |
| |
| impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError { |
| fn from(error: std::io::IntoInnerError<W>) -> Self { |
| ArrowError::IoError(error.to_string(), error.into()) |
| } |
| } |
| |
| impl Display for ArrowError { |
| fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
| match self { |
| ArrowError::NotYetImplemented(source) => { |
| write!(f, "Not yet implemented: {}", &source) |
| } |
| ArrowError::ExternalError(source) => write!(f, "External error: {}", &source), |
| ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"), |
| ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"), |
| ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"), |
| ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"), |
| ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"), |
| ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"), |
| ArrowError::DivideByZero => write!(f, "Divide by zero error"), |
| ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"), |
| ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"), |
| ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"), |
| ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"), |
| ArrowError::InvalidArgumentError(desc) => { |
| write!(f, "Invalid argument error: {desc}") |
| } |
| ArrowError::ParquetError(desc) => { |
| write!(f, "Parquet argument error: {desc}") |
| } |
| ArrowError::CDataInterface(desc) => { |
| write!(f, "C Data interface error: {desc}") |
| } |
| ArrowError::DictionaryKeyOverflowError => { |
| write!(f, "Dictionary key bigger than the key type") |
| } |
| ArrowError::RunEndIndexOverflowError => { |
| write!(f, "Run end encoded array index overflow error") |
| } |
| ArrowError::OffsetOverflowError(offset) => { |
| write!(f, "Offset overflow error: {offset}") |
| } |
| } |
| } |
| } |
| |
| impl Error for ArrowError { |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| match self { |
| ArrowError::ExternalError(source) => Some(source.as_ref()), |
| ArrowError::IoError(_, source) => Some(source), |
| _ => None, |
| } |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| |
| #[test] |
| fn error_source() { |
| let e1 = ArrowError::DivideByZero; |
| assert!(e1.source().is_none()); |
| |
| // one level of wrapping |
| let e2 = ArrowError::ExternalError(Box::new(e1)); |
| let source = e2.source().unwrap().downcast_ref::<ArrowError>().unwrap(); |
| assert!(matches!(source, ArrowError::DivideByZero)); |
| |
| // two levels of wrapping |
| let e3 = ArrowError::ExternalError(Box::new(e2)); |
| let source = e3 |
| .source() |
| .unwrap() |
| .downcast_ref::<ArrowError>() |
| .unwrap() |
| .source() |
| .unwrap() |
| .downcast_ref::<ArrowError>() |
| .unwrap(); |
| |
| assert!(matches!(source, ArrowError::DivideByZero)); |
| } |
| } |