use arrow_schema::ArrowError;
use core::num::TryFromIntError;
use std::error::Error;
use std::string::FromUtf8Error;
use std::{io, str};
#[derive(Debug)]
#[non_exhaustive]
pub enum AvroError {
General(String),
NYI(String),
EOF(String),
ArrowError(Box<ArrowError>),
IndexOutOfBound(usize, usize),
InvalidArgument(String),
ParseError(String),
SchemaError(String),
External(Box<dyn Error + Send + Sync>),
IoError(String, io::Error),
NeedMoreData(usize),
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()),
}
}
}