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.
1718//! Common Parquet errors and macros.
1920use std::error::Error;
21use std::{cell, io, result, str};
2223#[cfg(feature = "arrow")]
24use arrow_schema::ArrowError;
2526/// 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.
33General(String),
34/// "Not yet implemented" Parquet error.
35 /// Returned when functionality is not yet available.
36NYI(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.
40EOF(String),
41#[cfg(feature = "arrow")]
42/// Arrow error.
43 /// Returned when reading into arrow or writing from arrow.
44ArrowError(String),
45/// Error when the requested column index is more than the
46 /// number of columns in the row group
47IndexOutOfBound(usize, usize),
48/// An external error variant
49External(Box<dyn Error + Send + Sync>),
50}
5152impl std::fmt::Display for ParquetError {
53fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
54match &self {
55 ParquetError::General(message) => {
56write!(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")]
61ParquetError::ArrowError(message) => write!(fmt, "Arrow: {message}"),
62 ParquetError::IndexOutOfBound(index, ref bound) => {
63write!(fmt, "Index {index} out of bound: {bound}")
64 }
65 ParquetError::External(e) => write!(fmt, "External: {e}"),
66 }
67 }
68}
6970impl Error for ParquetError {
71fn source(&self) -> Option<&(dyn Error + 'static)> {
72match self {
73 ParquetError::External(e) => Some(e.as_ref()),
74_ => None,
75 }
76 }
77}
7879impl From<io::Error> for ParquetError {
80fn from(e: io::Error) -> ParquetError {
81 ParquetError::External(Box::new(e))
82 }
83}
8485#[cfg(any(feature = "snap", test))]
86impl From<snap::Error> for ParquetError {
87fn from(e: snap::Error) -> ParquetError {
88 ParquetError::External(Box::new(e))
89 }
90}
9192impl From<thrift::Error> for ParquetError {
93fn from(e: thrift::Error) -> ParquetError {
94 ParquetError::External(Box::new(e))
95 }
96}
9798impl From<cell::BorrowMutError> for ParquetError {
99fn from(e: cell::BorrowMutError) -> ParquetError {
100 ParquetError::External(Box::new(e))
101 }
102}
103104impl From<str::Utf8Error> for ParquetError {
105fn from(e: str::Utf8Error) -> ParquetError {
106 ParquetError::External(Box::new(e))
107 }
108}
109#[cfg(feature = "arrow")]
110impl From<ArrowError> for ParquetError {
111fn from(e: ArrowError) -> ParquetError {
112 ParquetError::External(Box::new(e))
113 }
114}
115116#[cfg(feature = "object_store")]
117impl From<object_store::Error> for ParquetError {
118fn from(e: object_store::Error) -> ParquetError {
119 ParquetError::External(Box::new(e))
120 }
121}
122123/// A specialized `Result` for Parquet errors.
124pub type Result<T, E = ParquetError> = result::Result<T, E>;
125126// ----------------------------------------------------------------------
127// Conversion from `ParquetError` to other types of `Error`s
128129impl From<ParquetError> for io::Error {
130fn from(e: ParquetError) -> Self {
131 io::Error::new(io::ErrorKind::Other, e)
132 }
133}
134135// ----------------------------------------------------------------------
136// Convenient macros for different errors
137138macro_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}
145146macro_rules! nyi_err {
147 ($fmt:expr) => (ParquetError::NYI($fmt.to_owned()));
148 ($fmt:expr, $($args:expr),*) => (ParquetError::NYI(format!($fmt, $($args),*)));
149}
150151macro_rules! eof_err {
152 ($fmt:expr) => (ParquetError::EOF($fmt.to_owned()));
153 ($fmt:expr, $($args:expr),*) => (ParquetError::EOF(format!($fmt, $($args),*)));
154}
155156#[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}
164165// ----------------------------------------------------------------------
166// Convert parquet error into other errors
167168#[cfg(feature = "arrow")]
169impl From<ParquetError> for ArrowError {
170fn from(p: ParquetError) -> Self {
171Self::ParquetError(format!("{p}"))
172 }
173}