Skip to main content

statime_wire/common/
time_source.rs

1/// What the time values for a system are derived from
2///
3/// This enum encodes the root source of a system's time values. For most use
4/// cases, the default [`InternalOscillator`](`Self::InternalOscillator`) will
5/// suffice.
6///
7/// For more details see *IEEE1588-2019 section 7.6.2.8*
8#[allow(missing_docs)] // These varaiants are pretty self explaining
9#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum TimeSource {
12    AtomicClock,
13    Gnss,
14    TerrestrialRadio,
15    SerialTimeCode,
16    Ptp,
17    Ntp,
18    HandSet,
19    Other,
20    #[default]
21    InternalOscillator,
22    ProfileSpecific(u8),
23    Reserved(u8),
24}
25
26impl TimeSource {
27    /// Get the u8 primitive representation of the `TimeSource`
28    // Converts enum variants back to their primitive values
29    // as specified in *IEEE1588-2019 section 7.6.2.8*
30    #[must_use]
31    pub fn to_primitive(self) -> u8 {
32        match self {
33            Self::AtomicClock => 0x10,
34            Self::Gnss => 0x20,
35            Self::TerrestrialRadio => 0x30,
36            Self::SerialTimeCode => 0x39,
37            Self::Ptp => 0x40,
38            Self::Ntp => 0x50,
39            Self::HandSet => 0x60,
40            Self::Other => 0x90,
41            Self::InternalOscillator => 0xa0,
42            Self::ProfileSpecific(v) | Self::Reserved(v) => v,
43        }
44    }
45
46    /// Create a `TimeSource` from its representation as a u8 primitive.
47    #[must_use]
48    pub fn from_primitive(value: u8) -> Self {
49        match value {
50            0x10 => Self::AtomicClock,
51            0x20 => Self::Gnss,
52            0x30 => Self::TerrestrialRadio,
53            0x39 => Self::SerialTimeCode,
54            0x40 => Self::Ptp,
55            0x50 => Self::Ntp,
56            0x60 => Self::HandSet,
57            0x90 => Self::Other,
58            0xa0 => Self::InternalOscillator,
59            0xf0..=0xfe => Self::ProfileSpecific(value),
60            v => TimeSource::Reserved(v),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn network_protocol_values() {
71        for i in 0..u8::MAX {
72            let protocol = TimeSource::from_primitive(i);
73            assert_eq!(protocol.to_primitive(), i);
74        }
75
76        assert_eq!(TimeSource::ProfileSpecific(0xf5).to_primitive(), 0xf5);
77    }
78}