mumble_protocol/
varint.rs

1//! Extension traits for Mumble's varint format.
2
3use byteorder::ReadBytesExt;
4use byteorder::WriteBytesExt;
5use bytes::BufMut;
6use std::io;
7
8/// Extension trait for reading varint values.
9pub trait ReadExt: io::Read {
10    /// Reads a 64-bit varint.
11    fn read_varint(&mut self) -> io::Result<u64>;
12}
13
14/// Extension trait for writing varint values.
15pub trait WriteExt: io::Write {
16    /// Writes a 64-bit varint.
17    fn write_varint(&mut self, val: u64) -> io::Result<()>;
18}
19
20/// Extension trait for writing varint values to [BufMut]s.
21pub trait BufMutExt: BufMut {
22    /// Writes a 64-bit varint.
23    fn put_varint(&mut self, val: u64);
24}
25
26impl<T: io::Read> ReadExt for T {
27    fn read_varint(&mut self) -> io::Result<u64> {
28        let b0 = self.read_u8()?;
29        if b0 & 0b1111_1100 == 0b1111_1000 {
30            return Ok(!self.read_varint()?);
31        }
32        if b0 & 0b1111_1100 == 0b1111_1100 {
33            return Ok(!u64::from(b0 & 0x03));
34        }
35        if (b0 & 0b1000_0000) == 0 {
36            return Ok(u64::from(b0 & 0b0111_1111));
37        }
38        let b1 = self.read_u8()?;
39        if (b0 & 0b0100_0000) == 0 {
40            return Ok(u64::from(b0 & 0b0011_1111) << 8 | u64::from(b1));
41        }
42        let b2 = self.read_u8()?;
43        if (b0 & 0b0010_0000) == 0 {
44            return Ok(u64::from(b0 & 0b0001_1111) << 16 | u64::from(b1) << 8 | u64::from(b2));
45        }
46        let b3 = self.read_u8()?;
47        if (b0 & 0b0001_0000) == 0 {
48            return Ok(u64::from(b0 & 0x0F) << 24
49                | u64::from(b1) << 16
50                | u64::from(b2) << 8
51                | u64::from(b3));
52        }
53        let b4 = self.read_u8()?;
54        if (b0 & 0b0000_0100) == 0 {
55            return Ok(u64::from(b1) << 24
56                | u64::from(b2) << 16
57                | u64::from(b3) << 8
58                | u64::from(b4));
59        }
60        let b5 = self.read_u8()?;
61        let b6 = self.read_u8()?;
62        let b7 = self.read_u8()?;
63        let b8 = self.read_u8()?;
64        Ok(u64::from(b1) << 56
65            | u64::from(b2) << 48
66            | u64::from(b3) << 40
67            | u64::from(b4) << 32
68            | u64::from(b5) << 24
69            | u64::from(b6) << 16
70            | u64::from(b7) << 8
71            | u64::from(b8))
72    }
73}
74
75impl<T: io::Write> WriteExt for T {
76    fn write_varint(&mut self, value: u64) -> io::Result<()> {
77        if value & 0xffff_ffff_ffff_fffc == 0xffff_ffff_ffff_fffc {
78            return self.write_u8(0b1111_1100 | (!value as u8));
79        }
80        if value & 0x8000_0000_0000_0000 == 0x8000_0000_0000_0000 {
81            self.write_u8(0b1111_1000)?;
82            return self.write_varint(!value);
83        }
84
85        if value > 0xffff_ffff {
86            self.write_u8(0b1111_0100)?;
87            self.write_u8((value >> 56) as u8)?;
88            self.write_u8((value >> 48) as u8)?;
89            self.write_u8((value >> 40) as u8)?;
90            self.write_u8((value >> 32) as u8)?;
91            self.write_u8((value >> 24) as u8)?;
92            self.write_u8((value >> 16) as u8)?;
93            self.write_u8((value >> 8) as u8)?;
94            return self.write_u8(value as u8);
95        }
96
97        if value > 0x0fff_ffff {
98            self.write_u8(0b1111_0000)?;
99            self.write_u8((value >> 24) as u8)?;
100            self.write_u8((value >> 16) as u8)?;
101            self.write_u8((value >> 8) as u8)?;
102            return self.write_u8(value as u8);
103        }
104
105        if value > 0x001f_ffff {
106            self.write_u8(0b1110_0000 | (value >> 24) as u8)?;
107            self.write_u8((value >> 16) as u8)?;
108            self.write_u8((value >> 8) as u8)?;
109            return self.write_u8(value as u8);
110        }
111
112        if value > 0x0000_3fff {
113            self.write_u8(0b1100_0000 | (value >> 16) as u8)?;
114            self.write_u8((value >> 8) as u8)?;
115            return self.write_u8(value as u8);
116        }
117
118        if value > 0x0000_007f {
119            self.write_u8(0b1000_0000 | (value >> 8) as u8)?;
120            return self.write_u8(value as u8);
121        }
122
123        self.write_u8(value as u8)
124    }
125}
126
127impl<T: BufMut> BufMutExt for T {
128    fn put_varint(&mut self, val: u64) {
129        self.writer()
130            .write_varint(val)
131            .expect("BufMut::writer never errors");
132    }
133}