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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::serde_json;
use std::io::Write;
/// A function that converts a float to a string the represents a human
/// readable version of that number.
pub fn human_size(size: f64) -> String {
let negative = if size.is_sign_positive() { "" } else { "-" };
let size = size.abs();
let units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
if size < 1_f64 {
return format!("{}{}{}", negative, size, "B");
}
let delimiter = 1024_f64;
let exponent = std::cmp::min(
(size.ln() / delimiter.ln()).floor() as i32,
(units.len() - 1) as i32,
);
let pretty_bytes = format!("{:.2}", size / delimiter.powi(exponent))
.parse::<f64>()
.unwrap()
* 1_f64;
let unit = units[exponent as usize];
format!("{negative}{pretty_bytes}{unit}")
}
const BYTES_TO_KIB: u64 = 2u64.pow(10);
const BYTES_TO_MIB: u64 = 2u64.pow(20);
/// Gets the size used for downloading data. The total bytes is used to
/// determine the units to use.
pub fn human_download_size(byte_count: u64, total_bytes: u64) -> String {
return if total_bytes < BYTES_TO_MIB {
get_in_format(byte_count, BYTES_TO_KIB, "KiB")
} else {
get_in_format(byte_count, BYTES_TO_MIB, "MiB")
};
fn get_in_format(byte_count: u64, conversion: u64, suffix: &str) -> String {
let converted_value = byte_count / conversion;
let decimal = (byte_count % conversion) * 100 / conversion;
format!("{converted_value}.{decimal:0>2}{suffix}")
}
}
/// A function that converts a millisecond elapsed time to a string that
/// represents a human readable version of that time.
pub fn human_elapsed(elapsed: u128) -> String {
if elapsed < 1_000 {
return format!("{elapsed}ms");
}
if elapsed < 1_000 * 60 {
return format!("{}s", elapsed / 1000);
}
let seconds = elapsed / 1_000;
let minutes = seconds / 60;
let seconds_remainder = seconds % 60;
format!("{minutes}m{seconds_remainder}s")
}
pub fn write_to_stdout_ignore_sigpipe(
bytes: &[u8],
) -> Result<(), std::io::Error> {
use std::io::ErrorKind;
match std::io::stdout().write_all(bytes) {
Ok(()) => Ok(()),
Err(e) => match e.kind() {
ErrorKind::BrokenPipe => Ok(()),
_ => Err(e),
},
}
}
pub fn write_json_to_stdout<T>(value: &T) -> Result<(), AnyError>
where
T: ?Sized + serde::ser::Serialize,
{
let mut writer = std::io::BufWriter::new(std::io::stdout());
serde_json::to_writer_pretty(&mut writer, value)?;
writeln!(&mut writer)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_human_size() {
assert_eq!(human_size(1_f64), "1B");
assert_eq!(human_size((12 * 1024) as f64), "12KB");
assert_eq!(human_size((24_i64 * 1024 * 1024) as f64), "24MB");
assert_eq!(human_size((24_i64 * 1024 * 1024 * 1024) as f64), "24GB");
assert_eq!(
human_size((24_i64 * 1024 * 1024 * 1024 * 1024) as f64),
"24TB"
);
assert_eq!(human_size(0_f64), "0B");
assert_eq!(human_size(-10_f64), "-10B");
}
#[test]
fn test_human_download_size() {
assert_eq!(
human_download_size(BYTES_TO_KIB / 100 - 1, BYTES_TO_KIB),
"0.00KiB"
);
assert_eq!(
human_download_size(BYTES_TO_KIB / 100 + 1, BYTES_TO_KIB),
"0.01KiB"
);
assert_eq!(
human_download_size(BYTES_TO_KIB / 5, BYTES_TO_KIB),
"0.19KiB"
);
assert_eq!(
human_download_size(BYTES_TO_MIB - 1, BYTES_TO_MIB - 1),
"1023.99KiB"
);
assert_eq!(human_download_size(BYTES_TO_MIB, BYTES_TO_MIB), "1.00MiB");
assert_eq!(
human_download_size(BYTES_TO_MIB * 9 - 1523, BYTES_TO_MIB),
"8.99MiB"
);
}
#[test]
fn test_human_elapsed() {
assert_eq!(human_elapsed(1), "1ms");
assert_eq!(human_elapsed(256), "256ms");
assert_eq!(human_elapsed(1000), "1s");
assert_eq!(human_elapsed(1001), "1s");
assert_eq!(human_elapsed(1020), "1s");
assert_eq!(human_elapsed(70 * 1000), "1m10s");
assert_eq!(human_elapsed(86 * 1000 + 100), "1m26s");
}
}
|