Skip to main content

asn1rs_model/model/
err.rs

1use std::error;
2use std::fmt::{Debug, Display, Formatter};
3
4use backtrace::Backtrace;
5
6use crate::parser::Token;
7
8#[derive(PartialOrd, PartialEq, Eq)]
9pub enum ErrorKind {
10    ExpectedText(Token),
11    ExpectedTextGot(String, Token),
12    ExpectedSeparator(Token),
13    ExpectedSeparatorGot(char, Token),
14    UnexpectedToken(Token),
15    MissingModuleName,
16    UnexpectedEndOfStream,
17    InvalidRangeValue(Token),
18    InvalidNumberForEnumVariant(Token),
19    InvalidValueForConstant(Token),
20    InvalidTag(Token),
21    InvalidPositionForExtensionMarker(Token),
22    InvalidIntText(Token),
23    UnsupportedLiteral(Token),
24    InvalidLiteral(Token),
25}
26
27pub struct Error {
28    kind: ErrorKind,
29    backtrace: Backtrace,
30}
31
32impl From<ErrorKind> for Error {
33    fn from(kind: ErrorKind) -> Self {
34        Error {
35            kind,
36            backtrace: Backtrace::new(),
37        }
38    }
39}
40
41impl PartialEq for Error {
42    fn eq(&self, other: &Self) -> bool {
43        self.kind.eq(&other.kind)
44    }
45}
46
47impl Error {
48    pub fn invalid_int_value(token: Token) -> Self {
49        ErrorKind::InvalidIntText(token).into()
50    }
51
52    pub fn invalid_position_for_extension_marker(token: Token) -> Self {
53        ErrorKind::InvalidPositionForExtensionMarker(token).into()
54    }
55
56    pub fn invalid_tag(token: Token) -> Self {
57        ErrorKind::InvalidTag(token).into()
58    }
59
60    pub fn invalid_value_for_constant(token: Token) -> Self {
61        ErrorKind::InvalidValueForConstant(token).into()
62    }
63
64    pub fn invalid_number_for_enum_variant(token: Token) -> Self {
65        ErrorKind::InvalidNumberForEnumVariant(token).into()
66    }
67
68    pub fn invalid_range_value(token: Token) -> Self {
69        ErrorKind::InvalidRangeValue(token).into()
70    }
71
72    pub fn no_text(token: Token) -> Self {
73        ErrorKind::ExpectedText(token).into()
74    }
75
76    pub fn expected_text(text: String, token: Token) -> Self {
77        ErrorKind::ExpectedTextGot(text, token).into()
78    }
79
80    pub fn no_separator(token: Token) -> Self {
81        ErrorKind::ExpectedSeparator(token).into()
82    }
83
84    pub fn expected_separator(separator: char, token: Token) -> Self {
85        ErrorKind::ExpectedSeparatorGot(separator, token).into()
86    }
87
88    pub fn missing_module_name() -> Self {
89        ErrorKind::MissingModuleName.into()
90    }
91
92    pub fn unexpected_token(token: Token) -> Self {
93        ErrorKind::UnexpectedToken(token).into()
94    }
95
96    pub fn unexpected_end_of_stream() -> Self {
97        ErrorKind::UnexpectedEndOfStream.into()
98    }
99
100    pub fn unsupported_value_reference_literal(token: Token) -> Self {
101        ErrorKind::UnsupportedLiteral(token).into()
102    }
103
104    fn backtrace(&self) -> &Backtrace {
105        &self.backtrace
106    }
107
108    pub fn token(&self) -> Option<&Token> {
109        match &self.kind {
110            ErrorKind::ExpectedText(t) => Some(t),
111            ErrorKind::ExpectedTextGot(_, t) => Some(t),
112            ErrorKind::ExpectedSeparator(t) => Some(t),
113            ErrorKind::ExpectedSeparatorGot(_, t) => Some(t),
114            ErrorKind::UnexpectedToken(t) => Some(t),
115            ErrorKind::MissingModuleName => None,
116            ErrorKind::UnexpectedEndOfStream => None,
117            ErrorKind::InvalidRangeValue(t) => Some(t),
118            ErrorKind::InvalidNumberForEnumVariant(t) => Some(t),
119            ErrorKind::InvalidValueForConstant(t) => Some(t),
120            ErrorKind::InvalidTag(t) => Some(t),
121            ErrorKind::InvalidPositionForExtensionMarker(t) => Some(t),
122            ErrorKind::InvalidIntText(t) => Some(t),
123            ErrorKind::UnsupportedLiteral(t) => Some(t),
124            ErrorKind::InvalidLiteral(t) => Some(t),
125        }
126    }
127}
128
129impl error::Error for Error {}
130
131impl Debug for Error {
132    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
133        writeln!(f, "{}", self)?;
134        writeln!(f, "{:?}", self.backtrace())?;
135        Ok(())
136    }
137}
138
139impl Display for Error {
140    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
141        match &self.kind {
142            ErrorKind::ExpectedText(token) => write!(
143                f,
144                "At line {}, column {} expected text, but instead got: {}",
145                token.location().line(),
146                token.location().column(),
147                token,
148            ),
149            ErrorKind::ExpectedTextGot(text, token) => write!(
150                f,
151                "At line {}, column {} expected a text like \"{}\", but instead got: {}",
152                token.location().line(),
153                token.location().column(),
154                text,
155                token,
156            ),
157            ErrorKind::ExpectedSeparator(token) => write!(
158                f,
159                "At line {}, column {} expected separator, but instead got: {}",
160                token.location().line(),
161                token.location().column(),
162                token,
163            ),
164            ErrorKind::ExpectedSeparatorGot(separator, token) => write!(
165                f,
166                "At line {}, column {} expected a separator like '{}', but instead got: {}",
167                token.location().line(),
168                token.location().column(),
169                separator,
170                token,
171            ),
172            ErrorKind::UnexpectedToken(token) => write!(
173                f,
174                "At line {}, column {} an unexpected token was encountered: {}",
175                token.location().line(),
176                token.location().column(),
177                token,
178            ),
179            ErrorKind::MissingModuleName => {
180                writeln!(f, "The ASN definition is missing the module name")
181            }
182            ErrorKind::UnexpectedEndOfStream => write!(f, "Unexpected end of stream or file"),
183            ErrorKind::InvalidRangeValue(token) => write!(
184                f,
185                "At line {}, column {} an unexpected range value was encountered: {}",
186                token.location().line(),
187                token.location().column(),
188                token,
189            ),
190            ErrorKind::InvalidNumberForEnumVariant(token) => write!(
191                f,
192                "At line {}, column {} an invalid value for an enum variant was encountered: {}",
193                token.location().line(),
194                token.location().column(),
195                token,
196            ),
197            ErrorKind::InvalidValueForConstant(token) => write!(
198                f,
199                "At line {}, column {} an invalid value for an constant value was encountered: {}",
200                token.location().line(),
201                token.location().column(),
202                token,
203            ),
204            ErrorKind::InvalidTag(token) => write!(
205                f,
206                "At line {}, column {} an invalid value for a tag was encountered: {}",
207                token.location().line(),
208                token.location().column(),
209                token,
210            ),
211            ErrorKind::InvalidPositionForExtensionMarker(token) => write!(
212                f,
213                "At line {}, column {} an extension marker is present, which this is not allowed at that position",
214                token.location().line(),
215                token.location().column(),
216            ),
217            ErrorKind::InvalidIntText(token) => write!(
218                f,
219                "At line {}, column {} a number was expected but instead got: {}",
220                token.location().line(),
221                token.location().column(),
222                token
223            ),
224            ErrorKind::UnsupportedLiteral(token) => write!(
225                f,
226                "At line {}, column {} an (yet) unsupported value reference literal was discovered: {}",
227                token.location().line(),
228                token.location().column(),
229                token
230            ),
231            ErrorKind::InvalidLiteral(token) => write!(
232                f,
233                "At line {}, column {} an invalid literal was discovered: {}",
234                token.location().line(),
235                token.location().column(),
236                token
237            ),
238        }
239    }
240}