simple_tlv/
error.rs

1//! Error types.
2
3// pub use core::str::Utf8Error;
4
5use crate::{Length, Tag};
6use core::{convert::Infallible, fmt};
7
8/// Result type.
9pub type Result<T> = core::result::Result<T, Error>;
10
11/// Error type.
12#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13pub struct Error {
14    /// Kind of error
15    kind: ErrorKind,
16
17    /// Position inside of message where error occurred
18    position: Option<Length>,
19}
20
21impl Error {
22    /// Create a new [`Error`]
23    pub fn new(kind: ErrorKind, position: Length) -> Error {
24        Error {
25            kind,
26            position: Some(position),
27        }
28    }
29
30    /// Get the [`ErrorKind`] which occurred.
31    pub fn kind(self) -> ErrorKind {
32        self.kind
33    }
34
35    /// Get the position inside of the message where the error occurred.
36    pub fn position(self) -> Option<Length> {
37        self.position
38    }
39
40    /// For errors occurring inside of a nested message, extend the position
41    /// count by the location where the nested message occurs.
42    pub fn nested(self, nested_position: Length) -> Self {
43        // TODO(tarcieri): better handle length overflows occurring in this calculation?
44        let position = (nested_position + self.position.unwrap_or_default()).ok();
45
46        Self {
47            kind: self.kind,
48            position,
49        }
50    }
51}
52
53impl fmt::Display for Error {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        write!(f, "{}", self.kind)?;
56
57        if let Some(pos) = self.position {
58            write!(f, " at SIMPLE-TLV byte {}", pos)?;
59        }
60
61        Ok(())
62    }
63}
64
65impl From<ErrorKind> for Error {
66    fn from(kind: ErrorKind) -> Error {
67        Error {
68            kind,
69            position: None,
70        }
71    }
72}
73
74impl From<core::convert::Infallible> for Error {
75    fn from(_: Infallible) -> Error {
76        unreachable!()
77    }
78}
79
80// impl From<Utf8Error> for Error {
81//     fn from(err: Utf8Error) -> Error {
82//         Error {
83//             kind: ErrorKind::Utf8(err),
84//             position: None,
85//         }
86//     }
87// }
88
89// #[cfg(feature = "oid")]
90// impl From<const_oid::Error> for Error {
91//     fn from(_: const_oid::Error) -> Error {
92//         ErrorKind::Oid.into()
93//     }
94// }
95
96#[cfg(feature = "std")]
97impl std::error::Error for ErrorKind {}
98
99/// Error type.
100#[derive(Copy, Clone, Debug, Eq, PartialEq)]
101#[non_exhaustive]
102pub enum ErrorKind {
103    /// Operation failed due to previous error
104    Failed,
105
106    /// Invalid tag
107    InvalidTag {
108        /// Raw byte value of the tag
109        byte: u8,
110    },
111
112    /// Length greater than u16::MAX
113    InvalidLength,
114
115    /// Incorrect length for a given field
116    Length {
117        /// Tag type of the value being decoded
118        tag: Tag,
119    },
120
121    // /// Message is not canonically encoded
122    // Noncanonical,
123
124    // /// Malformed OID
125    // Oid,
126
127    /// Integer overflow occurred (library bug!)
128    Overflow,
129
130    /// Message is longer than SIMPLE-TLV's limits support
131    Overlength,
132
133    /// Undecoded trailing data at end of message
134    TrailingData {
135        /// Length of the decoded data
136        decoded: Length,
137
138        /// Total length of the remaining data left in the buffer
139        remaining: Length,
140    },
141
142    /// Unexpected end-of-message/nested field when decoding
143    Truncated,
144
145    /// Encoded message is shorter than the expected length
146    /// (i.e. an `Encodable` impl on a particular type has a buggy `encoded_length`)
147    Underlength {
148        /// Expected length
149        expected: Length,
150
151        /// Actual length
152        actual: Length,
153    },
154
155    /// Unexpected tag
156    UnexpectedTag {
157        /// Tag the decoder was expecting (if there is a single such tag).
158        ///
159        /// `None` if multiple tags are expected/allowed, but the `actual` tag
160        /// does not match any of them.
161        expected: Option<Tag>,
162
163        /// Actual tag encountered in the message
164        actual: Tag,
165    },
166
167    // /// Unknown/unsupported tag
168    // UnknownTag {
169    //     /// Raw byte value of the tag
170    //     byte: u8,
171    // },
172
173    // /// UTF-8 errors
174    // Utf8(Utf8Error),
175
176    // /// Unexpected value
177    // Value {
178    //     /// Tag of the unexpected value
179    //     tag: Tag,
180    // },
181}
182
183impl ErrorKind {
184    /// Annotate an [`ErrorKind`] with context about where it occurred,
185    /// returning an error.
186    pub fn at(self, position: Length) -> Error {
187        Error::new(self, position)
188    }
189}
190
191impl fmt::Display for ErrorKind {
192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193        match self {
194            ErrorKind::Failed => write!(f, "operation failed"),
195            ErrorKind::InvalidLength => write!(f, "length greater than protocol maximum"),
196            ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
197            // ErrorKind::Noncanonical => write!(f, "DER is not canonically encoded"),
198            // ErrorKind::Oid => write!(f, "malformed OID"),
199            ErrorKind::Overflow => write!(f, "integer overflow"),
200            ErrorKind::Overlength => write!(f, "SIMPLE-TLV message is too long"),
201            ErrorKind::TrailingData { decoded, remaining } => {
202                write!(
203                    f,
204                    "trailing data at end of SIMPLE-TLV message: decoded {} bytes, {} bytes remaining",
205                    decoded, remaining
206                )
207            }
208            ErrorKind::Truncated => write!(f, "SIMPLE-TLV message is truncated"),
209            ErrorKind::Underlength { expected, actual } => write!(
210                f,
211                "SIMPLE-TLV message too short: expected {}, got {}",
212                expected, actual
213            ),
214            ErrorKind::UnexpectedTag { expected, actual } => {
215                write!(f, "unexpected SIMPLE-TLV tag: ")?;
216
217                if let Some(tag) = expected {
218                    write!(f, "expected {}, ", tag)?;
219                }
220
221                write!(f, "got {}", actual)
222            }
223            ErrorKind::InvalidTag { byte } => {
224                write!(f, "invalid SIMPLE-TLV tag: 0x{:02x}", byte)
225            }
226            // ErrorKind::UnknownTag { byte } => {
227            //     write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
228            // }
229            // ErrorKind::Utf8(e) => write!(f, "{}", e),
230            // ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
231        }
232    }
233}