bfy/src/bf_interpreter/error.rs

127 lines
3.7 KiB
Rust

use std::fmt::{Debug, Display, Formatter};
#[derive(PartialEq)]
pub struct InterpreterError {
message: String,
pub code: i32,
}
impl InterpreterError {
pub fn new(message: String, code: i32) -> Self {
Self {
message: message.to_string(),
code,
}
}
}
impl Display for InterpreterError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl Debug for InterpreterError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}, code: {}", self.message, self.code)
}
}
impl std::error::Error for InterpreterError {
fn description(&self) -> &str {
&self.message
}
}
pub enum InterpreterErrorKind {
PointerOutOfBounds(usize), // takes pointer value
ValueOutOfBounds,
IoError(std::io::Error),
FlushError(std::io::Error),
UnmatchedBracket,
InvalidUtf8,
}
impl InterpreterErrorKind {
pub fn to_error(&self) -> InterpreterError {
InterpreterError::new(self.to_string(), self.code())
}
fn code(&self) -> i32 {
match self {
InterpreterErrorKind::PointerOutOfBounds(_) => 11,
InterpreterErrorKind::ValueOutOfBounds => 12,
InterpreterErrorKind::IoError(_) => 13,
InterpreterErrorKind::FlushError(_) => 14,
InterpreterErrorKind::UnmatchedBracket => 15,
InterpreterErrorKind::InvalidUtf8 => 16,
}
}
}
impl Display for InterpreterErrorKind {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
InterpreterErrorKind::PointerOutOfBounds(pointer) => {
write!(f, "Pointer out of bounds {}", pointer)
}
InterpreterErrorKind::ValueOutOfBounds => write!(f, "Value out of bounds"),
InterpreterErrorKind::IoError(error) => write!(
f,
"Failed to read byte from stdin: no bytes available: {}",
error
),
InterpreterErrorKind::FlushError(e) => write!(f, "Failed to flush stdout: {}", e),
InterpreterErrorKind::UnmatchedBracket => write!(f, "Unmatched bracket"),
InterpreterErrorKind::InvalidUtf8 => write!(f, "Invalid utf8"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq; // for testing only
#[test]
fn test_error_kind_display() {
let error = InterpreterErrorKind::PointerOutOfBounds(10).to_error();
assert_eq!(error.to_string(), "Pointer out of bounds 10");
assert_eq!(error.code, 11);
let error = InterpreterErrorKind::ValueOutOfBounds.to_error();
assert_eq!(error.to_string(), "Value out of bounds");
assert_eq!(error.code, 12);
let error =
InterpreterErrorKind::IoError(std::io::Error::new(std::io::ErrorKind::Other, "test"))
.to_error();
assert_eq!(
error.to_string(),
"Failed to read byte from stdin: no bytes available: test"
);
assert_eq!(error.code, 13);
let error = InterpreterErrorKind::UnmatchedBracket.to_error();
assert_eq!(error.to_string(), "Unmatched bracket");
assert_eq!(error.code, 15);
let error = InterpreterErrorKind::InvalidUtf8.to_error();
assert_eq!(error.to_string(), "Invalid utf8");
assert_eq!(error.code, 16);
}
#[test]
fn test_error_display() {
let error = InterpreterError::new("test".to_string(), 10);
assert_eq!(error.to_string(), "test");
assert_eq!(error.code, 10);
}
#[test]
fn test_error_debug() {
let error = InterpreterError::new("test".to_string(), 10);
assert_eq!(format!("{:?}", error), "test, code: 10");
}
}