Coverage Report

Created: 2025-11-17 14:14

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 Avro-related operations.
50
    AvroError(String),
51
    /// Error during IO operations.
52
    IoError(String, std::io::Error),
53
    /// Error during IPC operations in `arrow-ipc` or `arrow-flight`.
54
    IpcError(String),
55
    /// Error indicating that an unexpected or bad argument was passed to a function.
56
    InvalidArgumentError(String),
57
    /// Error during Parquet operations.
58
    ParquetError(String),
59
    /// Error during import or export to/from the C Data Interface
60
    CDataInterface(String),
61
    /// Error when a dictionary key is bigger than the key type
62
    DictionaryKeyOverflowError,
63
    /// Error when the run end index in a REE array is bigger than the array length
64
    RunEndIndexOverflowError,
65
    /// Error when the offset overflows.
66
    OffsetOverflowError(usize),
67
}
68
69
impl ArrowError {
70
    /// Wraps an external error in an `ArrowError`.
71
0
    pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
72
0
        Self::ExternalError(error)
73
0
    }
74
}
75
76
impl From<std::io::Error> for ArrowError {
77
0
    fn from(error: std::io::Error) -> Self {
78
0
        ArrowError::IoError(error.to_string(), error)
79
0
    }
80
}
81
82
impl From<std::str::Utf8Error> for ArrowError {
83
0
    fn from(error: std::str::Utf8Error) -> Self {
84
0
        ArrowError::ParseError(error.to_string())
85
0
    }
86
}
87
88
impl From<std::string::FromUtf8Error> for ArrowError {
89
0
    fn from(error: std::string::FromUtf8Error) -> Self {
90
0
        ArrowError::ParseError(error.to_string())
91
0
    }
92
}
93
94
impl<W: Write> From<std::io::IntoInnerError<W>> for ArrowError {
95
0
    fn from(error: std::io::IntoInnerError<W>) -> Self {
96
0
        ArrowError::IoError(error.to_string(), error.into())
97
0
    }
98
}
99
100
impl Display for ArrowError {
101
10
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102
10
        match self {
103
0
            ArrowError::NotYetImplemented(source) => {
104
0
                write!(f, "Not yet implemented: {}", &source)
105
            }
106
0
            ArrowError::ExternalError(source) => write!(f, "External error: {}", &source),
107
0
            ArrowError::CastError(desc) => write!(f, "Cast error: {desc}"),
108
0
            ArrowError::MemoryError(desc) => write!(f, "Memory error: {desc}"),
109
0
            ArrowError::ParseError(desc) => write!(f, "Parser error: {desc}"),
110
0
            ArrowError::SchemaError(desc) => write!(f, "Schema error: {desc}"),
111
1
            ArrowError::ComputeError(desc) => write!(f, "Compute error: {desc}"),
112
0
            ArrowError::ArithmeticOverflow(desc) => write!(f, "Arithmetic overflow: {desc}"),
113
0
            ArrowError::DivideByZero => write!(f, "Divide by zero error"),
114
0
            ArrowError::AvroError(desc) => write!(f, "Avro error: {desc}"),
115
0
            ArrowError::CsvError(desc) => write!(f, "Csv error: {desc}"),
116
0
            ArrowError::JsonError(desc) => write!(f, "Json error: {desc}"),
117
0
            ArrowError::IoError(desc, _) => write!(f, "Io error: {desc}"),
118
0
            ArrowError::IpcError(desc) => write!(f, "Ipc error: {desc}"),
119
9
            ArrowError::InvalidArgumentError(desc) => {
120
9
                write!(f, "Invalid argument error: {desc}")
121
            }
122
0
            ArrowError::ParquetError(desc) => {
123
0
                write!(f, "Parquet argument error: {desc}")
124
            }
125
0
            ArrowError::CDataInterface(desc) => {
126
0
                write!(f, "C Data interface error: {desc}")
127
            }
128
            ArrowError::DictionaryKeyOverflowError => {
129
0
                write!(f, "Dictionary key bigger than the key type")
130
            }
131
            ArrowError::RunEndIndexOverflowError => {
132
0
                write!(f, "Run end encoded array index overflow error")
133
            }
134
0
            ArrowError::OffsetOverflowError(offset) => {
135
0
                write!(f, "Offset overflow error: {offset}")
136
            }
137
        }
138
10
    }
139
}
140
141
impl Error for ArrowError {
142
0
    fn source(&self) -> Option<&(dyn Error + 'static)> {
143
0
        match self {
144
0
            ArrowError::ExternalError(source) => Some(source.as_ref()),
145
0
            ArrowError::IoError(_, source) => Some(source),
146
0
            _ => None,
147
        }
148
0
    }
149
}
150
151
#[cfg(test)]
152
mod test {
153
    use super::*;
154
155
    #[test]
156
    fn error_source() {
157
        let e1 = ArrowError::DivideByZero;
158
        assert!(e1.source().is_none());
159
160
        // one level of wrapping
161
        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
        // two levels of wrapping
166
        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
}