Skip to main content

rstm_core/
error.rs

1/*
2    Appellation: error <module>
3    Contrib: @FL03
4*/
5//! this module defines the [`Error`] type alongisde other useful primitives that are used
6//! throughout the rules crate.
7#[cfg(feature = "alloc")]
8use alloc::{boxed::Box, string::String};
9
10/// A type alias for a [`Result`](core::result::Result) with a custom error type ([Error])
11pub type Result<T = ()> = core::result::Result<T, Error>;
12
13/// [`Error`] enumerates the various errors encountered when dealing with rules and their
14/// components.
15#[derive(Debug, thiserror::Error)]
16#[non_exhaustive]
17pub enum Error {
18    // custom errors
19    #[error("Unable to index into the given structure.")]
20    IndexError,
21    #[error("No inputs were provided for the program.")]
22    TapeIsEmpty,
23    #[error("The runtime exited without halting")]
24    ExitWithoutHalting,
25    #[error("Unable to find anything to read from the current position of the head.")]
26    NothingToRead,
27    #[error("No program or ruleset has been loaded into the actor.")]
28    NoProgram,
29    #[error("No rule found associated with the current state and symbol.")]
30    NoRuleFound,
31    #[error("The index ({idx}) is out of bounds for a tape of length {len}")]
32    IndexOutOfBounds { idx: usize, len: usize },
33    #[error("Attempted to perform an operation in a halted state.")]
34    Halted,
35    #[error("Unable to parse a rule from the given information.")]
36    ParseRuleError,
37    #[error("An invalid direction was specified.")]
38    InvalidDirection,
39    #[error("Unable to downcast {0:?} into type {1:?}.")]
40    DowncastFailure(core::any::TypeId, core::any::TypeId),
41    #[error("No symbol found at position {0}")]
42    NoSymbolFoundAt(usize),
43    // internal errors
44    #[error(transparent)]
45    StateError(#[from] rstm_state::StateError),
46    // external errors
47    #[error(transparent)]
48    AnyError(#[from] anyhow::Error),
49    #[cfg(feature = "serde")]
50    #[error(transparent)]
51    DeserializeError(#[from] serde::de::value::Error),
52    #[cfg(feature = "json")]
53    #[error(transparent)]
54    JsonError(#[from] serde_json::Error),
55    // Core Errors
56    #[error(transparent)]
57    FmtError(#[from] core::fmt::Error),
58    #[error(transparent)]
59    NetworkAddressParseError(#[from] core::net::AddrParseError),
60    #[error(transparent)]
61    Utf8Error(#[from] core::str::Utf8Error),
62    // alloc-dependendent errors
63    #[cfg(feature = "alloc")]
64    #[error(transparent)]
65    BoxError(#[from] Box<dyn core::error::Error + Send + Sync>),
66    #[cfg(feature = "alloc")]
67    #[error("An unknown error occurred: {0}")]
68    Unknown(String),
69    // std-dependend errors
70    #[cfg(feature = "std")]
71    #[error(transparent)]
72    IOError(#[from] std::io::Error),
73}
74
75impl Error {
76    /// a functional constructor for the [`IndexOutOfBounds`](Error::IndexOutOfBounds) variant
77    pub const fn index_out_of_bounds(idx: usize, len: usize) -> Self {
78        Self::IndexOutOfBounds { idx, len }
79    }
80    #[cfg(feature = "alloc")]
81    /// a utility function facilitating the creation of the [`BoxError`](Error::BoxError)
82    /// variant
83    pub fn box_error<E>(e: E) -> Self
84    where
85        E: 'static + core::error::Error + Send + Sync,
86    {
87        Self::BoxError(Box::new(e))
88    }
89}
90
91#[cfg(feature = "alloc")]
92impl From<&str> for Error {
93    fn from(s: &str) -> Self {
94        Self::Unknown(String::from(s))
95    }
96}
97
98#[cfg(feature = "alloc")]
99impl From<String> for Error {
100    fn from(s: String) -> Self {
101        Self::Unknown(s)
102    }
103}
104
105#[derive(
106    Clone,
107    Copy,
108    Debug,
109    Default,
110    Eq,
111    Hash,
112    PartialEq,
113    PartialOrd,
114    strum::AsRefStr,
115    strum::EnumCount,
116    strum::EnumIs,
117    strum::EnumString,
118    strum::VariantNames,
119)]
120#[cfg_attr(
121    feature = "serde",
122    derive(serde::Deserialize, serde::Serialize),
123    serde(rename_all = "snake_case")
124)]
125#[strum(serialize_all = "snake_case")]
126pub enum ErrorKind {
127    Empty,
128    IOError,
129    IndexError,
130    ExitWithoutHalting,
131    NothingToRead,
132    NoProgram,
133    NoRuleFound,
134    IndexOutOfBounds,
135    Halted,
136    ParseRuleError,
137    InvalidDirection,
138    DowncastFailure,
139    NoSymbolFoundAt,
140    StateError,
141    AnyError,
142    DeserializeError,
143    JsonError,
144    FmtError,
145    NetworkAddressParseError,
146    Utf8Error,
147    #[default]
148    Unknown,
149}
150
151#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
152pub struct ErrorBase<E> {
153    pub kind: ErrorKind,
154    pub error: E,
155}