Skip to main content

clock_kit/
quality.rs

1//! Sync-quality classification and clock-source identity — REQ-CLK-004.
2
3/// Advisory classification of the host's time synchronization.
4///
5/// A **hint** read at clock construction/discovery time — never a guarantee
6/// (G2): a [`SyncQuality::Ptp`]-labelled source may be in holdover.
7/// Consumers use it to decide whether derived timestamps may be correlated
8/// across machines, never for correctness. REQ-CLK-004.
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub enum SyncQuality {
11    /// PTP device present **and** coherent `CLOCK_TAI` offset. Still only a
12    /// hint: the source may be in holdover.
13    Ptp,
14    /// Disciplined by a network sync stack (NTP markers, or a coherent TAI
15    /// offset without a PTP device).
16    Ntp,
17    /// Nothing trustworthy detected — fail-closed to distrust.
18    #[default]
19    Fallback,
20}
21
22impl SyncQuality {
23    /// Stable machine-readable name (`"ptp" | "ntp" | "fallback"`).
24    #[must_use]
25    pub const fn as_str(&self) -> &'static str {
26        match self {
27            Self::Ptp => "ptp",
28            Self::Ntp => "ntp",
29            Self::Fallback => "fallback",
30        }
31    }
32}
33
34/// Which underlying source a [`Clock`](crate::Clock) is actually reading.
35///
36/// Observable per REQ-CLK-003: read cost and source used must be
37/// discoverable — e.g. a `CalibratedClock` that fell back reports the
38/// fallback, never the counter it failed to use.
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
40pub enum ClockSource {
41    /// `x86_64` `rdtsc` behind a calibrated multiply-shift.
42    Tsc,
43    /// aarch64 `cntvct_el0` behind a calibrated multiply-shift.
44    Cntvct,
45    /// `std::time::Instant` (the calibrated-clock fallback under `std`).
46    Instant,
47    /// `clock_gettime(CLOCK_MONOTONIC)` via libc (`no_std` hosts, and the
48    /// calibrated-clock fallback under the `libc` feature).
49    LibcMono,
50    /// Deterministic test clock — the OS is never consulted.
51    Mock,
52    /// Bridged `chronoshift::Clock` (the `chronoshift` feature).
53    External,
54}
55
56impl ClockSource {
57    /// Stable machine-readable name.
58    #[must_use]
59    pub const fn as_str(&self) -> &'static str {
60        match self {
61            Self::Tsc => "tsc",
62            Self::Cntvct => "cntvct",
63            Self::Instant => "instant",
64            Self::LibcMono => "libc-mono",
65            Self::Mock => "mock",
66            Self::External => "external",
67        }
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::{ClockSource, SyncQuality};
74
75    /// Stable names for machine-readable surfaces (logs, metrics labels).
76    #[test]
77    fn names_are_stable() {
78        assert_eq!(SyncQuality::Ptp.as_str(), "ptp");
79        assert_eq!(SyncQuality::Ntp.as_str(), "ntp");
80        assert_eq!(SyncQuality::Fallback.as_str(), "fallback");
81        assert_eq!(ClockSource::Tsc.as_str(), "tsc");
82        assert_eq!(ClockSource::Cntvct.as_str(), "cntvct");
83        assert_eq!(ClockSource::Instant.as_str(), "instant");
84        assert_eq!(ClockSource::LibcMono.as_str(), "libc-mono");
85        assert_eq!(ClockSource::Mock.as_str(), "mock");
86        assert_eq!(ClockSource::External.as_str(), "external");
87        // Default is fail-closed.
88        assert_eq!(SyncQuality::default(), SyncQuality::Fallback);
89    }
90}