Skip to main content

tuwunel_core/utils/time/
elapsed.rs

1use std::{
2	fmt::{Display, Formatter, Result as FmtResult},
3	time::Duration,
4};
5
6/// A compact, truncated display representation of an elapsed duration.
7///
8/// The value uses seconds, milliseconds, microseconds, or nanoseconds as
9/// appropriate. Fractional values retain at most two decimal places.
10#[derive(Clone, Copy, Debug)]
11pub struct Elapsed(Duration);
12
13impl Display for Elapsed {
14	fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
15		let (hundredths, unit) = match self.0 {
16			| duration if duration.as_secs() > 0 => (duration.as_millis() / 10, "s"),
17			| duration if duration.as_millis() > 0 => (duration.as_micros() / 10, "ms"),
18			| duration if duration.as_micros() > 0 => (duration.as_nanos() / 10, "µs"),
19			| duration => return write!(formatter, "{}ns", duration.as_nanos()),
20		};
21
22		let whole = hundredths / 100;
23		let fraction = hundredths % 100;
24
25		match fraction {
26			| 0 => write!(formatter, "{whole}{unit}"),
27			| fraction if fraction % 10 == 0 =>
28				write!(formatter, "{whole}.{}{unit}", fraction / 10),
29			| _ => write!(formatter, "{whole}.{fraction:02}{unit}"),
30		}
31	}
32}
33
34impl From<Duration> for Elapsed {
35	fn from(duration: Duration) -> Self { Self(duration) }
36}
37
38#[cfg(test)]
39mod tests {
40	use super::*;
41
42	#[test]
43	fn formats_units_and_truncates_fractions() {
44		let cases = [
45			(Duration::ZERO, "0ns"),
46			(Duration::from_nanos(999), "999ns"),
47			(Duration::from_micros(1), "1µs"),
48			(Duration::from_nanos(1_559), "1.55µs"),
49			(Duration::from_nanos(999_999), "999.99µs"),
50			(Duration::from_millis(1), "1ms"),
51			(Duration::from_nanos(12_559_999), "12.55ms"),
52			(Duration::from_nanos(999_999_999), "999.99ms"),
53			(Duration::from_secs(1), "1s"),
54			(Duration::from_millis(1_500), "1.5s"),
55			(Duration::from_nanos(1_559_999_999), "1.55s"),
56		];
57
58		for (duration, expected) in cases {
59			assert_eq!(Elapsed::from(duration).to_string(), expected);
60		}
61	}
62}