parity_ws/
message.rs

1use std::convert::{From, Into};
2use std::fmt;
3use std::result::Result as StdResult;
4use std::str::from_utf8;
5
6use protocol::OpCode;
7use result::Result;
8
9use self::Message::*;
10
11/// An enum representing the various forms of a WebSocket message.
12#[derive(Debug, Eq, PartialEq, Clone)]
13pub enum Message {
14    /// A text WebSocket message
15    Text(String),
16    /// A binary WebSocket message
17    Binary(Vec<u8>),
18}
19
20impl Message {
21    /// Create a new text WebSocket message from a stringable.
22    pub fn text<S>(string: S) -> Message
23    where
24        S: Into<String>,
25    {
26        Message::Text(string.into())
27    }
28
29    /// Create a new binary WebSocket message by converting to Vec<u8>.
30    pub fn binary<B>(bin: B) -> Message
31    where
32        B: Into<Vec<u8>>,
33    {
34        Message::Binary(bin.into())
35    }
36
37    /// Indicates whether a message is a text message.
38    pub fn is_text(&self) -> bool {
39        match *self {
40            Text(_) => true,
41            Binary(_) => false,
42        }
43    }
44
45    /// Indicates whether a message is a binary message.
46    pub fn is_binary(&self) -> bool {
47        match *self {
48            Text(_) => false,
49            Binary(_) => true,
50        }
51    }
52
53    /// Get the length of the WebSocket message.
54    pub fn len(&self) -> usize {
55        match *self {
56            Text(ref string) => string.len(),
57            Binary(ref data) => data.len(),
58        }
59    }
60
61    /// Returns true if the WebSocket message has no content.
62    /// For example, if the other side of the connection sent an empty string.
63    pub fn is_empty(&self) -> bool {
64        match *self {
65            Text(ref string) => string.is_empty(),
66            Binary(ref data) => data.is_empty(),
67        }
68    }
69
70    #[doc(hidden)]
71    pub fn opcode(&self) -> OpCode {
72        match *self {
73            Text(_) => OpCode::Text,
74            Binary(_) => OpCode::Binary,
75        }
76    }
77
78    /// Consume the WebSocket and return it as binary data.
79    pub fn into_data(self) -> Vec<u8> {
80        match self {
81            Text(string) => string.into_bytes(),
82            Binary(data) => data,
83        }
84    }
85
86    /// Attempt to consume the WebSocket message and convert it to a String.
87    pub fn into_text(self) -> Result<String> {
88        match self {
89            Text(string) => Ok(string),
90            Binary(data) => Ok(String::from_utf8(data).map_err(|err| err.utf8_error())?),
91        }
92    }
93
94    /// Attempt to get a &str from the WebSocket message,
95    /// this will try to convert binary data to utf8.
96    pub fn as_text(&self) -> Result<&str> {
97        match *self {
98            Text(ref string) => Ok(string),
99            Binary(ref data) => Ok(from_utf8(data)?),
100        }
101    }
102}
103
104impl From<String> for Message {
105    fn from(string: String) -> Message {
106        Message::text(string)
107    }
108}
109
110impl<'s> From<&'s str> for Message {
111    fn from(string: &'s str) -> Message {
112        Message::text(string)
113    }
114}
115
116impl<'b> From<&'b [u8]> for Message {
117    fn from(data: &'b [u8]) -> Message {
118        Message::binary(data)
119    }
120}
121
122impl From<Vec<u8>> for Message {
123    fn from(data: Vec<u8>) -> Message {
124        Message::binary(data)
125    }
126}
127
128impl fmt::Display for Message {
129    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
130        if let Ok(string) = self.as_text() {
131            write!(f, "{}", string)
132        } else {
133            write!(f, "Binary Data<length={}>", self.len())
134        }
135    }
136}
137
138mod test {
139    #![allow(unused_imports, unused_variables, dead_code)]
140    use super::*;
141
142    #[test]
143    fn display() {
144        let t = Message::text(format!("test"));
145        assert_eq!(t.to_string(), "test".to_owned());
146
147        let bin = Message::binary(vec![0, 1, 3, 4, 241]);
148        assert_eq!(bin.to_string(), "Binary Data<length=5>".to_owned());
149    }
150
151    #[test]
152    fn binary_convert() {
153        let bin = [6u8, 7, 8, 9, 10, 241];
154        let msg = Message::from(&bin[..]);
155        assert!(msg.is_binary());
156        assert!(msg.into_text().is_err());
157    }
158
159    #[test]
160    fn binary_convert_vec() {
161        let bin = vec![6u8, 7, 8, 9, 10, 241];
162        let msg = Message::from(bin);
163        assert!(msg.is_binary());
164        assert!(msg.into_text().is_err());
165    }
166
167    #[test]
168    fn text_convert() {
169        let s = "kiwotsukete";
170        let msg = Message::from(s);
171        assert!(msg.is_text());
172    }
173}