1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::collections::HashMap;

use bytes::{Buf, Bytes};

pub trait BinaryReader {
    fn read_string(&mut self) -> String;
    fn read_string_short(&mut self) -> String;
    fn read_bytes_short(&mut self) -> Bytes;
    fn read_tlv_map(&mut self, tag_size: usize) -> HashMap<u16, Bytes>;
    fn read_string_limit(&mut self, limit: usize) -> String;
}

impl<B> BinaryReader for B
where
    B: Buf,
{
    fn read_string(&mut self) -> String {
        let len = self.get_i32() as usize - 4;
        String::from_utf8_lossy(&self.copy_to_bytes(len)).into_owned()
    }

    fn read_string_short(&mut self) -> String {
        let len = self.get_u16() as usize;
        String::from_utf8_lossy(&self.copy_to_bytes(len)).into_owned()
    }

    fn read_bytes_short(&mut self) -> Bytes {
        let len = self.get_u16() as usize;
        self.copy_to_bytes(len)
    }

    fn read_tlv_map(&mut self, tag_size: usize) -> HashMap<u16, Bytes> {
        let mut m = HashMap::new();
        loop {
            if self.remaining() < tag_size {
                return m;
            }
            let mut k = 0;
            if tag_size == 1 {
                k = self.get_u8() as u16;
            } else if tag_size == 2 {
                k = self.get_u16();
            } else if tag_size == 4 {
                k = self.get_i32() as u16;
            }
            if k == 255 {
                return m;
            }
            if self.remaining() < 2 {
                return m;
            }
            let len = self.get_u16() as usize;
            if self.remaining() < len {
                return m;
            }
            m.insert(k, self.copy_to_bytes(len));
        }
    }

    fn read_string_limit(&mut self, limit: usize) -> String {
        String::from_utf8_lossy(&self.copy_to_bytes(limit)).into_owned()
    }
}