beid_api/_macro_support/
duration.rs

1use std::fmt::{self, Display};
2use std::time::{Duration, Instant};
3
4/// A helper struct that help formatting elapsed duration.
5///
6/// Example usage:
7/// ```
8/// use std::time::Duration;
9///
10/// use beid_api::_macro_support::AutoUnitDuration;
11///
12/// // Examples
13/// let actual = AutoUnitDuration::from(Duration::from_secs(7)).to_string();
14/// assert_eq!(actual, "7 s");
15/// let actual = AutoUnitDuration::from(Duration::from_millis(15)).to_string();
16/// assert_eq!(actual, "15 ms");
17/// let actual = AutoUnitDuration::from(Duration::from_micros(20)).to_string();
18/// assert_eq!(actual, "20 µs");
19/// let actual = AutoUnitDuration::from(Duration::from_nanos(25)).to_string();
20/// assert_eq!(actual, "25 ns");
21/// ```
22pub struct AutoUnitDuration(Duration);
23
24impl Display for AutoUnitDuration {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        let d = self.0;
27        match d.as_secs() {
28            0 => match d.as_millis() {
29                0 => match d.as_micros() {
30                    0 => write!(f, "{} ns", d.as_nanos()),
31                    n => write!(f, "{} µs", n),
32                },
33                n => write!(f, "{} ms", n),
34            },
35            n => write!(f, "{} s", n),
36        }
37    }
38}
39
40impl From<Duration> for AutoUnitDuration {
41    fn from(duration: Duration) -> Self {
42        AutoUnitDuration(duration)
43    }
44}
45
46impl From<Instant> for AutoUnitDuration {
47    fn from(start: Instant) -> Self {
48        AutoUnitDuration(start.elapsed())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn test_elapsed_duration() {
58        let actual = AutoUnitDuration(Duration::from_secs(7)).to_string();
59        assert_eq!(actual, "7 s");
60        let actual = AutoUnitDuration(Duration::from_millis(15)).to_string();
61        assert_eq!(actual, "15 ms");
62        let actual = AutoUnitDuration(Duration::from_micros(20)).to_string();
63        assert_eq!(actual, "20 µs");
64        let actual = AutoUnitDuration(Duration::from_nanos(25)).to_string();
65        assert_eq!(actual, "25 ns");
66        // this is ok, it is zero anyway
67        let actual = AutoUnitDuration(Duration::from_secs(0)).to_string();
68        assert_eq!(actual, "0 ns");
69    }
70}