1use std::path::PathBuf;
2
3use fluent_i18n::t;
4
5use crate::Architecture;
6
7#[derive(Debug, thiserror::Error, PartialEq)]
17pub enum Error {
18 #[error("{msg}", msg = t!("error-invalid-architectures", {
20 "architectures" => format!("{architectures:?}"),
21 "context" => context
22 }))]
23 InvalidArchitectures {
24 architectures: Vec<Architecture>,
26 context: &'static str,
28 },
29
30 #[error("{msg}", msg = t!("error-invalid-integer", { "kind" => format!("{kind:?}") }))]
32 InvalidInteger {
33 kind: std::num::IntErrorKind,
35 },
36
37 #[error("{msg}", msg = t!("error-invalid-variant", { "error" => .0.to_string() }))]
39 InvalidVariant(#[from] strum::ParseError),
40
41 #[error("{msg}", msg = t!("error-invalid-email", { "error" => .0.to_string() }))]
43 InvalidEmail(#[from] email_address::Error),
44
45 #[error("{msg}", msg = t!("error-invalid-url", { "error" => .0.to_string() }))]
47 InvalidUrl(#[from] url::ParseError),
48
49 #[error("{msg}", msg = t!("error-invalid-license", { "error" => .0.to_string() }))]
51 InvalidLicense(#[from] spdx::ParseError),
52
53 #[error("{msg}", msg = t!("error-invalid-semver", { "kind" => kind }))]
61 InvalidSemver {
62 kind: String,
64 },
65
66 #[error("{msg}", msg = t!("error-invalid-chars", { "invalid_char" => invalid_char.to_string() }))]
68 ValueContainsInvalidChars {
69 invalid_char: char,
71 },
72
73 #[error("{msg}", msg = t!("error-incorrect-length", { "length" => length, "expected" => expected }))]
75 IncorrectLength {
76 length: usize,
78 expected: usize,
80 },
81
82 #[error("{msg}", msg = t!("error-delimiter-not-found", { "delimiter" => delimiter.to_string() }))]
84 DelimiterNotFound {
85 delimiter: char,
87 },
88
89 #[error("{msg}", msg = t!("error-restrictions-not-met", {
91 "restrictions" => format!("{restrictions:?}")
92 }))]
93 ValueDoesNotMatchRestrictions {
94 restrictions: Vec<String>,
96 },
97
98 #[error("{msg}", msg = t!("error-regex-mismatch", {
100 "value" => value,
101 "regex_type" => regex_type,
102 "regex" => regex
103 }))]
104 RegexDoesNotMatch {
105 value: String,
107 regex_type: String,
109 regex: String,
111 },
112
113 #[error("{msg}", msg = t!("error-parse", { "error" => .0 }))]
115 ParseError(String),
116
117 #[error("{msg}", msg = t!("error-missing-component", { "component" => component }))]
119 MissingComponent {
120 component: &'static str,
122 },
123
124 #[error("{msg}", msg = t!("error-path-not-absolute", { "path" => .0 }))]
126 PathNotAbsolute(PathBuf),
127
128 #[error("{msg}", msg = t!("error-path-not-relative", { "path" => .0 }))]
130 PathNotRelative(PathBuf),
131
132 #[error("{msg}", msg = t!("error-path-not-file", { "path" => .0 }))]
134 PathIsNotAFile(PathBuf),
135
136 #[error("{msg}", msg = t!("error-filename-invalid-chars", {
138 "path" => .0,
139 "invalid_char" => .1.to_string()
140 }))]
141 FileNameContainsInvalidChars(PathBuf, char),
142
143 #[error("{msg}", msg = t!("error-filename-empty"))]
145 FileNameIsEmpty,
146
147 #[error("{msg}", msg = t!("error-deprecated-license", { "license" => .0 }))]
149 DeprecatedLicense(String),
150
151 #[error("{msg}", msg = t!("error-invalid-component", {
153 "component" => component,
154 "context" => context
155 }))]
156 InvalidComponent {
157 component: &'static str,
159 context: String,
164 },
165
166 #[error("{msg}", msg = t!("error-invalid-pgp-fingerprint"))]
168 InvalidOpenPGPv4Fingerprint,
169
170 #[error("{msg}", msg = t!("error-invalid-pgp-keyid", { "keyid" => .0 }))]
172 InvalidOpenPGPKeyId(String),
173
174 #[error("{msg}", msg = t!("error-invalid-base64-encoding", { "expected_item" => expected_item }))]
176 InvalidBase64Encoding {
177 expected_item: String,
179 },
180
181 #[error("{msg}", msg = t!("error-invalid-soname-v1", { "name" => .0 }))]
183 InvalidSonameV1(&'static str),
184
185 #[error("{msg}", msg = t!("error-package", { "error" => .0.to_string() }))]
187 Package(#[from] crate::PackageError),
188
189 #[error("{msg}", msg = t!("error-unknown-compression", { "value" => value }))]
191 UnknownCompressionAlgorithmFileExtension {
192 value: String,
194 },
195
196 #[error("{msg}", msg = t!("error-unknown-filetype", { "value" => value }))]
198 UnknownFileTypeIdentifier {
199 value: String,
201 },
202}
203
204impl From<std::num::ParseIntError> for crate::error::Error {
205 fn from(e: std::num::ParseIntError) -> Self {
207 Self::InvalidInteger { kind: *e.kind() }
208 }
209}
210
211impl<'a> From<winnow::error::ParseError<&'a str, winnow::error::ContextError>>
212 for crate::error::Error
213{
214 fn from(value: winnow::error::ParseError<&'a str, winnow::error::ContextError>) -> Self {
216 Self::ParseError(value.to_string())
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use std::num::IntErrorKind;
223
224 use rstest::rstest;
225
226 use super::*;
227
228 #[rstest]
229 #[case(
230 "Invalid integer (caused by InvalidDigit)",
231 Error::InvalidInteger {
232 kind: IntErrorKind::InvalidDigit
233 }
234 )]
235 #[case(
236 "Invalid integer (caused by InvalidDigit)",
237 Error::InvalidInteger {
238 kind: IntErrorKind::InvalidDigit
239 }
240 )]
241 #[case(
242 "Invalid integer (caused by PosOverflow)",
243 Error::InvalidInteger {
244 kind: IntErrorKind::PosOverflow
245 }
246 )]
247 #[allow(deprecated)]
248 #[case(
249 "Invalid integer (caused by InvalidDigit)",
250 Error::InvalidInteger {
251 kind: IntErrorKind::InvalidDigit
252 }
253 )]
254 #[case(
255 "Invalid e-mail (Missing separator character '@'.)",
256 email_address::Error::MissingSeparator.into()
257 )]
258 #[case(
259 "Invalid integer (caused by InvalidDigit)",
260 Error::InvalidInteger {
261 kind: IntErrorKind::InvalidDigit
262 }
263 )]
264 fn error_format_string(#[case] error_str: &str, #[case] error: Error) {
265 assert_eq!(error_str, format!("{error}"));
266 }
267}