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::Encoding(_) | 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::Encoding(msg) => {
295 write!(f, "{}: {}", Error::ENCODING_ERROR_PREFIX, msg)
296 }
297 Error::Validation(msg) => {
298 write!(f, "{}: {}", Error::VALIDATION_ERROR_PREFIX, msg)
299 }
300 }
301 }
302}
303
304impl From<core::num::ParseIntError> for Error {
305 fn from(_err: core::num::ParseIntError) -> Self {
306 Error::expected(Error::PARSE_NUMBER_FAILED)
307 }
308}
309
310#[cfg(feature = "std")]
312impl std::error::Error for Error {
313 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
314 None
315 }
316}
317
318#[cfg(test)]
319mod tests {
320 #![allow(clippy::float_cmp)]
321
322 #[cfg(feature = "std")]
324 mod tests_with_std {
325 use crate::Error;
326
327 #[test]
328 fn test_from_parse_int_error() {
329 let parse_error = "invalid".parse::<u32>().unwrap_err();
331 let error: Error = parse_error.into();
332
333 match error {
334 Error::Expected { msg, line } => {
335 assert_eq!(msg, Error::PARSE_NUMBER_FAILED);
336 assert_eq!(line, None);
337 }
338 _ => panic!("Expected Error::Expected"),
339 }
340 }
341
342 #[test]
343 fn test_display_decoding_error() {
344 let error = Error::Decoding("Test error message");
345 let display = error.to_string();
346 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
347 assert!(display.contains("Test error message"));
348 }
349
350 #[test]
351 fn test_display_signal_error() {
352 let error = Error::signal("Test signal error");
353 let display = error.to_string();
354 assert!(display.starts_with(Error::SIGNAL_ERROR_PREFIX));
355 assert!(display.contains("Test signal error"));
356 }
357
358 #[test]
359 fn test_display_formatting() {
360 let error = Error::Decoding(
362 "Duplicate message ID: 256 (messages 'EngineData' and 'BrakeData')",
363 );
364 let display = error.to_string();
365 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
366 assert!(display.contains("256"));
367 assert!(display.contains("EngineData"));
368 assert!(display.contains("BrakeData"));
369 }
370
371 #[test]
372 fn test_display_from_parse_int_error() {
373 let int_error = "not_a_number".parse::<u32>().unwrap_err();
374 let error: Error = int_error.into();
375 let display = error.to_string();
376
377 assert!(display.contains(Error::PARSE_NUMBER_FAILED));
378 }
379
380 #[test]
381 fn test_error_with_line_number() {
382 let error = Error::expected_at("Expected identifier", 42);
383 let display = error.to_string();
384 assert!(display.contains("line 42"));
385 assert!(display.contains("Expected identifier"));
386 }
387
388 #[test]
389 fn test_error_without_line_number() {
390 let error = Error::expected("Expected identifier");
391 let display = error.to_string();
392 assert!(!display.contains("line"));
393 assert!(display.contains("Expected identifier"));
394 }
395
396 #[test]
397 fn test_with_line_adds_line_info() {
398 let error = Error::expected("Expected whitespace");
399 assert_eq!(error.line(), None);
400
401 let error_with_line = error.with_line(10);
402 assert_eq!(error_with_line.line(), Some(10));
403 }
404
405 #[test]
406 fn test_with_line_preserves_existing_line() {
407 let error = Error::expected_at("Expected whitespace", 5);
408 let error_with_line = error.with_line(10);
409 assert_eq!(error_with_line.line(), Some(5));
411 }
412
413 #[test]
414 fn test_invalid_char_display() {
415 let error = Error::invalid_char_at('\t', 15);
416 let display = error.to_string();
417 assert!(display.contains("line 15"));
418 assert!(display.contains("\\t"));
419 }
420
421 #[test]
422 fn test_max_str_length_display() {
423 let error = Error::max_str_length_at(256, 20);
424 let display = error.to_string();
425 assert!(display.contains("line 20"));
426 assert!(display.contains("256"));
427 }
428 }
429
430 #[cfg(feature = "std")]
433 mod tests_std {
434 use super::super::Error;
435 use std::error::Error as StdError;
436
437 #[test]
438 fn test_std_error_trait() {
439 let error = Error::Decoding("Test");
440 let _: &dyn StdError = &error;
442
443 assert!(error.source().is_none());
445 }
446 }
447}