Coverage Report

Created: 2025-08-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-schema/src/error.rs
Line
Count
Source
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.
19
use std::fmt::{Debug, Display, Formatter};
20
use std::io::Write;
21
22
use std::error::Error;
23
24
/// Many different operations in the `arrow` crate return this error type.
25
#[derive(Debug)]
26
pub 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
67
impl ArrowError {
68
    /// Wraps an external error in an `ArrowError`.
69
0
    pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
70
0
        Self::ExternalError(error)
71
0
    }
72
}
73
74
impl From<std::io::Error> for ArrowError {
75
0
    fn from(error: std::io::Error) -> Self {
76
0
        ArrowError::IoError(error.to_string(), error)
77
0
    }
78
}
79
80
impl From<std::str::Utf8Error> for ArrowError {
81
0
    fn from(error: std::str::Utf8Error) -> Self {
82
0
        ArrowError::ParseError(error.to_string())
83
0
    }
84
}
85
86
impl From<std::string::FromUtf8Error> for ArrowError {
87
0
    fn from(error: std::string::FromUtf8Error) -> Self {
88
0
        ArrowError::ParseError(error.to_string())
89
0
    }
90
}
91
92
impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError {
93
0
    fn from(error: std::io::IntoInnerError<W>) -> Self {
94
0
        ArrowError::IoError(error.to_string(), error.into())
95
0
    }
96
}
97
98
impl Display for ArrowError {
99
8
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100
8
        match self {
101
1
            ArrowError::NotYetImplemented(source) => {
102
1
                write!(f, "Not yet implemented: {}", &source)
103
            }
104
0
            ArrowError::ExternalError(source) => write!(f, "External error: {}", &source),
105
0
            ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"),
106
0
            ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"),
107
5
            ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"),
108
2
            ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"),
109
0
            ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"),
110
0
            ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"),
111
0
            ArrowError::DivideByZero => write!(f, "Divide by zero error"),
112
0
            ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"),
113
0
            ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"),
114
0
            ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"),
115
0
            ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"),
116
0
            ArrowError::InvalidArgumentError(desc) => {
117
0
                write!(f, "Invalid argument error: {desc}")
118
            }
119
0
            ArrowError::ParquetError(desc) => {
120
0
                write!(f, "Parquet argument error: {desc}")
121
            }
122
0
            ArrowError::CDataInterface(desc) => {
123
0
                write!(f, "C Data interface error: {desc}")
124
            }
125
            ArrowError::DictionaryKeyOverflowError => {
126
0
                write!(f, "Dictionary key bigger than the key type")
127
            }
128
            ArrowError::RunEndIndexOverflowError => {
129
0
                write!(f, "Run end encoded array index overflow error")
130
            }
131
0
            ArrowError::OffsetOverflowError(offset) => {
132
0
                write!(f, "Offset overflow error: {offset}")
133
            }
134
        }
135
8
    }
136
}
137
138
impl Error for ArrowError {
139
0
    fn source(&self) -> Option<&(dyn Error + 'static)> {
140
0
        match self {
141
0
            ArrowError::ExternalError(source) => Some(source.as_ref()),
142
0
            ArrowError::IoError(_, source) => Some(source),
143
0
            _ => None,
144
        }
145
0
    }
146
}
147
148
#[cfg(test)]
149
mod 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
}