use crate::tag::Tag;
use std::error;
use std::fmt;
use std::io;
use std::string;
pub type Result<T> = std::result::Result<T, Error>;
pub fn partial_tag_ok(rs: Result<Tag>) -> Result<Tag> {
match rs {
Ok(tag) => Ok(tag),
Err(Error {
partial_tag: Some(tag),
..
}) => Ok(tag),
Err(err) => Err(err),
}
}
pub fn no_tag_ok(rs: Result<Tag>) -> Result<Option<Tag>> {
match rs {
Ok(tag) => Ok(Some(tag)),
Err(Error {
kind: ErrorKind::NoTag,
..
}) => Ok(None),
Err(err) => Err(err),
}
}
#[derive(Debug)]
pub enum ErrorKind {
Io(io::Error),
StringDecoding(Vec<u8>),
NoTag,
Parsing,
InvalidInput,
UnsupportedFeature,
}
pub struct Error {
pub kind: ErrorKind,
pub description: String,
pub partial_tag: Option<Tag>,
}
impl Error {
pub fn new(kind: ErrorKind, description: impl Into<String>) -> Error {
Error {
kind,
description: description.into(),
partial_tag: None,
}
}
pub(crate) fn with_tag(self, tag: Tag) -> Error {
Error {
partial_tag: Some(tag),
..self
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self.kind {
ErrorKind::Io(ref err) => Some(err),
_ => None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error {
kind: ErrorKind::Io(err),
description: "".to_string(),
partial_tag: None,
}
}
}
impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Error {
Error {
kind: ErrorKind::StringDecoding(err.into_bytes()),
description: "data is not valid utf-8".to_string(),
partial_tag: None,
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.description.is_empty() {
true => write!(f, "{:?}", self.kind),
false => write!(f, "{:?}: {}", self.kind, self.description),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.description.is_empty() {
true => write!(f, "{}", self.kind),
false => write!(f, "{}: {}", self.kind, self.description),
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ErrorKind::Io(io_error) => write!(f, "IO: {}", io_error),
ErrorKind::StringDecoding(_) => write!(f, "StringDecoding"),
ErrorKind::NoTag => write!(f, "NoTag"),
ErrorKind::Parsing => write!(f, "Parsing"),
ErrorKind::InvalidInput => write!(f, "InvalidInput"),
ErrorKind::UnsupportedFeature => write!(f, "UnsupportedFeature"),
}
}
}