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}