|
| 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 Avro errors and macros. |
| 19 | +
|
| 20 | +use arrow_schema::ArrowError; |
| 21 | +use core::num::TryFromIntError; |
| 22 | +use std::error::Error; |
| 23 | +use std::string::FromUtf8Error; |
| 24 | +use std::{io, str}; |
| 25 | + |
| 26 | +/// Avro error enumeration |
| 27 | +
|
| 28 | +#[derive(Debug)] |
| 29 | +#[non_exhaustive] |
| 30 | +pub enum AvroError { |
| 31 | + /// General Avro error. |
| 32 | + /// Returned when code violates normal workflow of working with Avro data. |
| 33 | + General(String), |
| 34 | + /// "Not yet implemented" Avro error. |
| 35 | + /// Returned when functionality is not yet available. |
| 36 | + NYI(String), |
| 37 | + /// "End of file" Avro error. |
| 38 | + /// Returned when IO related failures occur, e.g. when there are not enough bytes to |
| 39 | + /// decode. |
| 40 | + EOF(String), |
| 41 | + /// Arrow error. |
| 42 | + /// Returned when reading into arrow or writing from arrow. |
| 43 | + ArrowError(Box<ArrowError>), |
| 44 | + /// Error when the requested index is more than the |
| 45 | + /// number of items expected |
| 46 | + IndexOutOfBound(usize, usize), |
| 47 | + /// Error indicating that an unexpected or bad argument was passed to a function. |
| 48 | + InvalidArgument(String), |
| 49 | + /// Error indicating that a value could not be parsed. |
| 50 | + ParseError(String), |
| 51 | + /// Error indicating that a schema is invalid. |
| 52 | + SchemaError(String), |
| 53 | + /// An external error variant |
| 54 | + External(Box<dyn Error + Send + Sync>), |
| 55 | + /// Error during IO operations |
| 56 | + IoError(String, io::Error), |
| 57 | + /// Returned when a function needs more data to complete properly. The `usize` field indicates |
| 58 | + /// the total number of bytes required, not the number of additional bytes. |
| 59 | + NeedMoreData(usize), |
| 60 | + /// Returned when a function needs more data to complete properly. |
| 61 | + /// The `Range<u64>` indicates the range of bytes that are needed. |
| 62 | + NeedMoreDataRange(std::ops::Range<u64>), |
| 63 | +} |
| 64 | + |
| 65 | +impl std::fmt::Display for AvroError { |
| 66 | + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { |
| 67 | + match &self { |
| 68 | + AvroError::General(message) => { |
| 69 | + write!(fmt, "Avro error: {message}") |
| 70 | + } |
| 71 | + AvroError::NYI(message) => write!(fmt, "NYI: {message}"), |
| 72 | + AvroError::EOF(message) => write!(fmt, "EOF: {message}"), |
| 73 | + AvroError::ArrowError(message) => write!(fmt, "Arrow: {message}"), |
| 74 | + AvroError::IndexOutOfBound(index, bound) => { |
| 75 | + write!(fmt, "Index {index} out of bound: {bound}") |
| 76 | + } |
| 77 | + AvroError::InvalidArgument(message) => { |
| 78 | + write!(fmt, "Invalid argument: {message}") |
| 79 | + } |
| 80 | + AvroError::ParseError(message) => write!(fmt, "Parser error: {message}"), |
| 81 | + AvroError::SchemaError(message) => write!(fmt, "Schema error: {message}"), |
| 82 | + AvroError::External(e) => write!(fmt, "External: {e}"), |
| 83 | + AvroError::IoError(message, e) => write!(fmt, "I/O Error: {message}: {e}"), |
| 84 | + AvroError::NeedMoreData(needed) => write!(fmt, "NeedMoreData: {needed}"), |
| 85 | + AvroError::NeedMoreDataRange(range) => { |
| 86 | + write!(fmt, "NeedMoreDataRange: {}..{}", range.start, range.end) |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +impl Error for AvroError { |
| 93 | + fn source(&self) -> Option<&(dyn Error + 'static)> { |
| 94 | + match self { |
| 95 | + AvroError::External(e) => Some(e.as_ref()), |
| 96 | + AvroError::ArrowError(e) => Some(e.as_ref()), |
| 97 | + AvroError::IoError(_, e) => Some(e), |
| 98 | + _ => None, |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +impl From<TryFromIntError> for AvroError { |
| 104 | + fn from(e: TryFromIntError) -> AvroError { |
| 105 | + AvroError::General(format!("Integer overflow: {e}")) |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +impl From<io::Error> for AvroError { |
| 110 | + fn from(e: io::Error) -> AvroError { |
| 111 | + AvroError::External(Box::new(e)) |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +impl From<str::Utf8Error> for AvroError { |
| 116 | + fn from(e: str::Utf8Error) -> AvroError { |
| 117 | + AvroError::External(Box::new(e)) |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +impl From<FromUtf8Error> for AvroError { |
| 122 | + fn from(e: FromUtf8Error) -> AvroError { |
| 123 | + AvroError::External(Box::new(e)) |
| 124 | + } |
| 125 | +} |
| 126 | + |
| 127 | +impl From<ArrowError> for AvroError { |
| 128 | + fn from(e: ArrowError) -> Self { |
| 129 | + AvroError::ArrowError(Box::new(e)) |
| 130 | + } |
| 131 | +} |
| 132 | + |
| 133 | +impl From<AvroError> for io::Error { |
| 134 | + fn from(e: AvroError) -> Self { |
| 135 | + io::Error::other(e) |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +impl From<AvroError> for ArrowError { |
| 140 | + fn from(e: AvroError) -> Self { |
| 141 | + match e { |
| 142 | + AvroError::External(inner) => ArrowError::from_external_error(inner), |
| 143 | + AvroError::IoError(msg, err) => ArrowError::IoError(msg, err), |
| 144 | + AvroError::ArrowError(inner) => *inner, |
| 145 | + other => ArrowError::AvroError(other.to_string()), |
| 146 | + } |
| 147 | + } |
| 148 | +} |
0 commit comments