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 #[error("Download timed out")]
31 Timeout,
32 #[error("HTTP error status: {0}")]
34 HttpStatus(reqwest::StatusCode),
35 #[error("Other reqwest error: {0}")]
37 Reqwest(reqwest::Error),
38 #[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}