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}