Skip to main content

rasn/error/
decode.rs

1//! Error types associated with decoding from ASN.1 codecs.
2
3use core::num::ParseIntError;
4
5use super::strings::PermittedAlphabetError;
6use alloc::{boxed::Box, string::ToString};
7
8use snafu::Snafu;
9#[cfg(feature = "backtraces")]
10use snafu::{Backtrace, GenerateImplicitData};
11
12use crate::Codec;
13use crate::de::Error;
14use crate::types::{Tag, constraints::Bounded, variants::Variants};
15use num_bigint::BigInt;
16
17/// Variants for every codec-specific `DecodeError` kind.
18#[derive(Debug)]
19#[non_exhaustive]
20#[allow(missing_docs)]
21pub enum CodecDecodeError {
22    Ber(BerDecodeErrorKind),
23    Cer(CerDecodeErrorKind),
24    Der(DerDecodeErrorKind),
25    Uper(UperDecodeErrorKind),
26    Aper(AperDecodeErrorKind),
27    Jer(JerDecodeErrorKind),
28    Oer(OerDecodeErrorKind),
29    Coer(CoerDecodeErrorKind),
30    Xer(XerDecodeErrorKind),
31}
32
33impl core::fmt::Display for CodecDecodeError {
34    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35        match self {
36            CodecDecodeError::Ber(kind) => write!(f, "BER decoding error: {kind}"),
37            CodecDecodeError::Cer(kind) => write!(f, "CER decoding error: {kind}"),
38            CodecDecodeError::Der(kind) => write!(f, "DER decoding error: {kind}"),
39            CodecDecodeError::Uper(kind) => write!(f, "UPER decoding error: {kind}"),
40            CodecDecodeError::Aper(kind) => write!(f, "APER decoding error: {kind}"),
41            CodecDecodeError::Jer(kind) => write!(f, "JER decoding error: {kind}"),
42            CodecDecodeError::Oer(kind) => write!(f, "OER decoding error: {kind}"),
43            CodecDecodeError::Coer(kind) => write!(f, "COER decoding error: {kind}"),
44            CodecDecodeError::Xer(kind) => write!(f, "XER decoding error: {kind}"),
45        }
46    }
47}
48
49macro_rules! impl_from {
50    ($variant:ident, $error_kind:ty) => {
51        impl From<$error_kind> for DecodeError {
52            fn from(error: $error_kind) -> Self {
53                Self::from_codec_kind(CodecDecodeError::$variant(error))
54            }
55        }
56    };
57}
58
59// implement From for each variant of CodecDecodeError into DecodeError
60impl_from!(Ber, BerDecodeErrorKind);
61impl_from!(Cer, CerDecodeErrorKind);
62impl_from!(Der, DerDecodeErrorKind);
63impl_from!(Uper, UperDecodeErrorKind);
64impl_from!(Aper, AperDecodeErrorKind);
65impl_from!(Jer, JerDecodeErrorKind);
66impl_from!(Oer, OerDecodeErrorKind);
67impl_from!(Coer, CoerDecodeErrorKind);
68impl_from!(Xer, XerDecodeErrorKind);
69
70impl From<CodecDecodeError> for DecodeError {
71    fn from(error: CodecDecodeError) -> Self {
72        Self::from_codec_kind(error)
73    }
74}
75
76/// An error type for failed decoding for every decoder.
77/// Abstracts over the different generic and codec-specific errors.
78///
79/// `kind` field is used to determine the kind of error that occurred.
80/// `codec` field is used to determine the codec that failed.
81/// `backtrace` field is used to determine the backtrace of the error.
82///
83/// There is `Kind::CodecSpecific` variant which wraps the codec-specific
84/// errors as `CodecEncodeError` type.
85///
86/// # Example
87/// ```rust
88/// use nom::Needed;
89/// use rasn::{Codec, error::DecodeErrorKind, prelude::*};
90///
91/// #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
92/// #[rasn(delegate)]
93/// struct MyString(pub VisibleString);
94///
95/// // Hello, World! in decimal bytes with trailing zeros
96/// // Below sample requires that `backtraces` feature is enabled
97/// let hello_data = vec![
98///     13, 145, 151, 102, 205, 235, 16, 119, 223, 203, 102, 68, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99///     0,
100/// ];
101/// // Initially parse the first 2 bytes for Error demonstration purposes
102/// let mut total = 2;
103///
104/// loop {
105///     let decoded = Codec::Uper.decode_from_binary::<MyString>(&hello_data[0..hello_data.len().min(total)]);
106///     match decoded {
107///         Ok(succ) => {
108///             println!("Successful decoding!");
109///             println!("Decoded string: {}", succ.0);
110///             break;
111///         }
112///         Err(e) => {
113///             // e is DecodeError, kind is boxed
114///             match *e.kind {
115///                 DecodeErrorKind::Incomplete { needed } => {
116///                     println!("Codec error source: {}", e.codec);
117///                     println!("Error kind: {}", e.kind);
118///                     // Here you need to know, that VisibleString has width of 7 bits and UPER parses input
119///                     // as bits, if you want to build logic around it, and feed exactly the correct amount of data.
120///                     // Usually you might need to just provide one byte at time instead when something is missing, since
121///                     // inner logic might not be known to you, and data structures can get complex.
122///                     total += match needed {
123///                         Needed::Size(n) => {
124///                             let missing_bytes = n.get() / 7;
125///                             missing_bytes
126///
127///                         }
128///                         _ => {
129///                             #[cfg(feature = "backtraces")]
130///                             println!("Backtrace:\n{:?}", e.backtrace);
131///                             panic!("Unexpected error! {e:?}");
132///                         }
133///                     }
134///                 }
135///                 k => {
136///                     #[cfg(feature = "backtraces")]
137///                     println!("Backtrace:\n{:?}", e.backtrace);
138///                     panic!("Unexpected error! {k:?}");
139///                 }
140///             }
141///         }
142///     }
143/// }
144///```
145/// The previous will produce something like following:
146/// ```text
147/// Codec error: UPER
148/// Error kind: Need more BITS to continue: (Size(83)).
149/// Successful decoding!
150/// Decoded string: Hello, world!
151/// ```
152#[derive(Debug)]
153#[allow(clippy::module_name_repetitions)]
154pub struct DecodeError {
155    /// The kind of decoding error received.
156    pub kind: Box<DecodeErrorKind>,
157    /// The codec that returned the error.
158    pub codec: Codec,
159    /// The backtrace associated with the error.
160    #[cfg(feature = "backtraces")]
161    pub backtrace: Backtrace,
162}
163
164impl core::fmt::Display for DecodeError {
165    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
166        write!(f, "{} (Codec: {})", self.kind, self.codec)?;
167        #[cfg(feature = "backtraces")]
168        write!(f, "\n\nBacktrace:\n{}", self.backtrace)?;
169        Ok(())
170    }
171}
172
173impl DecodeError {
174    /// Creates a wrapper around  EOF error from a given codec.
175    fn eof(codec: Codec) -> Self {
176        Self::from_kind(DecodeErrorKind::Eof, codec)
177    }
178
179    /// Creates a wrapper around a permitted alphabet error from a given codec.
180    #[must_use]
181    pub fn permitted_alphabet_error(reason: PermittedAlphabetError, codec: Codec) -> Self {
182        Self::from_kind(DecodeErrorKind::PermittedAlphabetError { reason }, codec)
183    }
184
185    /// Creates a wrapper around a size error from a given codec.
186    #[must_use]
187    pub fn size_constraint_not_satisfied(
188        size: Option<usize>,
189        expected: alloc::string::String,
190        codec: Codec,
191    ) -> Self {
192        Self::from_kind(
193            DecodeErrorKind::SizeConstraintNotSatisfied { size, expected },
194            codec,
195        )
196    }
197
198    /// Creates a wrapper around a value error from a given codec.
199    #[must_use]
200    pub fn value_constraint_not_satisfied(
201        value: BigInt,
202        expected: Bounded<i128>,
203        codec: Codec,
204    ) -> Self {
205        Self::from_kind(
206            DecodeErrorKind::ValueConstraintNotSatisfied { value, expected },
207            codec,
208        )
209    }
210    /// Creates a wrapper around a inner subtype constraint error from a given codec.
211    /// This is mainly used by standards.
212    #[must_use]
213    pub fn inner_subtype_constraint_not_satisfied(
214        reason: super::InnerSubtypeConstraintError,
215        codec: Codec,
216    ) -> Self {
217        Self::from_kind(
218            DecodeErrorKind::InnerSubtypeConstraintNotSatisfied { reason },
219            codec,
220        )
221    }
222
223    /// Creates a wrapper around a discriminant value error from a given codec.
224    #[must_use]
225    pub fn discriminant_value_not_found(discriminant: isize, codec: Codec) -> Self {
226        Self::from_kind(
227            DecodeErrorKind::DiscriminantValueNotFound { discriminant },
228            codec,
229        )
230    }
231
232    /// Creates a wrapper around a range value error from a given codec.
233    #[must_use]
234    pub fn range_exceeds_platform_width(needed: u32, present: u32, codec: Codec) -> Self {
235        Self::from_kind(
236            DecodeErrorKind::RangeExceedsPlatformWidth { needed, present },
237            codec,
238        )
239    }
240
241    /// Creates a wrapper around a fixed string conversion error from a given codec.
242    #[must_use]
243    pub fn fixed_string_conversion_failed(
244        tag: Tag,
245        actual: usize,
246        expected: usize,
247        codec: Codec,
248    ) -> Self {
249        Self::from_kind(
250            DecodeErrorKind::FixedStringConversionFailed {
251                tag,
252                actual,
253                expected,
254            },
255            codec,
256        )
257    }
258
259    /// Creates a wrapper around a sequence item error from a given codec.
260    #[must_use]
261    pub fn incorrect_item_number_in_sequence(expected: usize, actual: usize, codec: Codec) -> Self {
262        Self::from_kind(
263            DecodeErrorKind::IncorrectItemNumberInSequence { expected, actual },
264            codec,
265        )
266    }
267
268    /// Creates a wrapper around a integer overflow error from a given codec.
269    #[must_use]
270    pub fn integer_overflow(max_width: u32, codec: Codec) -> Self {
271        Self::from_kind(DecodeErrorKind::IntegerOverflow { max_width }, codec)
272    }
273
274    /// Creates a wrapper around a integer conversion error from a given codec.
275    #[must_use]
276    pub fn integer_type_conversion_failed(msg: alloc::string::String, codec: Codec) -> Self {
277        Self::from_kind(DecodeErrorKind::IntegerTypeConversionFailed { msg }, codec)
278    }
279
280    /// Creates a wrapper around a invalid bit string error from a given codec.
281    #[must_use]
282    pub fn invalid_bit_string(bits: u8, codec: Codec) -> Self {
283        Self::from_kind(DecodeErrorKind::InvalidBitString { bits }, codec)
284    }
285
286    /// Creates a wrapper around a missing tag error from a given codec.
287    #[must_use]
288    pub fn missing_tag_class_or_value_in_sequence_or_set(
289        class: crate::types::Class,
290        value: u32,
291        codec: Codec,
292    ) -> Self {
293        Self::from_kind(
294            DecodeErrorKind::MissingTagClassOrValueInSequenceOrSet { class, value },
295            codec,
296        )
297    }
298
299    /// Creates a wrapper around a unexpected non-extensible type error from a given codec.
300    #[must_use]
301    pub fn type_not_extensible(codec: Codec) -> Self {
302        Self::from_kind(DecodeErrorKind::TypeNotExtensible, codec)
303    }
304
305    /// Creates a wrapper around a parser error from a given codec.
306    #[must_use]
307    pub fn parser_fail(msg: alloc::string::String, codec: Codec) -> Self {
308        DecodeError::from_kind(DecodeErrorKind::Parser { msg }, codec)
309    }
310
311    /// Creates a wrapper around using `REAL` with unsupported codecs.
312    #[must_use]
313    pub fn real_not_supported(codec: Codec) -> Self {
314        DecodeError::from_kind(DecodeErrorKind::RealNotSupported, codec)
315    }
316
317    /// Creates a wrapper around a missing required extension error from a given codec.
318    #[must_use]
319    pub fn required_extension_not_present(tag: Tag, codec: Codec) -> Self {
320        Self::from_kind(DecodeErrorKind::RequiredExtensionNotPresent { tag }, codec)
321    }
322
323    /// Creates a wrapper around a missing enum index error from a given codec.
324    #[must_use]
325    pub fn enumeration_index_not_found(index: usize, extended_list: bool, codec: Codec) -> Self {
326        Self::from_kind(
327            DecodeErrorKind::EnumerationIndexNotFound {
328                index,
329                extended_list,
330            },
331            codec,
332        )
333    }
334
335    /// Creates a wrapper around a choice index exceeding platform width error from a given codec.
336    #[must_use]
337    pub fn choice_index_exceeds_platform_width(
338        needed: u32,
339        present: DecodeError,
340        codec: Codec,
341    ) -> Self {
342        Self::from_kind(
343            DecodeErrorKind::ChoiceIndexExceedsPlatformWidth { needed, present },
344            codec,
345        )
346    }
347
348    /// Creates a wrapper around a length exceeding platform width error from a given codec.
349    #[must_use]
350    pub fn length_exceeds_platform_width(msg: alloc::string::String, codec: Codec) -> Self {
351        Self::from_kind(DecodeErrorKind::LengthExceedsPlatformWidth { msg }, codec)
352    }
353
354    /// Creates a wrapper around a missing choice index error from a given codec.
355    #[must_use]
356    pub fn choice_index_not_found(index: usize, variants: Variants, codec: Codec) -> Self {
357        Self::from_kind(
358            DecodeErrorKind::ChoiceIndexNotFound { index, variants },
359            codec,
360        )
361    }
362
363    /// Creates a wrapper around a string conversion error from a given codec.
364    #[must_use]
365    pub fn string_conversion_failed(tag: Tag, msg: alloc::string::String, codec: Codec) -> Self {
366        Self::from_kind(DecodeErrorKind::StringConversionFailed { tag, msg }, codec)
367    }
368
369    /// Creates a wrapper around unexpected extra data error from a given codec.
370    #[must_use]
371    pub fn unexpected_extra_data(length: usize, codec: Codec) -> Self {
372        Self::from_kind(DecodeErrorKind::UnexpectedExtraData { length }, codec)
373    }
374
375    /// Creates a wrapper around unexpected empty input error from a given codec.
376    #[must_use]
377    pub fn unexpected_empty_input(codec: Codec) -> Self {
378        Self::from_kind(DecodeErrorKind::UnexpectedEmptyInput, codec)
379    }
380
381    /// Checks whether the length matches, and returns an error if not.
382    pub fn assert_length(
383        expected: usize,
384        actual: usize,
385        codec: Codec,
386    ) -> core::result::Result<(), DecodeError> {
387        if expected == actual {
388            Ok(())
389        } else {
390            Err(DecodeError::from_kind(
391                DecodeErrorKind::MismatchedLength { expected, actual },
392                codec,
393            ))
394        }
395    }
396
397    pub(crate) fn map_nom_err<T: core::fmt::Debug>(
398        error: nom::Err<nom::error::Error<T>>,
399        codec: Codec,
400    ) -> DecodeError {
401        match error {
402            nom::Err::Incomplete(needed) => DecodeError::incomplete(needed, codec),
403            nom::Err::Failure(e) | nom::Err::Error(e) => {
404                if e.code == nom::error::ErrorKind::Eof {
405                    DecodeError::eof(codec)
406                } else {
407                    DecodeError::parser_fail(alloc::format!("Parsing Failure: {e:?}"), codec)
408                }
409            }
410        }
411    }
412
413    /// Creates a new error from a given decode error kind and codec.
414    #[must_use]
415    pub fn from_kind(kind: DecodeErrorKind, codec: Codec) -> Self {
416        Self {
417            kind: Box::new(kind),
418            codec,
419            #[cfg(feature = "backtraces")]
420            backtrace: Backtrace::generate(),
421        }
422    }
423
424    #[must_use]
425    fn from_codec_kind(inner: CodecDecodeError) -> Self {
426        let codec = match inner {
427            CodecDecodeError::Ber(_) => crate::Codec::Ber,
428            #[allow(unreachable_patterns)]
429            CodecDecodeError::Cer(_) => crate::Codec::Cer,
430            CodecDecodeError::Der(_) => crate::Codec::Der,
431            #[allow(unreachable_patterns)]
432            CodecDecodeError::Uper(_) => crate::Codec::Uper,
433            #[allow(unreachable_patterns)]
434            CodecDecodeError::Aper(_) => crate::Codec::Aper,
435            CodecDecodeError::Jer(_) => crate::Codec::Jer,
436            CodecDecodeError::Oer(_) => crate::Codec::Oer,
437            CodecDecodeError::Coer(_) => crate::Codec::Coer,
438            CodecDecodeError::Xer(_) => crate::Codec::Xer,
439        };
440        Self {
441            kind: Box::new(DecodeErrorKind::CodecSpecific { inner }),
442            codec,
443            #[cfg(feature = "backtraces")]
444            backtrace: Backtrace::generate(),
445        }
446    }
447
448    /// Check if the root cause of this error matches the given predicate.
449    #[must_use]
450    pub fn matches_root_cause<F>(&self, predicate: F) -> bool
451    where
452        F: Fn(&DecodeErrorKind) -> bool,
453    {
454        let mut root = self;
455        while let DecodeErrorKind::FieldError { nested, .. } = &*root.kind {
456            root = &**nested;
457        }
458
459        predicate(&root.kind)
460    }
461}
462
463impl core::error::Error for DecodeError {}
464
465/// `DecodeError` kinds which are common for all codecs.
466#[derive(Snafu)]
467#[snafu(visibility(pub))]
468#[derive(Debug)]
469#[non_exhaustive]
470pub enum DecodeErrorKind {
471    /// Permitted alphabet constraint wasn't satisfied.
472    #[snafu(display("Alphabet constraint not satisfied {}", reason))]
473    PermittedAlphabetError {
474        /// The reason the constraint wasn't satisfied.
475        reason: PermittedAlphabetError,
476    },
477
478    /// Size constraint wasn't satisfied.
479    #[snafu(display("Size constraint not satisfied: expected: {expected}; actual: {size:?}"))]
480    SizeConstraintNotSatisfied {
481        /// Actual sie of the data
482        size: Option<usize>,
483        /// Expected size by the constraint
484        expected: alloc::string::String,
485    },
486
487    /// Value constraint wasn't satisfied.
488    #[snafu(display("Value constraint not satisfied: expected: {expected}; actual: {value}"))]
489    ValueConstraintNotSatisfied {
490        /// Actual value of the data
491        value: BigInt,
492        /// Expected value by the constraint
493        expected: Bounded<i128>,
494    },
495    /// Inner subtype constraint not satisfied.
496    #[snafu(display("Inner subtype constraint not satisfied: {reason}"))]
497    InnerSubtypeConstraintNotSatisfied {
498        /// The reason the constraint wasn't satisfied.
499        reason: super::InnerSubtypeConstraintError,
500    },
501
502    /// Codec specific error.
503    #[snafu(display("{inner}"))]
504    CodecSpecific {
505        /// The inner error type.
506        inner: CodecDecodeError,
507    },
508
509    /// Enumeration index didn't match any variant.
510    #[snafu(display(
511        "Enumeration index {} did not match any variant. Extended list checked: {}",
512        index,
513        extended_list
514    ))]
515    EnumerationIndexNotFound {
516        /// The found index of the enumerated variant.
517        index: usize,
518        /// Whether the index was checked from the extended variants.
519        extended_list: bool,
520    },
521
522    /// Choice index didn't match any variant.
523    #[snafu(display("Choice index {index} did not match any variant"))]
524    ChoiceIndexNotFound {
525        /// The found index of the choice variant.
526        index: usize,
527        /// The variants checked for presence.
528        variants: Variants,
529    },
530
531    /// Choice index exceeds maximum possible address width.
532    #[snafu(display(
533        "Choice index exceeds platform index width. Needed {needed} bytes, present: {present}"
534    ))]
535    ChoiceIndexExceedsPlatformWidth {
536        /// Amount of bytes needed.
537        needed: u32,
538        /// Inner error
539        present: DecodeError,
540    },
541
542    /// Uncategorised error.
543    #[snafu(display("Custom error: {}", msg))]
544    Custom {
545        /// The error's message.
546        msg: alloc::string::String,
547    },
548
549    /// Discriminant index didn't match any variant.
550    #[snafu(display("Discriminant value {} did not match any variant", discriminant))]
551    DiscriminantValueNotFound {
552        /// The found value of the discriminant
553        discriminant: isize,
554    },
555
556    /// Duplicate fields found.
557    #[snafu(display("Duplicate field for `{}`", name))]
558    DuplicateField {
559        /// The field's name.
560        name: &'static str,
561    },
562
563    /// Exceeds maxmium allowed length.
564    #[snafu(display("Expected maximum of {} items", length))]
565    ExceedsMaxLength {
566        /// The maximum length.
567        length: num_bigint::BigUint,
568    },
569
570    ///  More than `usize::MAX` number of data requested.
571    #[snafu(display("Length of the data exceeds platform address width"))]
572    LengthExceedsPlatformWidth {
573        /// The specific message of the length error.
574        msg: alloc::string::String,
575    },
576
577    /// An error when decoding a field in a constructed type.
578    #[snafu(display("Error when decoding field `{}`: {}", name, nested))]
579    FieldError {
580        /// The field's name.
581        name: &'static str,
582        /// The underlying error type.
583        nested: Box<DecodeError>,
584    },
585
586    /// Input is provided as BIT slice for nom in UPER/APER.
587    /// On BER/CER/DER/OER/COER it is a BYTE slice.
588    /// Hence, `needed` field can describe either bits or bytes depending on the codec.
589    #[snafu(display("Need more data to continue: {:?}", needed))]
590    Incomplete {
591        /// Amount of bits/bytes needed.
592        needed: nom::Needed,
593    },
594    /// Encountered EOF when decoding.
595    /// BER/CER/DER uses EOF as part of the decoding logic.
596    #[snafu(display("Unexpected EOF when decoding"))]
597    Eof,
598
599    /// Invalid item number in sequence.
600    #[snafu(display(
601        "Invalid item number in Sequence: expected: {}; actual: {}",
602        expected,
603        actual
604    ))]
605    IncorrectItemNumberInSequence {
606        /// The expected item number.
607        expected: usize,
608        /// The actual item number.
609        actual: usize,
610    },
611
612    /// Integer conversion overflow.
613    #[snafu(display("Actual integer larger than expected {} bits", max_width))]
614    IntegerOverflow {
615        /// The maximum integer width.
616        max_width: u32,
617    },
618
619    /// Integer conversion failure.
620    #[snafu(display("Failed to cast integer to another integer type: {msg} "))]
621    IntegerTypeConversionFailed {
622        /// The reason the conversion failed.
623        msg: alloc::string::String,
624    },
625
626    /// Real conversion failure.
627    #[snafu(display("Invalid real encoding"))]
628    InvalidRealEncoding,
629
630    /// Decoder doesn't support REAL
631    #[snafu(display("Decoder doesn't support `REAL` type"))]
632    RealNotSupported,
633
634    /// `BitString` contains an invalid amount of unused bits.
635    #[snafu(display("BitString contains an invalid amount of unused bits: {}", bits))]
636    InvalidBitString {
637        /// The amount of invalid bits.
638        bits: u8,
639    },
640
641    /// BOOL value is not `0` or `0xFF`.
642    #[snafu(display(
643        "Bool value is not `0` or `0xFF` as canonical requires. Actual: {}",
644        value
645    ))]
646    InvalidBool {
647        /// The invalid bool value.
648        value: u8,
649    },
650
651    /// Length of Length cannot be zero.
652    #[snafu(display("Length of Length cannot be zero"))]
653    ZeroLengthOfLength,
654    /// The length does not match what was expected.
655    #[snafu(display("Expected {} bytes, actual length was {} bytes", expected, actual))]
656    MismatchedLength {
657        /// The expected length.
658        expected: usize,
659        /// The actual length.
660        actual: usize,
661    },
662
663    /// Missing field in a sequence.
664    #[snafu(display("Missing field `{}`", name))]
665    MissingField {
666        /// The field's name.
667        name: &'static str,
668    },
669    /// When there is a mismatch between the expected and actual tag class or `value`.
670    #[snafu(display(
671        "Expected class: {}, value: {} in sequence or set Missing tag class or value in sequence or set",
672        class,
673        value
674    ))]
675    MissingTagClassOrValueInSequenceOrSet {
676        /// The tag's class.
677        class: crate::types::Class,
678        /// The tag's value.
679        value: u32,
680    },
681
682    /// The range of the integer exceeds the platform width.
683    #[snafu(display(
684        "Integer range larger than possible to address on this platform. needed: {needed} present: {present}"
685    ))]
686    RangeExceedsPlatformWidth {
687        /// Amount of bytes needed.
688        needed: u32,
689        /// Amount of bytes needed.
690        present: u32,
691    },
692    /// A specific required extension not present.
693    #[snafu(display("Extension with class `{}` and tag `{}` required, but not present", tag.class, tag.value))]
694    RequiredExtensionNotPresent {
695        /// The tag of the required extension.
696        tag: crate::types::Tag,
697    },
698    /// General error when parsing data.
699    #[snafu(display("Error in Parser: {}", msg))]
700    Parser {
701        /// The error's message.
702        msg: alloc::string::String,
703    },
704    /// General error for failed ASN.1 string conversion from bytes.
705    #[snafu(display(
706        "Failed to convert byte array into valid ASN.1 string. String type as tag: {} Error: {}",
707        tag,
708        msg
709    ))]
710    StringConversionFailed {
711        /// Universal tag of the string type.
712        tag: Tag,
713        /// The error's message.
714        msg: alloc::string::String,
715    },
716    /// General error for failed ASN.1 fixed-sized string conversion from bytes.
717    #[snafu(display(
718        "Failed to convert byte array into valid fixed-sized ASN.1 string. String type as tag: {}, actual: {}, expected: {}",
719        tag,
720        actual,
721        expected
722    ))]
723    FixedStringConversionFailed {
724        /// Tag of the string type.
725        tag: Tag,
726        /// Expected length
727        expected: usize,
728        /// Actual length
729        actual: usize,
730    },
731    /// An error when the choice cannot be created from the given variant.
732    #[snafu(display("No valid choice for `{}`", name))]
733    NoValidChoice {
734        /// The field's name.
735        name: &'static str,
736    },
737
738    /// An error when the type is not extensible when it should.
739    #[snafu(display("Attempted to decode extension on non-extensible type"))]
740    TypeNotExtensible,
741    /// Unexpected extra data found.
742    #[snafu(display("Unexpected extra data found: length `{}` bytes", length))]
743    UnexpectedExtraData {
744        /// The amount of garbage data.
745        length: usize,
746    },
747    /// An error when a unknown field is found when decoding sequence.
748    #[snafu(display("Unknown field with index {} and tag {}", index, tag))]
749    UnknownField {
750        /// Index of the field.
751        index: usize,
752        /// Tag of the field.
753        tag: Tag,
754    },
755    /// An error when there should be more data but it is not present.
756    #[snafu(display("No input was provided where expected in the given SEQUENCE or INTEGER type"))]
757    UnexpectedEmptyInput,
758
759    /// An error when the decoder exceeds maximum allowed parse depth.
760    #[snafu(display("Exceeded maximum parse depth"))]
761    ExceedsMaxParseDepth,
762}
763
764/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for BER.
765#[derive(Snafu, Debug)]
766#[snafu(visibility(pub))]
767#[non_exhaustive]
768pub enum BerDecodeErrorKind {
769    /// An error when the length is not definite.
770    #[snafu(display("Indefinite length encountered but not allowed"))]
771    IndefiniteLengthNotAllowed,
772    /// An error if the value is not primitive when required.
773    #[snafu(display("Invalid constructed identifier for ASN.1 value: not primitive"))]
774    InvalidConstructedIdentifier,
775    /// Invalid date.
776    #[snafu(display("Invalid date string: {}", msg))]
777    InvalidDate {
778        /// The reason as string
779        msg: alloc::string::String,
780    },
781    /// An error when the object identifier is invalid.
782    #[snafu(display("Invalid object identifier with missing or corrupt root nodes"))]
783    InvalidObjectIdentifier,
784    /// The tag does not match what was expected.
785    #[snafu(display("Expected {:?} tag, actual tag: {:?}", expected, actual))]
786    MismatchedTag {
787        /// The expected tag.
788        expected: Tag,
789        /// The actual tag.
790        actual: Tag,
791    },
792}
793
794impl BerDecodeErrorKind {
795    /// A helper function to create an error [`BerDecodeErrorKind::InvalidDate`].
796    #[must_use]
797    pub fn invalid_date(msg: alloc::string::String) -> CodecDecodeError {
798        CodecDecodeError::Ber(Self::InvalidDate { msg })
799    }
800    /// A helper function to create an error [`BerDecodeErrorKind::MismatchedTag`].
801    pub fn assert_tag(expected: Tag, actual: Tag) -> core::result::Result<(), DecodeError> {
802        if expected == actual {
803            Ok(())
804        } else {
805            Err(BerDecodeErrorKind::MismatchedTag { expected, actual }.into())
806        }
807    }
808}
809// TODO check if there are more codec-specific errors here
810/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for CER.
811#[derive(Snafu, Debug)]
812#[snafu(visibility(pub))]
813#[non_exhaustive]
814pub enum CerDecodeErrorKind {}
815
816/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for DER.
817#[derive(Snafu, Debug)]
818#[snafu(visibility(pub))]
819#[non_exhaustive]
820pub enum DerDecodeErrorKind {
821    /// An error when constructed encoding encountered but not allowed.
822    #[snafu(display("Constructed encoding encountered but not allowed"))]
823    ConstructedEncodingNotAllowed,
824}
825
826/// An error that occurred when decoding JER.
827#[derive(Snafu, Debug)]
828#[snafu(visibility(pub))]
829#[non_exhaustive]
830pub enum JerDecodeErrorKind {
831    /// An error when the end of input is reached, but more data is needed.
832    #[snafu(display("Unexpected end of input while decoding JER"))]
833    EndOfInput {},
834    /// An error when the JSON type is not the expected type.
835    #[snafu(display(
836        "Found mismatching JSON value. Expected type: {}. Found value: {}",
837        needed,
838        found
839    ))]
840    TypeMismatch {
841        /// Expected JSON type.
842        needed: &'static str,
843        /// Found JSON value.
844        found: alloc::string::String,
845    },
846    /// An error when the JSON value is not a valid bit string.
847    #[snafu(display("Found invalid byte in bit string: {parse_int_err}"))]
848    InvalidJerBitstring {
849        /// The error that occurred when parsing the `BitString` byte.
850        parse_int_err: ParseIntError,
851    },
852    /// An error when the JSON value is not a valid octet string.
853    #[snafu(display("Found invalid character in octet string"))]
854    InvalidJerOctetString {},
855    /// An error when the JSON value is not a valid OID string.
856    #[snafu(display("Failed to construct OID from value {value}",))]
857    InvalidOIDString {
858        /// The JSON value that could not be converted to an OID.
859        value: serde_json::Value,
860    },
861    /// An error when the JSON value is not a valid enumerated discriminant.
862    #[snafu(display("Found invalid enumerated discriminant {discriminant}",))]
863    InvalidEnumDiscriminant {
864        /// The invalid enumerated discriminant.
865        discriminant: alloc::string::String,
866    },
867}
868
869impl JerDecodeErrorKind {
870    /// Helper function to create an error [`JerDecodeErrorKind::EndOfInput`].
871    #[must_use]
872    pub fn eoi() -> CodecDecodeError {
873        CodecDecodeError::Jer(JerDecodeErrorKind::EndOfInput {})
874    }
875}
876
877// TODO check if there codec-specific errors here
878/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for UPER.
879#[derive(Snafu, Debug)]
880#[snafu(visibility(pub))]
881#[non_exhaustive]
882pub enum UperDecodeErrorKind {}
883
884// TODO check if there codec-specific errors here
885/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for APER.
886#[derive(Snafu, Debug)]
887#[snafu(visibility(pub))]
888#[non_exhaustive]
889pub enum AperDecodeErrorKind {}
890
891/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for XER.
892#[derive(Snafu, Debug)]
893#[snafu(visibility(pub))]
894#[non_exhaustive]
895pub enum XerDecodeErrorKind {
896    #[snafu(display("Unexpected end of input while decoding XER"))]
897    /// An error that indicates that the XML input ended unexpectedly
898    EndOfXmlInput {},
899    #[snafu(display(
900        "Found mismatching XML value. Expected type: {}. Found value: {}.",
901        needed,
902        found
903    ))]
904    /// An error that indicates an unexpected XML tag type or value
905    XmlTypeMismatch {
906        /// the expected tag type or value
907        needed: &'static str,
908        /// the encountered tag type or value
909        found: alloc::string::String,
910    },
911    #[snafu(display("Found invalid character in octet string"))]
912    /// An error that indicates a character in an octet string that does not conform to the hex alphabet
913    InvalidXerOctetstring {
914        /// Inner error thrown by the `parse` method
915        parse_int_err: ParseIntError,
916    },
917    #[snafu(display("Encountered invalid value: {details}"))]
918    /// An error that indicates invalid input XML
919    InvalidInput {
920        /// Error details from the underlying XML parser
921        details: &'static str,
922    },
923    #[snafu(display("Found invalid open type encoding: {inner_err}"))]
924    /// An error that indicates invalid XML in an ASN.1 open type value
925    InvalidOpenType {
926        /// Error details from the underlying XML parser
927        inner_err: xml_no_std::writer::Error,
928    },
929    #[snafu(display("XML parser error: {details}"))]
930    /// Miscellaneous error in the underlying XML parser
931    XmlParser {
932        /// Error details from the underlying XML parser
933        details: alloc::string::String,
934    },
935    #[snafu(display("Error matching tag names: expected {needed}, found {found}"))]
936    /// An error indicating an unexpected XML tag name
937    XmlTag {
938        /// The expected tag name
939        needed: alloc::string::String,
940        /// The encountered tag name
941        found: alloc::string::String,
942    },
943    #[snafu(display("Encoding violates ITU-T X.693 (02/2021): {details}"))]
944    /// An error that quotes the ITU-T X.693 paragraph being violated
945    SpecViolation {
946        /// Paragraph and excerpt from the ITU-T X.693 spec
947        details: alloc::string::String,
948    },
949}
950
951/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for OER.
952#[derive(Snafu, Debug)]
953#[snafu(visibility(pub))]
954#[non_exhaustive]
955pub enum OerDecodeErrorKind {
956    /// Tag class must be one of Universal (0b00), Application (0b01), Context (0b10) or Private (0b11).
957    #[snafu(display("Invalid tag class when decoding choice: actual {:?}", class))]
958    InvalidTagClassOnChoice {
959        /// The actual class.
960        class: u8,
961    },
962    /// The tag number was incorrect when decoding a Choice type.
963    #[snafu(display("Invalid tag number when decoding Choice: {value}"))]
964    InvalidTagNumberOnChoice {
965        /// Invalid tag bytes at the time of decoding.
966        value: u32,
967    },
968    /// An error scenario where the tag number is not present in the expected Choice type.
969    #[snafu(display(
970        "Tag not found from the variants of the platform when decoding Choice. Tag: {value}, extensible status: {is_extensible}"
971    ))]
972    InvalidTagVariantOnChoice {
973        /// The tag number that was not found.
974        value: Tag,
975        /// The extensible status of the Choice type.
976        is_extensible: bool,
977    },
978
979    /// An error scenario where the extension header in preamble is invalid.
980    InvalidExtensionHeader {
981        /// The amount of invalid bits.
982        msg: alloc::string::String,
983    },
984    /// An error scenario where the `BitString` is invalid for some reason.
985    #[snafu(display("Invalid BitString: {msg}"))]
986    InvalidOerBitString {
987        /// The amount of invalid bits.
988        msg: alloc::string::String,
989    },
990    /// An error scenario where the preamble is invalid.
991    #[snafu(display("Invalid preamble: {msg}"))]
992    InvalidPreamble {
993        /// Message related to reason
994        msg: alloc::string::String,
995    },
996}
997
998impl OerDecodeErrorKind {
999    #[must_use]
1000    /// Helper function to create an error [`OerDecodeErrorKind::InvalidTagNumberOnChoice`].
1001    pub fn invalid_tag_number_on_choice(value: u32) -> DecodeError {
1002        CodecDecodeError::Oer(Self::InvalidTagNumberOnChoice { value }).into()
1003    }
1004    #[must_use]
1005    /// Helper function to create an error [`OerDecodeErrorKind::InvalidTagVariantOnChoice`].
1006    pub fn invalid_tag_variant_on_choice(value: Tag, is_extensible: bool) -> DecodeError {
1007        CodecDecodeError::Oer(Self::InvalidTagVariantOnChoice {
1008            value,
1009            is_extensible,
1010        })
1011        .into()
1012    }
1013
1014    /// Helper function to create an error [`OerDecodeErrorKind::InvalidExtensionHeader`].
1015    #[must_use]
1016    pub fn invalid_extension_header(msg: alloc::string::String) -> DecodeError {
1017        CodecDecodeError::Oer(Self::InvalidExtensionHeader { msg }).into()
1018    }
1019    /// Helper function to create an error [`OerDecodeErrorKind::InvalidOerBitString`].
1020    #[must_use]
1021    pub fn invalid_bit_string(msg: alloc::string::String) -> DecodeError {
1022        CodecDecodeError::Oer(Self::InvalidOerBitString { msg }).into()
1023    }
1024    /// Helper function to create an error [`OerDecodeErrorKind::InvalidPreamble`].
1025    #[must_use]
1026    pub fn invalid_preamble(msg: alloc::string::String) -> DecodeError {
1027        CodecDecodeError::Oer(Self::InvalidPreamble { msg }).into()
1028    }
1029}
1030
1031/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for COER.
1032#[derive(Snafu, Debug)]
1033#[snafu(visibility(pub))]
1034#[non_exhaustive]
1035pub enum CoerDecodeErrorKind {
1036    /// An error of a result where the stricter Canonical Octet Encoding is not reached.
1037    #[snafu(display(
1038        "Invalid Canonical Octet Encoding, not encoded as the smallest possible number of octets: {msg}"
1039    ))]
1040    NotValidCanonicalEncoding {
1041        /// Reason for the error.
1042        msg: alloc::string::String,
1043    },
1044}
1045
1046impl crate::de::Error for DecodeError {
1047    fn custom<D: core::fmt::Display>(msg: D, codec: Codec) -> Self {
1048        Self::from_kind(
1049            DecodeErrorKind::Custom {
1050                msg: msg.to_string(),
1051            },
1052            codec,
1053        )
1054    }
1055    fn incomplete(needed: nom::Needed, codec: Codec) -> Self {
1056        Self::from_kind(DecodeErrorKind::Incomplete { needed }, codec)
1057    }
1058
1059    fn exceeds_max_length(length: num_bigint::BigUint, codec: Codec) -> Self {
1060        Self::from_kind(DecodeErrorKind::ExceedsMaxLength { length }, codec)
1061    }
1062
1063    fn missing_field(name: &'static str, codec: Codec) -> Self {
1064        Self::from_kind(DecodeErrorKind::MissingField { name }, codec)
1065    }
1066
1067    fn no_valid_choice(name: &'static str, codec: Codec) -> Self {
1068        Self::from_kind(DecodeErrorKind::NoValidChoice { name }, codec)
1069    }
1070
1071    fn field_error(name: &'static str, nested: DecodeError, codec: Codec) -> Self {
1072        Self::from_kind(
1073            DecodeErrorKind::FieldError {
1074                name,
1075                nested: Box::new(nested),
1076            },
1077            codec,
1078        )
1079    }
1080
1081    fn duplicate_field(name: &'static str, codec: Codec) -> Self {
1082        Self::from_kind(DecodeErrorKind::DuplicateField { name }, codec)
1083    }
1084    fn unknown_field(index: usize, tag: Tag, codec: Codec) -> Self {
1085        Self::from_kind(DecodeErrorKind::UnknownField { index, tag }, codec)
1086    }
1087}
1088
1089#[cfg(test)]
1090mod tests {
1091    use crate::prelude::*;
1092    #[test]
1093    fn test_ber_decode_date() {
1094        use crate::error::{DecodeError, DecodeErrorKind};
1095        // "230122130000-050Z" as bytes
1096        let data = [
1097            23, 17, 50, 51, 48, 49, 50, 50, 49, 51, 48, 48, 48, 48, 45, 48, 53, 48, 90,
1098        ];
1099        let result = crate::ber::decode::<UtcTime>(&data);
1100        match result {
1101            Err(DecodeError { kind, .. }) => {
1102                if let DecodeErrorKind::CodecSpecific {
1103                    inner:
1104                        crate::error::CodecDecodeError::Ber(
1105                            crate::error::BerDecodeErrorKind::InvalidDate { msg },
1106                        ),
1107                    ..
1108                } = *kind
1109                {
1110                    assert_eq!(msg, "230122130000-050Z");
1111                } else {
1112                    // Handle other kinds of errors
1113                    panic!("Unexpected error kind: {kind}");
1114                }
1115            }
1116            Ok(_) => panic!("Expected error"),
1117        }
1118    }
1119    #[test]
1120    fn test_uper_missing_choice_index() {
1121        use crate as rasn;
1122        use crate::Codec;
1123        use crate::error::{DecodeError, DecodeErrorKind};
1124        #[derive(AsnType, Decode, Debug, PartialEq)]
1125        #[rasn(choice, automatic_tags)]
1126        enum MyChoice {
1127            Normal(Integer),
1128            High(Integer),
1129            Medium(Integer),
1130        }
1131        // Value 333 encoded for missing choice index 3
1132        let data = [192, 128, 83, 64];
1133        let result = Codec::Uper.decode_from_binary::<MyChoice>(&data);
1134        match result {
1135            Ok(_) => {
1136                panic!("Unexpected OK!");
1137            }
1138            Err(DecodeError { kind, .. }) => {
1139                if let DecodeErrorKind::ChoiceIndexNotFound { index, .. } = *kind {
1140                    assert_eq!(index, 3);
1141                } else {
1142                    // Handle other kinds of errors
1143                    panic!("Unexpected error kind: {kind}");
1144                }
1145            }
1146        }
1147    }
1148}