From 289fe68e6186902973d4eed7512f0535680d90b3 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sun, 20 Sep 2020 16:47:34 +0800 Subject: [PATCH] feat: add print_status_context --- Cargo.toml | 2 +- src/util_io.rs | 71 +++++++++++++++++++++++++++++++++++------------- src/util_time.rs | 4 +-- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b4ee294..e103f29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust_util" -version = "0.6.14" +version = "0.6.15" authors = ["Hatter Jiang "] edition = "2018" description = "Hatter's Rust Util" diff --git a/src/util_io.rs b/src/util_io.rs index 769e92d..483bb2a 100644 --- a/src/util_io.rs +++ b/src/util_io.rs @@ -8,16 +8,15 @@ use crate::{ XResult, new_box_ioerror }; use crate::util_size; use crate::util_msg; use crate::util_file; -use crate::util_time; pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; -// TODO add to print status line pub struct PrintStatusContext { pub print_interval_time: Duration, - pub print_interval_bytes: usize, - pub last_print_time: u128, - pub last_print_bytes: usize, + pub print_interval_bytes: i64, + pub init_print_time: SystemTime, + pub last_print_time: SystemTime, + pub total_written_bytes: i64, } impl PrintStatusContext { @@ -25,12 +24,38 @@ impl PrintStatusContext { Self::new_with(Duration::from_millis(100), 512 * 1024) } - pub fn new_with(print_interval_time: Duration, print_interval_bytes: usize) -> Self { + pub fn new_with(print_interval_time: Duration, print_interval_bytes: i64) -> Self { Self { print_interval_time, print_interval_bytes, - last_print_time: util_time::get_current_millis(), - last_print_bytes: 0, + init_print_time: SystemTime::now(), + last_print_time: SystemTime::now(), + total_written_bytes: 0, + } + } + + pub fn check_print(&mut self, total: i64, written: i64) -> (bool, Duration) { + let now = SystemTime::now(); + let total_cost = now.duration_since(self.init_print_time).unwrap_or_else(|_| Duration::from_millis(0)); + let last_print_cost = now.duration_since(self.last_print_time).unwrap_or_else(|_| Duration::from_millis(0)); + let should_update_status_line = || { + if total > written && (total - written < self.print_interval_bytes) { + return true; + } + if written > self.total_written_bytes && (written - self.total_written_bytes > self.print_interval_bytes) { + return true; + } + match last_print_cost.as_millis() { + m if m > self.print_interval_time.as_millis() => true, + _ => false, + } + }; + if should_update_status_line() { + self.last_print_time = now; + self.total_written_bytes = written; + (true, total_cost) + } else { + (false, total_cost) } } } @@ -64,26 +89,30 @@ pub fn read_to_bytes(read: &mut dyn Read) -> XResult> { Ok(buffer) } -pub fn copy_io(reader: &mut R, writer: &mut W, total: i64) -> io::Result +pub fn copy_io_default(reader: &mut R, writer: &mut W, total: i64) -> io::Result where R: io::Read, W: io::Write { - copy_io_with_head(reader, writer, total, "Downloading") + copy_io_with_head(reader, writer, total, "Downloading", &mut PrintStatusContext::default()) } -pub fn copy_io_with_head(reader: &mut R, writer: &mut W, total: i64, head: &str) -> io::Result +pub fn copy_io(reader: &mut R, writer: &mut W, total: i64, print_status_context: &mut PrintStatusContext) + -> io::Result where R: io::Read, W: io::Write { - let start = SystemTime::now(); - let written = copy_io_callback(reader, writer, total, &|total, written, _len| { - let cost = SystemTime::now().duration_since(start).unwrap(); - print_status_last_line(head, total, written as i64, cost); + copy_io_with_head(reader, writer, total, "Downloading", print_status_context) +} + +pub fn copy_io_with_head(reader: &mut R, writer: &mut W, total: i64, head: &str, print_status_context: &mut PrintStatusContext) -> io::Result + where R: io::Read, W: io::Write { + let written = copy_io_callback(reader, writer, total, print_status_context, &mut |total, written, _len, print_status_context| { + print_status_last_line(head, total, written as i64, print_status_context); }); println!(); written } -pub fn copy_io_callback(reader: &mut R, writer: &mut W, total: i64, callback: &FCallback) -> io::Result +pub fn copy_io_callback(reader: &mut R, writer: &mut W, total: i64, print_status_context: &mut PrintStatusContext, callback: &mut FCallback) -> io::Result where R: io::Read, W: io::Write, - FCallback: Fn(i64, u64, usize) { + FCallback: Fn(i64, u64, usize, &mut PrintStatusContext) { let mut written = 0u64; let mut buf: [u8; DEFAULT_BUF_SIZE] = [0u8; DEFAULT_BUF_SIZE]; loop { @@ -95,12 +124,16 @@ pub fn copy_io_callback(reader: &mut R, writer: }; writer.write_all(&buf[..len])?; written += len as u64; - callback(total, written, len); + callback(total, written, len, print_status_context); } } -pub fn print_status_last_line(head: &str, total: i64, written: i64, cost: Duration) { +pub fn print_status_last_line(head: &str, total: i64, written: i64, print_status_context: &mut PrintStatusContext) { let mut download_speed = "-".to_string(); + let (is_print, cost) = print_status_context.check_print(total, written); + if !is_print { + return; + } let cost_as_secs = cost.as_secs(); if cost_as_secs > 0 { download_speed = format!("{}/s", util_size::get_display_size((written / (cost_as_secs as i64)) as i64)); diff --git a/src/util_time.rs b/src/util_time.rs index 8849d0e..deee5d8 100644 --- a/src/util_time.rs +++ b/src/util_time.rs @@ -1,9 +1,9 @@ use std::time::SystemTime; pub fn get_current_secs() -> u64 { - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() + SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0 /* SHOULD NOT HAPPEN */ ) } pub fn get_current_millis() -> u128 { - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis() + SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_millis()).unwrap_or(0 /* SHOULD NOT HAPPEN */ ) }