Skip to main content

wowlab_centrifuge/
types.rs

1use wowlab_types::sim::FastMap;
2
3/// Identity and application metadata for a connected Centrifugo client.
4#[derive(Clone, Debug, Default)]
5pub struct ClientInfo {
6    pub user: String,
7    pub client: String,
8    pub conn_info: Vec<u8>,
9    pub chan_info: Vec<u8>,
10}
11
12impl From<crate::proto::ClientInfo> for ClientInfo {
13    fn from(info: crate::proto::ClientInfo) -> Self {
14        Self {
15            user: info.user,
16            client: info.client,
17            conn_info: info.conn_info,
18            chan_info: info.chan_info,
19        }
20    }
21}
22
23/// Publication delivered through a subscription or history result.
24#[derive(Clone, Debug)]
25pub struct Publication {
26    pub data: Vec<u8>,
27    pub info: Option<ClientInfo>,
28    pub offset: u64,
29    pub tags: FastMap<String, String>,
30    pub delta: bool,
31    pub time: i64,
32    pub channel: Option<String>,
33}
34
35impl From<crate::proto::Publication> for Publication {
36    fn from(pub_: crate::proto::Publication) -> Self {
37        Self {
38            data: pub_.data,
39            info: pub_.info.map(ClientInfo::from),
40            offset: pub_.offset,
41            tags: pub_.tags.into_iter().collect(),
42            delta: pub_.delta,
43            time: pub_.time,
44            channel: if pub_.channel.is_empty() {
45                None
46            } else {
47                Some(pub_.channel)
48            },
49        }
50    }
51}
52
53/// Recoverable stream cursor for history and subscriptions.
54#[derive(Clone, Debug, Default)]
55pub struct StreamPosition {
56    pub offset: u64,
57    pub epoch: String,
58}
59
60impl From<crate::proto::StreamPosition> for StreamPosition {
61    fn from(pos: crate::proto::StreamPosition) -> Self {
62        Self {
63            offset: pos.offset,
64            epoch: pos.epoch,
65        }
66    }
67}
68
69/// Successful connection handshake returned by Centrifugo.
70#[derive(Clone, Debug)]
71pub struct ConnectResult {
72    pub client: String,
73    pub version: String,
74    pub expires: bool,
75    pub ttl: u32,
76    pub data: Vec<u8>,
77    /// Server ping interval in seconds, or zero when disabled.
78    pub ping: u32,
79    pub pong: bool,
80    pub session: String,
81    pub node: String,
82    pub time: i64,
83}
84
85impl From<crate::proto::ConnectResult> for ConnectResult {
86    fn from(result: crate::proto::ConnectResult) -> Self {
87        Self {
88            client: result.client,
89            version: result.version,
90            expires: result.expires,
91            ttl: result.ttl,
92            data: result.data,
93            ping: result.ping,
94            pong: result.pong,
95            session: result.session,
96            node: result.node,
97            time: result.time,
98        }
99    }
100}
101
102/// Successful subscription handshake and recovery state returned by Centrifugo.
103#[derive(Clone, Debug)]
104#[expect(
105    clippy::struct_excessive_bools,
106    reason = "mirrors Centrifugo's public subscribe result protocol"
107)]
108pub struct SubscribeResult {
109    pub expires: bool,
110    pub ttl: u32,
111    pub recoverable: bool,
112    pub epoch: String,
113    pub publications: Vec<Publication>,
114    pub recovered: bool,
115    pub offset: u64,
116    pub positioned: bool,
117    pub data: Vec<u8>,
118    pub was_recovering: bool,
119    pub delta: bool,
120}
121
122impl From<crate::proto::SubscribeResult> for SubscribeResult {
123    fn from(result: crate::proto::SubscribeResult) -> Self {
124        Self {
125            expires: result.expires,
126            ttl: result.ttl,
127            recoverable: result.recoverable,
128            epoch: result.epoch,
129            publications: result
130                .publications
131                .into_iter()
132                .map(Publication::from)
133                .collect(),
134            recovered: result.recovered,
135            offset: result.offset,
136            positioned: result.positioned,
137            data: result.data,
138            was_recovering: result.was_recovering,
139            delta: result.delta,
140        }
141    }
142}
143
144/// Event emitted by the connection lifecycle.
145#[derive(Clone, Debug)]
146#[non_exhaustive]
147pub enum ClientEvent {
148    Connecting,
149    Connected(ConnectResult),
150    Disconnected {
151        code: u32,
152        reason: String,
153        reconnect: bool,
154    },
155    Error(String),
156    Message(Vec<u8>),
157}
158
159/// Event emitted by a channel subscription.
160#[derive(Clone, Debug)]
161#[non_exhaustive]
162pub enum SubscriptionEvent {
163    Subscribing,
164    Subscribed(SubscribeResult),
165    Unsubscribed { code: u32, reason: String },
166    Publication(Publication),
167    Join(ClientInfo),
168    Leave(ClientInfo),
169    Error(String),
170}
171
172/// Connected clients currently present on a channel, keyed by client identifier.
173#[derive(Clone, Debug, Default)]
174pub struct PresenceResult {
175    pub presence: FastMap<String, ClientInfo>,
176}
177
178impl From<crate::proto::PresenceResult> for PresenceResult {
179    fn from(result: crate::proto::PresenceResult) -> Self {
180        Self {
181            presence: result
182                .presence
183                .into_iter()
184                .map(|(k, v)| (k, ClientInfo::from(v)))
185                .collect(),
186        }
187    }
188}
189
190/// Aggregate client and user counts for a channel.
191#[derive(Clone, Debug, Default)]
192pub struct PresenceStats {
193    pub num_clients: u32,
194    pub num_users: u32,
195}
196
197impl From<crate::proto::PresenceStatsResult> for PresenceStats {
198    fn from(result: crate::proto::PresenceStatsResult) -> Self {
199        Self {
200            num_clients: result.num_clients,
201            num_users: result.num_users,
202        }
203    }
204}
205
206/// Publications and stream position returned by a history query.
207#[derive(Clone, Debug, Default)]
208pub struct HistoryResult {
209    pub publications: Vec<Publication>,
210    pub epoch: String,
211    pub offset: u64,
212}
213
214impl From<crate::proto::HistoryResult> for HistoryResult {
215    fn from(result: crate::proto::HistoryResult) -> Self {
216        Self {
217            publications: result
218                .publications
219                .into_iter()
220                .map(Publication::from)
221                .collect(),
222            epoch: result.epoch,
223            offset: result.offset,
224        }
225    }
226}
227
228/// Application payload returned by a Centrifugo RPC call.
229#[derive(Clone, Debug, Default)]
230pub struct RpcResult {
231    pub data: Vec<u8>,
232}
233
234impl From<crate::proto::RpcResult> for RpcResult {
235    fn from(result: crate::proto::RpcResult) -> Self {
236        Self { data: result.data }
237    }
238}
239
240/// Successful subscription-token refresh response.
241#[derive(Clone, Debug, Default)]
242pub struct SubRefreshResult {
243    pub expires: bool,
244    pub ttl: u32,
245}
246
247impl From<crate::proto::SubRefreshResult> for SubRefreshResult {
248    fn from(result: crate::proto::SubRefreshResult) -> Self {
249        Self {
250            expires: result.expires,
251            ttl: result.ttl,
252        }
253    }
254}