aboutsummaryrefslogtreecommitdiff
path: root/src/mqtt/varint.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mqtt/varint.rs')
-rw-r--r--src/mqtt/varint.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/mqtt/varint.rs b/src/mqtt/varint.rs
new file mode 100644
index 0000000..63bdd06
--- /dev/null
+++ b/src/mqtt/varint.rs
@@ -0,0 +1,69 @@
1#[derive(Debug)]
2pub enum Error {
3 NeedMoreData,
4 InvalidVarInt,
5}
6
7impl core::fmt::Display for Error {
8 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
9 match self {
10 Error::NeedMoreData => f.write_str("NeedMoreData"),
11 Error::InvalidVarInt => f.write_str("InvalidVarInt"),
12 }
13 }
14}
15
16impl core::error::Error for Error {}
17
18pub fn encode(mut v: u32) -> ([u8; 4], usize) {
19 let mut encoded = [0u8; 4];
20 let mut count = 0;
21
22 loop {
23 let mut byte = (v % 128) as u8;
24 v /= 128;
25
26 if v > 0 {
27 byte |= 0x80; // Set continuation bit
28 }
29
30 encoded[count] = byte;
31 count += 1;
32
33 if v == 0 {
34 break;
35 }
36 }
37
38 (encoded, count)
39}
40
41pub fn decode(buf: &[u8]) -> Result<(u32, usize), Error> {
42 let mut value = 0u32;
43
44 let v = buf.get(0).ok_or(Error::NeedMoreData)?;
45 value |= ((v & 0x7F) as u32) << 0;
46 if v & 0x80 == 0 {
47 return Ok((value, 1));
48 }
49
50 let v = buf.get(1).ok_or(Error::NeedMoreData)?;
51 value |= ((v & 0x7F) as u32) << 7;
52 if v & 0x80 == 0 {
53 return Ok((value, 2));
54 }
55
56 let v = buf.get(2).ok_or(Error::NeedMoreData)?;
57 value |= ((v & 0x7F) as u32) << 14;
58 if v & 0x80 == 0 {
59 return Ok((value, 3));
60 }
61
62 let v = buf.get(3).ok_or(Error::NeedMoreData)?;
63 value |= ((v & 0x7F) as u32) << 21;
64 if v & 0x80 != 0 {
65 return Err(Error::InvalidVarInt);
66 }
67
68 Ok((value, 4))
69}