1use crate::errors::*;
2use rmpv::{decode, encode, Integer, Utf8String, Value};
3use std::convert::From;
4use std::io::{self, Read};
5
6#[derive(PartialEq, Clone, Debug)]
9pub enum Message {
10 Request(Request),
11 Response(Response),
12 Notification(Notification),
13}
14
15#[derive(PartialEq, Clone, Debug)]
22pub struct Request {
23 pub id: u32,
26 pub method: String,
28 pub params: Vec<Value>,
30}
31
32#[derive(PartialEq, Clone, Debug)]
37pub struct Response {
38 pub id: u32,
40 pub result: Result<Value, Value>,
42}
43
44#[derive(PartialEq, Clone, Debug)]
51pub struct Notification {
52 pub method: String,
54 pub params: Vec<Value>,
56}
57
58const REQUEST_MESSAGE: u64 = 0;
59const RESPONSE_MESSAGE: u64 = 1;
60const NOTIFICATION_MESSAGE: u64 = 2;
61
62impl Message {
63 pub fn decode<R>(rd: &mut R) -> Result<Message, DecodeError>
64 where
65 R: Read,
66 {
67 let msg = decode::value::read_value(rd)?;
68 if let Value::Array(ref array) = msg {
69 if array.len() < 3 {
70 return Err(DecodeError::Invalid);
72 }
73 if let Value::Integer(msg_type) = array[0] {
74 match msg_type.as_u64() {
75 Some(REQUEST_MESSAGE) => Ok(Message::Request(Request::decode(array)?)),
76 Some(RESPONSE_MESSAGE) => Ok(Message::Response(Response::decode(array)?)),
77 Some(NOTIFICATION_MESSAGE) => {
78 Ok(Message::Notification(Notification::decode(array)?))
79 }
80 _ => Err(DecodeError::Invalid),
81 }
82 } else {
83 Err(DecodeError::Invalid)
84 }
85 } else {
86 Err(DecodeError::Invalid)
87 }
88 }
89
90 pub fn as_value(&self) -> Value {
91 match *self {
92 Message::Request(Request {
93 id,
94 ref method,
95 ref params,
96 }) => Value::Array(vec![
97 Value::Integer(Integer::from(REQUEST_MESSAGE)),
98 Value::Integer(Integer::from(id)),
99 Value::String(Utf8String::from(method.as_str())),
100 Value::Array(params.clone()),
101 ]),
102 Message::Response(Response { id, ref result }) => {
103 let (error, result) = match *result {
104 Ok(ref result) => (Value::Nil, result.to_owned()),
105 Err(ref err) => (err.to_owned(), Value::Nil),
106 };
107 Value::Array(vec![
108 Value::Integer(Integer::from(RESPONSE_MESSAGE)),
109 Value::Integer(Integer::from(id)),
110 error,
111 result,
112 ])
113 }
114 Message::Notification(Notification {
115 ref method,
116 ref params,
117 }) => Value::Array(vec![
118 Value::Integer(Integer::from(NOTIFICATION_MESSAGE)),
119 Value::String(Utf8String::from(method.as_str())),
120 Value::Array(params.to_owned()),
121 ]),
122 }
123 }
124
125 pub fn pack(&self) -> io::Result<Vec<u8>> {
126 let mut bytes = vec![];
127 encode::write_value(&mut bytes, &self.as_value())?;
128 Ok(bytes)
129 }
130}
131
132impl Notification {
133 fn decode(array: &[Value]) -> Result<Self, DecodeError> {
134 if array.len() < 3 {
135 return Err(DecodeError::Invalid);
136 }
137
138 let method = if let Value::String(ref method) = array[1] {
139 method
140 .as_str()
141 .map(|s| s.to_string())
142 .ok_or(DecodeError::Invalid)?
143 } else {
144 return Err(DecodeError::Invalid);
145 };
146
147 let params = if let Value::Array(ref params) = array[2] {
148 params.clone()
149 } else {
150 return Err(DecodeError::Invalid);
151 };
152
153 Ok(Notification { method, params })
154 }
155}
156
157impl Request {
158 fn decode(array: &[Value]) -> Result<Self, DecodeError> {
159 if array.len() < 4 {
160 return Err(DecodeError::Invalid);
161 }
162
163 let id = if let Value::Integer(id) = array[1] {
164 id.as_u64()
165 .map(|id| id as u32)
166 .ok_or(DecodeError::Invalid)?
167 } else {
168 return Err(DecodeError::Invalid);
169 };
170
171 let method = if let Value::String(ref method) = array[2] {
172 method
173 .as_str()
174 .map(|s| s.to_string())
175 .ok_or(DecodeError::Invalid)?
176 } else {
177 return Err(DecodeError::Invalid);
178 };
179
180 let params = if let Value::Array(ref params) = array[3] {
181 params.clone()
182 } else {
183 return Err(DecodeError::Invalid);
184 };
185
186 Ok(Request { id, method, params })
187 }
188}
189
190impl Response {
191 fn decode(array: &[Value]) -> Result<Self, DecodeError> {
192 if array.len() < 2 {
193 return Err(DecodeError::Invalid);
194 }
195
196 let id = if let Value::Integer(id) = array[1] {
197 id.as_u64()
198 .map(|id| id as u32)
199 .ok_or(DecodeError::Invalid)?
200 } else {
201 return Err(DecodeError::Invalid);
202 };
203
204 match array[2] {
205 Value::Nil => Ok(Response {
206 id,
207 result: Ok(array[3].clone()),
208 }),
209 ref error => Ok(Response {
210 id,
211 result: Err(error.clone()),
212 }),
213 }
214 }
215}
216
217#[test]
218fn test_decode_request() {
219 let valid = Message::Request(Request {
220 id: 1234,
221 method: "dummy".to_string(),
222 params: Vec::new(),
223 });
224 let bytes = valid.pack().unwrap();
225
226 {
228 let mut buf = io::Cursor::new(&bytes);
229 assert_eq!(valid, Message::decode(&mut buf).unwrap());
230 }
231
232 {
234 let bytes = Vec::from(&bytes[0..bytes.len() - 1]);
235 let mut buf = io::Cursor::new(&bytes);
236 assert!(matches!(
237 Message::decode(&mut buf),
238 Err(DecodeError::Truncated(_))
239 ));
240 }
241
242 {
244 let mut bytes = Vec::from(&bytes[..]);
245 bytes[1] = 5;
246 let mut buf = io::Cursor::new(&bytes);
247 assert!(matches!(
248 Message::decode(&mut buf),
249 Err(DecodeError::Invalid)
250 ));
251 }
252}