use thiserror::Error;
#[derive(Debug, Clone)]
pub enum ProgressEvent {
Resolving { name: String },
UrlCandidate { name: String, url: String },
Downloading {
name: String,
got: u64,
total: Option<u64>,
},
Verifying { name: String },
Extracting { name: String },
Installing { name: String },
Done { name: String, version: String },
Failed { name: String, reason: String },
}
#[derive(Debug, Error)]
pub enum DownloaderError {
#[error("downloader unsupported: {0:?}")]
Unsupported(UnsupportedReason),
#[error("downloader failed ({kind:?}): {source}")]
Failed {
kind: FailureKind,
#[source]
source: anyhow::Error,
},
#[error("cancelled by user")]
Cancelled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnsupportedReason {
NoMetadataAndNoConvention,
UnknownArchiveFormat,
UnsupportedPlatform,
GitSource,
PathSource,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FailureKind {
AllUrlsFailed,
DownloadInterrupted,
ChecksumMismatch,
ExtractFailed,
InstallFailed,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unsupported_display_includes_reason() {
let e = DownloaderError::Unsupported(UnsupportedReason::GitSource);
let s = format!("{e}");
assert!(s.contains("GitSource"), "got: {s}");
}
#[test]
fn failed_chains_source() {
let inner = anyhow::anyhow!("connect refused");
let e = DownloaderError::Failed {
kind: FailureKind::AllUrlsFailed,
source: inner,
};
let s = format!("{e}");
assert!(s.contains("AllUrlsFailed"), "got: {s}");
}
}