pkg/net_backend/
mod.rs

1use std::{cell::RefCell, io, path::Path, rc::Rc};
2use thiserror::Error;
3
4use crate::Callback;
5
6mod reqwest_backend;
7
8pub use reqwest_backend::ReqwestBackend as DefaultNetBackend;
9
10pub trait DownloadBackend {
11    fn new() -> Result<Self, DownloadError>
12    where
13        Self: Sized;
14
15    fn download(
16        &self,
17        remote_path: &str,
18        local_path: &Path,
19        callback: Rc<RefCell<dyn Callback>>,
20    ) -> Result<(), DownloadError>;
21
22    fn file_size(&self) -> Option<usize> {
23        None
24    }
25}
26
27#[derive(Error, Debug)]
28pub enum DownloadError {
29    // Specific variant for timeout errors
30    #[error("Download timed out")]
31    Timeout,
32    // Specific variant for HTTP status errors (e.g., 404, 500)
33    #[error("HTTP error status: {0}")]
34    HttpStatus(reqwest::StatusCode),
35    // Fallback for other generic reqwest errors
36    #[error("Other reqwest error: {0}")]
37    Reqwest(reqwest::Error),
38    // IO errors remain the same
39    #[error("IO error: {0}")]
40    IO(#[from] io::Error),
41}
42
43impl From<reqwest::Error> for DownloadError {
44    fn from(err: reqwest::Error) -> Self {
45        if err.is_timeout() {
46            DownloadError::Timeout
47        } else if err.is_status() {
48            DownloadError::HttpStatus(
49                err.status()
50                    .unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR),
51            )
52        } else {
53            DownloadError::Reqwest(err)
54        }
55    }
56}