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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
pub struct Bytes<'a> {
    data: &'a [u8],
    pos: usize,
}

impl<'a> Bytes<'a> {
    pub fn new(data: &'a [u8]) -> Self {
        Self { data, pos: 0 }
    }

    #[inline]
    fn remaining(&self) -> usize {
        self.data.len() - self.pos
    }

    #[inline]
    pub fn remaining_bytes(&self) -> &'a [u8] {
        &self.data[self.pos..]
    }

    #[inline]
    fn check_remaining(&self, count: usize) {
        assert!(
            self.remaining() >= count,
            "read buffer exhausted; remaining {} bytes, try read {count} bytes",
            self.remaining(),
        );
    }

    #[inline]
    pub fn get_bytes(&mut self, count: usize) -> &[u8] {
        self.check_remaining(count);

        let bytes = &self.data[self.pos..(self.pos + count)];
        self.pos += count;
        bytes
    }

    #[inline]
    pub fn get_array<const SIZE: usize>(&mut self) -> [u8; SIZE] {
        let bytes = self.get_bytes(SIZE);
        let mut arr = [0u8; SIZE];

        arr.copy_from_slice(bytes);

        debug_assert_eq!(arr.as_slice(), bytes);

        arr
    }

    #[inline]
    pub fn get_u8(&mut self) -> u8 {
        self.check_remaining(1);

        let val = self.data[self.pos];
        self.pos += 1;
        val
    }

    #[inline]
    pub fn get_i8(&mut self) -> i8 {
        self.check_remaining(1);

        let val = self.data[self.pos] as i8;
        self.pos += 1;
        val
    }

    #[inline]
    pub fn get_u16_le(&mut self) -> u16 {
        u16::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_i16_le(&mut self) -> i16 {
        i16::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_u24_le(&mut self) -> u32 {
        const SIZE: usize = 3;
        self.check_remaining(SIZE);

        let mut val = [0u8; SIZE + 1];
        val[..3].copy_from_slice(&self.data[self.pos..self.pos + SIZE]);
        self.pos += SIZE;

        debug_assert_eq!(val[3], 0);
        u32::from_le_bytes(val)
    }

    #[inline]
    pub fn get_i24_le(&mut self) -> i32 {
        const SIZE: usize = 3;
        self.check_remaining(SIZE);

        let mut val = [0u8; SIZE + 1];
        val[..3].copy_from_slice(&self.data[self.pos..self.pos + SIZE]);
        self.pos += SIZE;

        debug_assert_eq!(val[3], 0);
        i32::from_le_bytes(val)
    }

    #[inline]
    pub fn get_u32_le(&mut self) -> u32 {
        u32::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_i32_le(&mut self) -> i32 {
        i32::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_u64_le(&mut self) -> u64 {
        u64::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_i64_le(&mut self) -> i64 {
        i64::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_f32_le(&mut self) -> f32 {
        f32::from_le_bytes(self.get_array())
    }

    #[inline]
    pub fn get_f64_le(&mut self) -> f64 {
        f64::from_le_bytes(self.get_array())
    }
}