Skip to main content

rok_broadcasting/
channel.rs

1use std::sync::Arc;
2
3use serde::Serialize;
4use serde_json::Value;
5
6use crate::{driver::SharedDriver, BroadcastError, BroadcastEvent};
7
8/// Discriminates public / private / presence channels.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ChannelKind {
11    Public,
12    Private,
13    Presence,
14}
15
16/// A handle to a named broadcast channel.
17///
18/// Obtain one via [`Broadcasting::channel`], [`Broadcasting::private_channel`],
19/// or [`Broadcasting::presence_channel`].
20pub struct BroadcastChannel {
21    name: String,
22    kind: ChannelKind,
23    user_id: Option<String>,
24    driver: SharedDriver,
25}
26
27impl BroadcastChannel {
28    pub fn new(name: String, kind: ChannelKind, driver: Arc<dyn crate::BroadcastDriver>) -> Self {
29        Self {
30            name,
31            kind,
32            user_id: None,
33            driver,
34        }
35    }
36
37    /// Scope the emission to a specific user's channel (`{name}.{user_id}`).
38    pub fn to_user(mut self, user_id: impl ToString) -> Self {
39        self.user_id = Some(user_id.to_string());
40        self
41    }
42
43    /// Emit an event with a serializable payload.
44    pub async fn emit<T: Serialize>(
45        &self,
46        event: impl Into<String>,
47        data: &T,
48    ) -> Result<(), BroadcastError> {
49        let channel_name = match &self.user_id {
50            Some(uid) => format!("{}.{}", self.name, uid),
51            None => self.name.clone(),
52        };
53        let prefixed = match self.kind {
54            ChannelKind::Public => channel_name,
55            ChannelKind::Private => format!("private-{channel_name}"),
56            ChannelKind::Presence => format!("presence-{channel_name}"),
57        };
58        let payload = serde_json::to_value(data)?;
59        let evt = BroadcastEvent::new(prefixed, event.into(), payload);
60        self.driver.broadcast(evt).await
61    }
62
63    /// Emit a raw JSON value.
64    pub async fn emit_raw(
65        &self,
66        event: impl Into<String>,
67        data: Value,
68    ) -> Result<(), BroadcastError> {
69        let channel_name = match &self.user_id {
70            Some(uid) => format!("{}.{}", self.name, uid),
71            None => self.name.clone(),
72        };
73        let prefixed = match self.kind {
74            ChannelKind::Public => channel_name,
75            ChannelKind::Private => format!("private-{channel_name}"),
76            ChannelKind::Presence => format!("presence-{channel_name}"),
77        };
78        let evt = BroadcastEvent::new(prefixed, event.into(), data);
79        self.driver.broadcast(evt).await
80    }
81
82    pub fn kind(&self) -> ChannelKind {
83        self.kind
84    }
85
86    pub fn name(&self) -> &str {
87        &self.name
88    }
89}