diff --git a/src/lib.rs b/src/lib.rs index cb86c85..e56f5f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use std::{ io::{self, Write, Error, ErrorKind}, path::{Path, PathBuf}, process::Command, + time::SystemTime, }; pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; @@ -222,3 +223,49 @@ pub fn extract_package_and_wait(dir: &str, file_name: &str) -> io::Result<()> { run_command_and_wait(&mut cmd) } +pub fn copy_io(reader: &mut R, writer: &mut W, total: i64) -> io::Result + where R: io::Read, W: io::Write { + // let mut written = 0u64; + // let written_cell = RefCell::new(written); + let start = SystemTime::now(); + let written = copy_io_callback(reader, writer, total, &|total, written, _len| { + // let mut written_borrowed = written_cell.borrow_mut(); + //written_cell.replace_with(|&mut old_written| old_written + len as u64); + let cost = SystemTime::now().duration_since(start.clone()).unwrap().as_secs(); + let mut download_speed = "-".to_string(); + if cost > 0 { + download_speed = format!("{}/s", get_display_size((written / cost) as i64)); + } + if total > 0 { + print_lastline(&format!("Downloading, Total: {}, Downloaded: {}, Speed: {}", + get_display_size(total), + get_display_size(written as i64), + download_speed)); + } else { + print_lastline(&format!("Downloading, Downloaded: {}, Speed: {}", + get_display_size(written as i64), + download_speed)); + } + }); + println!(); + written +} + +pub fn copy_io_callback(reader: &mut R, writer: &mut W, total: i64, callback: &FCallback) -> io::Result + where R: io::Read, + W: io::Write, + FCallback: Fn(i64, u64, usize) -> () { + let mut written = 0u64; + let mut buf: [u8; DEFAULT_BUF_SIZE] = [0u8; DEFAULT_BUF_SIZE]; + loop { + let len = match reader.read(&mut buf) { + Ok(0) => return Ok(written), + Ok(len) => len, + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + }; + writer.write_all(&buf[..len])?; + written += len as u64; + callback(total, written, len); + } +}