Skip to main content

cc_downloader/
errors.rs

1use std::fmt;
2
3/// Error type returned by all fallible operations in this library.
4///
5/// Each variant wraps the underlying error from the relevant subsystem, so
6/// callers can pattern-match on specific failure modes or rely on the
7/// [`Display`](std::fmt::Display) impl for a human-readable message.
8///
9/// # Examples
10///
11/// ```no_run
12/// use cc_downloader::download::{DownloadOptions, download_paths};
13/// use cc_downloader::errors::DownloadError;
14///
15/// # #[tokio::main]
16/// # async fn main() {
17/// let options = DownloadOptions {
18///     snapshot: "CC-MAIN-2024-46".to_string(),
19///     data_type: "wet",
20///     dst: std::path::Path::new("./output"),
21///     ..Default::default()
22/// };
23/// match download_paths(options).await {
24///     Ok(_) => println!("Done"),
25///     Err(DownloadError::Custom(msg)) => eprintln!("Resource not found: {msg}"),
26///     Err(e) => eprintln!("Download failed: {e}"),
27/// }
28/// # }
29/// ```
30#[derive(Debug)]
31pub enum DownloadError {
32    /// An error from the underlying HTTP client ([`reqwest`]).
33    Reqwest(reqwest::Error),
34    /// An error from the retry middleware ([`reqwest_middleware`]).
35    ReqwestMiddleware(reqwest_middleware::Error),
36    /// An I/O error, either from [`tokio::io`] or the standard library.
37    Tokio(tokio::io::Error),
38    /// A URL parsing error.
39    Url(url::ParseError),
40    /// An error constructing a progress bar template ([`indicatif`]).
41    Indicatif(indicatif::style::TemplateError),
42    /// A task join error from the async runtime.
43    Join(tokio::task::JoinError),
44    /// A domain-level error, e.g. an unrecognised snapshot reference or an
45    /// inaccessible paths URL. The inner `String` contains the full message
46    /// printed to the user.
47    Custom(String),
48}
49
50impl fmt::Display for DownloadError {
51    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52        match *self {
53            DownloadError::Reqwest(ref err) => err.fmt(f),
54            DownloadError::ReqwestMiddleware(ref err) => err.fmt(f),
55            DownloadError::Tokio(ref err) => err.fmt(f),
56            DownloadError::Url(ref err) => err.fmt(f),
57            DownloadError::Indicatif(ref err) => err.fmt(f),
58            DownloadError::Join(ref err) => err.fmt(f),
59            DownloadError::Custom(ref err) => err.fmt(f),
60        }
61    }
62}
63
64impl From<reqwest::Error> for DownloadError {
65    fn from(err: reqwest::Error) -> Self {
66        DownloadError::Reqwest(err)
67    }
68}
69
70impl From<reqwest_middleware::Error> for DownloadError {
71    fn from(err: reqwest_middleware::Error) -> Self {
72        DownloadError::ReqwestMiddleware(err)
73    }
74}
75
76impl From<tokio::io::Error> for DownloadError {
77    fn from(err: tokio::io::Error) -> Self {
78        DownloadError::Tokio(err)
79    }
80}
81
82impl From<url::ParseError> for DownloadError {
83    fn from(err: url::ParseError) -> Self {
84        DownloadError::Url(err)
85    }
86}
87
88impl From<indicatif::style::TemplateError> for DownloadError {
89    fn from(err: indicatif::style::TemplateError) -> Self {
90        DownloadError::Indicatif(err)
91    }
92}
93
94impl From<tokio::task::JoinError> for DownloadError {
95    fn from(err: tokio::task::JoinError) -> Self {
96        DownloadError::Join(err)
97    }
98}
99
100impl From<String> for DownloadError {
101    fn from(s: String) -> DownloadError {
102        DownloadError::Custom(s)
103    }
104}