Skip to main content

trillium_channels/
channel_conn.rs

1use crate::{ChannelClient, ChannelEvent};
2use serde::Serialize;
3use std::ops::{Deref, DerefMut};
4use trillium_websockets::WebSocketConn;
5
6/// A ChannelConn is a wrapper around a [`WebSocketConn`] that also
7/// contains a [`ChannelClient`]
8///
9/// It that provides convenient access to functions from the ChannelClient
10/// held in the WebSocketConn's TypeSet, and dereferences to the
11/// `WebSocketConn` for other functionality.
12#[derive(Debug)]
13pub struct ChannelConn<'a> {
14    pub(crate) conn: &'a mut WebSocketConn,
15}
16
17macro_rules! channel_client {
18    ($conn:expr_2021) => {
19        match $conn.client() {
20            Some(client) => client,
21            None => {
22                log::error!("could not unwrap client on {}:{}", file!(), line!());
23                return;
24            }
25        }
26    };
27}
28
29impl ChannelConn<'_> {
30    /// Borrow the channel client
31    pub fn client(&self) -> Option<&ChannelClient> {
32        self.state()
33    }
34
35    /// Borrow the websocket conn
36    pub fn conn(&self) -> &WebSocketConn {
37        self
38    }
39
40    /// Send a [`ChannelEvent`] to all connected clients. Note that
41    /// these messages will only reach clients that subscribe to the
42    /// event's topic.
43    pub fn broadcast(&self, event: impl Into<ChannelEvent>) {
44        channel_client!(self).broadcast(event);
45    }
46
47    /// Send a [`ChannelEvent`] to this specific client. Note that
48    /// this message will only be received if the client subscribes to
49    /// the event's topic.
50    pub async fn send_event(&self, event: impl Into<ChannelEvent>) {
51        channel_client!(self).send_event(event).await;
52    }
53
54    /// Send an ok reply in reference to the provided ChannelEvent
55    /// with the provided response payload.
56    ///
57    /// Note that this sets the event as `"phx_reply"` and the payload as
58    /// `{"status": "ok", "response": response }`, as well as setting the
59    /// reference field.
60    pub async fn reply_ok(&self, event: &ChannelEvent, response: &impl Serialize) {
61        channel_client!(self).reply_ok(event, response).await;
62    }
63
64    /// Send an error reply in reference to the provided ChannelEvent
65    /// with the provided response payload.
66    ///
67    /// Note that this sets the event as `"phx_error"` as well as setting
68    /// the reference field.
69    pub async fn reply_error(&self, event: &ChannelEvent, error: &impl Serialize) {
70        channel_client!(self).reply_error(event, error).await;
71    }
72
73    /// Join a topic, sending an ok reply with the provided optional
74    /// value. This sends an ok reply to the client as well as adding the
75    /// topic to the client's subscriptions.
76    pub async fn allow_join(&self, event: &ChannelEvent, value: &impl Serialize) {
77        channel_client!(self).allow_join(event, value).await;
78    }
79
80    /// Leave a topic as requested by the provided channel event,
81    /// including the optional payload. This sends an ok reply to the
82    /// client as well as removing the channel from the client's
83    /// subscriptions.
84    pub async fn allow_leave(&self, event: &ChannelEvent, payload: &impl Serialize) {
85        channel_client!(self).allow_leave(event, payload).await;
86    }
87}
88
89impl Deref for ChannelConn<'_> {
90    type Target = WebSocketConn;
91
92    fn deref(&self) -> &Self::Target {
93        &*self.conn
94    }
95}
96
97impl DerefMut for ChannelConn<'_> {
98    fn deref_mut(&mut self) -> &mut Self::Target {
99        self.conn
100    }
101}