use std::error;
use std::fmt;
use std::io;
use std::string;
pub type Result<T> = ::std::result::Result<T, Error>;
#[derive(Debug)]
pub enum ErrorKind {
Io(io::Error),
StringDecoding(string::FromUtf8Error),
InvalidInput,
}
pub struct Error {
pub kind: ErrorKind,
pub description: &'static str,
}
impl Error {
pub fn new(kind: ErrorKind, description: &'static str) -> Error {
Error { kind, description }
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self.kind {
ErrorKind::Io(ref err) => Some(err),
ErrorKind::StringDecoding(ref err) => Some(err),
_ => None,
}
}
#[allow(deprecated)]
fn description(&self) -> &str {
if self.source().is_some() {
self.source().unwrap().description()
} else {
match self.kind {
ErrorKind::Io(ref err) => error::Error::description(err),
ErrorKind::StringDecoding(ref err) => err.description(),
_ => self.description,
}
}
}
fn cause(&self) -> Option<&dyn error::Error> {
error::Error::source(self)
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error {
kind: ErrorKind::Io(err),
description: "",
}
}
}
impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Error {
Error {
kind: ErrorKind::StringDecoding(err),
description: "",
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
if !self.description.is_empty() {
write!(out, "{:?}: {}", self.kind, self.description)
} else if let Some(source) = error::Error::source(self) {
write!(out, "{}", source)
} else {
write!(out, "{:?}", self.kind)
}
}
}
impl fmt::Display for Error {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
if !self.description.is_empty() {
write!(out, "{:?}: {}", self.kind, self.description)
} else if let Some(source) = error::Error::source(self) {
write!(out, "{}", source)
} else {
write!(out, "{:?}", self.kind)
}
}
}