use crate::io::FileError;
use crate::visitor::Visitor;
use base64::DecodeError;
use std::num::{ParseFloatError, ParseIntError};
use std::{
error::Error,
fmt::{Display, Formatter},
string::FromUtf8Error,
};
#[derive(Debug)]
pub enum VisitError {
Multiple(Vec<VisitError>),
Io(std::io::Error),
UnknownFieldType(u8),
FieldDoesNotExist(String),
FieldAlreadyExists(String),
RegionAlreadyExists(String),
InvalidCurrentNode,
FieldTypeDoesNotMatch {
expected: &'static str,
actual: String,
},
RegionDoesNotExist(String),
NoActiveNode,
NotSupportedFormat,
InvalidName,
TypeMismatch {
expected: &'static str,
actual: &'static str,
},
RefCellAlreadyMutableBorrowed,
User(String),
UnexpectedRcNullIndex,
PoisonedMutex,
FileLoadError(FileError),
ParseIntError(ParseIntError),
ParseFloatError(ParseFloatError),
DecodeError(DecodeError),
UuidError(uuid::Error),
Any(Box<dyn Error + Send + Sync>),
}
impl Error for VisitError {}
impl VisitError {
pub fn field_does_not_exist(name: &str, visitor: &Visitor) -> Self {
Self::FieldDoesNotExist(visitor.breadcrumbs() + " > " + name)
}
pub fn multiple(self, other: Self) -> Self {
match (self, other) {
(Self::Multiple(mut a), Self::Multiple(mut b)) => {
a.append(&mut b);
Self::Multiple(a)
}
(Self::Multiple(mut a), b) => {
a.push(b);
Self::Multiple(a)
}
(a, Self::Multiple(mut b)) => {
b.push(a);
Self::Multiple(b)
}
(a, b) => Self::Multiple(vec![a, b]),
}
}
}
impl Display for VisitError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
Self::Multiple(errs) => {
write!(f, "multiple errors:[")?;
for err in errs {
write!(f, "{err};")?;
}
write!(f, "]")
}
Self::Io(io) => write!(f, "io error: {io}"),
Self::UnknownFieldType(type_index) => write!(f, "unknown field type {type_index}"),
Self::FieldDoesNotExist(name) => write!(f, "field does not exist: {name}"),
Self::FieldAlreadyExists(name) => write!(f, "field already exists {name}"),
Self::RegionAlreadyExists(name) => write!(f, "region already exists {name}"),
Self::InvalidCurrentNode => write!(f, "invalid current node"),
Self::FieldTypeDoesNotMatch { expected, actual } => write!(
f,
"field type does not match. expected: {expected}, actual: {actual}"
),
Self::RegionDoesNotExist(name) => write!(f, "region does not exist: {name}"),
Self::NoActiveNode => write!(f, "no active node"),
Self::NotSupportedFormat => write!(f, "not supported format"),
Self::InvalidName => write!(f, "invalid name"),
Self::TypeMismatch { expected, actual } => {
write!(f, "type mismatch. expected: {expected}, actual: {actual}")
}
Self::RefCellAlreadyMutableBorrowed => write!(f, "ref cell already mutable borrowed"),
Self::User(msg) => write!(f, "user defined error: {msg}"),
Self::UnexpectedRcNullIndex => write!(f, "unexpected rc null index"),
Self::PoisonedMutex => write!(f, "attempt to lock poisoned mutex"),
Self::FileLoadError(e) => write!(f, "file load error: {e:?}"),
Self::ParseIntError(e) => write!(f, "unable to parse integer: {e:?}"),
Self::ParseFloatError(e) => write!(f, "unable to parse float: {e:?}"),
Self::DecodeError(e) => write!(f, "base64 decoding error: {e:?}"),
Self::UuidError(e) => write!(f, "uuid error: {e:?}"),
Self::Any(e) => {
write!(f, "{e}")
}
}
}
}
impl<T> From<std::sync::PoisonError<std::sync::MutexGuard<'_, T>>> for VisitError {
fn from(_: std::sync::PoisonError<std::sync::MutexGuard<'_, T>>) -> Self {
Self::PoisonedMutex
}
}
impl<T> From<std::sync::PoisonError<&mut T>> for VisitError {
fn from(_: std::sync::PoisonError<&mut T>) -> Self {
Self::PoisonedMutex
}
}
impl<T> From<std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>> for VisitError {
fn from(_: std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>) -> Self {
Self::PoisonedMutex
}
}
impl From<std::io::Error> for VisitError {
fn from(io_err: std::io::Error) -> Self {
Self::Io(io_err)
}
}
impl From<FromUtf8Error> for VisitError {
fn from(_: FromUtf8Error) -> Self {
Self::InvalidName
}
}
impl From<String> for VisitError {
fn from(s: String) -> Self {
Self::User(s)
}
}
impl From<FileError> for VisitError {
fn from(e: FileError) -> Self {
Self::FileLoadError(e)
}
}
impl From<ParseIntError> for VisitError {
fn from(value: ParseIntError) -> Self {
Self::ParseIntError(value)
}
}
impl From<ParseFloatError> for VisitError {
fn from(value: ParseFloatError) -> Self {
Self::ParseFloatError(value)
}
}
impl From<DecodeError> for VisitError {
fn from(value: DecodeError) -> Self {
Self::DecodeError(value)
}
}
impl From<uuid::Error> for VisitError {
fn from(value: uuid::Error) -> Self {
Self::UuidError(value)
}
}
impl From<Box<dyn Error + Send + Sync>> for VisitError {
fn from(value: Box<dyn Error + Send + Sync>) -> Self {
Self::Any(value)
}
}