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 NestingDepth,
246
247 Noncanonical {
249 tag: Tag,
251 },
252
253 OidMalformed,
255
256 #[cfg(feature = "oid")]
265 OidUnknown {
266 oid: ObjectIdentifier,
268 },
269
270 #[deprecated(
273 since = "0.8.1",
274 note = "per X.680, 27.3 NOTE 3 duplicates are allowed"
275 )]
276 SetDuplicate,
277
278 SetOrdering,
280
281 Overflow,
283
284 Overlength,
286
287 #[cfg(feature = "pem")]
289 Pem(pem::Error),
290
291 #[cfg(feature = "std")]
293 PermissionDenied,
294
295 Reader,
297
298 TagModeUnknown,
300
301 TagNumberInvalid,
307
308 TagUnexpected {
310 expected: Option<Tag>,
315
316 actual: Tag,
318 },
319
320 TagUnknown {
322 byte: u8,
324 },
325
326 TrailingData {
328 decoded: Length,
330
331 remaining: Length,
333 },
334
335 Utf8(Utf8Error),
337
338 Value {
340 tag: Tag,
342 },
343}
344
345impl ErrorKind {
346 #[must_use]
349 pub fn at(self, position: Length) -> Error {
350 Error::new(self, position)
351 }
352
353 #[must_use]
355 pub fn to_error(self) -> Error {
356 Error::from_kind(self)
357 }
358}
359
360impl fmt::Display for ErrorKind {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 match self {
363 ErrorKind::DateTime => write!(f, "date/time error"),
364 ErrorKind::EncodingRules => write!(f, "invalid encoding rules"),
365 ErrorKind::Failed => write!(f, "operation failed"),
366 #[cfg(feature = "std")]
367 ErrorKind::FileNotFound => write!(f, "file not found"),
368 ErrorKind::Incomplete {
369 expected_len,
370 actual_len,
371 } => write!(
372 f,
373 "ASN.1 DER message is incomplete: expected {expected_len}, actual {actual_len}"
374 ),
375 #[cfg(feature = "std")]
376 ErrorKind::Io(err) => write!(f, "I/O error: {err:?}"),
377 ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed/malformed"),
378 ErrorKind::Length { tag } => write!(f, "incorrect length for {tag}"),
379 ErrorKind::NestingDepth => write!(f, "too many nested productions encountered"),
380 ErrorKind::Noncanonical { tag } => {
381 write!(f, "ASN.1 {tag} not canonically encoded as DER")
382 }
383 ErrorKind::OidMalformed => write!(f, "malformed OID"),
384 #[cfg(feature = "oid")]
385 ErrorKind::OidUnknown { oid } => {
386 write!(f, "unknown/unsupported OID: {oid}")
387 }
388 #[allow(deprecated)]
389 ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
390 ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
391 ErrorKind::Overflow => write!(f, "integer overflow"),
392 ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
393 #[cfg(feature = "pem")]
394 ErrorKind::Pem(e) => write!(f, "PEM error: {e}"),
395 #[cfg(feature = "std")]
396 ErrorKind::PermissionDenied => write!(f, "permission denied"),
397 ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
398 ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
399 ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
400 ErrorKind::TagUnexpected { expected, actual } => {
401 write!(f, "unexpected ASN.1 DER tag: ")?;
402
403 if let Some(tag) = expected {
404 write!(f, "expected {tag}, ")?;
405 }
406
407 write!(f, "got {actual}")
408 }
409 ErrorKind::TagUnknown { byte } => {
410 write!(f, "unknown/unsupported ASN.1 DER tag: 0x{byte:02x}")
411 }
412 ErrorKind::TrailingData { decoded, remaining } => {
413 write!(
414 f,
415 "trailing data at end of DER message: decoded {decoded} bytes, {remaining} bytes remaining"
416 )
417 }
418 ErrorKind::Utf8(e) => write!(f, "{e}"),
419 ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {tag}"),
420 }
421 }
422}