1pub use core::str::Utf8Error;
4
5use crate::{Length, Tag};
6use core::{convert::Infallible, fmt, num::TryFromIntError};
7
8#[cfg(feature = "oid")]
9use crate::asn1::ObjectIdentifier;
10
11#[cfg(feature = "pem")]
12use crate::pem;
13
14#[cfg(doc)]
15use crate::{Reader, Writer};
16
17pub type Result<T> = core::result::Result<T, Error>;
19
20#[derive(Copy, Clone, Debug, Eq, PartialEq)]
37pub struct Error {
38 kind: ErrorKind,
40
41 position: Option<Length>,
43}
44
45impl Error {
46 #[must_use]
48 pub const fn new(kind: ErrorKind, position: Length) -> Error {
49 Error {
50 kind,
51 position: Some(position),
52 }
53 }
54 pub(crate) const fn from_kind(kind: ErrorKind) -> Error {
56 Error {
57 kind,
58 position: None,
59 }
60 }
61
62 #[must_use]
66 pub fn incomplete(actual_len: Length) -> Self {
67 match actual_len + Length::ONE {
68 Ok(expected_len) => ErrorKind::Incomplete {
69 expected_len,
70 actual_len,
71 }
72 .at(actual_len),
73 Err(err) => err.kind().at(actual_len),
74 }
75 }
76
77 #[must_use]
79 pub fn kind(self) -> ErrorKind {
80 self.kind
81 }
82
83 #[must_use]
85 pub fn position(self) -> Option<Length> {
86 self.position
87 }
88
89 pub(crate) fn nested(self, nested_position: Length) -> Self {
92 let position = (nested_position + self.position.unwrap_or_default()).ok();
94
95 Self {
96 kind: self.kind,
97 position,
98 }
99 }
100}
101
102impl core::error::Error for Error {}
103
104impl fmt::Display for Error {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(f, "{}", self.kind)?;
107
108 if let Some(pos) = self.position {
109 write!(f, " at DER byte {pos}")?;
110 }
111
112 Ok(())
113 }
114}
115
116impl From<ErrorKind> for Error {
117 fn from(kind: ErrorKind) -> Error {
118 Error::from_kind(kind)
119 }
120}
121
122impl From<Infallible> for Error {
123 fn from(_: Infallible) -> Error {
124 unreachable!()
125 }
126}
127
128impl From<TryFromIntError> for Error {
129 fn from(_: TryFromIntError) -> Error {
130 Error {
131 kind: ErrorKind::Overflow,
132 position: None,
133 }
134 }
135}
136
137impl From<Utf8Error> for Error {
138 fn from(err: Utf8Error) -> Error {
139 Error {
140 kind: ErrorKind::Utf8(err),
141 position: None,
142 }
143 }
144}
145
146#[cfg(feature = "alloc")]
147impl From<alloc::string::FromUtf8Error> for Error {
148 fn from(err: alloc::string::FromUtf8Error) -> Error {
149 ErrorKind::Utf8(err.utf8_error()).into()
150 }
151}
152
153#[cfg(feature = "oid")]
154impl From<const_oid::Error> for Error {
155 fn from(_: const_oid::Error) -> Error {
156 ErrorKind::OidMalformed.into()
157 }
158}
159
160#[cfg(feature = "pem")]
161impl From<pem::Error> for Error {
162 fn from(err: pem::Error) -> Error {
163 ErrorKind::Pem(err).into()
164 }
165}
166
167#[cfg(feature = "std")]
168impl From<std::io::Error> for Error {
169 fn from(err: std::io::Error) -> Error {
170 match err.kind() {
171 std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
172 std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
173 other => ErrorKind::Io(other),
174 }
175 .into()
176 }
177}
178
179#[cfg(feature = "time")]
180impl From<time::error::ComponentRange> for Error {
181 fn from(_: time::error::ComponentRange) -> Error {
182 ErrorKind::DateTime.into()
183 }
184}
185
186#[derive(Copy, Clone, Debug, Eq, PartialEq)]
197#[non_exhaustive]
198pub enum ErrorKind {
199 DateTime,
201
202 EncodingRules,
204
205 Failed,
211
212 #[cfg(feature = "std")]
214 FileNotFound,
215
216 Incomplete {
218 expected_len: Length,
226
227 actual_len: Length,
229 },
230
231 #[cfg(feature = "std")]
233 Io(std::io::ErrorKind),
234
235 IndefiniteLength,
237
238 Length {
240 tag: Tag,
242 },
243
244 Noncanonical {
246 tag: Tag,
248 },
249
250 OidMalformed,
252
253 #[cfg(feature = "oid")]
262 OidUnknown {
263 oid: ObjectIdentifier,
265 },
266
267 SetDuplicate,
269
270 SetOrdering,
272
273 Overflow,
275
276 Overlength,
278
279 #[cfg(feature = "pem")]
281 Pem(pem::Error),
282
283 #[cfg(feature = "std")]
285 PermissionDenied,
286
287 Reader,
289
290 TagModeUnknown,
292
293 TagNumberInvalid,
299
300 TagUnexpected {
302 expected: Option<Tag>,
307
308 actual: Tag,
310 },
311
312 TagUnknown {
314 byte: u8,
316 },
317
318 TrailingData {
320 decoded: Length,
322
323 remaining: Length,
325 },
326
327 Utf8(Utf8Error),
329
330 Value {
332 tag: Tag,
334 },
335}
336
337impl ErrorKind {
338 #[must_use]
341 pub fn at(self, position: Length) -> Error {
342 Error::new(self, position)
343 }
344
345 #[must_use]
347 pub fn to_error(self) -> Error {
348 Error::from_kind(self)
349 }
350}
351
352impl fmt::Display for ErrorKind {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 match self {
355 ErrorKind::DateTime => write!(f, "date/time error"),
356 ErrorKind::EncodingRules => write!(f, "invalid encoding rules"),
357 ErrorKind::Failed => write!(f, "operation failed"),
358 #[cfg(feature = "std")]
359 ErrorKind::FileNotFound => write!(f, "file not found"),
360 ErrorKind::Incomplete {
361 expected_len,
362 actual_len,
363 } => write!(
364 f,
365 "ASN.1 DER message is incomplete: expected {expected_len}, actual {actual_len}"
366 ),
367 #[cfg(feature = "std")]
368 ErrorKind::Io(err) => write!(f, "I/O error: {err:?}"),
369 ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed/malformed"),
370 ErrorKind::Length { tag } => write!(f, "incorrect length for {tag}"),
371 ErrorKind::Noncanonical { tag } => {
372 write!(f, "ASN.1 {tag} not canonically encoded as DER")
373 }
374 ErrorKind::OidMalformed => write!(f, "malformed OID"),
375 #[cfg(feature = "oid")]
376 ErrorKind::OidUnknown { oid } => {
377 write!(f, "unknown/unsupported OID: {oid}")
378 }
379 ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
380 ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
381 ErrorKind::Overflow => write!(f, "integer overflow"),
382 ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
383 #[cfg(feature = "pem")]
384 ErrorKind::Pem(e) => write!(f, "PEM error: {e}"),
385 #[cfg(feature = "std")]
386 ErrorKind::PermissionDenied => write!(f, "permission denied"),
387 ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
388 ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
389 ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
390 ErrorKind::TagUnexpected { expected, actual } => {
391 write!(f, "unexpected ASN.1 DER tag: ")?;
392
393 if let Some(tag) = expected {
394 write!(f, "expected {tag}, ")?;
395 }
396
397 write!(f, "got {actual}")
398 }
399 ErrorKind::TagUnknown { byte } => {
400 write!(f, "unknown/unsupported ASN.1 DER tag: 0x{byte:02x}")
401 }
402 ErrorKind::TrailingData { decoded, remaining } => {
403 write!(
404 f,
405 "trailing data at end of DER message: decoded {decoded} bytes, {remaining} bytes remaining"
406 )
407 }
408 ErrorKind::Utf8(e) => write!(f, "{e}"),
409 ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {tag}"),
410 }
411 }
412}