flexiber/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 BER-TLV byte {}", pos)?;
59 }
60
61 Ok(())
62 }
63}
64
65#[cfg(feature = "std")]
66impl std::error::Error for Error {}
67
68impl From<ErrorKind> for Error {
69 fn from(kind: ErrorKind) -> Error {
70 Error {
71 kind,
72 position: None,
73 }
74 }
75}
76
77impl From<core::convert::Infallible> for Error {
78 fn from(_: Infallible) -> Error {
79 unreachable!()
80 }
81}
82
83// impl From<Utf8Error> for Error {
84// fn from(err: Utf8Error) -> Error {
85// Error {
86// kind: ErrorKind::Utf8(err),
87// position: None,
88// }
89// }
90// }
91
92// #[cfg(feature = "oid")]
93// impl From<const_oid::Error> for Error {
94// fn from(_: const_oid::Error) -> Error {
95// ErrorKind::Oid.into()
96// }
97// }
98
99#[cfg(feature = "std")]
100impl std::error::Error for ErrorKind {}
101
102/// Error type.
103#[derive(Copy, Clone, Debug, Eq, PartialEq)]
104#[non_exhaustive]
105pub enum ErrorKind {
106 /// Operation failed due to previous error
107 Failed,
108
109 /// Class has more than 2 bytes
110 InvalidClass { value: u8 },
111
112 /// Invalid tag
113 InvalidTag {
114 /// Raw byte value of the tag
115 byte: u8,
116 },
117
118 /// Length greater than u16::MAX
119 InvalidLength,
120
121 /// Incorrect length for a given field
122 Length {
123 /// Tag type of the value being decoded
124 tag: Tag,
125 },
126
127 // /// Message is not canonically encoded
128 // Noncanonical,
129
130 // /// Malformed OID
131 // Oid,
132 /// Integer overflow occurred (library bug!)
133 Overflow,
134
135 /// Message is longer than BER-TLV's limits support
136 Overlength,
137
138 /// Undecoded trailing data at end of message
139 TrailingData {
140 /// Length of the decoded data
141 decoded: Length,
142
143 /// Total length of the remaining data left in the buffer
144 remaining: Length,
145 },
146
147 /// Unexpected end-of-message/nested field when decoding
148 Truncated,
149
150 /// Encoded message is shorter than the expected length
151 /// (i.e. an `Encodable` impl on a particular type has a buggy `encoded_length`)
152 Underlength {
153 /// Expected length
154 expected: Length,
155
156 /// Actual length
157 actual: Length,
158 },
159
160 /// Unexpected tag
161 UnexpectedTag {
162 /// Tag the decoder was expecting (if there is a single such tag).
163 ///
164 /// `None` if multiple tags are expected/allowed, but the `actual` tag
165 /// does not match any of them.
166 expected: Option<Tag>,
167
168 /// Actual tag encountered in the message
169 actual: Tag,
170 },
171
172 // /// Unknown/unsupported tag
173 // UnknownTag {
174 // /// Raw byte value of the tag
175 // byte: u8,
176 // },
177
178 // /// UTF-8 errors
179 // Utf8(Utf8Error),
180
181 // /// Unexpected value
182 // Value {
183 // /// Tag of the unexpected value
184 // tag: Tag,
185 // },
186 /// Tag does not fit in 3 bytes
187 UnsupportedTagSize,
188}
189
190impl ErrorKind {
191 /// Annotate an [`ErrorKind`] with context about where it occurred,
192 /// returning an error.
193 pub fn at(self, position: Length) -> Error {
194 Error::new(self, position)
195 }
196}
197
198impl fmt::Display for ErrorKind {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 match self {
201 ErrorKind::Failed => write!(f, "operation failed"),
202 ErrorKind::InvalidClass { value } => write!(f, "invalid class {}", value),
203 ErrorKind::InvalidLength => write!(f, "length greater than protocol maximum"),
204 ErrorKind::InvalidTag { byte } => {
205 write!(f, "invalid BER-TLV tag: 0x{:02x}", byte)
206 }
207 ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag),
208 // ErrorKind::Noncanonical => write!(f, "DER is not canonically encoded"),
209 // ErrorKind::Oid => write!(f, "malformed OID"),
210 ErrorKind::Overflow => write!(f, "integer overflow"),
211 ErrorKind::Overlength => write!(f, "BER-TLV message is too long"),
212 ErrorKind::TrailingData { decoded, remaining } => {
213 write!(
214 f,
215 "trailing data at end of BER-TLV message: decoded {} bytes, {} bytes remaining",
216 decoded, remaining
217 )
218 }
219 ErrorKind::Truncated => write!(f, "BER-TLV message is truncated"),
220 ErrorKind::Underlength { expected, actual } => write!(
221 f,
222 "BER-TLV message too short: expected {}, got {}",
223 expected, actual
224 ),
225 ErrorKind::UnexpectedTag { expected, actual } => {
226 write!(f, "unexpected BER-TLV tag: ")?;
227
228 if let Some(tag) = expected {
229 write!(f, "expected {}, ", tag)?;
230 }
231
232 write!(f, "got {}", actual)
233 }
234 // ErrorKind::UnknownTag { byte } => {
235 // write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
236 // }
237 // ErrorKind::Utf8(e) => write!(f, "{}", e),
238 // ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
239 ErrorKind::UnsupportedTagSize => {
240 write!(f, "tags occupying more than 3 octets not supported")
241 }
242 }
243 }
244}