1use rmpv::decode::read_value;
2use rmpv::encode::write_value;
3use rmpv::Value;
4use std::error::Error;
5use std::io;
6use std::io::{Read, Write};
7
8#[derive(Debug, PartialEq, Clone)]
9pub enum RpcMessage {
10 RpcRequest {
11 msgid: u64,
12 method: String,
13 params: Vec<Value>,
14 }, RpcResponse {
16 msgid: u64,
17 error: Value,
18 result: Value,
19 }, RpcNotification {
21 method: String,
22 params: Vec<Value>,
23 }, }
25
26macro_rules! try_str {
27 ($exp:expr, $msg:expr) => {
28 match $exp {
29 Value::String(val) => match val.into_str() {
30 Some(s) => s,
31 None => return Err(Box::new(io::Error::new(io::ErrorKind::Other, $msg))),
32 },
33 _ => return Err(Box::new(io::Error::new(io::ErrorKind::Other, $msg))),
34 }
35 };
36}
37
38macro_rules! try_int {
39 ($exp:expr, $msg:expr) => {
40 match $exp.as_u64() {
41 Some(val) => val,
42 _ => return Err(Box::new(io::Error::new(io::ErrorKind::Other, $msg))),
43 }
44 };
45}
46
47macro_rules! try_arr {
48 ($exp:expr, $msg:expr) => {
49 match $exp {
50 Value::Array(arr) => arr,
51 _ => return Err(Box::new(io::Error::new(io::ErrorKind::Other, $msg))),
52 }
53 };
54}
55
56macro_rules! rpc_args {
57 ($($e:expr), *) => {{
58 let mut vec = Vec::new();
59 $(
60 vec.push(Value::from($e));
61 )*
62 Value::from(vec)
63 }}
64}
65
66pub fn decode<R: Read>(reader: &mut R) -> Result<RpcMessage, Box<Error>> {
67 let mut arr = try_arr!(read_value(reader)?, "Rpc message must be array");
68 match try_int!(arr[0], "Can't find message type") {
69 0 => {
70 arr.truncate(4);
71 let params = try_arr!(arr.pop().unwrap(), "params not found"); let method = try_str!(arr.pop().unwrap(), "method not found"); let msgid = try_int!(arr.pop().unwrap(), "msgid not found"); Ok(RpcMessage::RpcRequest {
76 msgid,
77 method,
78 params,
79 })
80 }
81 1 => {
82 arr.truncate(4);
83 let msgid = try_int!(arr[1], "msgid not found");
84 let result = arr.pop().unwrap(); let error = arr.pop().unwrap(); Ok(RpcMessage::RpcResponse {
87 msgid,
88 error,
89 result,
90 })
91 }
92 2 => {
93 arr.truncate(3);
94 let params = try_arr!(arr.pop().unwrap(), "params not found"); let method = try_str!(arr.pop().unwrap(), "method not found"); Ok(RpcMessage::RpcNotification { method, params })
97 }
98 _ => Err(Box::new(io::Error::new(
99 io::ErrorKind::Other,
100 "Not nown type",
101 ))),
102 }
103}
104
105pub fn encode<W: Write>(writer: &mut W, msg: RpcMessage) -> Result<(), Box<Error>> {
106 match msg {
107 RpcMessage::RpcRequest {
108 msgid,
109 method,
110 params,
111 } => {
112 let val = rpc_args!(0, msgid, method, params);
113 write_value(writer, &val)?;
114 }
115 RpcMessage::RpcResponse {
116 msgid,
117 error,
118 result,
119 } => {
120 let val = rpc_args!(1, msgid, error, result);
121 write_value(writer, &val)?;
122 }
123 RpcMessage::RpcNotification { method, params } => {
124 let val = rpc_args!(2, method, params);
125 write_value(writer, &val)?;
126 }
127 };
128
129 writer.flush()?;
130
131 Ok(())
132}
133
134pub trait FromVal<T> {
135 fn from_val(T) -> Self;
136}
137
138impl FromVal<Value> for () {
139 fn from_val(_: Value) -> Self {
140 ()
141 }
142}
143
144impl FromVal<Value> for Value {
145 fn from_val(val: Value) -> Self {
146 val
147 }
148}
149
150impl FromVal<Value> for Vec<(Value, Value)> {
151 fn from_val(val: Value) -> Self {
152 if let Value::Map(vec) = val {
153 return vec;
154 }
155 panic!("Not supported value for map");
156 }
157}
158
159impl<T: FromVal<Value>> FromVal<Value> for Vec<T> {
160 fn from_val(val: Value) -> Self {
161 if let Value::Array(arr) = val {
162 return arr.into_iter().map(T::from_val).collect();
163 }
164 panic!("Can't convert to array");
165 }
166}
167
168impl FromVal<Value> for (i64, i64) {
169 fn from_val(val: Value) -> Self {
170 let res = val
171 .as_array()
172 .expect("Can't convert to point(i64,i64) value");
173 if res.len() != 2 {
174 panic!("Array length must be 2");
175 }
176
177 (
178 res[0].as_i64().expect("Can't get i64 value at position 0"),
179 res[1].as_i64().expect("Can't get i64 value at position 1"),
180 )
181 }
182}
183
184impl FromVal<Value> for bool {
185 fn from_val(val: Value) -> Self {
186 if let Value::Boolean(res) = val {
187 return res;
188 }
189 panic!("Can't convert to bool");
190 }
191}
192
193impl FromVal<Value> for String {
194 fn from_val(val: Value) -> Self {
195 val.as_str().expect("Can't convert to string").to_owned()
196 }
197}
198
199impl FromVal<Value> for i64 {
200 fn from_val(val: Value) -> Self {
201 val.as_i64().expect("Can't convert to i64")
202 }
203}
204
205pub trait IntoVal<T> {
206 fn into_val(self) -> T;
207}
208
209impl<'a> IntoVal<Value> for &'a str {
210 fn into_val(self) -> Value {
211 Value::from(self)
212 }
213}
214
215impl IntoVal<Value> for Vec<String> {
216 fn into_val(self) -> Value {
217 let vec: Vec<Value> = self.into_iter().map(Value::from).collect();
218 Value::from(vec)
219 }
220}
221
222impl IntoVal<Value> for Vec<Value> {
223 fn into_val(self) -> Value {
224 Value::from(self)
225 }
226}
227
228impl IntoVal<Value> for (i64, i64) {
229 fn into_val(self) -> Value {
230 Value::from(vec![Value::from(self.0), Value::from(self.1)])
231 }
232}
233
234impl IntoVal<Value> for bool {
235 fn into_val(self) -> Value {
236 Value::from(self)
237 }
238}
239
240impl IntoVal<Value> for i64 {
241 fn into_val(self) -> Value {
242 Value::from(self)
243 }
244}
245
246impl IntoVal<Value> for String {
247 fn into_val(self) -> Value {
248 Value::from(self)
249 }
250}
251
252impl IntoVal<Value> for Value {
253 fn into_val(self) -> Value {
254 self
255 }
256}
257
258impl IntoVal<Value> for Vec<(Value, Value)> {
259 fn into_val(self) -> Value {
260 Value::from(self)
261 }
262}
263
264#[cfg(test)]
265mod test {
266 use super::*;
267 use std::io::{Cursor, Seek, SeekFrom};
268
269 #[test]
270 fn request_test() {
271 let msg = RpcMessage::RpcRequest {
272 msgid: 1,
273 method: "test_method".to_owned(),
274 params: vec![],
275 };
276
277 let mut buff = Cursor::new(vec![]);
278 encode(&mut buff, msg.clone()).unwrap();
279
280 buff.seek(SeekFrom::Start(0)).unwrap();
281 let msg_dest = decode(&mut buff).unwrap();
282 assert_eq!(msg, msg_dest);
283 }
284}