parquet/
errors.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//! Common Parquet errors and macros.
19
20use std::error::Error;
21use std::{cell, io, result, str};
22
23#[cfg(feature = "arrow")]
24use arrow_schema::ArrowError;
25
26/// Parquet error enumeration
27// Note: we don't implement PartialEq as the semantics for the
28// external variant are not well defined (#4469)
29#[derive(Debug)]
30pub enum ParquetError {
31    /// General Parquet error.
32    /// Returned when code violates normal workflow of working with Parquet files.
33    General(String),
34    /// "Not yet implemented" Parquet error.
35    /// Returned when functionality is not yet available.
36    NYI(String),
37    /// "End of file" Parquet error.
38    /// Returned when IO related failures occur, e.g. when there are not enough bytes to
39    /// decode.
40    EOF(String),
41    #[cfg(feature = "arrow")]
42    /// Arrow error.
43    /// Returned when reading into arrow or writing from arrow.
44    ArrowError(String),
45    /// Error when the requested column index is more than the
46    /// number of columns in the row group
47    IndexOutOfBound(usize, usize),
48    /// An external error variant
49    External(Box<dyn Error + Send + Sync>),
50}
51
52impl std::fmt::Display for ParquetError {
53    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
54        match &self {
55            ParquetError::General(message) => {
56                write!(fmt, "Parquet error: {message}")
57            }
58            ParquetError::NYI(message) => write!(fmt, "NYI: {message}"),
59            ParquetError::EOF(message) => write!(fmt, "EOF: {message}"),
60            #[cfg(feature = "arrow")]
61            ParquetError::ArrowError(message) => write!(fmt, "Arrow: {message}"),
62            ParquetError::IndexOutOfBound(index, ref bound) => {
63                write!(fmt, "Index {index} out of bound: {bound}")
64            }
65            ParquetError::External(e) => write!(fmt, "External: {e}"),
66        }
67    }
68}
69
70impl Error for ParquetError {
71    fn source(&self) -> Option<&(dyn Error + 'static)> {
72        match self {
73            ParquetError::External(e) => Some(e.as_ref()),
74            _ => None,
75        }
76    }
77}
78
79impl From<io::Error> for ParquetError {
80    fn from(e: io::Error) -> ParquetError {
81        ParquetError::External(Box::new(e))
82    }
83}
84
85#[cfg(any(feature = "snap", test))]
86impl From<snap::Error> for ParquetError {
87    fn from(e: snap::Error) -> ParquetError {
88        ParquetError::External(Box::new(e))
89    }
90}
91
92impl From<thrift::Error> for ParquetError {
93    fn from(e: thrift::Error) -> ParquetError {
94        ParquetError::External(Box::new(e))
95    }
96}
97
98impl From<cell::BorrowMutError> for ParquetError {
99    fn from(e: cell::BorrowMutError) -> ParquetError {
100        ParquetError::External(Box::new(e))
101    }
102}
103
104impl From<str::Utf8Error> for ParquetError {
105    fn from(e: str::Utf8Error) -> ParquetError {
106        ParquetError::External(Box::new(e))
107    }
108}
109#[cfg(feature = "arrow")]
110impl From<ArrowError> for ParquetError {
111    fn from(e: ArrowError) -> ParquetError {
112        ParquetError::External(Box::new(e))
113    }
114}
115
116#[cfg(feature = "object_store")]
117impl From<object_store::Error> for ParquetError {
118    fn from(e: object_store::Error) -> ParquetError {
119        ParquetError::External(Box::new(e))
120    }
121}
122
123/// A specialized `Result` for Parquet errors.
124pub type Result<T, E = ParquetError> = result::Result<T, E>;
125
126// ----------------------------------------------------------------------
127// Conversion from `ParquetError` to other types of `Error`s
128
129impl From<ParquetError> for io::Error {
130    fn from(e: ParquetError) -> Self {
131        io::Error::new(io::ErrorKind::Other, e)
132    }
133}
134
135// ----------------------------------------------------------------------
136// Convenient macros for different errors
137
138macro_rules! general_err {
139    ($fmt:expr) => (ParquetError::General($fmt.to_owned()));
140    ($fmt:expr, $($args:expr),*) => (ParquetError::General(format!($fmt, $($args),*)));
141    ($e:expr, $fmt:expr) => (ParquetError::General($fmt.to_owned(), $e));
142    ($e:ident, $fmt:expr, $($args:tt),*) => (
143        ParquetError::General(&format!($fmt, $($args),*), $e));
144}
145
146macro_rules! nyi_err {
147    ($fmt:expr) => (ParquetError::NYI($fmt.to_owned()));
148    ($fmt:expr, $($args:expr),*) => (ParquetError::NYI(format!($fmt, $($args),*)));
149}
150
151macro_rules! eof_err {
152    ($fmt:expr) => (ParquetError::EOF($fmt.to_owned()));
153    ($fmt:expr, $($args:expr),*) => (ParquetError::EOF(format!($fmt, $($args),*)));
154}
155
156#[cfg(feature = "arrow")]
157macro_rules! arrow_err {
158    ($fmt:expr) => (ParquetError::ArrowError($fmt.to_owned()));
159    ($fmt:expr, $($args:expr),*) => (ParquetError::ArrowError(format!($fmt, $($args),*)));
160    ($e:expr, $fmt:expr) => (ParquetError::ArrowError($fmt.to_owned(), $e));
161    ($e:ident, $fmt:expr, $($args:tt),*) => (
162        ParquetError::ArrowError(&format!($fmt, $($args),*), $e));
163}
164
165// ----------------------------------------------------------------------
166// Convert parquet error into other errors
167
168#[cfg(feature = "arrow")]
169impl From<ParquetError> for ArrowError {
170    fn from(p: ParquetError) -> Self {
171        Self::ParquetError(format!("{p}"))
172    }
173}