asn1_rs/
error.rs

1#![allow(unknown_lints)]
2#![allow(non_local_definitions)] // false positive for displaydoc::Display: https://github.com/yaahc/displaydoc/issues/46
3
4use crate::{Class, Tag};
5use alloc::str;
6use alloc::string;
7#[cfg(not(feature = "std"))]
8use alloc::string::String;
9use displaydoc::Display;
10use nom::error::{ErrorKind, FromExternalError, ParseError};
11use nom::IResult;
12#[cfg(feature = "std")]
13use std::io;
14use thiserror::Error;
15
16#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, Error)]
17/// Error types for DER constraints
18pub enum DerConstraint {
19    /// Indefinite length not allowed
20    IndefiniteLength,
21    /// Object must not be constructed
22    Constructed,
23    /// Object must be constructed
24    NotConstructed,
25    /// DateTime object is missing timezone
26    MissingTimeZone,
27    /// DateTime object is missing seconds
28    MissingSeconds,
29    /// Bitstring unused bits must be set to zero
30    UnusedBitsNotZero,
31    /// Boolean value must be 0x00 of 0xff
32    InvalidBoolean,
33    /// Integer must not be empty
34    IntegerEmpty,
35    /// Leading zeroes in Integer encoding
36    IntegerLeadingZeroes,
37    /// Leading 0xff in negative Integer encoding
38    IntegerLeadingFF,
39}
40
41/// The error type for operations of the [`FromBer`](crate::FromBer),
42/// [`FromDer`](crate::FromDer), and associated traits.
43#[derive(Clone, Debug, Display, PartialEq, Eq, Error)]
44pub enum Error {
45    /// BER object does not have the expected type
46    BerTypeError,
47    /// BER object does not have the expected value
48    BerValueError,
49    /// Invalid Length
50    InvalidLength,
51    /// Invalid Value when parsing object with tag {tag:?} {msg:}
52    InvalidValue { tag: Tag, msg: String },
53    /// Invalid Tag
54    InvalidTag,
55    /// Unknown tag: {0:?}
56    UnknownTag(u32),
57    /// Unexpected Tag (expected: {expected:?}, actual: {actual:?})
58    UnexpectedTag { expected: Option<Tag>, actual: Tag },
59    /// Unexpected Class (expected: {expected:?}, actual: {actual:?})
60    UnexpectedClass {
61        expected: Option<Class>,
62        actual: Class,
63    },
64
65    /// Indefinite length not allowed
66    IndefiniteLengthUnexpected,
67
68    /// DER object was expected to be constructed (and found to be primitive)
69    ConstructExpected,
70    /// DER object was expected to be primitive (and found to be constructed)
71    ConstructUnexpected,
72
73    /// Integer too large to fit requested type
74    IntegerTooLarge,
75    /// BER integer is negative, while an unsigned integer was requested
76    IntegerNegative,
77    /// BER recursive parsing reached maximum depth
78    BerMaxDepth,
79
80    /// Invalid encoding or forbidden characters in string
81    StringInvalidCharset,
82    /// Invalid Date or Time
83    InvalidDateTime,
84
85    /// DER Failed constraint: {0:?}
86    DerConstraintFailed(DerConstraint),
87
88    /// Requesting borrowed data from a temporary object
89    LifetimeError,
90    /// Feature is not yet implemented
91    Unsupported,
92
93    /// incomplete data, missing: {0:?}
94    Incomplete(nom::Needed),
95
96    /// nom error: {0:?}
97    NomError(ErrorKind),
98}
99
100impl Error {
101    /// Build an error from the provided invalid value
102    #[inline]
103    pub const fn invalid_value(tag: Tag, msg: String) -> Self {
104        Self::InvalidValue { tag, msg }
105    }
106
107    /// Build an error from the provided unexpected class
108    #[inline]
109    pub const fn unexpected_class(expected: Option<Class>, actual: Class) -> Self {
110        Self::UnexpectedClass { expected, actual }
111    }
112
113    /// Build an error from the provided unexpected tag
114    #[inline]
115    pub const fn unexpected_tag(expected: Option<Tag>, actual: Tag) -> Self {
116        Self::UnexpectedTag { expected, actual }
117    }
118}
119
120impl<'a> ParseError<&'a [u8]> for Error {
121    fn from_error_kind(_input: &'a [u8], kind: ErrorKind) -> Self {
122        Error::NomError(kind)
123    }
124    fn append(_input: &'a [u8], kind: ErrorKind, _other: Self) -> Self {
125        Error::NomError(kind)
126    }
127}
128
129impl From<Error> for nom::Err<Error> {
130    fn from(e: Error) -> Self {
131        nom::Err::Error(e)
132    }
133}
134
135impl From<str::Utf8Error> for Error {
136    fn from(_: str::Utf8Error) -> Self {
137        Error::StringInvalidCharset
138    }
139}
140
141impl From<string::FromUtf8Error> for Error {
142    fn from(_: string::FromUtf8Error) -> Self {
143        Error::StringInvalidCharset
144    }
145}
146
147impl From<string::FromUtf16Error> for Error {
148    fn from(_: string::FromUtf16Error) -> Self {
149        Error::StringInvalidCharset
150    }
151}
152
153impl From<nom::Err<Error>> for Error {
154    fn from(e: nom::Err<Error>) -> Self {
155        match e {
156            nom::Err::Incomplete(n) => Self::Incomplete(n),
157            nom::Err::Error(e) | nom::Err::Failure(e) => e,
158        }
159    }
160}
161
162impl<I, E> FromExternalError<I, E> for Error {
163    fn from_external_error(_input: I, kind: ErrorKind, _e: E) -> Error {
164        Error::NomError(kind)
165    }
166}
167
168/// Flatten all `nom::Err` variants error into a single error type
169pub fn from_nom_error<E, F>(e: nom::Err<E>) -> F
170where
171    F: From<E> + From<Error>,
172{
173    match e {
174        nom::Err::Error(e) | nom::Err::Failure(e) => F::from(e),
175        nom::Err::Incomplete(n) => F::from(Error::Incomplete(n)),
176    }
177}
178
179/// Holds the result of BER/DER serialization functions
180pub type ParseResult<'a, T, E = Error> = IResult<&'a [u8], T, E>;
181
182/// A specialized `Result` type for all operations from this crate.
183pub type Result<T, E = Error> = core::result::Result<T, E>;
184
185/// The error type for serialization operations of the [`ToDer`](crate::ToDer) trait.
186#[cfg(feature = "std")]
187#[derive(Debug, Error)]
188pub enum SerializeError {
189    #[error("ASN.1 error: {0:?}")]
190    ASN1Error(#[from] Error),
191
192    #[error("Invalid Class {class:}")]
193    InvalidClass { class: u8 },
194
195    #[error("Invalid Length")]
196    InvalidLength,
197
198    #[error("I/O error: {0:?}")]
199    IOError(#[from] io::Error),
200}
201
202#[cfg(feature = "std")]
203/// Holds the result of BER/DER encoding functions
204pub type SerializeResult<T> = std::result::Result<T, SerializeError>;