Skip to main content

autoit/
error.rs

1//! Error types for AutoIt extraction.
2
3use core::fmt;
4
5/// Crate-wide error type.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Error {
8    kind: ErrorKind,
9}
10
11impl Error {
12    /// Creates a not-recognized error.
13    ///
14    /// # Returns
15    ///
16    /// An [`Error`] wrapping [`RecognitionFailure::NotRecognized`].
17    #[must_use]
18    pub const fn not_recognized() -> Self {
19        Self {
20            kind: ErrorKind::Recognition(RecognitionFailure::NotRecognized),
21        }
22    }
23
24    /// Creates an unsupported-encoding error.
25    ///
26    /// # Returns
27    ///
28    /// An [`Error`] wrapping [`RecognitionFailure::UnsupportedEncoding`].
29    #[must_use]
30    pub const fn unsupported_encoding() -> Self {
31        Self {
32            kind: ErrorKind::Recognition(RecognitionFailure::UnsupportedEncoding),
33        }
34    }
35
36    /// Creates a truncated-input error.
37    ///
38    /// # Returns
39    ///
40    /// An [`Error`] wrapping [`RecognitionFailure::Truncated`].
41    #[must_use]
42    pub const fn truncated() -> Self {
43        Self {
44            kind: ErrorKind::Recognition(RecognitionFailure::Truncated),
45        }
46    }
47
48    /// Creates a malformed-container error.
49    ///
50    /// # Returns
51    ///
52    /// An [`Error`] wrapping [`RecognitionFailure::MalformedContainer`].
53    #[must_use]
54    pub const fn malformed_container() -> Self {
55        Self {
56            kind: ErrorKind::Recognition(RecognitionFailure::MalformedContainer),
57        }
58    }
59
60    /// Creates a limit-exceeded error.
61    ///
62    /// # Returns
63    ///
64    /// An [`Error`] wrapping [`RecognitionFailure::LimitExceeded`].
65    #[must_use]
66    pub const fn limit_exceeded() -> Self {
67        Self {
68            kind: ErrorKind::Recognition(RecognitionFailure::LimitExceeded),
69        }
70    }
71
72    /// Creates a crypto-mismatch error.
73    ///
74    /// # Returns
75    ///
76    /// An [`Error`] wrapping [`RecognitionFailure::CryptoMismatch`].
77    #[must_use]
78    pub const fn crypto_mismatch() -> Self {
79        Self {
80            kind: ErrorKind::Recognition(RecognitionFailure::CryptoMismatch),
81        }
82    }
83
84    /// Creates a decompression error.
85    ///
86    /// # Returns
87    ///
88    /// An [`Error`] wrapping [`RecognitionFailure::CompressionError`].
89    #[must_use]
90    pub const fn compression_error() -> Self {
91        Self {
92            kind: ErrorKind::Recognition(RecognitionFailure::CompressionError),
93        }
94    }
95
96    /// Creates a token-decoding error.
97    ///
98    /// # Returns
99    ///
100    /// An [`Error`] wrapping [`RecognitionFailure::TokenError`].
101    #[must_use]
102    pub const fn token_error() -> Self {
103        Self {
104            kind: ErrorKind::Recognition(RecognitionFailure::TokenError),
105        }
106    }
107
108    /// Returns the recognition failure when this error represents one.
109    ///
110    /// # Returns
111    ///
112    /// `Some` with the wrapped [`RecognitionFailure`]; currently every [`Error`]
113    /// carries one, so this never returns `None`.
114    #[must_use]
115    pub const fn recognition_failure(&self) -> Option<RecognitionFailure> {
116        match self.kind {
117            ErrorKind::Recognition(failure) => Some(failure),
118        }
119    }
120}
121
122impl fmt::Display for Error {
123    /// Formats the error by delegating to its wrapped [`RecognitionFailure`].
124    ///
125    /// # Arguments
126    ///
127    /// * `f` - The formatter to write into.
128    ///
129    /// # Returns
130    ///
131    /// A [`fmt::Result`] propagating any formatter write error.
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        match self.kind {
134            ErrorKind::Recognition(failure) => write!(f, "{failure}"),
135        }
136    }
137}
138
139impl std::error::Error for Error {}
140
141/// Reasons an input could not be recognized or accepted as AutoIt.
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum RecognitionFailure {
144    /// No AutoIt container or payload markers were found.
145    NotRecognized,
146    /// AutoIt markers were found, but the encoding is not yet supported.
147    UnsupportedEncoding,
148    /// The outer container shape was recognized but malformed.
149    MalformedContainer,
150    /// The input ended before required AutoIt data could be read.
151    Truncated,
152    /// A configured extraction limit was exceeded.
153    LimitExceeded,
154    /// AutoIt data was recognized but a cryptographic validation step failed.
155    CryptoMismatch,
156    /// AutoIt data was recognized but decompression failed.
157    CompressionError,
158    /// AutoIt data was recognized but token decoding failed.
159    TokenError,
160}
161
162impl fmt::Display for RecognitionFailure {
163    /// Writes a human-readable description of the recognition failure.
164    ///
165    /// # Arguments
166    ///
167    /// * `f` - The formatter to write into.
168    ///
169    /// # Returns
170    ///
171    /// A [`fmt::Result`] propagating any formatter write error.
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        match self {
174            Self::NotRecognized => f.write_str("input is not recognized as AutoIt"),
175            Self::UnsupportedEncoding => f.write_str("AutoIt encoding is not supported"),
176            Self::MalformedContainer => f.write_str("AutoIt container is malformed"),
177            Self::Truncated => f.write_str("AutoIt input is truncated"),
178            Self::LimitExceeded => f.write_str("AutoIt extraction limit exceeded"),
179            Self::CryptoMismatch => f.write_str("AutoIt cryptographic validation failed"),
180            Self::CompressionError => f.write_str("AutoIt decompression failed"),
181            Self::TokenError => f.write_str("AutoIt token decoding failed"),
182        }
183    }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187enum ErrorKind {
188    Recognition(RecognitionFailure),
189}