messagepack_async/
sync.rs

1use crate::{Ext, Float, Int, Value};
2use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
3use std::io::Result;
4use std::io::{Read, Write};
5
6pub trait ReadFrom: Sized {
7    fn read_from<T: Read>(source: &mut T) -> Result<Self>;
8}
9
10pub trait WriteTo {
11    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()>;
12}
13
14impl WriteTo for bool {
15    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()> {
16        let byte: u8 = match self {
17            false => 0xc2,
18            true => 0xc3,
19        };
20        sink.write_u8(byte)
21    }
22}
23
24impl WriteTo for Int {
25    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()> {
26        match self {
27            Int::U8(i) => {
28                if *i >= 0b10000000 {
29                    sink.write_u8(0xcc)?;
30                }
31                sink.write_u8(*i)
32            }
33            Int::U16(i) => {
34                sink.write_u8(0xcd)?;
35                sink.write_u16::<BigEndian>(*i)
36            }
37            Int::U32(i) => {
38                sink.write_u8(0xce)?;
39                sink.write_u32::<BigEndian>(*i)
40            }
41            Int::U64(i) => {
42                sink.write_u8(0xcf)?;
43                sink.write_u64::<BigEndian>(*i)
44            }
45            Int::I8(i) => {
46                if *i > 0 || *i < -0b00100000 {
47                    sink.write_u8(0xd0)?;
48                    sink.write_i8(*i)
49                } else {
50                    let i: u8 = -*i as u8;
51                    sink.write_u8(0b11100000 | i)
52                }
53            }
54            Int::I16(i) => {
55                sink.write_u8(0xd1)?;
56                sink.write_i16::<BigEndian>(*i)
57            }
58            Int::I32(i) => {
59                sink.write_u8(0xd2)?;
60                sink.write_i32::<BigEndian>(*i)
61            }
62            Int::I64(i) => {
63                sink.write_u8(0xd3)?;
64                sink.write_i64::<BigEndian>(*i)
65            }
66        }
67    }
68}
69
70impl WriteTo for Float {
71    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()> {
72        match self {
73            Float::F32(f) => {
74                sink.write_u8(0xca)?;
75                sink.write_f32::<BigEndian>(*f)?;
76            }
77            Float::F64(f) => {
78                sink.write_u8(0xcb)?;
79                sink.write_f64::<BigEndian>(*f)?;
80            }
81        }
82        Ok(())
83    }
84}
85
86impl WriteTo for Ext {
87    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()> {
88        let len = self.data.len();
89        match len {
90            1 => sink.write_u8(0xd4)?,
91            2 => sink.write_u8(0xd5)?,
92            4 => sink.write_u8(0xd6)?,
93            8 => sink.write_u8(0xd7)?,
94            16 => sink.write_u8(0xd8)?,
95            i if i <= u8::MAX as usize => {
96                sink.write_u8(0xc7)?;
97                sink.write_u8(i.try_into().unwrap())?;
98            }
99            i if i <= u16::MAX as usize => {
100                sink.write_u8(0xc8)?;
101                sink.write_u16::<BigEndian>(i.try_into().unwrap())?;
102            }
103            i if i <= u32::MAX as usize => {
104                sink.write_u8(0xc9)?;
105                sink.write_u32::<BigEndian>(i.try_into().unwrap())?;
106            }
107            _ => panic!(),
108        }
109        sink.write_u8(self.r#type)?;
110        sink.write_all(self.data.as_slice())
111    }
112}
113
114impl ReadFrom for Value {
115    fn read_from<T: Read>(source: &mut T) -> Result<Self> {
116        let leading = source.read_u8()?;
117        Ok(match leading {
118            // Nil
119            0xc0 => Value::Nil,
120            // Bools
121            0xc2 => Value::Bool(false),
122            0xc3 => Value::Bool(true),
123            // Ints
124            // Positive fixint
125            i if i < 0b10000000 => Value::Int(Int::U8(i)),
126            // Negative fixint
127            i if i >= 0b11100000 => Value::Int(Int::I8(-((i - 0b11100000) as i8))),
128            // Unsigned
129            0xcc => Value::Int(Int::U8(source.read_u8()?)),
130            0xcd => Value::Int(Int::U16(source.read_u16::<BigEndian>()?)),
131            0xce => Value::Int(Int::U32(source.read_u32::<BigEndian>()?)),
132            0xcf => Value::Int(Int::U64(source.read_u64::<BigEndian>()?)),
133            // Signed
134            0xd0 => Value::Int(Int::I8(source.read_i8()?)),
135            0xd1 => Value::Int(Int::I16(source.read_i16::<BigEndian>()?)),
136            0xd2 => Value::Int(Int::I32(source.read_i32::<BigEndian>()?)),
137            0xd3 => Value::Int(Int::I64(source.read_i64::<BigEndian>()?)),
138            // Floats
139            0xca => Value::Float(Float::F32(source.read_f32::<BigEndian>()?)),
140            0xcb => Value::Float(Float::F64(source.read_f64::<BigEndian>()?)),
141            // Strings
142            i if i & 0b11100000 == 0b10100000 => {
143                let len: usize = (i & 0b00011111).into();
144                let mut bytes: Vec<u8> = vec![0u8; len];
145                source.read_exact(&mut bytes)?;
146                Value::Str(String::from_utf8(bytes).unwrap())
147            }
148            i @ (0xd9..=0xdb) => {
149                let len: usize = match i {
150                    0xd9 => source.read_u8()?.into(),
151                    0xda => source.read_u16::<BigEndian>()?.into(),
152                    0xdb => source.read_u32::<BigEndian>()?.try_into().unwrap(),
153                    _ => panic!(),
154                };
155                let mut bytes: Vec<u8> = vec![0u8; len];
156                source.read_exact(&mut bytes)?;
157                Value::Str(String::from_utf8(bytes).unwrap())
158            }
159            // Bin
160            i @ (0xc4..=0xc6) => {
161                let len: usize = match i {
162                    0xc4 => source.read_u8()?.into(),
163                    0xc5 => source.read_u16::<BigEndian>()?.into(),
164                    0xc6 => source.read_u32::<BigEndian>()?.try_into().unwrap(),
165                    _ => panic!(),
166                };
167                let mut bytes: Vec<u8> = vec![0u8; len];
168                source.read_exact(&mut bytes)?;
169                Value::Bin(bytes)
170            }
171            // Array
172            i if i & 0b11110000 == 0b10010000 => {
173                let len: usize = (i & 0b00001111).into();
174                let mut arr: Vec<Value> = vec![];
175                for _ in 0..len {
176                    arr.push(Value::read_from(&mut *source)?);
177                }
178                Value::Arr(arr)
179            }
180            i @ (0xdc | 0xdd) => {
181                let len: usize = match i {
182                    0xdc => source.read_u16::<BigEndian>()?.into(),
183                    0xdd => source.read_u32::<BigEndian>()?.try_into().unwrap(),
184                    _ => panic!(),
185                };
186
187                let mut arr: Vec<Value> = vec![];
188                for _ in 0..len {
189                    arr.push(Value::read_from(&mut *source)?);
190                }
191                Value::Arr(arr)
192            }
193            // Maps
194            i if (i & 0b11110000) == 0b10000000 => {
195                let len: usize = (i & 0b00001111).into();
196                let mut map = vec![];
197                for _ in 0..len {
198                    let key: Value = Value::read_from(&mut *source)?;
199                    let value: Value = Value::read_from(&mut *source)?;
200                    map.push((key, value));
201                }
202                Value::Map(map)
203            }
204            i @ (0xde | 0xdf) => {
205                let len: usize = match i {
206                    0xde => source.read_u16::<BigEndian>()?.into(),
207                    0xdf => source.read_u32::<BigEndian>()?.try_into().unwrap(),
208                    _ => panic!(),
209                };
210                let mut map = vec![];
211                for _ in 0..len {
212                    let key: Value = Value::read_from(&mut *source)?;
213                    let value: Value = Value::read_from(&mut *source)?;
214                    map.push((key, value));
215                }
216                Value::Map(map)
217            }
218            // Ext
219            i @ (0xd4 | 0xd5 | 0xd6 | 0xd7 | 0xd8 | 0xc7 | 0xc8 | 0xc9) => {
220                let len: usize = match i {
221                    0xd4 => 1,
222                    0xd5 => 2,
223                    0xd6 => 4,
224                    0xd7 => 8,
225                    0xd8 => 16,
226                    0xc7 => source.read_u8()?.into(),
227                    0xc8 => source.read_u16::<BigEndian>()?.into(),
228                    0xc9 => source.read_u32::<BigEndian>()?.try_into().unwrap(),
229                    _ => panic!(),
230                };
231                let r#type = source.read_u8()?;
232                let mut data = vec![0u8; len];
233                source.read_exact(&mut data)?;
234                Value::Ext(Ext { r#type, data })
235            }
236            i => {
237                panic!("Whaaaa?: {i:x?}");
238            }
239        })
240    }
241}
242
243impl WriteTo for Value {
244    fn write_to<T: Write>(&self, sink: &mut T) -> Result<()> {
245        match self {
246            Value::Nil => sink.write_u8(0xc0),
247            Value::Bool(b) => b.write_to(sink),
248            Value::Int(i) => i.write_to(sink),
249            Value::Float(f) => f.write_to(sink),
250            Value::Str(bytes) => {
251                let len = bytes.len();
252                if len < 0b100000 {
253                    let len: u8 = len.try_into().unwrap();
254                    sink.write_u8(0b10100000 | len)?;
255                } else if let Ok(len) = TryInto::<u8>::try_into(len) {
256                    sink.write_u8(0xd9)?;
257                    sink.write_u8(len)?;
258                } else if let Ok(len) = TryInto::<u16>::try_into(len) {
259                    sink.write_u8(0xda)?;
260                    sink.write_u16::<BigEndian>(len)?;
261                } else if let Ok(len) = TryInto::<u32>::try_into(len) {
262                    sink.write_u8(0xdb)?;
263                    sink.write_u32::<BigEndian>(len)?;
264                } else {
265                    panic!()
266                }
267                sink.write_all(bytes.as_bytes())
268            }
269            Value::Bin(bytes) => {
270                let len = bytes.len();
271                if let Ok(len) = TryInto::<u8>::try_into(len) {
272                    sink.write_u8(0xc4)?;
273                    sink.write_u8(len)?;
274                } else if let Ok(len) = TryInto::<u16>::try_into(len) {
275                    sink.write_u8(0xc5)?;
276                    sink.write_u16::<BigEndian>(len)?;
277                } else if let Ok(len) = TryInto::<u32>::try_into(len) {
278                    sink.write_u8(0xc6)?;
279                    sink.write_u32::<BigEndian>(len)?;
280                }
281                sink.write_all(bytes)
282            }
283            Value::Arr(arr) => {
284                let len = arr.len();
285                if len < 0b10000 {
286                    let len: u8 = len.try_into().unwrap();
287                    sink.write_u8(0b10010000 | len)?;
288                } else if let Ok(len) = TryInto::<u16>::try_into(len) {
289                    sink.write_u8(0xdc)?;
290                    sink.write_u16::<BigEndian>(len)?;
291                } else if let Ok(len) = TryInto::<u32>::try_into(len) {
292                    sink.write_u8(0xdd)?;
293                    sink.write_u32::<BigEndian>(len)?;
294                } else {
295                    panic!();
296                }
297                for v in arr {
298                    v.write_to(&mut *sink)?;
299                }
300                Ok(())
301            }
302            Value::Map(map) => {
303                let len = map.len();
304                if len < 0b10000 {
305                    let len: u8 = len.try_into().unwrap();
306                    sink.write_u8(0b10000000 | len)?;
307                } else if let Ok(len) = TryInto::<u16>::try_into(len) {
308                    sink.write_u8(0xde)?;
309                    sink.write_u16::<BigEndian>(len)?;
310                } else if let Ok(len) = TryInto::<u32>::try_into(len) {
311                    sink.write_u8(0xdf)?;
312                    sink.write_u32::<BigEndian>(len)?;
313                } else {
314                    panic!();
315                }
316                for (k, v) in map {
317                    k.write_to(&mut *sink)?;
318                    v.write_to(&mut *sink)?;
319                }
320                Ok(())
321            }
322            Value::Ext(e) => e.write_to(sink),
323        }
324    }
325}
326
327#[cfg(test)]
328mod tests {
329    use super::*;
330    fn assert_read_write(value: Value, bytes: &[u8]) {
331        // Write
332        let mut candidate_bytes: Vec<u8> = vec![];
333        value.write_to(&mut candidate_bytes).unwrap();
334        assert_eq!(bytes, candidate_bytes);
335        // Read
336        let mut cursor = bytes;
337        let candidate_value = Value::read_from(&mut cursor).unwrap();
338        assert_eq!(value, candidate_value)
339    }
340
341    #[test]
342    fn nil_read_write() {
343        assert_read_write(Value::Nil, &[0xc0]);
344    }
345
346    #[test]
347    fn bool_read_write() {
348        assert_read_write(Value::Bool(false), &[0xc2]);
349        assert_read_write(Value::Bool(true), &[0xc3]);
350    }
351
352    #[test]
353    fn int_read_write() {
354        // Fixint (positive)
355        assert_read_write(Value::Int(Int::U8(0)), &[0]);
356        assert_read_write(Value::Int(Int::U8(5)), &[5]);
357        // Uint 8
358        assert_read_write(Value::Int(Int::U8(230)), &[0xcc, 230]);
359        // Uint 16
360        assert_read_write(Value::Int(Int::U16(256)), &[0xcd, 1, 0]);
361        // Uint 32
362        assert_read_write(Value::Int(Int::U32(65_536)), &[0xce, 0, 1, 0, 0]);
363        // Uint 64
364        assert_read_write(
365            Value::Int(Int::U64(4_294_967_296)),
366            &[0xcf, 0, 0, 0, 1, 0, 0, 0, 0],
367        );
368        // Fixint (negative)
369        assert_read_write(Value::Int(Int::I8(-6)), &[0b11100000 + 6]);
370        // Int 8
371        assert_read_write(Value::Int(Int::I8(-100)), &[0xd0, u8::MAX - 100 + 1]);
372        // Int 16
373        assert_read_write(
374            Value::Int(Int::I16(-100)),
375            &[0xd1, u8::MAX, u8::MAX - 100 + 1],
376        );
377        // Int 32
378        assert_read_write(
379            Value::Int(Int::I32(-100)),
380            &[0xd2, u8::MAX, u8::MAX, u8::MAX, u8::MAX - 100 + 1],
381        );
382        // Int 64
383        assert_read_write(
384            Value::Int(Int::I64(-100)),
385            &[
386                0xd3,
387                u8::MAX,
388                u8::MAX,
389                u8::MAX,
390                u8::MAX,
391                u8::MAX,
392                u8::MAX,
393                u8::MAX,
394                u8::MAX - 100 + 1,
395            ],
396        );
397    }
398
399    #[test]
400    fn float_read_write() {
401        // F32
402        assert_read_write(
403            Value::Float(Float::F32(0.3)),
404            &[0xca, 0x3e, 0x99, 0x99, 0x9a],
405        );
406        // F64
407        assert_read_write(
408            Value::Float(Float::F64(0.3)),
409            &[0xcb, 0x3f, 0xd3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33],
410        );
411    }
412
413    #[test]
414    fn str_bin_read_write() {
415        let bytes: Vec<u8> = b"Oh hello there, isn't this an interesting test".into();
416        let len: u8 = bytes.len().try_into().unwrap();
417        assert_read_write(
418            Value::Str(String::from_utf8(bytes.clone()).unwrap()),
419            &[[0xd9, len].as_slice(), bytes.as_slice()].concat(),
420        );
421        assert_read_write(
422            Value::Bin(bytes.clone()),
423            &[[0xc4, len].as_slice(), bytes.as_slice()].concat(),
424        );
425    }
426
427    #[test]
428    fn arr_read_write() {
429        assert_read_write(
430            Value::Arr(vec![Value::Int(Int::U8(1)), Value::Int(Int::U8(2))]),
431            &[0b10010000 | 2, 1, 2],
432        );
433    }
434
435    #[test]
436    fn map_read_write() {
437        assert_read_write(
438            Value::Map(vec![
439                (Value::Int(Int::U8(1)), Value::Int(Int::U8(10))),
440                (Value::Int(Int::U8(2)), Value::Int(Int::U8(20))),
441            ]),
442            &[0b10000000 | 2, 1, 10, 2, 20],
443        );
444        assert_read_write(Value::Map(vec![]), &[128]);
445    }
446
447    #[test]
448    fn ext_read_write() {
449        assert_read_write(
450            Value::Ext(Ext {
451                r#type: 0xa8,
452                data: b"Hi there".into(),
453            }),
454            &[[0xd7, 0xa8].as_slice(), b"Hi there".as_slice()].concat(),
455        );
456    }
457
458    #[test]
459    fn compound_read_write() {
460        assert_read_write(
461            Value::Arr(
462                [
463                    Value::Int(Int::U8(0)),
464                    Value::Int(Int::U32(0xf264e4f)),
465                    Value::Str("nvim_subscribe".into()),
466                    Value::Arr([Value::Str("rsnote_open_window".into())].into()),
467                ]
468                .into(),
469            ),
470            &[
471                148, 0, 206, 15, 38, 78, 79, 174, 110, 118, 105, 109, 95, 115, 117, 98, 115, 99,
472                114, 105, 98, 101, 145, 178, 114, 115, 110, 111, 116, 101, 95, 111, 112, 101, 110,
473                95, 119, 105, 110, 100, 111, 119,
474            ],
475        );
476        assert_read_write(
477            Value::Arr(
478                [
479                    Value::Int(Int::I8(0)),
480                    Value::Int(Int::U32(0x3f0c4a25)),
481                    Value::Str("nvim_buf_set_keymap".into()),
482                    Value::Arr(
483                        [
484                            Value::Ext(Ext {
485                                r#type: 0,
486                                data: [0xcd, 1, 0x2f].into(),
487                            }),
488                            Value::Str("n".into()),
489                            Value::Str("<ESC>".into()),
490                            Value::Str("<Cmd>w! .tasks<CR><Cmd>q<CR>".into()),
491                            Value::Map([].into()),
492                        ]
493                        .into(),
494                    ),
495                ]
496                .into(),
497            ),
498            &[
499                148, 224, 206, 63, 12, 74, 37, 179, 110, 118, 105, 109, 95, 98, 117, 102, 95, 115,
500                101, 116, 95, 107, 101, 121, 109, 97, 112, 149, 199, 3, 0, 205, 1, 47, 161, 110,
501                165, 60, 69, 83, 67, 62, 188, 60, 67, 109, 100, 62, 119, 33, 32, 46, 116, 97, 115,
502                107, 115, 60, 67, 82, 62, 60, 67, 109, 100, 62, 113, 60, 67, 82, 62, 128,
503            ],
504        );
505        assert_read_write(
506            Value::Arr(
507                [
508                    Value::Int(Int::U8(0)),
509                    Value::Int(Int::U32(0xc032e486)),
510                    Value::Str("nvim_exec_lua".into()),
511                    Value::Arr(
512                        [
513                            Value::Str("return vim.o.columns".into()),
514                            Value::Arr([].into()),
515                        ]
516                        .into(),
517                    ),
518                ]
519                .into(),
520            ),
521            &[
522                148, 0, 206, 192, 50, 228, 134, 173, 110, 118, 105, 109, 95, 101, 120, 101, 99, 95,
523                108, 117, 97, 146, 180, 114, 101, 116, 117, 114, 110, 32, 118, 105, 109, 46, 111,
524                46, 99, 111, 108, 117, 109, 110, 115, 144,
525            ],
526        );
527        assert_read_write(
528            Value::Arr(
529                [
530                    Value::Int(Int::U8(0)),
531                    Value::Int(Int::U32(0x49d10de0)),
532                    Value::Str("nvim_buf_set_lines".into()),
533                    Value::Arr(
534                        [
535                            Value::Ext(Ext {
536                                r#type: 0,
537                                data: [25].into(),
538                            }),
539                            Value::Int(Int::U8(0)),
540                            Value::Int(Int::U8(1)),
541                            Value::Bool(false),
542                            Value::Arr(
543                                [
544                                    Value::Str("Add the messagepack-rs module".into()),
545                                    Value::Str(
546                                        "Delete the
547 local code"
548                                            .into(),
549                                    ),
550                                    Value::Str("Refactor to use the messagepack library".into()),
551                                    Value::Str("".into()),
552                                ]
553                                .into(),
554                            ),
555                        ]
556                        .into(),
557                    ),
558                ]
559                .into(),
560            ),
561            &[
562                148, 0, 206, 73, 209, 13, 224, 178, 110, 118, 105, 109, 95, 98, 117, 102, 95, 115,
563                101, 116, 95, 108, 105, 110, 101, 115, 149, 212, 0, 25, 0, 1, 194, 148, 189, 65,
564                100, 100, 32, 116, 104, 101, 32, 109, 101, 115, 115, 97, 103, 101, 112, 97, 99,
565                107, 45, 114, 115, 32, 109, 111, 100, 117, 108, 101, 182, 68, 101, 108, 101, 116,
566                101, 32, 116, 104, 101, 10, 32, 108, 111, 99, 97, 108, 32, 99, 111, 100, 101, 217,
567                39, 82, 101, 102, 97, 99, 116, 111, 114, 32, 116, 111, 32, 117, 115, 101, 32, 116,
568                104, 101, 32, 109, 101, 115, 115, 97, 103, 101, 112, 97, 99, 107, 32, 108, 105, 98,
569                114, 97, 114, 121, 160,
570            ],
571        );
572    }
573}