sim_lib_stream_core/envelope/domain.rs
1use sim_kernel::{Error, Result, Symbol};
2
3/// Clock a stream is timed against.
4///
5/// Each variant names one timeline a packet can ride; the kernel defines the
6/// clock-domain contract as [`Symbol`]s, and this enum is the concrete set this
7/// fabric understands. [`ClockDomain::symbol`] maps a variant to its kernel
8/// symbol and [`ClockDomain::from_symbol`] parses it back, accepting the bare
9/// label, the `clock/<label>` form, and the fully qualified
10/// `stream/clock-domain/<label>` form.
11///
12/// # Examples
13///
14/// ```
15/// use sim_lib_stream_core::ClockDomain;
16///
17/// let domain = ClockDomain::Sample;
18/// assert_eq!(domain.wire_label(), "sample");
19/// let parsed = ClockDomain::from_symbol(&domain.symbol()).unwrap();
20/// assert_eq!(parsed, domain);
21/// ```
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum ClockDomain {
24 /// Per-sample audio timeline (the finest audio clock).
25 Sample,
26 /// Per-block processing timeline (one tick per audio block).
27 Block,
28 /// Control-rate timeline for parameter and modulation updates.
29 Control,
30 /// MIDI tick timeline (musical clock pulses).
31 MidiTick,
32 /// Wall-clock (real-world) time.
33 Wall,
34 /// Transport timeline (musical position: bars/beats under play control).
35 Transport,
36 /// Server-side frame timeline.
37 ServerFrame,
38 /// Browser-side frame timeline (client render cadence).
39 BrowserFrame,
40 /// Trace-step timeline for stepped/replayed execution.
41 TraceStep,
42 /// Job timeline keyed to background job progress.
43 Job,
44}
45
46impl ClockDomain {
47 /// Returns the stable wire label for this domain (for example `"sample"`).
48 pub fn wire_label(self) -> &'static str {
49 match self {
50 Self::Sample => "sample",
51 Self::Block => "block",
52 Self::Control => "control",
53 Self::MidiTick => "midi-tick",
54 Self::Wall => "wall",
55 Self::Transport => "transport",
56 Self::ServerFrame => "server-frame",
57 Self::BrowserFrame => "browser-frame",
58 Self::TraceStep => "trace-step",
59 Self::Job => "job",
60 }
61 }
62
63 /// Returns the kernel [`Symbol`] for this domain, namespaced under
64 /// `stream/clock-domain`.
65 pub fn symbol(self) -> Symbol {
66 Symbol::qualified("stream/clock-domain", self.wire_label())
67 }
68
69 /// Parses a [`ClockDomain`] from a kernel [`Symbol`].
70 ///
71 /// Accepts the bare label, the compatibility `clock/<label>` form, and the
72 /// fully qualified `stream/clock-domain/<label>` form. Returns an error for
73 /// any unrecognized clock domain.
74 pub fn from_symbol(symbol: &Symbol) -> Result<Self> {
75 match symbol.as_qualified_str().as_str() {
76 "sample" | "clock/sample" | "stream/clock-domain/sample" => Ok(Self::Sample),
77 "block" | "clock/block" | "stream/clock-domain/block" => Ok(Self::Block),
78 "control" | "clock/control" | "stream/clock-domain/control" => Ok(Self::Control),
79 "midi"
80 | "midi-tick"
81 | "clock/midi"
82 | "clock/midi-tick"
83 | "stream/clock-domain/midi-tick" => Ok(Self::MidiTick),
84 "wall" | "clock/wall" | "stream/clock-domain/wall" => Ok(Self::Wall),
85 "transport" | "clock/transport" | "stream/clock-domain/transport" => {
86 Ok(Self::Transport)
87 }
88 "server-frame" | "clock/server-frame" | "stream/clock-domain/server-frame" => {
89 Ok(Self::ServerFrame)
90 }
91 "browser-frame" | "clock/browser-frame" | "stream/clock-domain/browser-frame" => {
92 Ok(Self::BrowserFrame)
93 }
94 "trace-step" | "clock/trace-step" | "stream/clock-domain/trace-step" => {
95 Ok(Self::TraceStep)
96 }
97 "job" | "clock/job" | "stream/clock-domain/job" => Ok(Self::Job),
98 other => Err(Error::Eval(format!("unknown stream clock domain {other}"))),
99 }
100 }
101
102 /// Resolves the clock domain for a stream's declared clock symbol.
103 ///
104 /// Returns an error when the declared clock is outside the canonical stream
105 /// clock-domain aliases accepted by [`ClockDomain::from_symbol`].
106 pub fn for_stream_clock(symbol: &Symbol) -> Result<Self> {
107 Self::from_symbol(symbol)
108 }
109}