126 lines
3.7 KiB
Rust
126 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");
|
|
}
|
|
}
|