neovim_lib/rpc/
model.rs

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    }, // 0
15    RpcResponse {
16        msgid: u64,
17        error: Value,
18        result: Value,
19    }, // 1
20    RpcNotification {
21        method: String,
22        params: Vec<Value>,
23    }, // 2
24}
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"); // [3]
72            let method = try_str!(arr.pop().unwrap(), "method not found"); // [2]
73            let msgid = try_int!(arr.pop().unwrap(), "msgid not found"); // [1]
74
75            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(); // [3]
85            let error = arr.pop().unwrap(); // [2]
86            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"); // [2]
95            let method = try_str!(arr.pop().unwrap(), "method not found"); // [1]
96            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}