diff --git a/src/downloader/downloader.rs b/src/downloader/downloader.rs index da730e1..348eda8 100644 --- a/src/downloader/downloader.rs +++ b/src/downloader/downloader.rs @@ -1,9 +1,9 @@ use super::pd_file::PdFile; -use super::pd_file::PdFilePartStatus; use super::pd_file::PdFileResult; use super::enums::DownloaderResult; use super::enums::DownloaderStatus; use super::error::DownloaderError; +use super::tasks::create_download_tasks_simple; use crate::ext::atomic::AtomicQuick; use crate::ext::rw_lock::GetRwLock; use crate::utils::ask_need_overwrite; @@ -24,7 +24,7 @@ use url::Url; #[derive(Debug)] /// A file downloader -pub struct Downloader { +pub struct DownloaderInternal { /// The webclient client: Arc, /// The download status @@ -38,18 +38,18 @@ pub struct Downloader { /// The status of the downloader status: RwLock, /// All tasks - tasks: Vec>, + tasks: RwLock>>, /// Whether to enable mulitple thread mode multi: AtomicBool, } -impl Downloader { - /// Create a new [Downloader] instance +impl DownloaderInternal { + /// Create a new [DownloaderInternal] instance /// * `url` - The url of the file /// * `header` - HTTP headers /// * `path` - The path to store downloaded file. /// * `overwrite` - Whether to overwrite file - pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result, DownloaderError> { + pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result, DownloaderError> { let h = match headers.to_headers() { Some(h) => { h } None => { HashMap::new() } @@ -105,20 +105,21 @@ impl Downloader { headers: Arc::new(h), file: RwLock::new(file), status: RwLock::new(DownloaderStatus::Created), - tasks: Vec::new(), + tasks: RwLock::new(Vec::new()), multi: AtomicBool::new(false), })) } } -impl Downloader { - /// Start download if download not started. - /// - /// Returns the status of the Downloader - pub fn download(&self) -> DownloaderStatus { - if !self.is_created() { - return self.status.get_ref().clone(); - } +impl DownloaderInternal { + /// Add a new task to tasks + /// * `task` - Task + pub fn add_task(&self, task: JoinHandle) { + self.tasks.get_mut().push(task) + } + + /// Return the status of the downloader. + pub fn get_status(&self) -> DownloaderStatus { self.status.get_ref().clone() } @@ -138,3 +139,54 @@ impl Downloader { } } } + +/// A file downloader +pub struct Downloader { + /// internal type + downloader: Arc>, +} + +impl Downloader { + /// Create a new [Downloader] instance + /// * `url` - The url of the file + /// * `header` - HTTP headers + /// * `path` - The path to store downloaded file. + /// * `overwrite` - Whether to overwrite file + pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result, DownloaderError> { + Ok(match DownloaderInternal::::new(url, headers, path, overwrite)? { + DownloaderResult::Ok(d) => { + DownloaderResult::Ok(Self { downloader: Arc::new(d) }) + } + DownloaderResult::Canceled => { DownloaderResult::Canceled } + }) + } +} + +macro_rules! define_downloader_fn { + {$f:ident, $t:ty, $doc:expr} => { + #[inline] + #[doc = $doc] + pub fn $f(&self) -> $t { + self.downloader.$f() + } + } +} + +impl Downloader { + /// Start download if download not started. + /// + /// Returns the status of the Downloader + pub fn download(&self) -> DownloaderStatus { + if !self.is_created() { + return self.downloader.get_status(); + } + if !self.is_multi_threads() { + let task = tokio::spawn(create_download_tasks_simple(Arc::clone(&self.downloader))); + self.downloader.add_task(task); + } + self.downloader.get_status() + } + + define_downloader_fn!(is_created, bool, "Returns true if the downloader is created just now."); + define_downloader_fn!(is_multi_threads, bool, "Returns true if is multiple thread mode."); +} diff --git a/src/downloader/enums.rs b/src/downloader/enums.rs index d558c0e..e5f473d 100644 --- a/src/downloader/enums.rs +++ b/src/downloader/enums.rs @@ -1,18 +1,14 @@ -use super::downloader::Downloader; -use std::io::Seek; -use std::io::Write; - #[derive(Debug)] -/// The result when try create a new [Downloader] interface -pub enum DownloaderResult { +/// The result when try create a new [super::Downloader] interface +pub enum DownloaderResult { /// Created successfully - Ok(Downloader), + Ok(T), /// The target file already downloaded and overwrite is disabled. Canceled, } #[derive(Clone, Debug, PartialEq, PartialOrd)] -/// The status of the [Downloader] +/// The status of the [super::Downloader] pub enum DownloaderStatus { /// The downloader is just created Created, diff --git a/src/downloader/mod.rs b/src/downloader/mod.rs index 14a7f30..8b89889 100644 --- a/src/downloader/mod.rs +++ b/src/downloader/mod.rs @@ -6,4 +6,6 @@ pub mod enums; pub mod error; /// The pd file pub mod pd_file; +/// Deal download tasks +pub mod tasks; pub use downloader::Downloader; diff --git a/src/downloader/tasks.rs b/src/downloader/tasks.rs new file mode 100644 index 0000000..057b7cd --- /dev/null +++ b/src/downloader/tasks.rs @@ -0,0 +1,9 @@ +use super::downloader::DownloaderInternal; +use std::io::Seek; +use std::io::Write; +use std::sync::Arc; + +/// Create a download tasks in simple thread mode. +pub async fn create_download_tasks_simple(d: Arc>) -> bool { + false +}