1use std::error::Error as StdError;
2use std::fmt;
3
4pub type Result<T> = std::result::Result<T, Error>;
6
7pub 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 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#[derive(Debug)]
89pub enum Kind {
90 Parse(Parse),
92 Rule,
94 Token(Token),
96 Validation,
98}
99
100#[derive(Debug)]
102pub enum Parse {
103 InvalidExpression,
105 InvalidIdentifier,
107 InvalidToken,
109 LedFollowing,
111 LedPreceding,
113}
114
115#[derive(Debug)]
117pub enum Token {
118 InvalidCharacter,
120 InvalidNumber,
122}
123
124#[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}