1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
use std::{ fs::File, io::{ self, ErrorKind, prelude::* }, time::{ SystemTime, Duration }, }; use super::{ XResult, new_box_ioerror, }; use super::util_size::get_display_size; use super::util_msg::print_lastline; use super::util_file::resolve_file_path; pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; pub fn get_read_stdin_or_file(file: &str) -> XResult<Box<dyn Read>> { if file.is_empty() { Ok(Box::new(io::stdin())) } else { match File::open(&resolve_file_path(file)) { Ok(f) => Ok(Box::new(f)), Err(err) => Err(new_box_ioerror(&format!("Open file {}, erorr: {}", file, err))), } } } pub fn read_to_string(read: &mut dyn Read) -> XResult<String> { let mut buffer = String::new(); read.read_to_string(&mut buffer)?; Ok(buffer) } pub fn read_to_bytes(read: &mut dyn Read) -> XResult<Vec<u8>> { let mut buffer = vec![]; read.read_to_end(&mut buffer)?; Ok(buffer) } pub fn copy_io<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, total: i64) -> io::Result<u64> where R: io::Read, W: io::Write { copy_io_with_head(reader, writer, total, "Downloading") } pub fn print_status_last_line(head: &str, total: i64, written: i64, cost: Duration) { let mut download_speed = "-".to_string(); let cost_as_secs = cost.as_secs(); if cost_as_secs > 0 { download_speed = format!("{}/s", get_display_size((written / (cost_as_secs as i64)) as i64)); } if total > 0 { print_lastline(&format!("{}, Total: {}, Finished: {}, Speed: {}", head, get_display_size(total), get_display_size(written), download_speed)); } else { print_lastline(&format!("{}, Finished: {}, Speed: {}", head, get_display_size(written), download_speed)); } } pub fn copy_io_with_head<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, total: i64, head: &str) -> io::Result<u64> 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); }); println!(); written } pub fn copy_io_callback<R: ?Sized, W: ?Sized, FCallback>(reader: &mut R, writer: &mut W, total: i64, callback: &FCallback) -> io::Result<u64> 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); } }