| // 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. |
| |
| //! Common Avro errors and macros. |
| |
| use arrow_schema::ArrowError; |
| use core::num::TryFromIntError; |
| use std::error::Error; |
| use std::string::FromUtf8Error; |
| use std::{io, str}; |
| |
| /// Avro error enumeration |
| |
| #[derive(Debug)] |
| #[non_exhaustive] |
| pub enum AvroError { |
| /// General Avro error. |
| /// Returned when code violates normal workflow of working with Avro data. |
| General(String), |
| /// "Not yet implemented" Avro error. |
| /// Returned when functionality is not yet available. |
| NYI(String), |
| /// "End of file" Avro error. |
| /// Returned when IO related failures occur, e.g. when there are not enough bytes to |
| /// decode. |
| EOF(String), |
| /// Arrow error. |
| /// Returned when reading into arrow or writing from arrow. |
| ArrowError(Box<ArrowError>), |
| /// Error when the requested index is more than the |
| /// number of items expected |
| IndexOutOfBound(usize, usize), |
| /// Error indicating that an unexpected or bad argument was passed to a function. |
| InvalidArgument(String), |
| /// Error indicating that a value could not be parsed. |
| ParseError(String), |
| /// Error indicating that a schema is invalid. |
| SchemaError(String), |
| /// An external error variant |
| External(Box<dyn Error + Send + Sync>), |
| /// Error during IO operations |
| IoError(String, io::Error), |
| /// Returned when a function needs more data to complete properly. The `usize` field indicates |
| /// the total number of bytes required, not the number of additional bytes. |
| NeedMoreData(usize), |
| /// Returned when a function needs more data to complete properly. |
| /// The `Range<u64>` indicates the range of bytes that are needed. |
| NeedMoreDataRange(std::ops::Range<u64>), |
| } |
| |
| impl std::fmt::Display for AvroError { |
| fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { |
| match &self { |
| AvroError::General(message) => { |
| write!(fmt, "Avro error: {message}") |
| } |
| AvroError::NYI(message) => write!(fmt, "NYI: {message}"), |
| AvroError::EOF(message) => write!(fmt, "EOF: {message}"), |
| AvroError::ArrowError(message) => write!(fmt, "Arrow: {message}"), |
| AvroError::IndexOutOfBound(index, bound) => { |
| write!(fmt, "Index {index} out of bound: {bound}") |
| } |
| AvroError::InvalidArgument(message) => { |
| write!(fmt, "Invalid argument: {message}") |
| } |
| AvroError::ParseError(message) => write!(fmt, "Parser error: {message}"), |
| AvroError::SchemaError(message) => write!(fmt, "Schema error: {message}"), |
| AvroError::External(e) => write!(fmt, "External: {e}"), |
| AvroError::IoError(message, e) => write!(fmt, "I/O Error: {message}: {e}"), |
| AvroError::NeedMoreData(needed) => write!(fmt, "NeedMoreData: {needed}"), |
| AvroError::NeedMoreDataRange(range) => { |
| write!(fmt, "NeedMoreDataRange: {}..{}", range.start, range.end) |
| } |
| } |
| } |
| } |
| |
| impl Error for AvroError { |
| fn source(&self) -> Option<&(dyn Error + 'static)> { |
| match self { |
| AvroError::External(e) => Some(e.as_ref()), |
| AvroError::ArrowError(e) => Some(e.as_ref()), |
| AvroError::IoError(_, e) => Some(e), |
| _ => None, |
| } |
| } |
| } |
| |
| impl From<TryFromIntError> for AvroError { |
| fn from(e: TryFromIntError) -> AvroError { |
| AvroError::General(format!("Integer overflow: {e}")) |
| } |
| } |
| |
| impl From<io::Error> for AvroError { |
| fn from(e: io::Error) -> AvroError { |
| AvroError::External(Box::new(e)) |
| } |
| } |
| |
| impl From<str::Utf8Error> for AvroError { |
| fn from(e: str::Utf8Error) -> AvroError { |
| AvroError::External(Box::new(e)) |
| } |
| } |
| |
| impl From<FromUtf8Error> for AvroError { |
| fn from(e: FromUtf8Error) -> AvroError { |
| AvroError::External(Box::new(e)) |
| } |
| } |
| |
| impl From<ArrowError> for AvroError { |
| fn from(e: ArrowError) -> Self { |
| AvroError::ArrowError(Box::new(e)) |
| } |
| } |
| |
| impl From<AvroError> for io::Error { |
| fn from(e: AvroError) -> Self { |
| io::Error::other(e) |
| } |
| } |
| |
| impl From<AvroError> for ArrowError { |
| fn from(e: AvroError) -> Self { |
| match e { |
| AvroError::External(inner) => ArrowError::from_external_error(inner), |
| AvroError::IoError(msg, err) => ArrowError::IoError(msg, err), |
| AvroError::ArrowError(inner) => *inner, |
| other => ArrowError::AvroError(other.to_string()), |
| } |
| } |
| } |