Skip to main content

boytacean_common/
error.rs

1//! Error related data structures to be shared and used.
2//!
3//! This module contains the [`Error`] enum, which is used to represent
4//! errors that can occur within Boytacean domain.
5
6use std::{
7    backtrace::Backtrace,
8    error,
9    fmt::{self, Display, Formatter},
10    io,
11    string::FromUtf8Error,
12};
13
14/// Top level enum for error handling within Boytacean.
15///
16/// Most of the time, you will want to use the `CustomError` variant
17/// to provide a more detailed error message.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum Error {
20    InvalidData,
21    InvalidKey,
22    RomSize,
23    IncompatibleBootRom,
24    NotImplemented,
25    MissingOption(String),
26    IoError(String),
27    DataError(String),
28    InvalidParameter(String),
29    CustomError(String),
30}
31
32impl Error {
33    pub fn description(&self) -> String {
34        match self {
35            Error::InvalidData => String::from("Invalid data format"),
36            Error::InvalidKey => String::from("Invalid key"),
37            Error::RomSize => String::from("Invalid ROM size"),
38            Error::IncompatibleBootRom => String::from("Incompatible boot ROM"),
39            Error::NotImplemented => String::from("Not implemented"),
40            Error::MissingOption(option) => format!("Missing option: {option}"),
41            Error::IoError(message) => format!("IO error: {message}"),
42            Error::DataError(message) => format!("Data error: {message}"),
43            Error::InvalidParameter(message) => format!("Invalid parameter: {message}"),
44            Error::CustomError(message) => String::from(message),
45        }
46    }
47}
48
49impl error::Error for Error {
50    fn description(&self) -> &str {
51        match self {
52            Error::InvalidData => "Invalid data format",
53            Error::InvalidKey => "Invalid key",
54            Error::RomSize => "Invalid ROM size",
55            Error::IncompatibleBootRom => "Incompatible boot ROM",
56            Error::NotImplemented => "Not implemented",
57            Error::MissingOption(_) => "Missing option",
58            Error::IoError(_) => "IO error",
59            Error::DataError(_) => "Data error",
60            Error::InvalidParameter(_) => "Invalid parameter",
61            Error::CustomError(_) => "Custom error",
62        }
63    }
64
65    fn cause(&self) -> Option<&dyn error::Error> {
66        None
67    }
68
69    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
70        None
71    }
72}
73
74impl Display for Error {
75    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
76        write!(f, "{}", self.description())
77    }
78}
79
80impl From<io::Error> for Error {
81    fn from(error: io::Error) -> Self {
82        Error::IoError(error.to_string())
83    }
84}
85
86impl From<FromUtf8Error> for Error {
87    fn from(_error: FromUtf8Error) -> Self {
88        Error::CustomError(String::from("From UTF8 error"))
89    }
90}
91
92impl From<Error> for String {
93    fn from(error: Error) -> Self {
94        error.description()
95    }
96}
97
98#[derive(Debug)]
99pub struct TraceError {
100    error: Error,
101    backtrace: Backtrace,
102}
103
104impl TraceError {
105    pub fn new(error: Error) -> Self {
106        Self {
107            error,
108            backtrace: Backtrace::capture(),
109        }
110    }
111
112    pub fn backtrace(&self) -> Option<&Backtrace> {
113        Some(&self.backtrace)
114    }
115}
116
117impl Display for TraceError {
118    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
119        write!(f, "{}", self.error.description())
120    }
121}