1use anyhow::{bail, ensure, Context, Result};
13use serde_json::{json, Map, Number, Value};
14use std::time::Duration;
15use tokio::io::{AsyncRead, AsyncReadExt};
16
17pub const MAX_MESSAGE: usize = 1024 * 1024;
19pub const MAX_DEPTH: usize = 32;
21pub const IO_TIMEOUT: Duration = Duration::from_secs(30);
23
24pub const REQUEST: u64 = 0;
25pub const RESPONSE: u64 = 1;
26pub const NOTIFICATION: u64 = 2;
27
28enum Need {
30 More,
31}
32
33struct Cursor<'a> {
34 buf: &'a [u8],
35 pos: usize,
36}
37
38type Step<T> = std::result::Result<Result<T>, Need>;
39
40macro_rules! need {
41 ($e:expr) => {
42 match $e {
43 Ok(Ok(v)) => v,
44 Ok(Err(e)) => return Ok(Err(e)),
45 Err(n) => return Err(n),
46 }
47 };
48}
49
50impl Cursor<'_> {
51 fn take(&mut self, n: usize) -> Step<&[u8]> {
52 if self.buf.len() - self.pos < n {
53 return Err(Need::More);
54 }
55 let s = &self.buf[self.pos..self.pos + n];
56 self.pos += n;
57 Ok(Ok(s))
58 }
59 fn uint(&mut self, n: usize) -> Step<u64> {
60 let b = need!(self.take(n));
61 Ok(Ok(b.iter().fold(0u64, |acc, x| (acc << 8) | u64::from(*x))))
62 }
63 fn count(&mut self, n: u64, per_item: usize) -> Step<usize> {
65 let remaining = (self.buf.len() - self.pos) as u64;
66 if n.saturating_mul(per_item as u64) > MAX_MESSAGE as u64 {
67 return Ok(Err(anyhow::anyhow!(
68 "MessagePack count {n} exceeds the message bound"
69 )));
70 }
71 if n.saturating_mul(per_item as u64) > remaining {
72 return Err(Need::More);
73 }
74 Ok(Ok(n as usize))
75 }
76 fn hex(b: &[u8]) -> String {
77 b.iter().map(|x| format!("{x:02x}")).collect()
78 }
79 fn value(&mut self, depth: usize) -> Step<Value> {
80 if depth > MAX_DEPTH {
81 return Ok(Err(anyhow::anyhow!(
82 "MessagePack nested deeper than {MAX_DEPTH}"
83 )));
84 }
85 let tag = need!(self.take(1))[0];
86 let v = match tag {
87 0x00..=0x7f => json!(tag),
88 0xe0..=0xff => json!(tag as i8),
89 0xc0 => Value::Null,
90 0xc2 => json!(false),
91 0xc3 => json!(true),
92 0xcc => json!(need!(self.uint(1))),
93 0xcd => json!(need!(self.uint(2))),
94 0xce => json!(need!(self.uint(4))),
95 0xcf => json!(need!(self.uint(8))),
96 0xd0 => json!(need!(self.uint(1)) as u8 as i8),
97 0xd1 => json!(need!(self.uint(2)) as u16 as i16),
98 0xd2 => json!(need!(self.uint(4)) as u32 as i32),
99 0xd3 => json!(need!(self.uint(8)) as i64),
100 0xca => {
101 let f = f32::from_bits(need!(self.uint(4)) as u32);
102 Number::from_f64(f64::from(f))
103 .map(Value::Number)
104 .unwrap_or(Value::Null)
105 }
106 0xcb => Number::from_f64(f64::from_bits(need!(self.uint(8))))
107 .map(Value::Number)
108 .unwrap_or(Value::Null),
109 0xa0..=0xbf | 0xd9 | 0xda | 0xdb => {
110 let n = match tag {
111 0xd9 => need!(self.uint(1)),
112 0xda => need!(self.uint(2)),
113 0xdb => need!(self.uint(4)),
114 t => u64::from(t & 0x1f),
115 };
116 let n = need!(self.count(n, 1));
117 let b = need!(self.take(n));
118 match std::str::from_utf8(b) {
119 Ok(s) => json!(s),
120 Err(_) => json!({"$bin": Self::hex(b)}),
121 }
122 }
123 0xc4..=0xc6 => {
124 let n = need!(self.uint(1 << (tag - 0xc4)));
125 let n = need!(self.count(n, 1));
126 json!({"$bin": Self::hex(need!(self.take(n)))})
127 }
128 0x90..=0x9f | 0xdc | 0xdd => {
129 let n = match tag {
130 0xdc => need!(self.uint(2)),
131 0xdd => need!(self.uint(4)),
132 t => u64::from(t & 0x0f),
133 };
134 let n = need!(self.count(n, 1));
135 let mut items = Vec::with_capacity(n);
136 for _ in 0..n {
137 items.push(need!(self.value(depth + 1)));
138 }
139 Value::Array(items)
140 }
141 0x80..=0x8f | 0xde | 0xdf => {
142 let n = match tag {
143 0xde => need!(self.uint(2)),
144 0xdf => need!(self.uint(4)),
145 t => u64::from(t & 0x0f),
146 };
147 let n = need!(self.count(n, 2));
148 let mut map = Map::new();
149 for _ in 0..n {
150 let k = need!(self.value(depth + 1));
151 let v = need!(self.value(depth + 1));
152 let key = match k {
153 Value::String(s) => s,
154 other => other.to_string(),
155 };
156 map.insert(key, v);
157 }
158 Value::Object(map)
159 }
160 0xd4..=0xd8 | 0xc7..=0xc9 => {
161 let n = match tag {
162 0xd4..=0xd8 => 1usize << (tag - 0xd4),
163 0xc7 => need!(self.uint(1)) as usize,
164 0xc8 => need!(self.uint(2)) as usize,
165 _ => need!(self.uint(4)) as usize,
166 };
167 let ext = need!(self.take(1))[0] as i8;
168 let n = need!(self.count(n as u64, 1));
169 json!({"$ext": ext, "hex": Self::hex(need!(self.take(n)))})
170 }
171 0xc1 => return Ok(Err(anyhow::anyhow!("MessagePack byte 0xc1 is never used"))),
172 };
173 Ok(Ok(v))
174 }
175}
176
177pub fn decode(buf: &[u8]) -> Result<Option<(Value, usize)>> {
180 let mut c = Cursor { buf, pos: 0 };
181 match c.value(0) {
182 Ok(Ok(v)) => Ok(Some((v, c.pos))),
183 Ok(Err(e)) => Err(e),
184 Err(Need::More) => Ok(None),
185 }
186}
187
188fn unhex(s: &str) -> Result<Vec<u8>> {
189 ensure!(
190 s.is_ascii() && s.len().is_multiple_of(2),
191 "hex must be an even number of hex digits"
192 );
193 (0..s.len())
194 .step_by(2)
195 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).context("invalid hex"))
196 .collect()
197}
198
199fn put_len(out: &mut Vec<u8>, n: usize, fix: Option<(u8, usize)>, tags: [u8; 3]) {
200 match fix {
201 Some((base, max)) if n <= max => out.push(base | n as u8),
202 _ if tags[0] != 0 && n <= 0xff => {
203 out.push(tags[0]);
204 out.push(n as u8);
205 }
206 _ if n <= 0xffff => {
207 out.push(tags[1]);
208 out.extend((n as u16).to_be_bytes());
209 }
210 _ => {
211 out.push(tags[2]);
212 out.extend((n as u32).to_be_bytes());
213 }
214 }
215}
216
217pub fn encode(v: &Value, out: &mut Vec<u8>, depth: usize) -> Result<()> {
219 ensure!(depth <= MAX_DEPTH, "value nested deeper than {MAX_DEPTH}");
220 match v {
221 Value::Null => out.push(0xc0),
222 Value::Bool(b) => out.push(if *b { 0xc3 } else { 0xc2 }),
223 Value::Number(n) => {
224 if let Some(u) = n.as_u64() {
225 if u <= 0x7f {
226 out.push(u as u8);
227 } else {
228 out.push(0xcf);
229 out.extend(u.to_be_bytes());
230 }
231 } else if let Some(i) = n.as_i64() {
232 if i >= -32 {
233 out.push(i as i8 as u8);
234 } else {
235 out.push(0xd3);
236 out.extend(i.to_be_bytes());
237 }
238 } else {
239 out.push(0xcb);
240 out.extend(n.as_f64().unwrap_or(0.0).to_be_bytes());
241 }
242 }
243 Value::String(s) => {
244 put_len(out, s.len(), Some((0xa0, 31)), [0xd9, 0xda, 0xdb]);
245 out.extend_from_slice(s.as_bytes());
246 }
247 Value::Array(items) => {
248 put_len(out, items.len(), Some((0x90, 15)), [0, 0xdc, 0xdd]);
249 for i in items {
250 encode(i, out, depth + 1)?;
251 }
252 }
253 Value::Object(map) => {
254 if let (1, Some(Value::String(h))) = (map.len(), map.get("$bin")) {
255 let b = unhex(h)?;
256 put_len(out, b.len(), None, [0xc4, 0xc5, 0xc6]);
257 out.extend(b);
258 return Ok(());
259 }
260 if let (2, Some(t), Some(Value::String(h))) = (
261 map.len(),
262 map.get("$ext").and_then(Value::as_i64),
263 map.get("hex"),
264 ) {
265 let b = unhex(h)?;
266 ensure!((-128..=127).contains(&t), "extension type out of range");
267 match b.len() {
268 1 => out.push(0xd4),
269 2 => out.push(0xd5),
270 4 => out.push(0xd6),
271 8 => out.push(0xd7),
272 16 => out.push(0xd8),
273 n => put_len(out, n, None, [0xc7, 0xc8, 0xc9]),
274 }
275 out.push(t as i8 as u8);
276 out.extend(b);
277 return Ok(());
278 }
279 put_len(out, map.len(), Some((0x80, 15)), [0, 0xde, 0xdf]);
280 for (k, v) in map {
281 encode(&Value::String(k.clone()), out, depth + 1)?;
282 encode(v, out, depth + 1)?;
283 }
284 }
285 }
286 Ok(())
287}
288
289pub fn encode_message(v: &Value) -> Result<Vec<u8>> {
290 let mut out = Vec::new();
291 encode(v, &mut out, 0)?;
292 ensure!(
293 out.len() <= MAX_MESSAGE,
294 "message exceeds {MAX_MESSAGE} bytes"
295 );
296 Ok(out)
297}
298
299pub struct Stream<R> {
301 reader: R,
302 buf: Vec<u8>,
303}
304
305impl<R: AsyncRead + Unpin> Stream<R> {
306 pub fn new(reader: R) -> Self {
307 Self {
308 reader,
309 buf: Vec::new(),
310 }
311 }
312
313 pub async fn next(&mut self, idle: Duration) -> Result<Option<Value>> {
316 let mut deadline = None;
317 loop {
318 if let Some((v, used)) = decode(&self.buf)? {
319 self.buf.drain(..used);
320 return Ok(Some(v));
321 }
322 ensure!(
323 self.buf.len() < MAX_MESSAGE,
324 "message exceeds {MAX_MESSAGE} bytes"
325 );
326 let wait = if self.buf.is_empty() {
327 idle
328 } else {
329 deadline
330 .get_or_insert_with(|| tokio::time::Instant::now() + IO_TIMEOUT)
331 .saturating_duration_since(tokio::time::Instant::now())
332 };
333 let mut chunk = vec![0u8; 64 * 1024];
334 let n = match tokio::time::timeout(wait, self.reader.read(&mut chunk)).await {
335 Ok(r) => r?,
336 Err(_) if self.buf.is_empty() => {
337 bail!("MessagePack-RPC peer idle for {}s", idle.as_secs())
338 }
339 Err(_) => bail!(
340 "MessagePack-RPC message incomplete after {}s",
341 IO_TIMEOUT.as_secs()
342 ),
343 };
344 if n == 0 {
345 ensure!(self.buf.is_empty(), "connection closed inside a message");
346 return Ok(None);
347 }
348 self.buf.extend_from_slice(&chunk[..n]);
349 }
350 }
351}
352
353#[derive(Debug, Clone, PartialEq)]
355pub enum Rpc {
356 Request {
357 msgid: u64,
358 method: String,
359 params: Value,
360 },
361 Response {
362 msgid: u64,
363 error: Value,
364 result: Value,
365 },
366 Notification {
367 method: String,
368 params: Value,
369 },
370}
371
372pub fn parse(v: Value) -> Result<Rpc> {
373 let Value::Array(items) = v else {
374 bail!("an RPC message is an array")
375 };
376 let kind = items
377 .first()
378 .and_then(Value::as_u64)
379 .context("an RPC message starts with its type")?;
380 let msgid = |v: &Value| {
381 v.as_u64()
382 .filter(|m| *m <= u64::from(u32::MAX))
383 .context("msgid must be a 32-bit unsigned integer")
384 };
385 let params = |v: &Value| -> Result<Value> {
386 ensure!(v.is_array(), "params must be an array");
387 Ok(v.clone())
388 };
389 Ok(match (kind, items.len()) {
390 (REQUEST, 4) => Rpc::Request {
391 msgid: msgid(&items[1])?,
392 method: items[2]
393 .as_str()
394 .context("method must be a string")?
395 .to_string(),
396 params: params(&items[3])?,
397 },
398 (RESPONSE, 4) => Rpc::Response {
399 msgid: msgid(&items[1])?,
400 error: items[2].clone(),
401 result: items[3].clone(),
402 },
403 (NOTIFICATION, 3) => Rpc::Notification {
404 method: items[1]
405 .as_str()
406 .context("method must be a string")?
407 .to_string(),
408 params: params(&items[2])?,
409 },
410 (k, n) => bail!("RPC message of type {k} with {n} elements"),
411 })
412}
413
414pub fn request(msgid: u64, method: &str, params: &Value) -> Result<Vec<u8>> {
415 encode_message(&json!([REQUEST, msgid, method, params]))
416}
417
418pub fn response(msgid: u64, error: &Value, result: &Value) -> Result<Vec<u8>> {
419 encode_message(&json!([RESPONSE, msgid, error, result]))
420}
421
422pub fn notification(method: &str, params: &Value) -> Result<Vec<u8>> {
423 encode_message(&json!([NOTIFICATION, method, params]))
424}