From ed9057e6e0e5967abc63cf857ba50eadd362062d Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 13 Jul 2020 03:02:28 +0100 Subject: [PATCH] download works! --- src/work_async.rs | 31 +++++++++----- src/work_async/progress.rs | 87 ++++++++++++++++++++++++++++++++------ src/work_async/tasklist.rs | 6 +++ 3 files changed, 100 insertions(+), 24 deletions(-) diff --git a/src/work_async.rs b/src/work_async.rs index 17824a0..3879c6d 100644 --- a/src/work_async.rs +++ b/src/work_async.rs @@ -22,13 +22,17 @@ pub async fn perform(url: impl AsRef, path: impl AsRef, mut progress: let url = url.as_ref(); let path = path.as_ref(); - let task = url.to_owned(); //TODO: Real task name + let task = format!("{:?}", path); //TODO: Real task name - prog_send!(link progress.push_task(&task)); - let mut resp = reqwest::get(url).await?; let len = resp.content_length(); + prog_send!(link progress.push_task(&task)); + if let Some(len) = len { + prog_send!(progress.bump_max(len)); + } else { + prog_send!(progress.bump_max(1)); + } let mut file = OpenOptions::new() .create(true) @@ -37,19 +41,26 @@ pub async fn perform(url: impl AsRef, path: impl AsRef, mut progress: .read(true) .open(path).await?; - prog_send!(progress.println(format!("req ok {:?}, file ok ({:?}), starting download", len, path))); + prog_send!(progress.println(format!("Starting download of {:?} bytes to {:?}", len, path))); let mut bytes = resp.bytes_stream(); while let Some(buffer) = bytes.next().await { - file.write(buffer?.as_ref()).await?; - prog_send!(progress.bump()); + let slice = buffer?; + let slice = slice.as_ref(); + file.write(slice).await?; + + if let Some(_) = len { + prog_send!(progress.bump(slice.len() as u64)); + } + } + if len.is_none() { + prog_send!(progress.bump(1)); } //TODO: Decode `file`. prog_send!(progress.println(format!("done for {}", url))); - prog_send!(progress.bump()); - prog_send!(progress.pop_task(task)); + prog_send!(link progress.pop_task(task)); Ok(()) } @@ -59,7 +70,7 @@ pub async fn work(conf: config::Config) -> Result<(), Box let rating = conf.rating; let mut children = Vec::new(); - let prog = progress::AsyncProgressCounter::new("Initialising..."); + let prog = progress::AsyncProgressCounter::new("Initialising...", 1); let mut prog_writer = prog.writer(); let prog = prog.host(); @@ -96,7 +107,7 @@ pub async fn work(conf: config::Config) -> Result<(), Box }, } } - + prog_send!(link prog_writer.set_title("")); prog_send!(try link prog_writer.kill()); prog.await.expect("mpsc fatal"); diff --git a/src/work_async/progress.rs b/src/work_async/progress.rs index 1a3d702..e768284 100644 --- a/src/work_async/progress.rs +++ b/src/work_async/progress.rs @@ -31,10 +31,12 @@ use std::{ enum CommandInternal { PrintLine(String), - Bump, + BumpMax(u64), + Bump(u64), Kill(Option), PushTask(String), PopTask(String), + ClearTask(Option), } // TODO: Change from `Spinner` to `Bar`. Have push max, push current, etc. @@ -58,6 +60,9 @@ pub struct AsyncProgressCounter writer: Sender, reader: Receiver, title: String, + + small: u64, + large: u64, } #[derive(Clone)] @@ -148,14 +153,23 @@ impl CommandSender Ok(call) } - /// Finalise the progress counter - pub async fn bump(&mut self) -> Result + /// Bump the progress counter's upper bound + pub async fn bump_max(&mut self, by: u64) -> Result + { + let (com, call) = Command::new(CommandInternal::BumpMax(by)); + self.0.send(com).await?; + Ok(call) + } + + /// Bump the progress counter's upper bound + pub async fn bump(&mut self, by: u64) -> Result { - let (com, call) = Command::new(CommandInternal::Bump); + let (com, call) = Command::new(CommandInternal::Bump(by)); self.0.send(com).await?; Ok(call) } + /// Finalise the progress counter pub async fn kill(&mut self) -> Result { @@ -188,6 +202,22 @@ impl CommandSender self.0.send(com).await?; Ok(call) } + + /// Clear all tasks + pub async fn clear_task(&mut self) -> Result + { + let (com, call) = Command::new(CommandInternal::ClearTask(None)); + self.0.send(com).await?; + Ok(call) + } + + /// Clear all tasks and set new title + pub async fn set_title(&mut self, title: impl Into) -> Result + { + let (com, call) = Command::new(CommandInternal::ClearTask(Some(title.into()))); + self.0.send(com).await?; + Ok(call) + } } impl CommandCallback @@ -202,7 +232,7 @@ impl CommandCallback impl AsyncProgressCounter { /// Create a new `AsyncProgressCounter` - pub fn new(title: impl Into) -> Self + pub fn new(title: impl Into, max: u64) -> Self { let (tx, rx) = channel(16); @@ -210,6 +240,8 @@ impl AsyncProgressCounter reader: rx, writer: tx, title: title.into(), + small: 0, + large: max, } } @@ -224,37 +256,64 @@ impl AsyncProgressCounter CommandSender(self.writer.clone(), None) } - /// Consume the instance and host it's receiver + /// Consume the instance and host its receiver pub fn host(mut self) -> JoinHandle<()> { - let mut spin = spinner::Spin::with_title(&self.title[..], Default::default()); + //let mut spin = spinner::Spin::with_title(&self.title[..], Default::default()); + let mut bar = termprogress::progress::Bar::with_title(50, &self.title[..]); + + bar.update(); let mut task = tasklist::TaskList::new(); + task::spawn(async move { + + let mut small = 0;//self.small; + let mut large = 0; + + fn prog_calc(small: u64, large: u64) -> f64 { + (small as f64) / (large as f64) + } + while let Some(com) = self.reader.recv().await { match &com.internal { - CommandInternal::PrintLine(line) => spin.println(&line[..]), - CommandInternal::Bump => { - spin.bump(); //TODO: We'll have to change this when we change to real progress + CommandInternal::PrintLine(line) => bar.println(&line[..]), + CommandInternal::BumpMax(by) => { + large += by; + bar.set_progress(prog_calc(small,large)); + }, + CommandInternal::Bump(by) => { + small += by; + bar.set_progress(prog_calc(small,large)); }, CommandInternal::Kill(Some(line)) => { - spin.complete_with(line.as_str()); + bar.println(&line[..]); + bar.complete(); self.reader.close(); break; }, CommandInternal::Kill(_) => { - spin.complete(); + bar.complete(); self.reader.close(); break; }, CommandInternal::PushTask(tstr) => { task.push(tstr); - spin.set_title(task.as_str()); + bar.set_title(task.as_str()); }, CommandInternal::PopTask(tstr) => { task.pop_value(tstr); - spin.set_title(task.as_str()); + bar.set_title(task.as_str()); + }, + CommandInternal::ClearTask(None) => { + task.clear(); + bar.set_title(&self.title[..]); + }, + CommandInternal::ClearTask(Some(title)) => { + task.clear(); + bar.set_title(&title[..]); + self.title = title.clone(); }, } } diff --git a/src/work_async/tasklist.rs b/src/work_async/tasklist.rs index e8c4619..0faa6fb 100644 --- a/src/work_async/tasklist.rs +++ b/src/work_async/tasklist.rs @@ -50,6 +50,12 @@ impl TaskList } } + pub fn clear(&mut self) + { + self.0.clear(); + self.recalc_buffer(); + } + pub fn pop_value(&mut self, string: impl AsRef) -> bool { let string = string.as_ref();