1use core::fmt;
2
3use super::Error;
4
5impl Error {
6 #[inline]
12 pub fn unexpected_eof() -> Self {
13 Error::UnexpectedEof { line: None }
14 }
15
16 #[inline]
18 pub fn unexpected_eof_at(line: usize) -> Self {
19 Error::UnexpectedEof { line: Some(line) }
20 }
21
22 #[inline]
24 pub fn expected(msg: &'static str) -> Self {
25 Error::Expected { msg, line: None }
26 }
27
28 #[inline]
30 pub fn expected_at(msg: &'static str, line: usize) -> Self {
31 Error::Expected {
32 msg,
33 line: Some(line),
34 }
35 }
36
37 #[inline]
39 pub fn invalid_char(char: char) -> Self {
40 Error::InvalidChar { char, line: None }
41 }
42
43 #[inline]
45 pub fn invalid_char_at(char: char, line: usize) -> Self {
46 Error::InvalidChar {
47 char,
48 line: Some(line),
49 }
50 }
51
52 #[inline]
54 pub fn max_str_length(max: usize) -> Self {
55 Error::MaxStrLength { max, line: None }
56 }
57
58 #[inline]
60 pub fn max_str_length_at(max: usize, line: usize) -> Self {
61 Error::MaxStrLength {
62 max,
63 line: Some(line),
64 }
65 }
66
67 #[inline]
69 pub fn version(msg: &'static str) -> Self {
70 Error::Version { msg, line: None }
71 }
72
73 #[inline]
75 pub fn version_at(msg: &'static str, line: usize) -> Self {
76 Error::Version {
77 msg,
78 line: Some(line),
79 }
80 }
81
82 #[inline]
84 pub fn message(msg: &'static str) -> Self {
85 Error::Message { msg, line: None }
86 }
87
88 #[inline]
90 pub fn message_at(msg: &'static str, line: usize) -> Self {
91 Error::Message {
92 msg,
93 line: Some(line),
94 }
95 }
96
97 #[inline]
99 pub fn receivers(msg: &'static str) -> Self {
100 Error::Receivers { msg, line: None }
101 }
102
103 #[inline]
105 pub fn receivers_at(msg: &'static str, line: usize) -> Self {
106 Error::Receivers {
107 msg,
108 line: Some(line),
109 }
110 }
111
112 #[inline]
114 pub fn nodes(msg: &'static str) -> Self {
115 Error::Nodes { msg, line: None }
116 }
117
118 #[inline]
120 pub fn nodes_at(msg: &'static str, line: usize) -> Self {
121 Error::Nodes {
122 msg,
123 line: Some(line),
124 }
125 }
126
127 #[inline]
129 pub fn signal(msg: &'static str) -> Self {
130 Error::Signal { msg, line: None }
131 }
132
133 #[inline]
135 pub fn signal_at(msg: &'static str, line: usize) -> Self {
136 Error::Signal {
137 msg,
138 line: Some(line),
139 }
140 }
141
142 #[inline]
148 pub fn line(&self) -> Option<usize> {
149 match self {
150 Error::UnexpectedEof { line } => *line,
151 Error::Expected { line, .. } => *line,
152 Error::InvalidChar { line, .. } => *line,
153 Error::MaxStrLength { line, .. } => *line,
154 Error::Version { line, .. } => *line,
155 Error::Message { line, .. } => *line,
156 Error::Receivers { line, .. } => *line,
157 Error::Nodes { line, .. } => *line,
158 Error::Signal { line, .. } => *line,
159 Error::Decoding(_) | Error::Validation(_) => None,
160 }
161 }
162
163 #[inline]
166 pub fn with_line(self, line: usize) -> Self {
167 match self {
168 Error::UnexpectedEof { line: None } => Error::UnexpectedEof { line: Some(line) },
169 Error::Expected { msg, line: None } => Error::Expected {
170 msg,
171 line: Some(line),
172 },
173 Error::InvalidChar { char, line: None } => Error::InvalidChar {
174 char,
175 line: Some(line),
176 },
177 Error::MaxStrLength { max, line: None } => Error::MaxStrLength {
178 max,
179 line: Some(line),
180 },
181 Error::Version { msg, line: None } => Error::Version {
182 msg,
183 line: Some(line),
184 },
185 Error::Message { msg, line: None } => Error::Message {
186 msg,
187 line: Some(line),
188 },
189 Error::Receivers { msg, line: None } => Error::Receivers {
190 msg,
191 line: Some(line),
192 },
193 Error::Nodes { msg, line: None } => Error::Nodes {
194 msg,
195 line: Some(line),
196 },
197 Error::Signal { msg, line: None } => Error::Signal {
198 msg,
199 line: Some(line),
200 },
201 other => other,
203 }
204 }
205}
206
207impl fmt::Display for Error {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 match self {
210 Error::UnexpectedEof { line } => {
211 if let Some(line) = line {
212 write!(f, "line {}: {}", line, Error::UNEXPECTED_EOF)
213 } else {
214 write!(f, "{}", Error::UNEXPECTED_EOF)
215 }
216 }
217 Error::Expected { msg, line } => {
218 if let Some(line) = line {
219 write!(f, "line {}: {}", line, msg)
220 } else {
221 write!(f, "{}", msg)
222 }
223 }
224 Error::InvalidChar { char, line } => {
225 if let Some(line) = line {
226 write!(
227 f,
228 "line {}: {}: {}",
229 line,
230 Error::INVALID_CHARACTER,
231 char.escape_debug()
232 )
233 } else {
234 write!(f, "{}: {}", Error::INVALID_CHARACTER, char.escape_debug())
235 }
236 }
237 Error::MaxStrLength { max, line } => {
238 if let Some(line) = line {
239 write!(
240 f,
241 "line {}: {}: {}",
242 line,
243 Error::STRING_LENGTH_EXCEEDS_MAX,
244 max
245 )
246 } else {
247 write!(f, "{}: {}", Error::STRING_LENGTH_EXCEEDS_MAX, max)
248 }
249 }
250 Error::Version { msg, line } => {
251 if let Some(line) = line {
252 write!(f, "line {}: {}: {}", line, Error::VERSION_ERROR_PREFIX, msg)
253 } else {
254 write!(f, "{}: {}", Error::VERSION_ERROR_PREFIX, msg)
255 }
256 }
257 Error::Message { msg, line } => {
258 if let Some(line) = line {
259 write!(f, "line {}: {}: {}", line, Error::MESSAGE_ERROR_PREFIX, msg)
260 } else {
261 write!(f, "{}: {}", Error::MESSAGE_ERROR_PREFIX, msg)
262 }
263 }
264 Error::Receivers { msg, line } => {
265 if let Some(line) = line {
266 write!(
267 f,
268 "line {}: {}: {}",
269 line,
270 Error::RECEIVERS_ERROR_PREFIX,
271 msg
272 )
273 } else {
274 write!(f, "{}: {}", Error::RECEIVERS_ERROR_PREFIX, msg)
275 }
276 }
277 Error::Nodes { msg, line } => {
278 if let Some(line) = line {
279 write!(f, "line {}: {}: {}", line, Error::NODES_ERROR_PREFIX, msg)
280 } else {
281 write!(f, "{}: {}", Error::NODES_ERROR_PREFIX, msg)
282 }
283 }
284 Error::Signal { msg, line } => {
285 if let Some(line) = line {
286 write!(f, "line {}: {}: {}", line, Error::SIGNAL_ERROR_PREFIX, msg)
287 } else {
288 write!(f, "{}: {}", Error::SIGNAL_ERROR_PREFIX, msg)
289 }
290 }
291 Error::Decoding(msg) => {
292 write!(f, "{}: {}", Error::DECODING_ERROR_PREFIX, msg)
293 }
294 Error::Validation(msg) => {
295 write!(f, "{}: {}", Error::VALIDATION_ERROR_PREFIX, msg)
296 }
297 }
298 }
299}
300
301impl From<core::num::ParseIntError> for Error {
302 fn from(_err: core::num::ParseIntError) -> Self {
303 Error::expected(Error::PARSE_NUMBER_FAILED)
304 }
305}
306
307#[cfg(feature = "std")]
309impl std::error::Error for Error {
310 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
311 None
312 }
313}
314
315#[cfg(test)]
316mod tests {
317 #![allow(clippy::float_cmp)]
318
319 #[cfg(feature = "std")]
321 mod tests_with_std {
322 use crate::Error;
323
324 #[test]
325 fn test_from_parse_int_error() {
326 let parse_error = "invalid".parse::<u32>().unwrap_err();
328 let error: Error = parse_error.into();
329
330 match error {
331 Error::Expected { msg, line } => {
332 assert_eq!(msg, Error::PARSE_NUMBER_FAILED);
333 assert_eq!(line, None);
334 }
335 _ => panic!("Expected Error::Expected"),
336 }
337 }
338
339 #[test]
340 fn test_display_decoding_error() {
341 let error = Error::Decoding("Test error message");
342 let display = error.to_string();
343 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
344 assert!(display.contains("Test error message"));
345 }
346
347 #[test]
348 fn test_display_signal_error() {
349 let error = Error::signal("Test signal error");
350 let display = error.to_string();
351 assert!(display.starts_with(Error::SIGNAL_ERROR_PREFIX));
352 assert!(display.contains("Test signal error"));
353 }
354
355 #[test]
356 fn test_display_formatting() {
357 let error = Error::Decoding(
359 "Duplicate message ID: 256 (messages 'EngineData' and 'BrakeData')",
360 );
361 let display = error.to_string();
362 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
363 assert!(display.contains("256"));
364 assert!(display.contains("EngineData"));
365 assert!(display.contains("BrakeData"));
366 }
367
368 #[test]
369 fn test_display_from_parse_int_error() {
370 let int_error = "not_a_number".parse::<u32>().unwrap_err();
371 let error: Error = int_error.into();
372 let display = error.to_string();
373
374 assert!(display.contains(Error::PARSE_NUMBER_FAILED));
375 }
376
377 #[test]
378 fn test_error_with_line_number() {
379 let error = Error::expected_at("Expected identifier", 42);
380 let display = error.to_string();
381 assert!(display.contains("line 42"));
382 assert!(display.contains("Expected identifier"));
383 }
384
385 #[test]
386 fn test_error_without_line_number() {
387 let error = Error::expected("Expected identifier");
388 let display = error.to_string();
389 assert!(!display.contains("line"));
390 assert!(display.contains("Expected identifier"));
391 }
392
393 #[test]
394 fn test_with_line_adds_line_info() {
395 let error = Error::expected("Expected whitespace");
396 assert_eq!(error.line(), None);
397
398 let error_with_line = error.with_line(10);
399 assert_eq!(error_with_line.line(), Some(10));
400 }
401
402 #[test]
403 fn test_with_line_preserves_existing_line() {
404 let error = Error::expected_at("Expected whitespace", 5);
405 let error_with_line = error.with_line(10);
406 assert_eq!(error_with_line.line(), Some(5));
408 }
409
410 #[test]
411 fn test_invalid_char_display() {
412 let error = Error::invalid_char_at('\t', 15);
413 let display = error.to_string();
414 assert!(display.contains("line 15"));
415 assert!(display.contains("\\t"));
416 }
417
418 #[test]
419 fn test_max_str_length_display() {
420 let error = Error::max_str_length_at(256, 20);
421 let display = error.to_string();
422 assert!(display.contains("line 20"));
423 assert!(display.contains("256"));
424 }
425 }
426
427 #[cfg(feature = "std")]
430 mod tests_std {
431 use super::super::Error;
432 use std::error::Error as StdError;
433
434 #[test]
435 fn test_std_error_trait() {
436 let error = Error::Decoding("Test");
437 let _: &dyn StdError = &error;
439
440 assert!(error.source().is_none());
442 }
443 }
444}