routerify_websocket/
message.rs1use crate::CloseCode;
2#[cfg(feature = "json")]
3use serde::{de::DeserializeOwned, ser::Serialize};
4use std::borrow::Cow;
5use std::fmt;
6use tokio_tungstenite::tungstenite::protocol::{self, CloseFrame};
7
8#[derive(Eq, PartialEq, Clone)]
10pub struct Message {
11 pub(crate) inner: protocol::Message,
12}
13
14impl Message {
15 pub fn text<S: Into<String>>(s: S) -> Message {
17 Message {
18 inner: protocol::Message::text(s),
19 }
20 }
21
22 #[cfg(feature = "json")]
28 pub fn json<T: Serialize>(value: &T) -> crate::Result<Message> {
29 Ok(Message::text(
30 serde_json::to_string(&value).map_err(|err| crate::WebsocketError::EncodeJson(err.into()))?,
31 ))
32 }
33
34 pub fn binary<V: Into<Vec<u8>>>(v: V) -> Message {
36 Message {
37 inner: protocol::Message::binary(v),
38 }
39 }
40
41 pub fn ping<V: Into<Vec<u8>>>(v: V) -> Message {
45 Message {
46 inner: protocol::Message::Ping(v.into()),
47 }
48 }
49
50 pub fn pong<V: Into<Vec<u8>>>(v: V) -> Message {
54 Message {
55 inner: protocol::Message::Pong(v.into()),
56 }
57 }
58
59 pub fn close() -> Message {
61 Message {
62 inner: protocol::Message::Close(None),
63 }
64 }
65
66 pub fn close_with<R: Into<Cow<'static, str>>>(code: CloseCode, reason: R) -> Message {
68 Message {
69 inner: protocol::Message::Close(Some(CloseFrame {
70 code,
71 reason: reason.into(),
72 })),
73 }
74 }
75
76 pub fn is_text(&self) -> bool {
78 self.inner.is_text()
79 }
80
81 pub fn is_binary(&self) -> bool {
83 self.inner.is_binary()
84 }
85
86 pub fn is_close(&self) -> bool {
88 self.inner.is_close()
89 }
90
91 pub fn is_ping(&self) -> bool {
93 self.inner.is_ping()
94 }
95
96 pub fn is_pong(&self) -> bool {
98 self.inner.is_pong()
99 }
100
101 pub fn len(&self) -> usize {
103 self.inner.len()
104 }
105
106 pub fn is_empty(&self) -> bool {
109 self.inner.is_empty()
110 }
111
112 pub fn close_code(&self) -> Option<CloseCode> {
114 match self.inner {
115 protocol::Message::Close(Some(ref data)) => Some(data.code),
116 _ => None,
117 }
118 }
119
120 pub fn close_reason(&self) -> Option<&str> {
122 match self.inner {
123 protocol::Message::Close(Some(ref data)) => Some(&data.reason),
124 _ => None,
125 }
126 }
127
128 pub fn as_text(&self) -> crate::Result<&str> {
130 self.inner
131 .to_text()
132 .map_err(|err| crate::WebsocketError::DecodeText(err.into()))
133 }
134
135 pub fn as_bytes(&self) -> &[u8] {
137 match self.inner {
138 protocol::Message::Text(ref s) => s.as_bytes(),
139 protocol::Message::Binary(ref v) => v,
140 protocol::Message::Ping(ref v) => v,
141 protocol::Message::Pong(ref v) => v,
142 protocol::Message::Close(_) => &[],
143 }
144 }
145
146 pub fn into_bytes(self) -> Vec<u8> {
148 self.inner.into_data()
149 }
150
151 pub fn into_text(self) -> crate::Result<String> {
153 self.inner
154 .into_text()
155 .map_err(|err| crate::WebsocketError::DecodeText(err.into()))
156 }
157
158 #[cfg(feature = "json")]
164 pub fn decode_json<T: DeserializeOwned>(self) -> crate::Result<T> {
165 serde_json::from_slice(&self.into_bytes()).map_err(|err| crate::WebsocketError::DecodeJson(err.into()))
166 }
167}
168
169impl fmt::Debug for Message {
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 fmt::Debug::fmt(&self.inner, f)
172 }
173}
174
175impl Into<Vec<u8>> for Message {
176 fn into(self) -> Vec<u8> {
177 self.into_bytes()
178 }
179}