wsprism_gateway/realtime/
types.rs

1use axum::extract::ws::Message;
2use bytes::Bytes;
3use serde_json::Value;
4
5use wsprism_core::error::{Result, WsPrismError};
6
7/// Quality-of-Service strategy for outgoing delivery.
8///
9/// Chooses between latency-first (drop on backpressure) and reliability-first
10/// (await with optional timeout) behavior.
11#[derive(Debug, Clone)]
12pub enum QoS {
13    /// Latency-critical: do not await; if the user's queue is full, drop.
14    Lossy,
15    /// Reliability-critical: attempt delivery and optionally time out.
16    Reliable { timeout_ms: u64 },
17}
18
19impl Default for QoS {
20    fn default() -> Self {
21        QoS::Lossy
22    }
23}
24
25/// Outgoing payload variants.
26#[derive(Debug, Clone)]
27pub enum Payload {
28    /// JSON value serialized to text.
29    TextJson(Value),
30    /// Raw UTF-8 bytes. (Still sent as Text in WS transport.)
31    Utf8Bytes(Bytes),
32    /// Raw binary bytes.
33    Binary(Bytes),
34}
35
36/// Application-level outgoing message.
37#[derive(Debug, Clone)]
38pub struct Outgoing {
39    pub qos: QoS,
40    pub payload: Payload,
41}
42
43/// Prepared message cached for broadcasting (serialize once, send N times).
44#[derive(Debug, Clone)]
45pub enum PreparedMsg {
46    Text(String),
47    Binary(Bytes),
48}
49
50impl PreparedMsg {
51    pub fn prepare(out: &Outgoing) -> Result<Self> {
52        match &out.payload {
53            Payload::TextJson(v) => {
54                let s = serde_json::to_string(v)
55                    .map_err(|e| WsPrismError::BadRequest(format!("json encode failed: {e}")))?;
56                Ok(PreparedMsg::Text(s))
57            }
58            Payload::Utf8Bytes(b) => {
59                // validate UTF-8 once; send as Text
60                let s = std::str::from_utf8(b)
61                    .map_err(|e| WsPrismError::BadRequest(format!("utf8 invalid: {e}")))?
62                    .to_owned();
63                Ok(PreparedMsg::Text(s))
64            }
65            Payload::Binary(b) => Ok(PreparedMsg::Binary(b.clone())),
66        }
67    }
68
69    /// Convert to axum::ws::Message for transport.
70    /// NOTE: axum::Message::Binary requires `Vec<u8>`, so Binary path clones into Vec.
71    pub fn to_ws_message(&self) -> Message {
72        match self {
73            PreparedMsg::Text(s) => Message::Text(s.clone()),
74            PreparedMsg::Binary(b) => Message::Binary(b.to_vec()),
75        }
76    }
77}