///|
/// Represents a connected WebSocket client with its connection ID, subscribed
/// channels, and route parameters captured from the upgrade URL.
pub struct WebSocketPeer {
/// Unique identifier for this connection within the WebSocket hub.
priv connection_id : String
/// Pub/sub channels this peer is currently subscribed to.
priv subscribed_channels : Array[String]
/// Route parameters captured from the WebSocket upgrade URL (e.g., `/ws/:room`).
priv params : Map[String, String]
}
///|
/// Creates a new `WebSocketPeer` with the given connection ID and optional
/// route parameters (extracted from dynamic WebSocket routes like `/ws/:room`).
pub fn WebSocketPeer::WebSocketPeer(
connection_id~ : String,
params? : Map[String, String],
) -> WebSocketPeer {
{ connection_id, subscribed_channels: [], params: params.unwrap_or({}) }
}
///|
/// Returns the unique connection ID assigned to this peer by the runtime.
/// Stable for the lifetime of the connection.
pub fn WebSocketPeer::connection_id(self : WebSocketPeer) -> String {
self.connection_id
}
///|
/// Returns a route parameter captured from the WebSocket upgrade URL,
/// or `None` if the parameter was not present.
///
/// For example, a route `/ws/:room` matched against `/ws/lobby` makes
/// `peer.param("room")` return `Some("lobby")`.
pub fn WebSocketPeer::param(self : WebSocketPeer, name : String) -> String? {
self.params.get(name)
}
///|
/// Sends a text message to this WebSocket peer.
pub fn WebSocketPeer::text(self : WebSocketPeer, message : String) -> Unit {
ws_send(self.connection_id, message)
}
///|
/// Sends a binary message to this WebSocket peer.
pub fn WebSocketPeer::binary(self : WebSocketPeer, message : Bytes) -> Unit {
ws_send_bytes(self.connection_id, message)
}
///|
/// Subscribes this WebSocket peer to the given pub/sub channel.
pub fn WebSocketPeer::subscribe(self : WebSocketPeer, channel : String) -> Unit {
if !self.subscribed_channels.contains(channel) {
self.subscribed_channels.push(channel)
}
ws_subscribe(self.connection_id, channel)
}
///|
/// Unsubscribes this WebSocket peer from the given pub/sub channel.
pub fn WebSocketPeer::unsubscribe(
self : WebSocketPeer,
channel : String,
) -> Unit {
let mut index = None
for i, ch in self.subscribed_channels {
if ch == channel {
index = Some(i)
break
}
}
match index {
Some(i) => ignore(self.subscribed_channels.remove(i))
None => ()
}
ws_unsubscribe(self.connection_id, channel)
}
///|
/// Publishes a text message to a pub/sub channel on behalf of this peer.
pub fn WebSocketPeer::publish(
self : WebSocketPeer,
channel : String,
message : String,
) -> Unit {
ws_publish(self.connection_id, channel, message)
}
///|
/// Returns a string representation of this WebSocket peer.
pub fn WebSocketPeer::to_string(self : WebSocketPeer) -> String {
"WebSocketPeer(\{self.connection_id})"
}
///|
/// Events delivered to a WebSocket handler: open, message, or close.
pub(all) enum WebSocketEvent {
Open(WebSocketPeer)
Message(WebSocketPeer, WebSocketAggregatedMessage)
Close(WebSocketPeer)
}
///|
/// A fully assembled WebSocket message, either text or binary.
pub(all) enum WebSocketAggregatedMessage {
Text(String)
Binary(Bytes)
}
///|
/// Handler function type for WebSocket route events.
pub(all) struct WebSocketHandler((WebSocketEvent) -> Unit)
///|
/// Policy for handling a full outbound WebSocket message queue.
pub(all) enum NativeWebSocketOverflowPolicy {
DropOldest
DropLatest
} derive(Debug, Eq)
///|
pub impl Show for NativeWebSocketOverflowPolicy with fn output(self, logger) {
match self {
DropOldest => logger.write_string("DropOldest")
DropLatest => logger.write_string("DropLatest")
}
}