Skip to main content

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}