use {
failure::{Compat, Fail},
serde::de,
std::{
error,
fmt::{self, Display, Formatter},
io, result,
string::FromUtf8Error,
},
};
#[derive(Debug, Fail)]
pub enum DeserializationError {
#[fail(display = "custom error message: {}", message)]
Custom {
message: String,
},
#[fail(display = "failed to deserialize a value of type: {}", type_name)]
Failure {
type_name: String,
#[cause]
cause: Box<CompatDeserializationError>,
},
#[fail(display = "deserialization of an identifier is not supported")]
IdentifierNotSupported,
#[fail(display = "deserialized an invalid bool: {}", raw_value)]
InvalidBool {
raw_value: u32,
},
#[fail(display = "deserialized an invalid char: 0x{:X}", raw_value)]
InvalidChar {
raw_value: u32,
},
#[cfg(not(feature = "ignore-enum-variant-names"))]
#[fail(
display = "deserialized an invalid enum variant: variant index is {}, valid variants are {:?}",
variant, variants
)]
InvalidEnumVariant {
variant: u32,
variants: &'static [&'static str],
},
#[fail(
display = "deserialized invalid {}-bit signed integer: {}",
bits, value
)]
InvalidInteger {
bits: u8,
value: i32,
},
#[fail(display = "deserialized an invalid option")]
InvalidOption,
#[fail(display = "deserialized an invalid UTF-8 string")]
InvalidString {
cause: FromUtf8Error,
},
#[fail(
display = "deserialized invalid {}-bit unsigned integer: {}",
bits, value
)]
InvalidUnsignedInteger {
bits: u8,
value: u32,
},
#[fail(
display = "IO error while deserializing a value of type {}: {}",
type_name, cause
)]
IoError {
type_name: String,
#[cause]
cause: io::Error,
},
#[fail(display = "XDR does not support a map type")]
MapIsNotSupported,
#[fail(display = "tuple has too many elements: {}", length)]
TupleHasTooManyElements {
length: usize,
},
#[fail(display = "can't deserialize unknown type")]
UnknownType,
}
impl DeserializationError {
pub fn failure<S, E>(type_name: S, cause: E) -> Self
where
S: ToString,
E: Into<CompatDeserializationError>,
{
DeserializationError::Failure {
type_name: type_name.to_string(),
cause: Box::new(cause.into()),
}
}
pub fn io_error<S>(type_name: S, cause: io::Error) -> Self
where
S: ToString,
{
DeserializationError::IoError {
type_name: type_name.to_string(),
cause,
}
}
}
impl From<CompatDeserializationError> for DeserializationError {
fn from(wrapped_error: CompatDeserializationError) -> Self {
match wrapped_error {
CompatDeserializationError(error) => error.into_inner(),
}
}
}
#[derive(Debug)]
pub struct CompatDeserializationError(Compat<DeserializationError>);
impl From<DeserializationError> for CompatDeserializationError {
fn from(error: DeserializationError) -> Self {
CompatDeserializationError(error.compat())
}
}
impl Display for CompatDeserializationError {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl error::Error for CompatDeserializationError {
fn description(&self) -> &str {
self.0.description()
}
}
impl de::Error for CompatDeserializationError {
fn custom<T: Display>(message: T) -> Self {
let error = DeserializationError::Custom {
message: message.to_string(),
};
CompatDeserializationError(error.compat())
}
}
pub type Result<T> = result::Result<T, CompatDeserializationError>;