1use std::{error::Error, fmt::Display, io};
2
3#[derive(Debug)]
4pub enum DownloadError {
5 InvalidUrl {
6 url: String,
7 source: url::ParseError,
8 },
9 IoError(io::Error),
10 NetworkError {
11 source: reqwest::Error,
12 },
13 ResourceError {
14 url: String,
15 status: reqwest::StatusCode,
16 },
17 InvalidResponse,
18 LayersNotFound,
19 ChunkError,
20 FileNameNotFound,
21 ZipError(zip::result::ZipError),
22}
23
24impl Display for DownloadError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 DownloadError::IoError(err) => write!(f, "IO error: {}", err),
28 DownloadError::InvalidUrl { url, .. } => write!(f, "Invalid URL: {}", url),
29 DownloadError::NetworkError { .. } => write!(f, "Network Request failed"),
30 DownloadError::ResourceError { url, status } => {
31 write!(f, "Failed to fetch resource from {} [{}]", url, status)
32 }
33 DownloadError::LayersNotFound => write!(f, "No downloadable layers found"),
34 DownloadError::InvalidResponse => write!(f, "Failed to parse response"),
35 DownloadError::ChunkError => write!(f, "Failed to read chunk"),
36 DownloadError::FileNameNotFound => {
37 write!(
38 f,
39 "Couldn't find filename. Please provide filename explicitly."
40 )
41 }
42 DownloadError::ZipError(err) => write!(f, "Zip error: {}", err),
43 }
44 }
45}
46
47impl Error for DownloadError {
48 fn source(&self) -> Option<&(dyn Error + 'static)> {
49 match self {
50 DownloadError::IoError(err) => Some(err),
51 DownloadError::InvalidUrl { source, .. } => Some(source),
52 DownloadError::NetworkError { source } => Some(source),
53 _ => None,
54 }
55 }
56}
57
58impl From<io::Error> for DownloadError {
59 fn from(value: io::Error) -> Self {
60 Self::IoError(value)
61 }
62}
63
64#[derive(Debug)]
65pub enum PlatformError {
66 ApiError { status: reqwest::StatusCode },
67 DownloadError(DownloadError),
68 InvalidInput(String),
69 InvalidResponse,
70 NoMatchingAssets { available_assets: Vec<String> },
71 NoRelease { tag: Option<String> },
72 RepositoryNotFound { owner: String, repo: String },
73}
74
75impl Display for PlatformError {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 PlatformError::ApiError { status } => write!(f, "API error [{}]", status),
79 PlatformError::DownloadError(err) => write!(f, "Download error: {}", err),
80 PlatformError::InvalidInput(msg) => {
81 write!(f, "{} is invalid", msg)
82 }
83 PlatformError::InvalidResponse => write!(f, "Failed to parse response"),
84 PlatformError::NoRelease { tag } => write!(
85 f,
86 "No {} found.",
87 tag.clone()
88 .map(|t| format!("tag {}", t))
89 .unwrap_or("release".to_string())
90 ),
91 PlatformError::NoMatchingAssets { .. } => write!(f, "No matching assets found"),
92 PlatformError::RepositoryNotFound { owner, repo } => {
93 write!(f, "Repository not found: {}/{}", owner, repo)
94 }
95 }
96 }
97}
98
99impl From<DownloadError> for PlatformError {
100 fn from(value: DownloadError) -> Self {
101 Self::DownloadError(value)
102 }
103}