Skip to main content

lsp_max_protocol/
stream.rs

1use serde::{Deserialize, Serialize};
2
3// max/stream.subscribe
4pub const STREAM_SUBSCRIBE: &str = "max/stream.subscribe";
5// max/stream.unsubscribe
6pub const STREAM_UNSUBSCRIBE: &str = "max/stream.unsubscribe";
7// max/stream.event — pushed from server to client
8pub const STREAM_EVENT: &str = "max/stream.event";
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct StreamSubscribeParams {
12    /// Subscription ID chosen by the client
13    pub subscription_id: String,
14    /// Which event kinds to subscribe to
15    pub event_kinds: Vec<StreamEventKind>,
16    /// Optional: only events for this document URI (serialised URI string)
17    pub uri_filter: Option<String>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct StreamSubscribeResult {
22    pub subscription_id: String,
23    /// "CANDIDATE" — streaming is active but not ADMITTED
24    pub status: String,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct StreamUnsubscribeParams {
29    pub subscription_id: String,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct StreamUnsubscribeResult {
34    pub subscription_id: String,
35    pub events_received: u64,
36    pub status: String,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
40pub enum StreamEventKind {
41    Diagnostic,
42    ConformanceChange,
43    GateChange,
44    ReceiptAdmission,
45    LawViolation,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct StreamEvent {
50    pub subscription_id: String,
51    pub sequence: u64,
52    pub kind: StreamEventKind,
53    pub payload: serde_json::Value,
54    /// Law-axis status of this event's source.
55    pub status: String,
56    pub timestamp_secs: u64,
57}
58
59/// In-process event bus for max/stream subscriptions.
60/// Backed by tokio::sync::broadcast.
61pub struct StreamBus {
62    sender: tokio::sync::broadcast::Sender<StreamEvent>,
63}
64
65impl StreamBus {
66    pub fn new(capacity: usize) -> Self {
67        let (sender, _) = tokio::sync::broadcast::channel(capacity);
68        Self { sender }
69    }
70
71    pub fn subscribe(&self) -> tokio::sync::broadcast::Receiver<StreamEvent> {
72        self.sender.subscribe()
73    }
74
75    /// Publish an event to all current subscribers. Returns the receiver count.
76    pub fn publish(&self, event: StreamEvent) -> usize {
77        self.sender.send(event).unwrap_or(0)
78    }
79
80    pub fn subscriber_count(&self) -> usize {
81        self.sender.receiver_count()
82    }
83}