tau_engine/
error.rs

1use std::error::Error as StdError;
2use std::fmt;
3
4/// A `Result` alias where `Err` case is `tau_engine::Error`.
5pub type Result<T> = std::result::Result<T, Error>;
6
7/// The errors that may occur when using the Tau Engine.
8pub struct Error {
9    inner: Box<Inner>,
10}
11
12pub(crate) type Source = Box<dyn StdError + Send + Sync>;
13
14struct Inner {
15    kind: Kind,
16    source: Option<Source>,
17}
18
19impl Error {
20    pub(crate) fn new(kind: Kind) -> Error {
21        Error {
22            inner: Box::new(Inner { kind, source: None }),
23        }
24    }
25
26    pub(crate) fn with<S: Into<Source>>(mut self, source: S) -> Error {
27        self.inner.source = Some(source.into());
28        self
29    }
30
31    /// Returns the kind of this error.
32    pub fn kind(&self) -> &Kind {
33        &self.inner.kind
34    }
35}
36
37impl fmt::Debug for Error {
38    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
39        let mut builder = fmt.debug_struct("tau_engine::Error");
40        builder.field("kind", &self.inner.kind);
41        if let Some(ref source) = self.inner.source {
42            builder.field("source", source);
43        }
44        builder.finish()
45    }
46}
47
48impl fmt::Display for Error {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        let desc = match self.inner.kind {
51            Kind::Parse(Parse::InvalidIdentifier) => {
52                "an invalid identifier was encountered during parsing"
53            }
54            Kind::Parse(Parse::InvalidExpression) => {
55                "an invalid expression was provided to the parser"
56            }
57            Kind::Parse(Parse::InvalidToken) => "an invalid token was encountered during parsing",
58            Kind::Parse(Parse::LedFollowing) => {
59                "an invalid expression was encountered following the LED during parsing"
60            }
61            Kind::Parse(Parse::LedPreceding) => {
62                "an invalid expression was encountered preceding the LED during parsing"
63            }
64            Kind::Rule => "an invalid rule was provided",
65            Kind::Token(Token::InvalidCharacter) => {
66                "an invalid character was encountered during tokenisation"
67            }
68            Kind::Token(Token::InvalidNumber) => {
69                "an invalid number was encountered during tokenisation"
70            }
71            Kind::Validation => "failed to validate rule",
72        };
73        if let Some(ref source) = self.inner.source {
74            write!(f, "{}: {}", desc, source)
75        } else {
76            f.write_str(desc)
77        }
78    }
79}
80
81impl StdError for Error {
82    fn source(&self) -> Option<&(dyn StdError + 'static)> {
83        self.inner.source.as_ref().map(|e| &**e as _)
84    }
85}
86
87/// The `Kind` of `tau_engine::Error`.
88#[derive(Debug)]
89pub enum Kind {
90    /// Parsing Errors
91    Parse(Parse),
92    /// Invalid rule
93    Rule,
94    /// Tokenising Errors
95    Token(Token),
96    /// Failed to validate the rule
97    Validation,
98}
99
100/// The `Kind` of `tau_engine::Error` when parsing.
101#[derive(Debug)]
102pub enum Parse {
103    /// An invalid expression was provided
104    InvalidExpression,
105    /// An invalid identifier was encountered
106    InvalidIdentifier,
107    /// An invalid token was encountered
108    InvalidToken,
109    /// An invalid following expression was encountered
110    LedFollowing,
111    /// An invalid preceding expression was encountered
112    LedPreceding,
113}
114
115/// The `Kind` of `tau_engine::Error` when tokenising.
116#[derive(Debug)]
117pub enum Token {
118    /// An invalid character was encountered
119    InvalidCharacter,
120    /// An invalid number was encountered
121    InvalidNumber,
122}
123
124// Helpers
125#[inline]
126pub(crate) fn parse_invalid_expr<E: Into<Source>>(e: E) -> Error {
127    Error::new(Kind::Parse(Parse::InvalidExpression)).with(e)
128}
129
130#[inline]
131pub(crate) fn parse_invalid_ident<E: Into<Source>>(e: E) -> Error {
132    Error::new(Kind::Parse(Parse::InvalidIdentifier)).with(e)
133}
134
135#[inline]
136pub(crate) fn parse_invalid_token<E: Into<Source>>(e: E) -> Error {
137    Error::new(Kind::Parse(Parse::InvalidToken)).with(e)
138}
139
140#[inline]
141pub(crate) fn parse_led_following<E: Into<Source>>(e: E) -> Error {
142    Error::new(Kind::Parse(Parse::LedFollowing)).with(e)
143}
144
145#[inline]
146pub(crate) fn parse_led_preceding<E: Into<Source>>(e: E) -> Error {
147    Error::new(Kind::Parse(Parse::LedPreceding)).with(e)
148}
149
150#[inline]
151pub(crate) fn rule_invalid<E: Into<Source>>(e: E) -> Error {
152    Error::new(Kind::Rule).with(e)
153}
154
155#[inline]
156pub(crate) fn token_invalid_char<E: Into<Source>>(e: E) -> Error {
157    Error::new(Kind::Token(Token::InvalidCharacter)).with(e)
158}
159
160#[inline]
161pub(crate) fn token_invalid_num<E: Into<Source>>(e: E) -> Error {
162    Error::new(Kind::Token(Token::InvalidNumber)).with(e)
163}