twilight_gateway/
message.rs1use std::borrow::Cow;
10
11use tokio_websockets::{CloseCode, Message as WebsocketMessage};
12use twilight_model::gateway::CloseFrame;
13
14#[derive(Clone, Debug, Eq, PartialEq)]
16pub enum Message {
17    Close(Option<CloseFrame<'static>>),
20    Text(String),
24}
25
26impl Message {
27    pub(crate) const ABNORMAL_CLOSE: Self = Self::Close(Some(CloseFrame::new(1006, "")));
29
30    pub const fn is_close(&self) -> bool {
32        matches!(self, Self::Close(_))
33    }
34
35    pub const fn is_text(&self) -> bool {
37        matches!(self, Self::Text(_))
38    }
39
40    pub(crate) fn from_websocket_msg(msg: &WebsocketMessage) -> Option<Self> {
43        if msg.is_close() {
44            let (code, reason) = msg.as_close().unwrap();
45
46            let frame = (code != CloseCode::NO_STATUS_RECEIVED).then(|| CloseFrame {
47                code: code.into(),
48                reason: Cow::Owned(reason.to_string()),
49            });
50
51            Some(Self::Close(frame))
52        } else if msg.is_text() {
53            Some(Self::Text(msg.as_text().unwrap().to_owned()))
54        } else {
55            None
56        }
57    }
58
59    pub(crate) fn into_websocket_msg(self) -> WebsocketMessage {
62        match self {
63            Self::Close(frame) => WebsocketMessage::close(
64                frame
65                    .as_ref()
66                    .and_then(|f| CloseCode::try_from(f.code).ok()),
67                frame.map(|f| f.reason).as_deref().unwrap_or_default(),
68            ),
69            Self::Text(string) => WebsocketMessage::text(string),
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::Message;
77    use static_assertions::assert_impl_all;
78    use std::fmt::Debug;
79
80    assert_impl_all!(Message: Clone, Debug, Eq, PartialEq);
81}