1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum SwiftError {
8 #[error("Failed to parse Package.swift: {message}")]
10 ParseError { message: String },
11
12 #[error("Invalid SPM version specifier '{specifier}': {message}")]
14 InvalidVersionSpecifier { specifier: String, message: String },
15
16 #[error("GitHub API request failed for '{package}': {source}")]
18 RegistryError {
19 package: String,
20 #[source]
21 source: Box<dyn std::error::Error + Send + Sync>,
22 },
23
24 #[error("GitHub API error: {status} {message}")]
26 GitHubApiError { status: u16, message: String },
27
28 #[error("I/O error: {0}")]
30 Io(#[from] std::io::Error),
31}
32
33pub type Result<T> = std::result::Result<T, SwiftError>;
35
36impl SwiftError {
37 pub fn registry_error(
38 package: impl Into<String>,
39 error: impl std::error::Error + Send + Sync + 'static,
40 ) -> Self {
41 Self::RegistryError {
42 package: package.into(),
43 source: Box::new(error),
44 }
45 }
46
47 pub fn parse_error(message: impl Into<String>) -> Self {
48 Self::ParseError {
49 message: message.into(),
50 }
51 }
52
53 pub fn github_api_error(message: impl Into<String>) -> Self {
54 Self::GitHubApiError {
55 status: 0,
56 message: message.into(),
57 }
58 }
59}
60
61impl From<deps_core::DepsError> for SwiftError {
62 fn from(err: deps_core::DepsError) -> Self {
63 match err {
64 deps_core::DepsError::CacheError(msg) => Self::ParseError { message: msg },
65 deps_core::DepsError::InvalidVersionReq(msg) => Self::InvalidVersionSpecifier {
66 specifier: String::new(),
67 message: msg,
68 },
69 deps_core::DepsError::Io(e) => Self::Io(e),
70 other => Self::ParseError {
71 message: other.to_string(),
72 },
73 }
74 }
75}
76
77impl From<SwiftError> for deps_core::DepsError {
78 fn from(err: SwiftError) -> Self {
79 match err {
80 SwiftError::ParseError { message } => Self::CacheError(message),
81 SwiftError::InvalidVersionSpecifier { message, .. } => Self::InvalidVersionReq(message),
82 SwiftError::RegistryError { package, source } => Self::ParseError {
83 file_type: format!("GitHub API for {package}"),
84 source,
85 },
86 SwiftError::GitHubApiError { status, message } => {
87 Self::CacheError(format!("GitHub API {status}: {message}"))
88 }
89 SwiftError::Io(e) => Self::Io(e),
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_error_display() {
100 let err = SwiftError::ParseError {
101 message: "unexpected token".into(),
102 };
103 assert_eq!(
104 err.to_string(),
105 "Failed to parse Package.swift: unexpected token"
106 );
107
108 let err = SwiftError::GitHubApiError {
109 status: 403,
110 message: "rate limited".into(),
111 };
112 assert_eq!(err.to_string(), "GitHub API error: 403 rate limited");
113 }
114
115 #[test]
116 fn test_conversion_to_deps_error() {
117 let err = SwiftError::ParseError {
118 message: "test".into(),
119 };
120 let deps_err: deps_core::DepsError = err.into();
121 assert!(deps_err.to_string().contains("test"));
122 }
123}