microsandbox_utils/
format.rs1use std::time::Duration;
11
12pub fn format_bytes(bytes: u64) -> String {
24 const UNITS: [&str; 5] = ["B", "KiB", "MiB", "GiB", "TiB"];
25
26 let mut value = bytes as f64;
27 let mut unit = 0usize;
28 while value >= 1024.0 && unit < UNITS.len() - 1 {
29 value /= 1024.0;
30 unit += 1;
31 }
32
33 if unit == 0 {
34 format!("{bytes} {}", UNITS[unit])
35 } else {
36 format!("{value:.1} {}", UNITS[unit])
37 }
38}
39
40pub fn format_duration(d: Duration) -> String {
50 let secs = d.as_secs_f64();
51 if secs < 60.0 {
52 format!("{secs:.1}s")
53 } else {
54 let mins = secs as u64 / 60;
55 let remaining = secs as u64 % 60;
56 format!("{mins}m{remaining}s")
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn bytes_renders_each_unit_boundary() {
66 assert_eq!(format_bytes(0), "0 B");
67 assert_eq!(format_bytes(1023), "1023 B");
68 assert_eq!(format_bytes(1024), "1.0 KiB");
69 assert_eq!(format_bytes(1024 * 1024), "1.0 MiB");
70 assert_eq!(format_bytes(1024 * 1024 * 1024), "1.0 GiB");
71 assert_eq!(format_bytes(1024 * 1024 * 1024 * 1024), "1.0 TiB");
72 }
73
74 #[test]
75 fn bytes_uses_one_decimal_above_one_kib() {
76 assert_eq!(format_bytes(14 * 1024 * 1024), "14.0 MiB");
77 assert_eq!(format_bytes(14_628_864), "14.0 MiB");
78 }
79
80 #[test]
81 fn duration_under_minute_uses_seconds() {
82 assert_eq!(format_duration(Duration::from_secs_f64(0.0)), "0.0s");
83 assert_eq!(format_duration(Duration::from_secs_f64(59.9)), "59.9s");
84 }
85
86 #[test]
87 fn duration_over_minute_uses_mins_secs() {
88 assert_eq!(format_duration(Duration::from_secs(60)), "1m0s");
89 assert_eq!(format_duration(Duration::from_secs(125)), "2m5s");
90 assert_eq!(format_duration(Duration::from_secs(3661)), "61m1s");
91 }
92}