1use std::path::PathBuf;
2
3use crate::Architecture;
4
5#[derive(Debug, thiserror::Error, PartialEq)]
15pub enum Error {
16 #[error("The architecture combination is invalid: {architectures:?}. {context}")]
18 InvalidArchitectures {
19 architectures: Vec<Architecture>,
21 context: &'static str,
23 },
24
25 #[error("Invalid integer (caused by {kind:?})")]
27 InvalidInteger {
28 kind: std::num::IntErrorKind,
30 },
31
32 #[error("Invalid variant ({0})")]
34 InvalidVariant(#[from] strum::ParseError),
35
36 #[error("Invalid e-mail ({0})")]
38 InvalidEmail(#[from] email_address::Error),
39
40 #[error("Invalid URL ({0})")]
42 InvalidUrl(#[from] url::ParseError),
43
44 #[error("Invalid license ({0})")]
46 InvalidLicense(#[from] spdx::ParseError),
47
48 #[error("Invalid semver ({kind})")]
56 InvalidSemver {
57 kind: String,
59 },
60
61 #[error("Value contains invalid characters: {invalid_char:?}")]
63 ValueContainsInvalidChars {
64 invalid_char: char,
66 },
67
68 #[error("Incorrect length, got {length} expected {expected}")]
70 IncorrectLength {
71 length: usize,
73 expected: usize,
75 },
76
77 #[error("Value is missing the required delimiter: {delimiter}")]
79 DelimiterNotFound {
80 delimiter: char,
82 },
83
84 #[error("Does not match the restrictions ({restrictions:?})")]
86 ValueDoesNotMatchRestrictions {
87 restrictions: Vec<String>,
89 },
90
91 #[error("Value '{value}' does not match the '{regex_type}' regex: {regex}")]
93 RegexDoesNotMatch {
94 value: String,
96 regex_type: String,
98 regex: String,
100 },
101
102 #[error("Parser failed with the following error:\n{0}")]
104 ParseError(String),
105
106 #[error("Missing component: {component}")]
108 MissingComponent {
109 component: &'static str,
111 },
112
113 #[error("The path is not absolute: {0}")]
115 PathNotAbsolute(PathBuf),
116
117 #[error("The path is not relative: {0}")]
119 PathNotRelative(PathBuf),
120
121 #[error("File name ({0}) contains invalid characters: {1:?}")]
123 FileNameContainsInvalidChars(PathBuf, char),
124
125 #[error("File name is empty")]
127 FileNameIsEmpty,
128
129 #[error("Deprecated license: {0}")]
131 DeprecatedLicense(String),
132
133 #[error("Invalid component {component} encountered while {context}")]
135 InvalidComponent {
136 component: &'static str,
138 context: &'static str,
143 },
144
145 #[error("Invalid OpenPGP v4 fingerprint, only 40 uppercase hexadecimal characters are allowed")]
147 InvalidOpenPGPv4Fingerprint,
148
149 #[error("The string is not a valid OpenPGP key ID: {0}, must be 16 hexadecimal characters")]
151 InvalidOpenPGPKeyId(String),
152
153 #[error("Invalid shared object name (v1): {0}")]
155 InvalidSonameV1(&'static str),
156
157 #[error("Package error: {0}")]
159 Package(#[from] crate::PackageError),
160
161 #[error("Unknown compression algorithm file extension: {value:?}")]
163 UnknownCompressionAlgorithmFileExtension {
164 value: String,
166 },
167
168 #[error("Unknown file type identifier: {value:?}")]
170 UnknownFileTypeIdentifier {
171 value: String,
173 },
174}
175
176impl From<std::num::ParseIntError> for crate::error::Error {
177 fn from(e: std::num::ParseIntError) -> Self {
179 Self::InvalidInteger { kind: *e.kind() }
180 }
181}
182
183impl<'a> From<winnow::error::ParseError<&'a str, winnow::error::ContextError>>
184 for crate::error::Error
185{
186 fn from(value: winnow::error::ParseError<&'a str, winnow::error::ContextError>) -> Self {
188 Self::ParseError(value.to_string())
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use std::num::IntErrorKind;
195
196 use rstest::rstest;
197
198 use super::*;
199
200 #[rstest]
201 #[case(
202 "Invalid integer (caused by InvalidDigit)",
203 Error::InvalidInteger {
204 kind: IntErrorKind::InvalidDigit
205 }
206 )]
207 #[case(
208 "Invalid integer (caused by InvalidDigit)",
209 Error::InvalidInteger {
210 kind: IntErrorKind::InvalidDigit
211 }
212 )]
213 #[case(
214 "Invalid integer (caused by PosOverflow)",
215 Error::InvalidInteger {
216 kind: IntErrorKind::PosOverflow
217 }
218 )]
219 #[allow(deprecated)]
220 #[case(
221 "Invalid integer (caused by InvalidDigit)",
222 Error::InvalidInteger {
223 kind: IntErrorKind::InvalidDigit
224 }
225 )]
226 #[case(
227 "Invalid e-mail (Missing separator character '@'.)",
228 email_address::Error::MissingSeparator.into()
229 )]
230 #[case(
231 "Invalid integer (caused by InvalidDigit)",
232 Error::InvalidInteger {
233 kind: IntErrorKind::InvalidDigit
234 }
235 )]
236 fn error_format_string(#[case] error_str: &str, #[case] error: Error) {
237 assert_eq!(error_str, format!("{error}"));
238 }
239}