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
use std::fmt::Write as FmtWrite;
use std::io::{self, BufRead, Read, Write};
use std::time::{Duration, Instant};
const MAX_LINE: u64 = 1024 * 8;
pub fn duration_to_human(d: &Duration) -> String {
let ts = d.as_secs();
let ns = d.subsec_nanos();
let mut ret = String::with_capacity(10);
if ts > 0 {
let mut s = ts;
let mut cs = (f64::from(ns) / 10_000_000_f64).round() as u64;
if cs == 100 {
s += 1;
cs = 0;
}
if ts >= 86400 {
write!(ret, "{}d", s / 86400).unwrap();
s %= 86400;
}
if ts >= 3600 {
write!(ret, "{}h", s / 3600).unwrap();
s %= 3600;
}
if ts >= 60 {
write!(ret, "{}m", s / 60).unwrap();
s %= 60
}
write!(ret, "{}.{:02}s", s, cs).unwrap();
} else if ns > 100_000 {
write!(ret, "{:.1}ms", f64::from(ns) / 1_000_000_f64).unwrap();
} else if ns > 100 {
write!(ret, "{:.1}μs", f64::from(ns) / 1_000_f64).unwrap();
}
ret
}
pub fn line_timing_copy<R: io::Read, W: io::Write>(
input: &mut R,
output: &mut W,
separator: char,
start: &Instant,
) -> io::Result<u64> {
let mut input = io::BufReader::new(input);
let mut output = io::BufWriter::new(output);
let mut buf = Vec::with_capacity(256);
let mut last = Instant::now();
let mut run_on = false;
let mut n = 0_u64;
while input.by_ref().take(MAX_LINE).read_until(b'\n', &mut buf)? > 0 {
n += buf.len() as u64;
let since_last = last.elapsed();
let since_start = start.elapsed();
last = Instant::now();
if !run_on {
write!(
output,
"{:>8} {:>8} {} ",
duration_to_human(&since_start),
duration_to_human(&since_last),
separator
)?;
}
run_on = buf.last().expect("buf can't be empty") != &b'\n';
output.write_all(&buf)?;
output.flush()?;
buf.clear();
}
Ok(n)
}