1use core::fmt;
2
3use crate::error::lang;
4
5#[derive(Debug, PartialEq, Clone)]
9pub enum Error {
10 UnexpectedEof,
12 Expected(&'static str),
14 InvalidChar(char),
16 MaxStrLength(usize),
18 Version(&'static str),
20 Message(&'static str),
22 Receivers(&'static str),
24 Nodes(&'static str),
26 Signal(&'static str),
28 Decoding(&'static str),
30 Validation(&'static str),
32}
33
34impl Error {
35 pub const UNEXPECTED_EOF: &'static str = lang::UNEXPECTED_EOF;
37 pub const EXPECTED_WHITESPACE: &'static str = lang::EXPECTED_WHITESPACE;
38 pub const EXPECTED_PATTERN: &'static str = lang::EXPECTED_PATTERN;
39 pub const EXPECTED_KEYWORD: &'static str = lang::EXPECTED_KEYWORD;
40 pub const EXPECTED_NUMBER: &'static str = lang::EXPECTED_NUMBER;
41 pub const EXPECTED_IDENTIFIER: &'static str = lang::EXPECTED_IDENTIFIER;
42 pub const INVALID_UTF8: &'static str = lang::INVALID_UTF8;
43 pub const INVALID_NUMBER_FORMAT: &'static str = lang::INVALID_NUMBER_FORMAT;
44 pub const PARSE_NUMBER_FAILED: &'static str = lang::PARSE_NUMBER_FAILED;
45 pub const INVALID_CHARACTER: &'static str = lang::INVALID_CHARACTER;
46 pub const STRING_LENGTH_EXCEEDS_MAX: &'static str = lang::STRING_LENGTH_EXCEEDS_MAX;
47 pub const MAX_NAME_SIZE_EXCEEDED: &'static str = lang::MAX_NAME_SIZE_EXCEEDED;
48
49 pub const DECODING_ERROR_PREFIX: &'static str = lang::DECODING_ERROR_PREFIX;
51 pub const VALIDATION_ERROR_PREFIX: &'static str = lang::VALIDATION_ERROR_PREFIX;
52 pub const VERSION_ERROR_PREFIX: &'static str = lang::VERSION_ERROR_PREFIX;
53 pub const MESSAGE_ERROR_PREFIX: &'static str = lang::MESSAGE_ERROR_PREFIX;
54 pub const RECEIVERS_ERROR_PREFIX: &'static str = lang::RECEIVERS_ERROR_PREFIX;
55 pub const NODES_ERROR_PREFIX: &'static str = lang::NODES_ERROR_PREFIX;
56 pub const SIGNAL_ERROR_PREFIX: &'static str = lang::SIGNAL_ERROR_PREFIX;
57
58 pub const SIGNAL_PARSE_INVALID_START_BIT: &'static str = lang::SIGNAL_PARSE_INVALID_START_BIT;
60 pub const SIGNAL_PARSE_INVALID_LENGTH: &'static str = lang::SIGNAL_PARSE_INVALID_LENGTH;
61 pub const SIGNAL_PARSE_INVALID_FACTOR: &'static str = lang::SIGNAL_PARSE_INVALID_FACTOR;
62 pub const SIGNAL_PARSE_INVALID_OFFSET: &'static str = lang::SIGNAL_PARSE_INVALID_OFFSET;
63 pub const SIGNAL_PARSE_INVALID_MIN: &'static str = lang::SIGNAL_PARSE_INVALID_MIN;
64 pub const SIGNAL_PARSE_INVALID_MAX: &'static str = lang::SIGNAL_PARSE_INVALID_MAX;
65 pub const SIGNAL_PARSE_UNIT_TOO_LONG: &'static str = lang::SIGNAL_PARSE_UNIT_TOO_LONG;
66 pub const SIGNAL_NAME_EMPTY: &'static str = lang::SIGNAL_NAME_EMPTY;
67 pub const SIGNAL_LENGTH_TOO_SMALL: &'static str = lang::SIGNAL_LENGTH_TOO_SMALL;
68 pub const SIGNAL_LENGTH_TOO_LARGE: &'static str = lang::SIGNAL_LENGTH_TOO_LARGE;
69 #[cfg(feature = "std")]
70 pub const SIGNAL_LENGTH_REQUIRED: &'static str = lang::SIGNAL_LENGTH_REQUIRED;
71 #[cfg(feature = "std")]
72 pub const SIGNAL_START_BIT_REQUIRED: &'static str = lang::SIGNAL_START_BIT_REQUIRED;
73 pub const SIGNAL_OVERLAP: &'static str = lang::SIGNAL_OVERLAP;
74 pub const SIGNAL_EXTENDS_BEYOND_MESSAGE: &'static str = lang::SIGNAL_EXTENDS_BEYOND_MESSAGE;
75 pub const SIGNAL_EXTENDS_BEYOND_DATA: &'static str = lang::SIGNAL_EXTENDS_BEYOND_DATA;
76 pub const SIGNAL_RECEIVERS_TOO_MANY: &'static str = lang::SIGNAL_RECEIVERS_TOO_MANY;
77
78 pub const NODES_DUPLICATE_NAME: &'static str = lang::NODES_DUPLICATE_NAME;
80 pub const NODES_TOO_MANY: &'static str = lang::NODES_TOO_MANY;
81 pub const DUPLICATE_MESSAGE_ID: &'static str = lang::DUPLICATE_MESSAGE_ID;
82 pub const SENDER_NOT_IN_NODES: &'static str = lang::SENDER_NOT_IN_NODES;
83 pub const INVALID_RANGE: &'static str = lang::INVALID_RANGE;
84 pub const MESSAGE_TOO_MANY_SIGNALS: &'static str = lang::MESSAGE_TOO_MANY_SIGNALS;
85 pub const MESSAGE_NAME_EMPTY: &'static str = lang::MESSAGE_NAME_EMPTY;
86 pub const MESSAGE_SENDER_EMPTY: &'static str = lang::MESSAGE_SENDER_EMPTY;
87 pub const MESSAGE_DLC_TOO_SMALL: &'static str = lang::MESSAGE_DLC_TOO_SMALL;
88 pub const MESSAGE_DLC_TOO_LARGE: &'static str = lang::MESSAGE_DLC_TOO_LARGE;
89 #[cfg(feature = "std")]
90 pub const MESSAGE_DLC_REQUIRED: &'static str = lang::MESSAGE_DLC_REQUIRED;
91 pub const MESSAGE_ID_OUT_OF_RANGE: &'static str = lang::MESSAGE_ID_OUT_OF_RANGE;
92 #[cfg(feature = "std")]
93 pub const MESSAGE_ID_REQUIRED: &'static str = lang::MESSAGE_ID_REQUIRED;
94 pub const MESSAGE_INVALID_ID: &'static str = lang::MESSAGE_INVALID_ID;
95 pub const MESSAGE_INVALID_DLC: &'static str = lang::MESSAGE_INVALID_DLC;
96 pub const MESSAGE_NOT_FOUND: &'static str = lang::MESSAGE_NOT_FOUND;
97 pub const PAYLOAD_LENGTH_MISMATCH: &'static str = lang::PAYLOAD_LENGTH_MISMATCH;
98 #[cfg(feature = "std")]
99 pub const RECEIVERS_DUPLICATE_NAME: &'static str = lang::RECEIVERS_DUPLICATE_NAME;
100 #[cfg(feature = "std")]
101 pub const VALUE_DESCRIPTION_MESSAGE_NOT_FOUND: &'static str =
102 lang::VALUE_DESCRIPTION_MESSAGE_NOT_FOUND;
103 #[cfg(feature = "std")]
104 pub const VALUE_DESCRIPTION_SIGNAL_NOT_FOUND: &'static str =
105 lang::VALUE_DESCRIPTION_SIGNAL_NOT_FOUND;
106 #[cfg(feature = "std")]
107 pub const VALUE_DESCRIPTIONS_TOO_MANY: &'static str = lang::VALUE_DESCRIPTIONS_TOO_MANY;
108}
109
110impl fmt::Display for Error {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 match self {
113 Error::UnexpectedEof => write!(f, "{}", Error::UNEXPECTED_EOF),
114 Error::Expected(msg) => write!(f, "Expected {}", msg),
115 Error::InvalidChar(c) => write!(f, "{}: {}", Error::INVALID_CHARACTER, c),
116 Error::MaxStrLength(max) => {
117 write!(f, "{}: {}", Error::STRING_LENGTH_EXCEEDS_MAX, max)
118 }
119 Error::Version(msg) => write!(f, "{}: {}", Error::VERSION_ERROR_PREFIX, msg),
120 Error::Message(msg) => write!(f, "{}: {}", Error::MESSAGE_ERROR_PREFIX, msg),
121 Error::Receivers(msg) => {
122 write!(f, "{}: {}", Error::RECEIVERS_ERROR_PREFIX, msg)
123 }
124 Error::Nodes(msg) => write!(f, "{}: {}", Error::NODES_ERROR_PREFIX, msg),
125 Error::Signal(msg) => write!(f, "{}: {}", Error::SIGNAL_ERROR_PREFIX, msg),
126 Error::Decoding(msg) => write!(f, "{}: {}", Error::DECODING_ERROR_PREFIX, msg),
127 Error::Validation(msg) => write!(f, "{}: {}", Error::VALIDATION_ERROR_PREFIX, msg),
128 }
129 }
130}
131
132impl From<core::num::ParseIntError> for Error {
133 fn from(_err: core::num::ParseIntError) -> Self {
134 Error::Expected(Error::PARSE_NUMBER_FAILED)
135 }
136}
137
138#[cfg(feature = "std")]
140impl std::error::Error for Error {
141 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
142 None
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 #![allow(clippy::float_cmp)]
149
150 #[cfg(feature = "std")]
152 mod tests_with_std {
153 use crate::Error;
154
155 #[test]
156 fn test_from_parse_int_error() {
157 let parse_error = "invalid".parse::<u32>().unwrap_err();
159 let error: Error = parse_error.into();
160
161 match error {
162 Error::Expected(msg) => {
163 assert_eq!(msg, Error::PARSE_NUMBER_FAILED);
164 }
165 _ => panic!("Expected Error::Expected(Error::PARSE_NUMBER_FAILED)"),
166 }
167 }
168
169 #[test]
170 fn test_display_decoding_error() {
171 let error = Error::Decoding("Test error message");
172 let display = error.to_string();
173 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
174 assert!(display.contains("Test error message"));
175 }
176
177 #[test]
178 fn test_display_signal_error() {
179 let error = Error::Signal("Test signal error");
180 let display = error.to_string();
181 assert!(display.starts_with(Error::SIGNAL_ERROR_PREFIX));
182 assert!(display.contains("Test signal error"));
183 }
184
185 #[test]
186 fn test_display_formatting() {
187 let error = Error::Decoding(
189 "Duplicate message ID: 256 (messages 'EngineData' and 'BrakeData')",
190 );
191 let display = error.to_string();
192 assert!(display.starts_with(Error::DECODING_ERROR_PREFIX));
193 assert!(display.contains("256"));
194 assert!(display.contains("EngineData"));
195 assert!(display.contains("BrakeData"));
196 }
197
198 #[test]
199 fn test_display_from_parse_int_error() {
200 let int_error = "not_a_number".parse::<u32>().unwrap_err();
201 let error: Error = int_error.into();
202 let display = error.to_string();
203
204 assert!(display.contains(Error::PARSE_NUMBER_FAILED));
205 }
206 }
207
208 #[cfg(feature = "std")]
211 mod tests_std {
212 use super::super::Error;
213 use std::error::Error as StdError;
214
215 #[test]
216 fn test_std_error_trait() {
217 let error = Error::Decoding("Test");
218 let _: &dyn StdError = &error;
220
221 assert!(error.source().is_none());
223 }
224 }
225}