Skip to main content

phoxal_runtime_contract/
clock.rs

1//! The persisted execution time domain shared by bundles and process protocols.
2
3use crate::wire_schema::{DescribeWire, EnumRepresentation, VariantBody, WireSchema, WireVariant};
4
5/// The time domain one compiled robot executes in.
6#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
7#[serde(rename_all = "snake_case")]
8pub enum Clock {
9    /// Host boot-anchored time driven by real hardware.
10    #[default]
11    Real,
12    /// Time published by a simulation world authority.
13    Simulated,
14}
15
16impl Clock {
17    /// The wire token for this domain, identical to the `snake_case` rename
18    /// serde derives.
19    #[must_use]
20    pub const fn as_str(self) -> &'static str {
21        match self {
22            Self::Real => "real",
23            Self::Simulated => "simulated",
24        }
25    }
26
27    /// Every domain, so the wire declaration and `as_str` cannot cover
28    /// different sets.
29    const ALL: [Self; 2] = [Self::Real, Self::Simulated];
30}
31
32// Hand-written for the same reason as the rest of this crate's declarations:
33// the process-contract floor sits below `phoxal-macros`, so it cannot use the
34// derive that reads these serde attributes.
35impl DescribeWire for Clock {
36    // Invariant: this states what the derived `Serialize` above writes - one
37    // externally tagged unit variant per domain, spelled by the `snake_case`
38    // rename that `as_str` also returns.
39    fn wire_schema() -> WireSchema {
40        WireSchema::enumeration(
41            EnumRepresentation::ExternallyTagged,
42            Clock::ALL.map(|clock| WireVariant::new(clock.as_str(), VariantBody::Unit)),
43        )
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    /// The declared shape is checked against a real serialized value, so the
52    /// hand-written declaration cannot drift from the derive beside it.
53    #[test]
54    fn the_declared_shape_is_the_shape_serde_writes() {
55        for clock in Clock::ALL {
56            let json = serde_json::to_value(clock).expect("a clock domain serializes");
57            assert_eq!(json, serde_json::Value::from(clock.as_str()));
58            assert_eq!(Clock::wire_schema().conforms(&json), Ok(()));
59        }
60    }
61}