yabfi/
error.rs

1use std::{
2    error::Error,
3    fmt::{Debug, Display},
4};
5
6/// Represents a generic error when parsing and running brainfuck code.
7#[derive(Debug)]
8pub enum BfError<'a, IoErr: Error> {
9    /// Represents a syntax error when parsing brainfuck code, see [ParseError](crate::error::ParseError).
10    ParseError { inner: ParseError<'a> },
11    /// Represents a runtime error when running brainfuck code, see [RuntimeError](crate::error::RuntimeError).
12    RuntimeError { inner: RuntimeError<IoErr> },
13}
14
15impl<'a, IoErr: Error> Display for BfError<'a, IoErr> {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            Self::ParseError { inner } => Display::fmt(inner, f),
19            Self::RuntimeError { inner } => Display::fmt(inner, f),
20        }
21    }
22}
23
24impl<'a, IoError: Error> From<ParseError<'a>> for BfError<'a, IoError> {
25    fn from(inner: ParseError<'a>) -> Self {
26        BfError::ParseError { inner }
27    }
28}
29
30impl<'a, IoErr: Error> From<RuntimeError<IoErr>> for BfError<'a, IoErr> {
31    fn from(inner: RuntimeError<IoErr>) -> Self {
32        BfError::RuntimeError { inner }
33    }
34}
35
36/// Represents a syntax error when parsing brainfuck code.
37#[derive(Debug)]
38pub struct ParseError<'a> {
39    inner: nom::error::Error<&'a str>,
40}
41
42impl Display for ParseError<'_> {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        let input_str: String = self.inner.input.chars().take(50).collect();
45        let error_string = format!("ParseError[{:?}] at: {:?}", self.inner.code, input_str);
46        f.write_str(error_string.as_str())
47    }
48}
49
50impl Error for ParseError<'_> {}
51
52impl<'a> From<nom::error::Error<&'a str>> for ParseError<'a> {
53    fn from(inner: nom::error::Error<&'a str>) -> Self {
54        Self { inner }
55    }
56}
57
58/// Represents a runtime error when evaluating brainfuck code.
59#[derive(Debug)]
60pub enum RuntimeError<IoErr: Error> {
61    /// Returned if an error is encountered when reading or writing to a buffer.
62    IoErr { inner: IoErr },
63    /// Returned if pointer tries to go past [isize::MAX](std::isize::MAX)
64    PtrOverflow,
65    /// Returned if pointer tries to go past 0 into the negatives.
66    PtrUnderflow,
67}
68
69impl<IoErr: Error> Display for RuntimeError<IoErr> {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self {
72            Self::IoErr { inner } => {
73                f.write_str("RuntimeError[IoErr]: ")?;
74                Display::fmt(inner, f)
75            }
76            Self::PtrOverflow => f.write_str("RuntimeError[PtrOverflow]"),
77            Self::PtrUnderflow => f.write_str("RuntimeError[PtrUnderflow]"),
78        }
79    }
80}
81
82impl<IoErr: Error> Error for RuntimeError<IoErr> {}
83
84impl<IoErr: Error> From<IoErr> for RuntimeError<IoErr> {
85    fn from(inner: IoErr) -> Self {
86        Self::IoErr { inner }
87    }
88}