pako_tools/
duration.rs

1use std::ops::{Add, Sub};
2
3/// Reimplementation of std::time::Duration, but panic-free
4/// and partial, only to match our needs:
5///   - use micros instead of nanos, avoid casts
6///   - expose fields
7#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
8pub struct Duration {
9    pub secs: u32,
10    pub micros: u32,
11}
12
13pub const MICROS_PER_SEC: u32 = 1_000_000;
14
15impl Duration {
16    /// Build Duration from secs and micros
17    pub fn new(secs: u32, micros: u32) -> Duration {
18        Duration { secs, micros }
19    }
20    /// Test if Duration object is null
21    #[inline]
22    pub fn is_null(self) -> bool {
23        self.secs == 0 && self.micros == 0
24    }
25}
26
27impl Add for Duration {
28    type Output = Duration;
29
30    #[allow(clippy::suspicious_arithmetic_impl)]
31    fn add(self, other: Duration) -> Self::Output {
32        let secs = self.secs.wrapping_add(other.secs);
33        let micros = self.micros.wrapping_add(other.micros);
34        let (secs, micros) = if micros > MICROS_PER_SEC {
35            (secs + (micros / MICROS_PER_SEC), micros % MICROS_PER_SEC)
36        } else {
37            (secs, micros)
38        };
39
40        Duration { secs, micros }
41    }
42}
43
44impl Sub for Duration {
45    type Output = Duration;
46
47    #[allow(clippy::suspicious_arithmetic_impl)]
48    fn sub(self, other: Duration) -> Self::Output {
49        let secs = self.secs.wrapping_sub(other.secs);
50        let (secs, micros) = if self.micros >= other.micros {
51            (secs, self.micros - other.micros)
52        } else {
53            let diff = other.micros.wrapping_sub(self.micros);
54            let secs_less = diff / MICROS_PER_SEC;
55            let micros = MICROS_PER_SEC - diff;
56            (secs.wrapping_sub(1 + secs_less), micros)
57        };
58
59        Duration { secs, micros }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::Duration;
66    #[test]
67    fn duration_sub() {
68        let d1 = Duration::new(1234, 5678);
69        let d2 = Duration::new(1234, 6789);
70        let d = d2 - d1;
71        assert_eq!(d.secs, 0);
72        assert_eq!(d.micros, 1111);
73    }
74}