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}