1use std::{convert::TryFrom, fmt::Debug, fmt::Display};
4
5use crate::types::{self, ByteOffset, FieldType, TtlvTag, TtlvType};
6
7pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Debug)]
16#[non_exhaustive]
17pub struct Error {
18 kind: ErrorKind,
19 location: ErrorLocation,
20}
21
22impl Error {
23 pub(crate) fn new(kind: ErrorKind, location: ErrorLocation) -> Self {
24 Self { kind, location }
25 }
26
27 pub(crate) fn into_inner(self) -> (ErrorKind, ErrorLocation) {
28 (self.kind, self.location)
29 }
30
31 pub fn kind(&self) -> &ErrorKind {
33 &self.kind
34 }
35
36 pub fn location(&self) -> &ErrorLocation {
38 &self.location
39 }
40}
41
42impl std::error::Error for Error {}
43
44impl Display for Error {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 match &self.kind {
47 ErrorKind::IoError(error) => f.write_fmt(format_args!(
48 "IO error {:?}: {} (at {})",
49 error.kind(),
50 error,
51 self.location
52 )),
53 ErrorKind::ResponseSizeExceedsLimit(size) => {
54 f.write_fmt(format_args!("Response size {} exceeds the configured limit", size))
55 }
56 ErrorKind::MalformedTtlv(error) => {
57 f.write_fmt(format_args!("Malformed TTLV: {:?} (at {})", error, self.location))
58 }
59 ErrorKind::SerdeError(error) => {
60 f.write_fmt(format_args!("Serde error : {:?} (at {})", error, self.location))
61 }
62 }
63 }
64}
65
66impl Error {
67 pub(crate) fn pinpoint<T, L>(error: T, location: L) -> Self
68 where
69 ErrorKind: From<T>,
70 ErrorLocation: From<L>,
71 {
72 Self {
73 kind: error.into(),
74 location: location.into(),
75 }
76 }
77
78 pub(crate) fn pinpoint_with_tag<T, L>(error: T, location: L, tag: TtlvTag) -> Self
79 where
80 ErrorKind: From<T>,
81 ErrorLocation: From<L>,
82 {
83 Self {
84 kind: error.into(),
85 location: ErrorLocation::from(location).with_tag(tag),
86 }
87 }
88
89 pub(crate) fn pinpoint_with_tag_and_type<T, L>(error: T, location: L, tag: TtlvTag, r#type: TtlvType) -> Self
90 where
91 ErrorKind: From<T>,
92 ErrorLocation: From<L>,
93 {
94 Self {
95 kind: error.into(),
96 location: ErrorLocation::from(location).with_tag(tag).with_type(r#type),
97 }
98 }
99}
100
101#[derive(Debug)]
114#[non_exhaustive]
115pub enum ErrorKind {
116 IoError(std::io::Error),
117 ResponseSizeExceedsLimit(usize),
118 MalformedTtlv(MalformedTtlvError),
119 SerdeError(SerdeError),
120}
121
122impl From<std::io::Error> for ErrorKind {
123 fn from(err: std::io::Error) -> Self {
124 Self::IoError(err)
125 }
126}
127
128impl From<types::Error> for ErrorKind {
129 fn from(err: types::Error) -> Self {
130 match err {
131 types::Error::IoError(e) => Self::IoError(e),
132 types::Error::UnexpectedTtlvField { expected, actual } => {
133 Self::MalformedTtlv(MalformedTtlvError::UnexpectedTtlvField { expected, actual })
134 }
135 types::Error::InvalidTtlvTag(v) => Self::SerdeError(SerdeError::InvalidTag(v)),
136 types::Error::UnsupportedTtlvType(v) => Self::MalformedTtlv(MalformedTtlvError::UnsupportedType(v)),
137 types::Error::InvalidTtlvType(v) => Self::MalformedTtlv(MalformedTtlvError::InvalidType(v)),
138 types::Error::InvalidTtlvValueLength {
139 expected,
140 actual,
141 r#type,
142 } => Self::MalformedTtlv(MalformedTtlvError::InvalidLength {
143 expected,
144 actual,
145 r#type,
146 }),
147 types::Error::InvalidTtlvValue(r#type) => Self::MalformedTtlv(MalformedTtlvError::InvalidValue { r#type }),
148 types::Error::InvalidStateMachineOperation => Self::SerdeError(SerdeError::Other(
149 "Internal error: invalid state machine operaiton".into(),
150 )),
151 }
152 }
153}
154
155impl From<MalformedTtlvError> for ErrorKind {
156 fn from(err: MalformedTtlvError) -> Self {
157 Self::MalformedTtlv(err)
158 }
159}
160
161impl From<SerdeError> for ErrorKind {
162 fn from(err: SerdeError) -> Self {
163 Self::SerdeError(err)
164 }
165}
166
167#[derive(Clone, Debug, Default)]
171pub struct ErrorLocation {
172 offset: Option<ByteOffset>,
173 parent_tags: Vec<TtlvTag>,
174 tag: Option<TtlvTag>,
175 r#type: Option<TtlvType>,
176}
177
178impl From<ByteOffset> for ErrorLocation {
179 fn from(offset: ByteOffset) -> Self {
180 Self {
181 offset: Some(offset),
182 ..Default::default()
183 }
184 }
185}
186
187impl From<u8> for ErrorLocation {
188 fn from(offset: u8) -> Self {
189 Self::from(ByteOffset(offset.into()))
190 }
191}
192
193impl From<u16> for ErrorLocation {
194 fn from(offset: u16) -> Self {
195 Self::from(ByteOffset(offset.into()))
196 }
197}
198
199impl From<u32> for ErrorLocation {
200 fn from(offset: u32) -> Self {
201 Self::from(ByteOffset(offset.into()))
202 }
203}
204
205impl From<u64> for ErrorLocation {
206 fn from(offset: u64) -> Self {
207 Self::from(ByteOffset(offset))
208 }
209}
210
211impl From<usize> for ErrorLocation {
212 fn from(value: usize) -> ErrorLocation {
213 match ByteOffset::try_from(value) {
214 Ok(offset) => ErrorLocation::from(offset),
215 Err(_) => ErrorLocation::unknown(),
216 }
217 }
218}
219
220impl<T> From<std::io::Cursor<T>> for ErrorLocation {
221 fn from(cursor: std::io::Cursor<T>) -> Self {
222 Self {
223 offset: Some(cursor.position().into()),
224 ..Default::default()
225 }
226 }
227}
228
229impl<T> From<&std::io::Cursor<T>> for ErrorLocation {
230 fn from(cursor: &std::io::Cursor<T>) -> Self {
231 Self {
232 offset: Some(cursor.position().into()),
233 ..Default::default()
234 }
235 }
236}
237
238impl<T> From<&mut std::io::Cursor<T>> for ErrorLocation {
239 fn from(cursor: &mut std::io::Cursor<T>) -> Self {
240 Self {
241 offset: Some(cursor.position().into()),
242 ..Default::default()
243 }
244 }
245}
246
247impl Display for ErrorLocation {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 if self.is_unknown() {
250 return f.write_str("Unknown");
251 }
252
253 let mut sep_str = "";
254
255 #[rustfmt::skip]
256 let mut sep = || { let s = sep_str; sep_str = ", "; s };
257
258 if let Some(offset) = self.offset {
259 f.write_fmt(format_args!("{}pos: {} bytes", sep(), *offset))?;
260 }
261 if !self.parent_tags.is_empty() {
262 let mut iter = self.parent_tags.iter();
263 f.write_fmt(format_args!("{}parent tags: {}", sep(), iter.next().unwrap()))?;
264 for tag in iter {
265 f.write_fmt(format_args!(" > {}", tag))?
266 }
267 }
268 if let Some(tag) = self.tag {
269 f.write_fmt(format_args!("{}tag: {}", sep(), tag))?;
270 }
271 if let Some(r#type) = self.r#type {
272 f.write_fmt(format_args!("{}type: {}", sep(), r#type))?;
273 }
274
275 Ok(())
276 }
277}
278
279impl ErrorLocation {
280 pub(crate) fn at(offset: ByteOffset) -> Self {
281 Self {
282 offset: Some(offset),
283 ..Default::default()
284 }
285 }
286
287 pub(crate) fn unknown() -> Self {
289 Self::default()
290 }
291
292 pub(crate) fn with_offset(mut self, offset: ByteOffset) -> Self {
293 let _ = self.offset.get_or_insert(offset);
294 self
295 }
296
297 pub(crate) fn with_parent_tags(mut self, parent_tags: &[TtlvTag]) -> Self {
298 if self.parent_tags.is_empty() {
299 self.parent_tags.extend(parent_tags);
300 }
301 self
302 }
303
304 pub(crate) fn with_tag(mut self, tag: TtlvTag) -> Self {
305 let _ = self.tag.get_or_insert(tag);
306 self
307 }
308
309 pub(crate) fn with_type(mut self, r#type: TtlvType) -> Self {
310 let _ = self.r#type.get_or_insert(r#type);
311 self
312 }
313
314 pub(crate) fn merge(mut self, loc: ErrorLocation) -> Self {
315 if let Some(offset) = loc.offset {
316 self = self.with_offset(offset);
317 }
318 self = self.with_parent_tags(&loc.parent_tags);
319 if let Some(tag) = loc.tag {
320 self = self.with_tag(tag);
321 }
322 if let Some(r#type) = loc.r#type {
323 self = self.with_type(r#type);
324 }
325 self
326 }
327
328 pub fn is_unknown(&self) -> bool {
329 matches!(
330 (self.offset, self.parent_tags.is_empty(), self.tag, self.r#type),
331 (None, true, None, None)
332 )
333 }
334
335 pub fn offset(&self) -> Option<ByteOffset> {
336 self.offset
337 }
338
339 pub fn parent_tags(&self) -> &[TtlvTag] {
340 &self.parent_tags
341 }
342
343 pub fn tag(&self) -> Option<TtlvTag> {
344 self.tag
345 }
346
347 pub fn r#type(&self) -> Option<TtlvType> {
348 self.r#type
349 }
350}
351
352#[derive(Debug)]
356#[non_exhaustive]
357pub enum MalformedTtlvError {
358 InvalidType(u8),
360
361 InvalidLength {
363 expected: u32,
364 actual: u32,
365 r#type: TtlvType,
366 },
367
368 InvalidValue { r#type: TtlvType },
370
371 Overflow { field_end: ByteOffset },
373
374 UnexpectedTtlvField { expected: FieldType, actual: FieldType },
376
377 UnexpectedType { expected: TtlvType, actual: TtlvType },
381
382 UnsupportedType(u8),
384
385 UnknownStructureLength,
391}
392
393impl MalformedTtlvError {
394 pub fn overflow<T>(field_end: T) -> Self
395 where
396 ByteOffset: From<T>,
397 {
398 Self::Overflow {
399 field_end: field_end.into(),
400 }
401 }
402}
403
404#[derive(Debug)]
408#[non_exhaustive]
409pub enum SerdeError {
410 InvalidVariant(&'static str),
416
417 InvalidVariantMatcherSyntax(String),
419
420 InvalidTag(String),
423
424 MissingIdentifier,
427
428 Other(String),
432
433 UnexpectedTag { expected: TtlvTag, actual: TtlvTag },
438
439 UnexpectedType { expected: TtlvType, actual: TtlvType },
442
443 UnsupportedRustType(&'static str),
445}