1use std::path::PathBuf;
2
3#[derive(Debug, thiserror::Error, PartialEq)]
13#[allow(missing_docs)]
14pub enum Error {
15 #[error("Invalid integer (caused by {kind:?})")]
17 InvalidInteger { kind: std::num::IntErrorKind },
18
19 #[error("Invalid variant ({0})")]
21 InvalidVariant(#[from] strum::ParseError),
22
23 #[error("Invalid e-mail ({0})")]
25 InvalidEmail(#[from] email_address::Error),
26
27 #[error("Invalid URL ({0})")]
29 InvalidUrl(#[from] url::ParseError),
30
31 #[error("Invalid license ({0})")]
33 InvalidLicense(#[from] spdx::ParseError),
34
35 #[error("Invalid semver ({kind})")]
43 InvalidSemver { kind: String },
44
45 #[error("Value contains invalid characters: {invalid_char:?}")]
47 ValueContainsInvalidChars { invalid_char: char },
48
49 #[error("Incorrect length, got {length} expected {expected}")]
51 IncorrectLength { length: usize, expected: usize },
52
53 #[error("Value is missing the required delimiter: {delimiter}")]
55 DelimiterNotFound { delimiter: char },
56
57 #[error("Does not match the restrictions ({restrictions:?})")]
59 ValueDoesNotMatchRestrictions { restrictions: Vec<String> },
60
61 #[error("Value '{value}' does not match the '{regex_type}' regex: {regex}")]
63 RegexDoesNotMatch {
64 value: String,
65 regex_type: String,
66 regex: String,
67 },
68
69 #[error("Parser failed with the following error:\n{0}")]
71 ParseError(String),
72
73 #[error("Missing component: {component}")]
75 MissingComponent { component: &'static str },
76
77 #[error("The path is not absolute: {0}")]
79 PathNotAbsolute(PathBuf),
80
81 #[error("The path is not relative: {0}")]
83 PathNotRelative(PathBuf),
84
85 #[error("File name ({0}) contains invalid characters: {1:?}")]
87 FileNameContainsInvalidChars(PathBuf, char),
88
89 #[error("File name is empty")]
91 FileNameIsEmpty,
92
93 #[error("Deprecated license: {0}")]
95 DeprecatedLicense(String),
96
97 #[error("Invalid OpenPGP v4 fingerprint, only 40 uppercase hexadecimal characters are allowed")]
99 InvalidOpenPGPv4Fingerprint,
100
101 #[error("The string is not a valid OpenPGP key ID: {0}, must be 16 hexadecimal characters")]
103 InvalidOpenPGPKeyId(String),
104
105 #[error("Invalid shared object name (v1): {0}")]
107 InvalidSonameV1(&'static str),
108
109 #[error("Package error: {0}")]
111 Package(#[from] crate::PackageError),
112
113 #[error("Unknown compression algorithm file extension: {value:?}")]
115 UnknownCompressionAlgorithmFileExtension {
116 value: String,
118 },
119
120 #[error("Unknown file type identifier: {value:?}")]
122 UnknownFileTypeIdentifier {
123 value: String,
125 },
126}
127
128impl From<std::num::ParseIntError> for crate::error::Error {
129 fn from(e: std::num::ParseIntError) -> Self {
131 Self::InvalidInteger {
132 kind: e.kind().clone(),
133 }
134 }
135}
136
137impl<'a> From<winnow::error::ParseError<&'a str, winnow::error::ContextError>>
138 for crate::error::Error
139{
140 fn from(value: winnow::error::ParseError<&'a str, winnow::error::ContextError>) -> Self {
142 Self::ParseError(value.to_string())
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use std::num::IntErrorKind;
149
150 use rstest::rstest;
151
152 use super::*;
153 use crate::openpgp::PACKAGER_REGEX;
154
155 #[rstest]
156 #[case(
157 "Invalid integer (caused by InvalidDigit)",
158 Error::InvalidInteger {
159 kind: IntErrorKind::InvalidDigit
160 }
161 )]
162 #[case(
163 "Invalid integer (caused by InvalidDigit)",
164 Error::InvalidInteger {
165 kind: IntErrorKind::InvalidDigit
166 }
167 )]
168 #[case(
169 "Invalid integer (caused by PosOverflow)",
170 Error::InvalidInteger {
171 kind: IntErrorKind::PosOverflow
172 }
173 )]
174 #[allow(deprecated)]
175 #[case(
176 "Invalid integer (caused by InvalidDigit)",
177 Error::InvalidInteger {
178 kind: IntErrorKind::InvalidDigit
179 }
180 )]
181 #[case(
182 "Value '€i²' does not match the 'packager' regex: ^(?P<name>[\\w\\s\\-().]+) <(?P<email>.*)>$",
183 Error::RegexDoesNotMatch {
184 value: "€i²".to_string(),
185 regex_type: "packager".to_string(),
186 regex: PACKAGER_REGEX.to_string(),
187 }
188 )]
189 #[case(
190 "Invalid e-mail (Missing separator character '@'.)",
191 email_address::Error::MissingSeparator.into()
192 )]
193 #[case(
194 "Invalid integer (caused by InvalidDigit)",
195 Error::InvalidInteger {
196 kind: IntErrorKind::InvalidDigit
197 }
198 )]
199 fn error_format_string(#[case] error_str: &str, #[case] error: Error) {
200 assert_eq!(error_str, format!("{}", error));
201 }
202}