Skip to main content

sim_lib_web_bridge/
transport.rs

1//! The transport trait and session status.
2//!
3//! The UI never speaks a transport-specific API. It targets the Intent/Scene
4//! bus, which is expressed here as the [`Transport`] trait: reading a resource
5//! value, realizing a checked operation against it (the `realize_final`
6//! surface), and draining change events (the `realize_events` surface). Four
7//! interchangeable transports implement it -- a deterministic fixture, plus
8//! in-browser wasm, local server, and remote server -- so wasm, local, remote,
9//! and fixture sessions are interchangeable behind the session bridge.
10
11use sim_kernel::{CapabilityName, Expr, Result, Symbol};
12use sim_lib_stream_core::{
13    PushResult, StreamEnvelope, StreamInspectorSnapshot, StreamInspectorStatus, StreamItem,
14    StreamStats, stream_cancel_capability, stream_open_capability, stream_push_capability,
15    stream_read_capability, stream_stats_capability,
16};
17use sim_lib_stream_fabric::{
18    stream_control_cancel_symbol, stream_control_next_symbol, stream_control_open_symbol,
19    stream_control_push_symbol, stream_control_stats_symbol,
20};
21
22/// The visible state of a session's connection.
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub enum SessionStatus {
25    /// Establishing the connection.
26    Connecting,
27    /// Connected and live.
28    Connected,
29    /// Lost the connection; the UI surfaces this rather than crashing.
30    Disconnected,
31    /// Attempting to restore a lost connection.
32    Reconnecting,
33    /// Deliberately closed.
34    Closed,
35}
36
37impl SessionStatus {
38    /// Whether reads and operations can flow right now.
39    pub fn is_live(self) -> bool {
40        matches!(self, SessionStatus::Connected)
41    }
42}
43
44/// A change notification: a resource whose value was updated.
45#[derive(Clone, Debug, PartialEq, Eq)]
46pub struct ChangeEvent {
47    /// The resource that changed.
48    pub resource: Symbol,
49}
50
51/// Browser-visible stream status for inspectors and transport badges.
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub enum BrowserStreamStatus {
54    /// Packets can flow.
55    Live,
56    /// The transport is disconnected.
57    Disconnected,
58    /// The transport is reconnecting.
59    Reconnecting,
60    /// A stream profile was refused by the bridge.
61    RefusedProfile,
62    /// Backpressure dropped or rejected packets.
63    BufferOverflow,
64    /// The stream was cancelled.
65    Cancelled,
66    /// A finite stream ended normally.
67    Ended,
68}
69
70impl BrowserStreamStatus {
71    /// Stable label for browser/UI data.
72    pub fn wire_label(self) -> &'static str {
73        match self {
74            Self::Live => "live",
75            Self::Disconnected => "disconnected",
76            Self::Reconnecting => "reconnecting",
77            Self::RefusedProfile => "refused-profile",
78            Self::BufferOverflow => "buffer-overflow",
79            Self::Cancelled => "cancelled",
80            Self::Ended => "ended",
81        }
82    }
83
84    /// Stable symbol for inspector data.
85    pub fn symbol(self) -> Symbol {
86        Symbol::qualified("stream/browser-status", self.wire_label())
87    }
88
89    /// Maps this browser status to the inspector status enum.
90    pub fn inspector_status(self) -> StreamInspectorStatus {
91        match self {
92            Self::Live => StreamInspectorStatus::Live,
93            Self::Disconnected => StreamInspectorStatus::Disconnected,
94            Self::Reconnecting => StreamInspectorStatus::Reconnecting,
95            Self::RefusedProfile => StreamInspectorStatus::RefusedProfile,
96            Self::BufferOverflow => StreamInspectorStatus::BufferOverflow,
97            Self::Cancelled => StreamInspectorStatus::Cancelled,
98            Self::Ended => StreamInspectorStatus::Ended,
99        }
100    }
101}
102
103/// Web bridge stream operations and their corresponding fabric controls.
104#[derive(Clone, Copy, Debug, PartialEq, Eq)]
105pub enum WebStreamOperation {
106    /// Read up to `limit` packets.
107    Read,
108    /// Subscribe to stream metadata and status.
109    Subscribe,
110    /// Push one envelope into a stream.
111    Push,
112    /// Cancel the stream.
113    Cancel,
114    /// Inspect stream statistics.
115    Stats,
116}
117
118impl WebStreamOperation {
119    /// Returns the stable wire label for this operation.
120    pub fn wire_label(self) -> &'static str {
121        match self {
122            Self::Read => "read",
123            Self::Subscribe => "subscribe",
124            Self::Push => "push",
125            Self::Cancel => "cancel",
126            Self::Stats => "stats",
127        }
128    }
129
130    /// Returns the stable symbol naming this operation.
131    pub fn symbol(self) -> Symbol {
132        Symbol::qualified("stream/web", self.wire_label())
133    }
134
135    /// Returns the fabric control symbol this operation maps to.
136    pub fn fabric_symbol(self) -> Symbol {
137        match self {
138            Self::Read => stream_control_next_symbol(),
139            Self::Subscribe => stream_control_open_symbol(),
140            Self::Push => stream_control_push_symbol(),
141            Self::Cancel => stream_control_cancel_symbol(),
142            Self::Stats => stream_control_stats_symbol(),
143        }
144    }
145
146    /// Returns the capability required to invoke this operation.
147    pub fn capability(self) -> CapabilityName {
148        match self {
149            Self::Read => stream_read_capability(),
150            Self::Subscribe => stream_open_capability(),
151            Self::Push => stream_push_capability(),
152            Self::Cancel => stream_cancel_capability(),
153            Self::Stats => stream_stats_capability(),
154        }
155    }
156}
157
158/// Operation names exposed by the web bridge.
159pub fn web_stream_operation_symbols() -> [Symbol; 5] {
160    [
161        WebStreamOperation::Read.symbol(),
162        WebStreamOperation::Subscribe.symbol(),
163        WebStreamOperation::Push.symbol(),
164        WebStreamOperation::Cancel.symbol(),
165        WebStreamOperation::Stats.symbol(),
166    ]
167}
168
169/// Capability names required by browser-visible stream operations.
170pub fn web_stream_operation_capability_names() -> Vec<CapabilityName> {
171    [
172        WebStreamOperation::Read,
173        WebStreamOperation::Subscribe,
174        WebStreamOperation::Push,
175        WebStreamOperation::Cancel,
176        WebStreamOperation::Stats,
177    ]
178    .into_iter()
179    .map(WebStreamOperation::capability)
180    .collect()
181}
182
183/// Inspector data shown by browser stream tools.
184#[derive(Clone, Debug, PartialEq, Eq)]
185pub struct StreamInspectorRecord {
186    /// Id of the inspected stream.
187    pub stream_id: Symbol,
188    /// Current browser-side status of the stream.
189    pub status: BrowserStreamStatus,
190    /// Number of buffered packets.
191    pub buffered: usize,
192    /// Accumulated stream statistics.
193    pub stats: StreamStats,
194    /// Diagnostics reported for the stream.
195    pub diagnostics: Vec<Symbol>,
196    /// Inspector snapshot of the stream.
197    pub snapshot: StreamInspectorSnapshot,
198}
199
200/// Which kind of runtime a transport connects to.
201#[derive(Clone, Copy, Debug, PartialEq, Eq)]
202pub enum TransportKind {
203    /// A deterministic in-memory fixture (tests, replay).
204    Fixture,
205    /// An in-browser wasm runtime.
206    Wasm,
207    /// A local server (HTTP bootstrap + WebSocket live).
208    LocalServer,
209    /// A remote server (HTTP bootstrap + WebSocket live).
210    RemoteServer,
211    /// A kernel [`EvalFabric`](sim_kernel::EvalFabric) target: commits are
212    /// delegated to `realize`, proving a session is a realize target.
213    Fabric,
214}
215
216/// The location-transparent bus the UI targets. Implementors map these calls to
217/// `realize`/`EvalFabric` (`realize_final` for [`Transport::realize`] and
218/// `realize_events` for [`Transport::drain_events`]); the fixture maps them to
219/// an in-memory store.
220pub trait Transport {
221    /// Which kind of runtime this transport connects to.
222    fn kind(&self) -> TransportKind;
223
224    /// The current connection status.
225    fn status(&self) -> SessionStatus;
226
227    /// Read the current value of a resource.
228    fn read(&self, resource: &Symbol) -> Result<Expr>;
229
230    /// Realize a checked operation against a resource, returning the new value
231    /// (the `realize_final` surface). Implementations also record a
232    /// [`ChangeEvent`] for the resource.
233    fn realize(&mut self, resource: &Symbol, operation: &Expr) -> Result<Expr>;
234
235    /// Drain the pending change events (the `realize_events` surface).
236    fn drain_events(&mut self) -> Vec<ChangeEvent>;
237
238    /// Subscribe to a stream and return browser-visible inspector data.
239    fn stream_subscribe(&mut self, stream_id: &Symbol) -> Result<StreamInspectorRecord>;
240
241    /// Read at most `limit` packets from a stream.
242    fn stream_read(&mut self, stream_id: &Symbol, limit: usize) -> Result<Vec<StreamItem>>;
243
244    /// Push one stream envelope.
245    fn stream_push(&mut self, stream_id: &Symbol, envelope: StreamEnvelope) -> Result<PushResult>;
246
247    /// Cancel a stream.
248    fn stream_cancel(&mut self, stream_id: &Symbol) -> Result<()>;
249
250    /// Return current stream stats.
251    fn stream_stats(&self, stream_id: &Symbol) -> Result<StreamStats>;
252
253    /// Return browser-visible inspector data without changing stream state.
254    fn stream_inspector(&self, stream_id: &Symbol) -> Result<StreamInspectorRecord>;
255}