buswatch_types/
duration.rs

1//! Duration representation for serialization.
2//!
3//! We use microseconds as the canonical unit for durations to ensure
4//! consistent serialization across formats and languages.
5
6use core::time::Duration;
7
8/// Duration in microseconds.
9///
10/// This wrapper provides consistent serialization of durations across
11/// different formats. Microseconds offer good precision while fitting
12/// in a u64 for durations up to ~584,000 years.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[cfg_attr(feature = "serde", serde(transparent))]
16#[cfg_attr(feature = "minicbor", derive(minicbor::Encode, minicbor::Decode))]
17#[cfg_attr(feature = "minicbor", cbor(transparent))]
18pub struct Microseconds(#[cfg_attr(feature = "minicbor", n(0))] pub u64);
19
20impl Microseconds {
21    /// Create from microseconds.
22    pub const fn from_micros(micros: u64) -> Self {
23        Self(micros)
24    }
25
26    /// Create from milliseconds.
27    pub const fn from_millis(millis: u64) -> Self {
28        Self(millis * 1000)
29    }
30
31    /// Create from seconds.
32    pub const fn from_secs(secs: u64) -> Self {
33        Self(secs * 1_000_000)
34    }
35
36    /// Get the value in microseconds.
37    pub const fn as_micros(&self) -> u64 {
38        self.0
39    }
40
41    /// Get the value in milliseconds (truncated).
42    pub const fn as_millis(&self) -> u64 {
43        self.0 / 1000
44    }
45
46    /// Get the value in seconds (truncated).
47    pub const fn as_secs(&self) -> u64 {
48        self.0 / 1_000_000
49    }
50
51    /// Convert to a standard Duration.
52    pub const fn to_duration(&self) -> Duration {
53        Duration::from_micros(self.0)
54    }
55}
56
57impl From<Duration> for Microseconds {
58    fn from(d: Duration) -> Self {
59        Self(d.as_micros() as u64)
60    }
61}
62
63impl From<Microseconds> for Duration {
64    fn from(m: Microseconds) -> Self {
65        Duration::from_micros(m.0)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_conversions() {
75        let d = Duration::from_millis(1500);
76        let m = Microseconds::from(d);
77        assert_eq!(m.as_micros(), 1_500_000);
78        assert_eq!(m.as_millis(), 1500);
79        assert_eq!(m.as_secs(), 1);
80
81        let d2: Duration = m.into();
82        assert_eq!(d, d2);
83    }
84}