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