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
92
93
94
95
96
97
98
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.clone()).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);
}
}