1use std::sync::LazyLock;
6
7const USEC_IN_NANOS: i64 = 1000;
9pub const MSEC_IN_NANOS: i64 = 1000 * USEC_IN_NANOS;
10const SEC_IN_NANOS: i64 = 1000 * MSEC_IN_NANOS;
11const MIN_IN_NANOS: i64 = SEC_IN_NANOS * 60;
12const HOUR_IN_NANOS: i64 = MIN_IN_NANOS * 60;
13const DAY_IN_NANOS: i64 = HOUR_IN_NANOS * 24;
14const WEEK_IN_NANOS: i64 = DAY_IN_NANOS * 7;
15const YEAR_IN_NANOS: i64 = DAY_IN_NANOS * 365; static UNITS: LazyLock<Vec<(i64, &'static str)>> = LazyLock::new(|| {
18 vec![
19 (YEAR_IN_NANOS, "year(s)"),
20 (WEEK_IN_NANOS, "week(s)"),
21 (DAY_IN_NANOS, "day(s)"),
22 (HOUR_IN_NANOS, "h"),
23 (MIN_IN_NANOS, "min"),
24 (SEC_IN_NANOS, "s"),
25 (MSEC_IN_NANOS, "ms"),
26 (USEC_IN_NANOS, "μs"),
27 (1, "ns"),
28 ]
29});
30
31pub fn format_common(mut value: i64) -> String {
34 let value_copy = value;
35 let mut repr: Vec<String> = vec![];
36 for (unit_value, unit_str) in UNITS.iter() {
37 if value == 0 {
38 break;
39 }
40 let num_units = value / unit_value;
41 if num_units.abs() > 0 {
42 repr.push(format!("{}{}", num_units, unit_str));
43 value = value % unit_value;
44 }
45 }
46 if repr.len() == 0 {
47 repr.push("0ns".to_string());
48 }
49 let repr = repr.join("_");
51
52 let mut ret = vec![];
53 ret.push(repr);
54 ret.push(format!("({})", value_copy));
56 ret.join(" ")
57}
58
59pub fn format_timer<T: zx::Timeline>(timer: zx::Instant<T>) -> String {
61 format_common(timer.into_nanos())
62}
63
64pub fn format_duration<T: zx::Timeline>(duration: zx::Duration<T>) -> String {
66 format_common(duration.into_nanos())
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72 use test_case::test_case;
73
74 #[test_case(0, "0ns (0)" ; "zero")]
76 #[test_case(1000, "1μs (1000)" ; "1us positive")]
77 #[test_case(-1000, "-1μs (-1000)"; "1us negative")]
78 #[test_case(YEAR_IN_NANOS, "1year(s) (31536000000000000)"; "A year")]
79 #[test_case(YEAR_IN_NANOS + 8 * DAY_IN_NANOS + 1,
80 "1year(s)_1week(s)_1day(s)_1ns (32227200000000001)" ; "A weird duration")]
81 #[test_case(2 * HOUR_IN_NANOS + 8 * MIN_IN_NANOS + 32 * SEC_IN_NANOS + 1,
82 "2h_8min_32s_1ns (7712000000001)" ; "A reasonable long duration")]
83 fn test_format_common(value: i64, repr: &str) {
84 assert_eq!(format_common(value), repr.to_string());
85 }
86}