rasn/error/
decode.rs

1use core::num::ParseIntError;
2
3use super::strings::PermittedAlphabetError;
4use alloc::{boxed::Box, string::ToString};
5
6use jzon::JsonValue;
7use snafu::Snafu;
8#[cfg(feature = "backtraces")]
9use snafu::{Backtrace, GenerateImplicitData};
10
11use crate::de::Error;
12use crate::types::{constraints::Bounded, variants::Variants, Integer, Tag};
13use crate::Codec;
14
15/// Variants for every codec-specific `DecodeError` kind.
16#[derive(Debug)]
17#[non_exhaustive]
18pub enum CodecDecodeError {
19    Ber(BerDecodeErrorKind),
20    Cer(CerDecodeErrorKind),
21    Der(DerDecodeErrorKind),
22    Uper(UperDecodeErrorKind),
23    Aper(AperDecodeErrorKind),
24    Jer(JerDecodeErrorKind),
25    Oer(OerDecodeErrorKind),
26    Coer(CoerDecodeErrorKind),
27}
28
29macro_rules! impl_from {
30    ($variant:ident, $error_kind:ty) => {
31        impl From<$error_kind> for DecodeError {
32            fn from(error: $error_kind) -> Self {
33                Self::from_codec_kind(CodecDecodeError::$variant(error))
34            }
35        }
36    };
37}
38
39// implement From for each variant of CodecDecodeError into DecodeError
40impl_from!(Ber, BerDecodeErrorKind);
41impl_from!(Cer, CerDecodeErrorKind);
42impl_from!(Der, DerDecodeErrorKind);
43impl_from!(Uper, UperDecodeErrorKind);
44impl_from!(Aper, AperDecodeErrorKind);
45impl_from!(Jer, JerDecodeErrorKind);
46impl_from!(Oer, OerDecodeErrorKind);
47impl_from!(Coer, CoerDecodeErrorKind);
48
49impl From<CodecDecodeError> for DecodeError {
50    fn from(error: CodecDecodeError) -> Self {
51        Self::from_codec_kind(error)
52    }
53}
54
55/// An error type for failed decoding for every decoder.
56/// Abstracts over the different generic and codec-specific errors.
57///
58/// `kind` field is used to determine the kind of error that occurred.
59/// `codec` field is used to determine the codec that failed.
60/// `backtrace` field is used to determine the backtrace of the error.
61///
62/// There is `Kind::CodecSpecific` variant which wraps the codec-specific
63/// errors as `CodecEncodeError` type.
64///
65/// # Example
66/// ```rust
67/// use nom::Needed;
68/// use rasn::codec::Codec;
69/// use rasn::error::DecodeErrorKind;
70/// use rasn::prelude::*;
71///
72/// #[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
73/// #[rasn(delegate)]
74/// struct MyString(pub VisibleString);
75///
76/// fn main() {
77///     // Hello, World! in decimal bytes with trailing zeros
78///     // Below sample requires that `backtraces` feature is enabled
79///     let hello_data = vec![
80///         13, 145, 151, 102, 205, 235, 16, 119, 223, 203, 102, 68, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81///         0,
82///     ];
83///     // Initially parse the first 2 bytes for Error demonstration purposes
84///     let mut total = 2;
85///
86///     loop {
87///         let decoded = Codec::Uper.decode_from_binary::<MyString>(&hello_data[0..hello_data.len().min(total)]);
88///         match decoded {
89///             Ok(succ) => {
90///                 println!("Successful decoding!");
91///                 println!("Decoded string: {}", succ.0);
92///                 break;
93///             }
94///             Err(e) => {
95///                 // e is DecodeError, kind is boxed
96///                 match *e.kind {
97///                     DecodeErrorKind::Incomplete { needed } => {
98///                         println!("Codec error source: {}", e.codec);
99///                         println!("Error kind: {}", e.kind);
100///                         // Here you need to know, that VisibleString has width of 7 bits and UPER parses input
101///                         // as bits, if you want to build logic around it, and feed exactly the correct amount of data.
102///                         // Usually you might need to just provide one byte at time instead when something is missing, since
103///                         // inner logic might not be known to you, and data structures can get complex.
104///                         total += match needed {
105///                             Needed::Size(n) => {
106///                                 let missing_bytes = n.get() / 7;
107///                                 missing_bytes
108///                                
109///                             }
110///                             _ => {
111///                                 #[cfg(feature = "backtraces")]
112///                                 println!("Backtrace:\n{:?}", e.backtrace);
113///                                 panic!("Unexpected error! {e:?}");
114///                             }
115///                         }
116///                     }
117///                     k => {
118///                         #[cfg(feature = "backtraces")]
119///                         println!("Backtrace:\n{:?}", e.backtrace);
120///                         panic!("Unexpected error! {k:?}");
121///                     }
122///                 }
123///             }
124///         }
125///     }
126/// }
127///```
128/// The previous will produce something like following:
129/// ```text
130/// Codec error: UPER
131/// Error kind: Need more BITS to continue: (Size(83)).
132/// Successful decoding!
133/// Decoded string: Hello, world!
134/// ```
135#[derive(Debug)]
136#[allow(clippy::module_name_repetitions)]
137pub struct DecodeError {
138    pub kind: Box<DecodeErrorKind>,
139    pub codec: Codec,
140    #[cfg(feature = "backtraces")]
141    pub backtrace: Backtrace,
142}
143impl core::fmt::Display for DecodeError {
144    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
145        writeln!(f, "Error Kind: {}", self.kind)?;
146        writeln!(f, "Codec: {}", self.codec)?;
147        #[cfg(feature = "backtraces")]
148        write!(f, "\nBacktrace:\n{}", self.backtrace)?;
149        Ok(())
150    }
151}
152
153impl DecodeError {
154    #[must_use]
155    pub fn alphabet_constraint_not_satisfied(reason: PermittedAlphabetError, codec: Codec) -> Self {
156        Self::from_kind(
157            DecodeErrorKind::AlphabetConstraintNotSatisfied { reason },
158            codec,
159        )
160    }
161    #[must_use]
162    pub fn size_constraint_not_satisfied(
163        size: Option<usize>,
164        expected: alloc::string::String,
165        codec: Codec,
166    ) -> Self {
167        Self::from_kind(
168            DecodeErrorKind::SizeConstraintNotSatisfied { size, expected },
169            codec,
170        )
171    }
172    #[must_use]
173    pub fn value_constraint_not_satisfied(
174        value: Integer,
175        expected: Bounded<i128>,
176        codec: Codec,
177    ) -> Self {
178        Self::from_kind(
179            DecodeErrorKind::ValueConstraintNotSatisfied { value, expected },
180            codec,
181        )
182    }
183    #[must_use]
184    pub fn discriminant_value_not_found(discriminant: isize, codec: Codec) -> Self {
185        Self::from_kind(
186            DecodeErrorKind::DiscriminantValueNotFound { discriminant },
187            codec,
188        )
189    }
190    #[must_use]
191    pub fn range_exceeds_platform_width(needed: u32, present: u32, codec: Codec) -> Self {
192        Self::from_kind(
193            DecodeErrorKind::RangeExceedsPlatformWidth { needed, present },
194            codec,
195        )
196    }
197    #[must_use]
198    pub fn fixed_string_conversion_failed(
199        tag: Tag,
200        actual: usize,
201        expected: usize,
202        codec: Codec,
203    ) -> Self {
204        Self::from_kind(
205            DecodeErrorKind::FixedStringConversionFailed {
206                tag,
207                actual,
208                expected,
209            },
210            codec,
211        )
212    }
213    #[must_use]
214    pub fn incorrect_item_number_in_sequence(expected: usize, actual: usize, codec: Codec) -> Self {
215        Self::from_kind(
216            DecodeErrorKind::IncorrectItemNumberInSequence { expected, actual },
217            codec,
218        )
219    }
220    #[must_use]
221    pub fn integer_overflow(max_width: u32, codec: Codec) -> Self {
222        Self::from_kind(DecodeErrorKind::IntegerOverflow { max_width }, codec)
223    }
224    #[must_use]
225    pub fn integer_type_conversion_failed(msg: alloc::string::String, codec: Codec) -> Self {
226        Self::from_kind(DecodeErrorKind::IntegerTypeConversionFailed { msg }, codec)
227    }
228    #[must_use]
229    pub fn invalid_bit_string(bits: u8, codec: Codec) -> Self {
230        Self::from_kind(DecodeErrorKind::InvalidBitString { bits }, codec)
231    }
232    #[must_use]
233    pub fn missing_tag_class_or_value_in_sequence_or_set(
234        class: crate::types::Class,
235        value: u32,
236        codec: Codec,
237    ) -> Self {
238        Self::from_kind(
239            DecodeErrorKind::MissingTagClassOrValueInSequenceOrSet { class, value },
240            codec,
241        )
242    }
243
244    #[must_use]
245    pub fn type_not_extensible(codec: Codec) -> Self {
246        Self::from_kind(DecodeErrorKind::TypeNotExtensible, codec)
247    }
248    #[must_use]
249    pub fn parser_fail(msg: alloc::string::String, codec: Codec) -> Self {
250        DecodeError::from_kind(DecodeErrorKind::Parser { msg }, codec)
251    }
252
253    #[must_use]
254    pub fn required_extension_not_present(tag: Tag, codec: Codec) -> Self {
255        Self::from_kind(DecodeErrorKind::RequiredExtensionNotPresent { tag }, codec)
256    }
257    #[must_use]
258    pub fn extension_present_but_not_required(tag: crate::types::Tag, codec: Codec) -> Self {
259        Self::from_kind(
260            DecodeErrorKind::ExtensionPresentButNotRequired { tag },
261            codec,
262        )
263    }
264    #[must_use]
265    pub fn enumeration_index_not_found(index: usize, extended_list: bool, codec: Codec) -> Self {
266        Self::from_kind(
267            DecodeErrorKind::EnumerationIndexNotFound {
268                index,
269                extended_list,
270            },
271            codec,
272        )
273    }
274    #[must_use]
275    pub fn choice_index_exceeds_platform_width(needed: u32, present: u64, codec: Codec) -> Self {
276        Self::from_kind(
277            DecodeErrorKind::ChoiceIndexExceedsPlatformWidth { needed, present },
278            codec,
279        )
280    }
281    #[must_use]
282    pub fn length_exceeds_platform_width(msg: alloc::string::String, codec: Codec) -> Self {
283        Self::from_kind(DecodeErrorKind::LengthExceedsPlatformWidth { msg }, codec)
284    }
285
286    #[must_use]
287    pub fn choice_index_not_found(index: usize, variants: Variants, codec: Codec) -> Self {
288        Self::from_kind(
289            DecodeErrorKind::ChoiceIndexNotFound { index, variants },
290            codec,
291        )
292    }
293    #[must_use]
294    pub fn string_conversion_failed(tag: Tag, msg: alloc::string::String, codec: Codec) -> Self {
295        Self::from_kind(DecodeErrorKind::StringConversionFailed { tag, msg }, codec)
296    }
297    #[must_use]
298    pub fn unexpected_extra_data(length: usize, codec: Codec) -> Self {
299        Self::from_kind(DecodeErrorKind::UnexpectedExtraData { length }, codec)
300    }
301    #[must_use]
302    pub fn unexpected_empty_input(codec: Codec) -> Self {
303        Self::from_kind(DecodeErrorKind::UnexpectedEmptyInput, codec)
304    }
305
306    pub fn assert_length(
307        expected: usize,
308        actual: usize,
309        codec: Codec,
310    ) -> core::result::Result<(), DecodeError> {
311        if expected == actual {
312            Ok(())
313        } else {
314            Err(DecodeError::from_kind(
315                DecodeErrorKind::MismatchedLength { expected, actual },
316                codec,
317            ))
318        }
319    }
320
321    pub fn map_nom_err<T: core::fmt::Debug>(
322        error: nom::Err<nom::error::Error<T>>,
323        codec: Codec,
324    ) -> DecodeError {
325        let msg = match error {
326            nom::Err::Incomplete(needed) => return DecodeError::incomplete(needed, codec),
327            err => alloc::format!("Parsing Failure: {err}"),
328        };
329        DecodeError::parser_fail(msg, codec)
330    }
331    #[must_use]
332    pub fn from_kind(kind: DecodeErrorKind, codec: Codec) -> Self {
333        Self {
334            kind: Box::new(kind),
335            codec,
336            #[cfg(feature = "backtraces")]
337            backtrace: Backtrace::generate(),
338        }
339    }
340    #[must_use]
341    fn from_codec_kind(inner: CodecDecodeError) -> Self {
342        let codec = match inner {
343            CodecDecodeError::Ber(_) => crate::Codec::Ber,
344            CodecDecodeError::Cer(_) => crate::Codec::Cer,
345            CodecDecodeError::Der(_) => crate::Codec::Der,
346            CodecDecodeError::Uper(_) => crate::Codec::Uper,
347            CodecDecodeError::Aper(_) => crate::Codec::Aper,
348            CodecDecodeError::Jer(_) => crate::Codec::Jer,
349            CodecDecodeError::Oer(_) => crate::Codec::Oer,
350            CodecDecodeError::Coer(_) => crate::Codec::Coer,
351        };
352        Self {
353            kind: Box::new(DecodeErrorKind::CodecSpecific { inner }),
354            codec,
355            #[cfg(feature = "backtraces")]
356            backtrace: Backtrace::generate(),
357        }
358    }
359}
360
361/// `DecodeError` kinds which are common for all codecs.
362#[derive(Snafu)]
363#[snafu(visibility(pub))]
364#[derive(Debug)]
365#[non_exhaustive]
366pub enum DecodeErrorKind {
367    #[snafu(display("Alphabet constraint not satisfied {}", reason))]
368    AlphabetConstraintNotSatisfied { reason: PermittedAlphabetError },
369    #[snafu(display("Size constraint not satisfied: expected: {expected}; actual: {size:?}"))]
370    SizeConstraintNotSatisfied {
371        /// Actual sie of the data
372        size: Option<usize>,
373        /// Expected size by the constraint
374        expected: alloc::string::String,
375    },
376    #[snafu(display("Value constraint not satisfied: expected: {expected}; actual: {value}"))]
377    ValueConstraintNotSatisfied {
378        /// Actual value of the data
379        value: Integer,
380        /// Expected value by the constraint
381        expected: Bounded<i128>,
382    },
383    #[snafu(display("Wrapped codec-specific decode error"))]
384    CodecSpecific { inner: CodecDecodeError },
385
386    #[snafu(display(
387        "Enumeration index '{}' did not match any variant. Extended list: {}",
388        index,
389        extended_list
390    ))]
391    EnumerationIndexNotFound {
392        /// The found index of the enumerated variant.
393        index: usize,
394        /// Whether the index was checked from the extended variants.
395        extended_list: bool,
396    },
397    #[snafu(display("choice index '{index}' did not match any variant"))]
398    ChoiceIndexNotFound {
399        /// The found index of the choice variant.
400        index: usize,
401        /// The variants checked for presence.
402        variants: Variants,
403    },
404    #[snafu(display("integer range larger than possible to address on this platform. needed: {needed} present: {present}"))]
405    ChoiceIndexExceedsPlatformWidth {
406        /// Amount of bytes needed.
407        needed: u32,
408        /// Amount of bytes needed.
409        present: u64,
410    },
411    #[snafu(display("Custom: {}", msg))]
412    Custom {
413        /// The error's message.
414        msg: alloc::string::String,
415    },
416    #[snafu(display("Discriminant value '{}' did not match any variant", discriminant))]
417    DiscriminantValueNotFound {
418        /// The found value of the discriminant
419        discriminant: isize,
420    },
421    #[snafu(display("Duplicate field for `{}`", name))]
422    DuplicateField {
423        /// The field's name.
424        name: &'static str,
425    },
426    #[snafu(display("Expected maximum of {} items", length))]
427    ExceedsMaxLength {
428        /// The maximum length.
429        length: num_bigint::BigUint,
430    },
431    ///  More than `usize::MAX` number of data requested.
432    #[snafu(display(
433        "Length of the incoming data is either incorrect or your device is up by miracle."
434    ))]
435    LengthExceedsPlatformWidth { msg: alloc::string::String },
436    #[snafu(display("Error when decoding field `{}`: {}", name, nested))]
437    FieldError {
438        /// The field's name.
439        name: &'static str,
440        nested: Box<DecodeError>,
441    },
442    /// Input is provided as BIT slice for nom in UPER/APER.
443    /// On BER/CER/DER it is as BYTE slice.
444    /// Hence, `needed` field can describe either bits or bytes depending on the codec.
445    #[snafu(display("Need more BITS to continue: ({:?}).", needed))]
446    Incomplete {
447        /// Amount of bits/bytes needed.
448        needed: nom::Needed,
449    },
450    #[snafu(display(
451        "Invalid item number in Sequence: expected {}, actual {}",
452        expected,
453        actual
454    ))]
455    IncorrectItemNumberInSequence {
456        /// The expected item number.
457        expected: usize,
458        /// The actual item number.
459        actual: usize,
460    },
461    #[snafu(display("Actual integer larger than expected {} bits", max_width))]
462    IntegerOverflow {
463        /// The maximum integer width.
464        max_width: u32,
465    },
466    #[snafu(display("Failed to cast integer to another integer type: {msg} "))]
467    IntegerTypeConversionFailed { msg: alloc::string::String },
468    #[snafu(display("BitString contains an invalid amount of unused bits: {}", bits))]
469    InvalidBitString {
470        /// The amount of invalid bits.
471        bits: u8,
472    },
473    /// BOOL value is not `0` or `0xFF`. Applies: BER/COER/PER? TODO categorize better
474    #[snafu(display(
475        "Bool value is not `0` or `0xFF` as canonical requires. Actual: {}",
476        value
477    ))]
478    InvalidBool { value: u8 },
479    // Length of Length zero
480    #[snafu(display("Length of Length cannot be zero"))]
481    ZeroLengthOfLength,
482    /// The length does not match what was expected.
483    #[snafu(display("Expected {:?} bytes, actual length: {:?}", expected, actual))]
484    MismatchedLength {
485        /// The expected length.
486        expected: usize,
487        /// The actual length.
488        actual: usize,
489    },
490
491    #[snafu(display("Missing field `{}`", name))]
492    MissingField {
493        /// The field's name.
494        name: &'static str,
495    },
496    #[snafu(display("Expected class: {}, value: {} in sequence or set Missing tag class or value in sequence or set", class, value))]
497    MissingTagClassOrValueInSequenceOrSet {
498        /// The field's name.
499        class: crate::types::Class,
500        value: u32,
501    },
502
503    #[snafu(display("integer range larger than possible to address on this platform. needed: {needed} present: {present}"))]
504    RangeExceedsPlatformWidth {
505        /// Amount of bytes needed.
506        needed: u32,
507        /// Amount of bytes needed.
508        present: u32,
509    },
510    #[snafu(display("Extension with class `{}` and tag `{}` required, but not present", tag.class, tag.value))]
511    RequiredExtensionNotPresent { tag: crate::types::Tag },
512    #[snafu(display("Extension {} present but but not required", tag.class))]
513    ExtensionPresentButNotRequired { tag: crate::types::Tag },
514    #[snafu(display("Error in Parser: {}", msg))]
515    Parser {
516        /// The error's message.
517        msg: alloc::string::String,
518    },
519    #[snafu(display(
520        "Failed to convert byte array into valid ASN.1 string. String type as tag: {} Error: {}",
521        tag,
522        msg
523    ))]
524    StringConversionFailed {
525        /// Universal tag of the string type.
526        tag: Tag,
527        /// The error's message.
528        msg: alloc::string::String,
529    },
530    #[snafu(display(
531    "Failed to convert byte array into valid fixed-sized ASN.1 string. String type as tag: {}, actual: {}, expected: {}",
532    tag,
533    actual,
534    expected
535    ))]
536    FixedStringConversionFailed {
537        /// Tag of the string type.
538        tag: Tag,
539        /// Expected length
540        expected: usize,
541        /// Actual length
542        actual: usize,
543    },
544    #[snafu(display("No valid choice for `{}`", name))]
545    NoValidChoice {
546        /// The field's name.
547        name: &'static str,
548    },
549
550    #[snafu(display("Attempted to decode extension on non-extensible type"))]
551    TypeNotExtensible,
552    /// Unexpected extra data found.
553    #[snafu(display("Unexpected extra data found: length `{}` bytes", length))]
554    UnexpectedExtraData {
555        /// The amount of garbage data.
556        length: usize,
557    },
558    #[snafu(display("Unknown field with index {} and tag {}", index, tag))]
559    UnknownField { index: usize, tag: Tag },
560    #[snafu(display("SEQUENCE has at least one required field, but no input provided"))]
561    UnexpectedEmptyInput,
562}
563
564/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for BER.
565#[derive(Snafu, Debug)]
566#[snafu(visibility(pub))]
567#[non_exhaustive]
568pub enum BerDecodeErrorKind {
569    #[snafu(display("Indefinite length encountered but not allowed."))]
570    IndefiniteLengthNotAllowed,
571    #[snafu(display("Invalid constructed identifier for ASN.1 value: not primitive."))]
572    InvalidConstructedIdentifier,
573    /// Invalid date.
574    #[snafu(display("Invalid date string: {}", msg))]
575    InvalidDate { msg: alloc::string::String },
576    #[snafu(display("Invalid object identifier with missing or corrupt root nodes."))]
577    InvalidObjectIdentifier,
578    /// The tag does not match what was expected.
579    #[snafu(display("Expected {:?} tag, actual tag: {:?}", expected, actual))]
580    MismatchedTag {
581        /// The expected tag.
582        expected: Tag,
583        /// The actual tag.
584        actual: Tag,
585    },
586}
587
588impl BerDecodeErrorKind {
589    #[must_use]
590    pub fn invalid_date(msg: alloc::string::String) -> CodecDecodeError {
591        CodecDecodeError::Ber(Self::InvalidDate { msg })
592    }
593    pub fn assert_tag(expected: Tag, actual: Tag) -> core::result::Result<(), DecodeError> {
594        if expected == actual {
595            Ok(())
596        } else {
597            Err(BerDecodeErrorKind::MismatchedTag { expected, actual }.into())
598        }
599    }
600}
601// TODO check if there are more codec-specific errors here
602/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for CER.
603#[derive(Snafu, Debug)]
604#[snafu(visibility(pub))]
605#[non_exhaustive]
606pub enum CerDecodeErrorKind {}
607
608/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for DER.
609#[derive(Snafu, Debug)]
610#[snafu(visibility(pub))]
611#[non_exhaustive]
612pub enum DerDecodeErrorKind {
613    #[snafu(display("Constructed encoding encountered but not allowed."))]
614    ConstructedEncodingNotAllowed,
615}
616
617/// An error that occurred when decoding JER.
618#[derive(Snafu, Debug)]
619#[snafu(visibility(pub))]
620#[non_exhaustive]
621pub enum JerDecodeErrorKind {
622    #[snafu(display("Unexpected end of input while decoding JER JSON."))]
623    EndOfInput {},
624    #[snafu(display(
625        "Found mismatching JSON value. Expected type {}. Found value {}.",
626        needed,
627        found
628    ))]
629    TypeMismatch {
630        needed: &'static str,
631        found: alloc::string::String,
632    },
633    #[snafu(display("Found invalid byte in bit string. {parse_int_err}"))]
634    InvalidJerBitstring { parse_int_err: ParseIntError },
635    #[snafu(display("Found invalid character in octet string."))]
636    InvalidJerOctetString {},
637    #[snafu(display("Failed to construct OID from value {value}",))]
638    InvalidOIDString { value: JsonValue },
639    #[snafu(display("Found invalid enumerated discriminant {discriminant}",))]
640    InvalidEnumDiscriminant { discriminant: alloc::string::String },
641}
642
643impl JerDecodeErrorKind {
644    pub fn eoi() -> CodecDecodeError {
645        CodecDecodeError::Jer(JerDecodeErrorKind::EndOfInput {})
646    }
647}
648
649// TODO check if there codec-specific errors here
650/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for UPER.
651#[derive(Snafu, Debug)]
652#[snafu(visibility(pub))]
653#[non_exhaustive]
654pub enum UperDecodeErrorKind {}
655
656// TODO check if there codec-specific errors here
657/// `DecodeError` kinds of `Kind::CodecSpecific` which are specific for APER.
658#[derive(Snafu, Debug)]
659#[snafu(visibility(pub))]
660#[non_exhaustive]
661pub enum AperDecodeErrorKind {}
662
663#[derive(Snafu, Debug)]
664#[snafu(visibility(pub))]
665#[non_exhaustive]
666pub enum OerDecodeErrorKind {
667    /// Tag class must be one of Universal (0b00), Application (0b01), Context (0b10) or Private (0b11).
668    #[snafu(display("Invalid tag class when decoding choice: actual {:?}", class))]
669    InvalidTagClassOnChoice {
670        /// The actual class.
671        class: u8,
672    },
673    #[snafu(display("Invalid tag number when decoding Choice. Value: {value}"))]
674    InvalidTagNumberOnChoice { value: u32 },
675    #[snafu(display(
676        "Tag not found from the variants of the platform when decoding Choice. Tag: {value}, extensible status: {is_extensible}"
677    ))]
678    InvalidTagVariantOnChoice { value: Tag, is_extensible: bool },
679
680    InvalidExtensionHeader {
681        /// The amount of invalid bits.
682        msg: alloc::string::String,
683    },
684    #[snafu(display("Invalid BitString: {msg}"))]
685    InvalidOerBitString {
686        /// The amount of invalid bits.
687        msg: alloc::string::String,
688    },
689}
690
691impl OerDecodeErrorKind {
692    #[must_use]
693    pub fn invalid_tag_number_on_choice(value: u32) -> DecodeError {
694        CodecDecodeError::Oer(Self::InvalidTagNumberOnChoice { value }).into()
695    }
696    #[must_use]
697    pub fn invalid_tag_variant_on_choice(value: Tag, is_extensible: bool) -> DecodeError {
698        CodecDecodeError::Oer(Self::InvalidTagVariantOnChoice {
699            value,
700            is_extensible,
701        })
702        .into()
703    }
704
705    #[must_use]
706    pub fn invalid_extension_header(msg: alloc::string::String) -> DecodeError {
707        CodecDecodeError::Oer(Self::InvalidExtensionHeader { msg }).into()
708    }
709    #[must_use]
710    pub fn invalid_bit_string(msg: alloc::string::String) -> DecodeError {
711        CodecDecodeError::Oer(Self::InvalidOerBitString { msg }).into()
712    }
713}
714
715#[derive(Snafu, Debug)]
716#[snafu(visibility(pub))]
717#[non_exhaustive]
718pub enum CoerDecodeErrorKind {
719    #[snafu(display("Invalid Canonical Octet Encoding, not encoded as the smallest possible number of octets: {msg}"))]
720    NotValidCanonicalEncoding { msg: alloc::string::String },
721}
722
723impl crate::de::Error for DecodeError {
724    fn custom<D: core::fmt::Display>(msg: D, codec: Codec) -> Self {
725        Self::from_kind(
726            DecodeErrorKind::Custom {
727                msg: msg.to_string(),
728            },
729            codec,
730        )
731    }
732    fn incomplete(needed: nom::Needed, codec: Codec) -> Self {
733        Self::from_kind(DecodeErrorKind::Incomplete { needed }, codec)
734    }
735
736    fn exceeds_max_length(length: num_bigint::BigUint, codec: Codec) -> Self {
737        Self::from_kind(DecodeErrorKind::ExceedsMaxLength { length }, codec)
738    }
739
740    fn missing_field(name: &'static str, codec: Codec) -> Self {
741        Self::from_kind(DecodeErrorKind::MissingField { name }, codec)
742    }
743
744    fn no_valid_choice(name: &'static str, codec: Codec) -> Self {
745        Self::from_kind(DecodeErrorKind::NoValidChoice { name }, codec)
746    }
747
748    fn field_error(name: &'static str, nested: DecodeError, codec: Codec) -> Self {
749        Self::from_kind(
750            DecodeErrorKind::FieldError {
751                name,
752                nested: Box::new(nested),
753            },
754            codec,
755        )
756    }
757
758    fn duplicate_field(name: &'static str, codec: Codec) -> Self {
759        Self::from_kind(DecodeErrorKind::DuplicateField { name }, codec)
760    }
761    fn unknown_field(index: usize, tag: Tag, codec: Codec) -> Self {
762        Self::from_kind(DecodeErrorKind::UnknownField { index, tag }, codec)
763    }
764}
765
766#[cfg(test)]
767mod tests {
768    use crate::prelude::*;
769    #[test]
770    fn test_ber_decode_date() {
771        use crate::error::{DecodeError, DecodeErrorKind};
772        // "230122130000-050Z" as bytes
773        let data = [
774            23, 17, 50, 51, 48, 49, 50, 50, 49, 51, 48, 48, 48, 48, 45, 48, 53, 48, 90,
775        ];
776        let result = crate::ber::decode::<UtcTime>(&data);
777        match result {
778            Err(DecodeError { kind, .. }) => {
779                if let DecodeErrorKind::CodecSpecific {
780                    inner:
781                        crate::error::CodecDecodeError::Ber(
782                            crate::error::BerDecodeErrorKind::InvalidDate { msg },
783                        ),
784                    ..
785                } = *kind
786                {
787                    assert_eq!(msg, "230122130000-050Z");
788                } else {
789                    // Handle other kinds of errors
790                    panic!("Unexpected error kind: {kind}");
791                }
792            }
793            Ok(_) => panic!("Expected error"),
794        }
795    }
796    #[test]
797    fn test_uper_missing_choice_index() {
798        use crate as rasn;
799        use crate::error::{DecodeError, DecodeErrorKind};
800        use crate::Codec;
801        #[derive(AsnType, Decode, Debug, PartialEq)]
802        #[rasn(choice, automatic_tags)]
803        enum MyChoice {
804            Normal(Integer),
805            High(Integer),
806            Medium(Integer),
807        }
808        // Value 333 encoded for missing choice index 3
809        let data = [192, 128, 83, 64];
810        let result = Codec::Uper.decode_from_binary::<MyChoice>(&data);
811        match result {
812            Ok(_) => {
813                panic!("Unexpected OK!");
814            }
815            Err(DecodeError { kind, .. }) => {
816                if let DecodeErrorKind::ChoiceIndexNotFound { index, .. } = *kind {
817                    assert_eq!(index, 3);
818                } else {
819                    // Handle other kinds of errors
820                    panic!("Unexpected error kind: {kind}");
821                }
822            }
823        }
824    }
825}