websocket_simple/
message.rs

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