statime/datastructures/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,
24    /// Time source is unknown. This is not an official variant from the spec,
25    /// but we just need it in practise
26    Unknown(u8),
27}
28
29impl TimeSource {
30    /// Converts enum variants back to their primitive values
31    /// as specified in *IEEE1588-2019 section 7.6.2.8*
32    pub fn to_primitive(self) -> u8 {
33        match self {
34            Self::AtomicClock => 0x10,
35            Self::Gnss => 0x20,
36            Self::TerrestrialRadio => 0x30,
37            Self::SerialTimeCode => 0x39,
38            Self::Ptp => 0x40,
39            Self::Ntp => 0x50,
40            Self::HandSet => 0x60,
41            Self::Other => 0x90,
42            Self::InternalOscillator => 0xa0,
43            Self::ProfileSpecific(p) => 0xf0 + p,
44            Self::Reserved => 0xff,
45            Self::Unknown(v) => v,
46        }
47    }
48
49    pub(crate) fn from_primitive(value: u8) -> Self {
50        match value {
51            0x10 => Self::AtomicClock,
52            0x20 => Self::Gnss,
53            0x30 => Self::TerrestrialRadio,
54            0x39 => Self::SerialTimeCode,
55            0x40 => Self::Ptp,
56            0x50 => Self::Ntp,
57            0x60 => Self::HandSet,
58            0x90 => Self::Other,
59            0xa0 => Self::InternalOscillator,
60            0xf0..=0xfe => Self::ProfileSpecific(value - 0xf0),
61            0xff => TimeSource::Reserved,
62            v => TimeSource::Unknown(v),
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn network_protocol_values() {
73        for i in 0..u8::MAX {
74            let protocol = TimeSource::from_primitive(i);
75            assert_eq!(protocol.to_primitive(), i);
76        }
77
78        assert_eq!(TimeSource::ProfileSpecific(5).to_primitive(), 0xf5);
79    }
80}