use rune::ContextError;
use rune::Module;
use rune::alloc::fmt::TryWrite;
use rune::runtime::Formatter;
use rune::vm_write;
use std::fmt::Display;
pub type KResult<T, E = KError> = Result<T, E>;
#[derive(Debug, rune::Any)]
#[rune(item = ::error)]
pub struct KError {
inner: Option<eyre::Error>,
}
impl KError {
pub(crate) fn inner(&self) -> &eyre::Error {
self.inner.as_ref().expect("Must be initialised")
}
pub(crate) fn take_inner(&mut self) -> eyre::Error {
std::mem::take(&mut self.inner).expect("Must be initialised")
}
}
impl Display for KError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.inner {
Some(inner) => Display::fmt(inner, f),
None => Display::fmt(&eyre::eyre!("<ALREADY TAKEN>"), f),
}
}
}
impl From<eyre::Error> for KError {
fn from(inner: eyre::Error) -> Self {
Self { inner: Some(inner) }
}
}
impl From<std::io::Error> for KError {
fn from(inner: std::io::Error) -> Self {
Self {
inner: Some(eyre::Error::from(inner)),
}
}
}
impl From<std::fmt::Error> for KError {
fn from(inner: std::fmt::Error) -> Self {
Self {
inner: Some(eyre::Error::from(inner)),
}
}
}
impl From<KError> for eyre::Error {
fn from(error: KError) -> Self {
error.inner.expect("Must be initialised")
}
}
impl KError {
#[rune::function(vm_result, protocol = STRING_DEBUG)]
fn string_debug(&self, f: &mut Formatter) {
vm_write!(f, "{:?}", self);
}
#[rune::function(vm_result, protocol = STRING_DISPLAY)]
fn string_display(&self, f: &mut Formatter) {
vm_write!(f, "{}", self);
}
}
#[rune::module(::error)]
pub(crate) fn module() -> Result<Module, ContextError> {
let mut m = Module::from_meta(module_meta)?;
m.ty::<KError>()?;
m.function_meta(KError::string_debug)?;
m.function_meta(KError::string_display)?;
Ok(m)
}