1use std::path::PathBuf;
2
3#[derive(Debug, thiserror::Error, PartialEq)]
13pub enum Error {
14 #[error("Invalid integer (caused by {kind:?})")]
16 InvalidInteger {
17 kind: std::num::IntErrorKind,
19 },
20
21 #[error("Invalid variant ({0})")]
23 InvalidVariant(#[from] strum::ParseError),
24
25 #[error("Invalid e-mail ({0})")]
27 InvalidEmail(#[from] email_address::Error),
28
29 #[error("Invalid URL ({0})")]
31 InvalidUrl(#[from] url::ParseError),
32
33 #[error("Invalid license ({0})")]
35 InvalidLicense(#[from] spdx::ParseError),
36
37 #[error("Invalid semver ({kind})")]
45 InvalidSemver {
46 kind: String,
48 },
49
50 #[error("Value contains invalid characters: {invalid_char:?}")]
52 ValueContainsInvalidChars {
53 invalid_char: char,
55 },
56
57 #[error("Incorrect length, got {length} expected {expected}")]
59 IncorrectLength {
60 length: usize,
62 expected: usize,
64 },
65
66 #[error("Value is missing the required delimiter: {delimiter}")]
68 DelimiterNotFound {
69 delimiter: char,
71 },
72
73 #[error("Does not match the restrictions ({restrictions:?})")]
75 ValueDoesNotMatchRestrictions {
76 restrictions: Vec<String>,
78 },
79
80 #[error("Value '{value}' does not match the '{regex_type}' regex: {regex}")]
82 RegexDoesNotMatch {
83 value: String,
85 regex_type: String,
87 regex: String,
89 },
90
91 #[error("Parser failed with the following error:\n{0}")]
93 ParseError(String),
94
95 #[error("Missing component: {component}")]
97 MissingComponent {
98 component: &'static str,
100 },
101
102 #[error("The path is not absolute: {0}")]
104 PathNotAbsolute(PathBuf),
105
106 #[error("The path is not relative: {0}")]
108 PathNotRelative(PathBuf),
109
110 #[error("File name ({0}) contains invalid characters: {1:?}")]
112 FileNameContainsInvalidChars(PathBuf, char),
113
114 #[error("File name is empty")]
116 FileNameIsEmpty,
117
118 #[error("Deprecated license: {0}")]
120 DeprecatedLicense(String),
121
122 #[error("Invalid component {component} encountered while {context}")]
124 InvalidComponent {
125 component: &'static str,
127 context: &'static str,
132 },
133
134 #[error("Invalid OpenPGP v4 fingerprint, only 40 uppercase hexadecimal characters are allowed")]
136 InvalidOpenPGPv4Fingerprint,
137
138 #[error("The string is not a valid OpenPGP key ID: {0}, must be 16 hexadecimal characters")]
140 InvalidOpenPGPKeyId(String),
141
142 #[error("Invalid shared object name (v1): {0}")]
144 InvalidSonameV1(&'static str),
145
146 #[error("Package error: {0}")]
148 Package(#[from] crate::PackageError),
149
150 #[error("Unknown compression algorithm file extension: {value:?}")]
152 UnknownCompressionAlgorithmFileExtension {
153 value: String,
155 },
156
157 #[error("Unknown file type identifier: {value:?}")]
159 UnknownFileTypeIdentifier {
160 value: String,
162 },
163}
164
165impl From<std::num::ParseIntError> for crate::error::Error {
166 fn from(e: std::num::ParseIntError) -> Self {
168 Self::InvalidInteger { kind: *e.kind() }
169 }
170}
171
172impl<'a> From<winnow::error::ParseError<&'a str, winnow::error::ContextError>>
173 for crate::error::Error
174{
175 fn from(value: winnow::error::ParseError<&'a str, winnow::error::ContextError>) -> Self {
177 Self::ParseError(value.to_string())
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use std::num::IntErrorKind;
184
185 use rstest::rstest;
186
187 use super::*;
188
189 #[rstest]
190 #[case(
191 "Invalid integer (caused by InvalidDigit)",
192 Error::InvalidInteger {
193 kind: IntErrorKind::InvalidDigit
194 }
195 )]
196 #[case(
197 "Invalid integer (caused by InvalidDigit)",
198 Error::InvalidInteger {
199 kind: IntErrorKind::InvalidDigit
200 }
201 )]
202 #[case(
203 "Invalid integer (caused by PosOverflow)",
204 Error::InvalidInteger {
205 kind: IntErrorKind::PosOverflow
206 }
207 )]
208 #[allow(deprecated)]
209 #[case(
210 "Invalid integer (caused by InvalidDigit)",
211 Error::InvalidInteger {
212 kind: IntErrorKind::InvalidDigit
213 }
214 )]
215 #[case(
216 "Invalid e-mail (Missing separator character '@'.)",
217 email_address::Error::MissingSeparator.into()
218 )]
219 #[case(
220 "Invalid integer (caused by InvalidDigit)",
221 Error::InvalidInteger {
222 kind: IntErrorKind::InvalidDigit
223 }
224 )]
225 fn error_format_string(#[case] error_str: &str, #[case] error: Error) {
226 assert_eq!(error_str, format!("{error}"));
227 }
228}