use core::fmt::{Debug, Display};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum InternalError {
OperandStack(&'static str),
FrameStack(&'static str),
ResultShape(&'static str),
GcMetadata(&'static str),
Compiler(&'static str),
}
impl Display for InternalError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let (area, detail) = match self {
InternalError::OperandStack(detail) => ("operand stack", detail),
InternalError::FrameStack(detail) => ("frame stack", detail),
InternalError::ResultShape(detail) => ("result shape", detail),
InternalError::GcMetadata(detail) => ("GC metadata", detail),
InternalError::Compiler(detail) => ("compiler", detail),
};
write!(f, "internal {area} invariant violated: {detail}")
}
}
impl std::error::Error for InternalError {}
pub struct Error(anyhow::Error);
pub type Result<T, E = Error> = core::result::Result<T, E>;
impl Error {
pub fn new<E>(error: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Error(anyhow::Error::new(error))
}
pub fn msg<M>(message: M) -> Self
where
M: Display + Debug + Send + Sync + 'static,
{
Error(anyhow::Error::msg(message))
}
#[must_use]
pub fn context<C>(self, context: C) -> Self
where
C: Display + Send + Sync + 'static,
{
Error(self.0.context(context))
}
pub fn downcast<E>(self) -> Result<E, Self>
where
E: Display + Debug + Send + Sync + 'static,
{
self.0.downcast::<E>().map_err(Error)
}
#[must_use]
pub fn is<E>(&self) -> bool
where
E: Display + Debug + Send + Sync + 'static,
{
self.0.is::<E>()
}
#[must_use]
pub fn downcast_ref<E>(&self) -> Option<&E>
where
E: Display + Debug + Send + Sync + 'static,
{
self.0.downcast_ref::<E>()
}
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
where
E: Display + Debug + Send + Sync + 'static,
{
self.0.downcast_mut::<E>()
}
#[must_use]
pub fn root_cause(&self) -> &(dyn std::error::Error + 'static) {
self.0.root_cause()
}
}
impl Debug for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<E> From<E> for Error
where
E: std::error::Error + Send + Sync + 'static,
{
fn from(error: E) -> Self {
Error(anyhow::Error::new(error))
}
}
impl From<Error> for anyhow::Error {
fn from(error: Error) -> Self {
error.0
}
}
#[macro_export]
macro_rules! format_err {
($($arg:tt)*) => { $crate::Error::msg(::std::format!($($arg)*)) };
}
#[macro_export]
macro_rules! bail {
($($arg:tt)*) => {
return ::core::result::Result::Err($crate::format_err!($($arg)*))
};
}
#[macro_export]
macro_rules! ensure {
($cond:expr $(,)?) => {
if !($cond) {
$crate::bail!(::core::concat!("condition failed: ", ::core::stringify!($cond)));
}
};
($cond:expr, $($arg:tt)*) => {
if !($cond) {
$crate::bail!($($arg)*);
}
};
}