use std::{error::Error, fmt::Display};
use crate::{IndexError, KeyError, ModuleResolveError, SliceError, ValueError, data::DataSourceError, SelectorError};
pub type RuntimeResult<T> = Result<T, RuntimeError>;
#[derive(Debug)]
pub struct RuntimeError {
pub error_type: RuntimeErrorType,
pub description: Option<String>,
pub stack_trace: Option<String>,
}
impl Error for RuntimeError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.error_type {
RuntimeErrorType::IndexError(err) => Some(err),
RuntimeErrorType::KeyError(err) => Some(err),
RuntimeErrorType::ValueError(err) => Some(err),
_ => None,
}
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
impl Display for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}] ", self.error_type.id())?;
if let Some(desc) =& self.description {
write!(f, "{}", desc)?;
} else {
write!(f, "{}", self.error_type)?;
}
Ok(())
}
}
#[derive(Debug)]
pub enum RuntimeErrorType {
StackOverflow,
StackUnderflow,
InvalidAccess,
InvalidOperation,
InternalError,
ArgumentMismatch,
ArgumentError,
CannotInvokeValue,
AssertError,
TypeError,
ValueError(ValueError),
IndexError(IndexError),
KeyError(KeyError),
SliceError(SliceError),
SelectorError(SelectorError),
ModuleError(ModuleResolveError),
UserError,
ControlFlowError,
DataSourceError(DataSourceError),
}
impl RuntimeErrorType {
pub fn id(&self) -> &'static str {
match self {
Self::StackOverflow => "STACK_OVERFLOW_ERROR",
Self::StackUnderflow => "STACK_UNDERFLOW_ERROR",
Self::InvalidAccess => "INVALID_ACCESS_ERROR",
Self::InvalidOperation => "INVALID_OP_ERROR",
Self::InternalError => "INTERNAL_ERROR",
Self::ArgumentMismatch => "ARG_MISMATCH_ERROR",
Self::ArgumentError => "ARG_ERROR",
Self::CannotInvokeValue => "INVOKE_ERROR",
Self::UserError => "USER_ERROR",
Self::AssertError => "ASSERT_ERROR",
Self::TypeError => "TYPE_ERROR",
Self::ValueError(_) => "VALUE_ERROR",
Self::IndexError(_) => "INDEX_ERROR",
Self::KeyError(_) => "KEY_ERROR",
Self::SliceError(_) => "SLICE_ERROR",
Self::SelectorError(_) => "SELECTOR_ERROR",
Self::ModuleError(_) => "MODULE_ERROR",
Self::ControlFlowError => "CONTROL_FLOW_ERROR",
Self::DataSourceError(_) => "DATA_SOURCE_ERROR",
}
}
}
impl Display for RuntimeErrorType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ValueError(e) => write!(f, "{}", e),
Self::IndexError(e) => write!(f, "{}", e),
Self::KeyError(e) => write!(f, "{}", e),
Self::SliceError(e) => write!(f, "{}", e),
Self::SelectorError(e) => write!(f, "{}", e),
Self::ModuleError(e) => write!(f, "{}", e),
Self::DataSourceError(e) => write!(f, "{}", e),
_ => write!(f, "{}", self.id()),
}
}
}
pub(crate) trait IntoRuntimeResult<T> {
fn into_runtime_result(self) -> RuntimeResult<T>;
}