use crate::base::InternalIndex;
use std::fmt;
#[derive(Debug, PartialEq, Eq)]
pub enum ErrorKind {
UnknownRank(String),
ImportError { line: usize, msg: String },
InvalidTaxonomy(String),
NoSuchTaxId(String),
NoSuchInternalIndex(InternalIndex),
OperationNotAllowed(String),
}
#[derive(Debug)]
pub struct Error {
pub(crate) kind: ErrorKind,
source: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl Error {
pub fn new(kind: ErrorKind) -> Self {
Self { kind, source: None }
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
ErrorKind::NoSuchTaxId(s) => write!(f, "Tax ID {} not found in taxonomy", s),
ErrorKind::NoSuchInternalIndex(s) => write!(f, "Index {} not found in taxonomy", s),
ErrorKind::UnknownRank(r) => write!(f, "Rank {} is unknown", r),
ErrorKind::ImportError { line, msg } => {
write!(f, "Failed to import taxonomy {} at line {}", msg, line)
}
ErrorKind::InvalidTaxonomy(s) => write!(f, "Invalid taxonomy: {}", s),
ErrorKind::OperationNotAllowed(s) => {
write!(f, "Operation on taxonomy not allowed: {}", s)
}
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source.as_ref().map(|e| e.as_ref() as _)
}
}
impl From<serde_json::error::Error> for Error {
fn from(error: serde_json::error::Error) -> Self {
let mut err = Error::new(ErrorKind::ImportError {
line: error.line(),
msg: error.to_string(),
});
err.source = Some(Box::new(error));
err
}
}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
let mut err = Error::new(ErrorKind::ImportError {
line: 0,
msg: "Failed to read data".to_owned(),
});
err.source = Some(Box::new(error));
err
}
}
impl From<quick_xml::Error> for Error {
fn from(error: quick_xml::Error) -> Self {
let mut err = Error::new(ErrorKind::ImportError {
line: 0,
msg: "Error parsing XML".to_owned(),
});
err.source = Some(Box::new(error));
err
}
}
pub type TaxonomyResult<T> = Result<T, Error>;