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