use std::{
error::Error,
fmt::{Debug, Display},
};
#[derive(Debug)]
pub enum BfError<'a, IoErr: Error> {
ParseError { inner: ParseError<'a> },
RuntimeError { inner: RuntimeError<IoErr> },
}
impl<'a, IoErr: Error> Display for BfError<'a, IoErr> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ParseError { inner } => Display::fmt(inner, f),
Self::RuntimeError { inner } => Display::fmt(inner, f),
}
}
}
impl<'a, IoError: Error> From<ParseError<'a>> for BfError<'a, IoError> {
fn from(inner: ParseError<'a>) -> Self {
BfError::ParseError { inner }
}
}
impl<'a, IoErr: Error> From<RuntimeError<IoErr>> for BfError<'a, IoErr> {
fn from(inner: RuntimeError<IoErr>) -> Self {
BfError::RuntimeError { inner }
}
}
#[derive(Debug)]
pub struct ParseError<'a> {
inner: nom::error::Error<&'a str>,
}
impl Display for ParseError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let input_str: String = self.inner.input.chars().take(50).collect();
let error_string = format!("ParseError[{:?}] at: {:?}", self.inner.code, input_str);
f.write_str(error_string.as_str())
}
}
impl Error for ParseError<'_> {}
impl<'a> From<nom::error::Error<&'a str>> for ParseError<'a> {
fn from(inner: nom::error::Error<&'a str>) -> Self {
Self { inner }
}
}
#[derive(Debug)]
pub enum RuntimeError<IoErr: Error> {
IoErr { inner: IoErr },
PtrOverflow,
PtrUnderflow,
}
impl<IoErr: Error> Display for RuntimeError<IoErr> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::IoErr { inner } => {
f.write_str("RuntimeError[IoErr]: ")?;
Display::fmt(inner, f)
}
Self::PtrOverflow => f.write_str("RuntimeError[PtrOverflow]"),
Self::PtrUnderflow => f.write_str("RuntimeError[PtrUnderflow]"),
}
}
}
impl<IoErr: Error> Error for RuntimeError<IoErr> {}
impl<IoErr: Error> From<IoErr> for RuntimeError<IoErr> {
fn from(inner: IoErr) -> Self {
Self::IoErr { inner }
}
}