msgpack_rpc/
message.rs

1use crate::errors::*;
2use rmpv::{decode, encode, Integer, Utf8String, Value};
3use std::convert::From;
4use std::io::{self, Read};
5
6/// Represents a `MessagePack-RPC` message as described in the
7/// [specifications](https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md#messagepack-rpc-protocol-specification).
8#[derive(PartialEq, Clone, Debug)]
9pub enum Message {
10    Request(Request),
11    Response(Response),
12    Notification(Notification),
13}
14
15/// Represents a `MessagePack-RPC` request as described in the
16/// [specifications](https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md#messagepack-rpc-protocol-specification).
17///
18/// A request is a message that a client sends to a server when it expects a response. Sending a
19/// request is like calling a method: it includes a method name and an array of parameters. The
20/// response is like the return value.
21#[derive(PartialEq, Clone, Debug)]
22pub struct Request {
23    /// The `id` is used to associate a response with a request. If a client sends a request with a
24    /// particular `id`, the server should send a response with the same `id`.
25    pub id: u32,
26    /// A string representing the method name.
27    pub method: String,
28    /// An array of parameters to the method.
29    pub params: Vec<Value>,
30}
31
32/// Represents a `MessagePack-RPC` response as described in the
33/// [specifications](https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md#messagepack-rpc-protocol-specification).
34///
35/// After a client sends a [`Request`], the server will send a response back.
36#[derive(PartialEq, Clone, Debug)]
37pub struct Response {
38    /// The `id` of the [`Request`] that triggered this response.
39    pub id: u32,
40    /// The result of the [`Request`] that triggered this response.
41    pub result: Result<Value, Value>,
42}
43
44/// Represents a `MessagePack-RPC` notification as described in the
45/// [specifications](https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md#messagepack-rpc-protocol-specification).
46///
47/// A notification is a message that a client sends to a server when it doesn't expect a response.
48/// Sending a notification is like calling a method with no return value: the notification includes
49/// a method name and an array of parameters.
50#[derive(PartialEq, Clone, Debug)]
51pub struct Notification {
52    /// A string representing the method name.
53    pub method: String,
54    /// An array of parameters to the method.
55    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                // notification are the shortest message and have 3 items
71                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    // valid message
227    {
228        let mut buf = io::Cursor::new(&bytes);
229        assert_eq!(valid, Message::decode(&mut buf).unwrap());
230    }
231
232    // truncated
233    {
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    // invalid message type
243    {
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}