mooshroom_core/
varint.rs

1use std::io;
2
3use byteorder::{ReadBytesExt, WriteBytesExt};
4
5use super::{
6    io::{MoshroomReadable, MoshroomWritable},
7    ProtocolVersion,
8};
9use crate::error::{MoshroomError, Result};
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq)]
12pub struct VarInt(pub i32);
13
14impl MoshroomReadable for VarInt {
15    fn read(reader: &mut impl io::Read, _: ProtocolVersion) -> Result<Self> {
16        let mut num_read = 0;
17        let mut result = 0;
18
19        loop {
20            let read = reader.read_u8()?;
21            let value = i32::from(read & 0b0111_1111);
22            result |= value.overflowing_shl(7 * num_read).0;
23
24            num_read += 1;
25
26            if num_read > 5 {
27                return Err(MoshroomError::VarIntTooLong);
28            }
29            if read & 0b1000_0000 == 0 {
30                break;
31            }
32        }
33        Ok(Self(result))
34    }
35}
36
37impl MoshroomWritable for VarInt {
38    fn write(&self, writer: &mut impl io::Write, _: ProtocolVersion) -> Result<()> {
39        let mut x = self.0 as u32;
40        loop {
41            let mut temp = (x & 0b0111_1111) as u8;
42            x >>= 7;
43            if x != 0 {
44                temp |= 0b1000_0000;
45            }
46
47            writer.write_all(&[temp])?;
48
49            if x == 0 {
50                break;
51            }
52        }
53        Ok(())
54    }
55}
56
57#[derive(Copy, Clone, Debug, PartialEq, Eq)]
58pub struct VarLong(pub i64);
59
60impl MoshroomReadable for VarLong {
61    fn read(reader: &mut impl io::Read, _: ProtocolVersion) -> Result<Self> {
62        let mut num_read = 0;
63        let mut result = 0;
64
65        loop {
66            let read = reader.read_u8()?;
67            let value = i64::from(read & 0b0111_1111);
68            result |= value.overflowing_shl(7 * num_read).0;
69
70            num_read += 1;
71
72            if read & 0b1000_0000 == 0 {
73                break;
74            }
75
76            if num_read > 10 {
77                return Err(MoshroomError::VarIntTooLong);
78            }
79        }
80        Ok(Self(result))
81    }
82}
83
84impl MoshroomWritable for VarLong {
85    fn write(&self, writer: &mut impl io::Write, _: ProtocolVersion) -> Result<()> {
86        let mut x = self.0 as u64;
87        writer
88            .write_u8(((x & 0b0111_1111) | (0b1000_0000 * ((x >> 7 != 0) as u64))) as u8)
89            .map_err(MoshroomError::IoError)?;
90        x >>= 7;
91        loop {
92            if x == 0 {
93                break;
94            }
95            let mut temp = (x & 0b0111_1111) as u8;
96
97            x >>= 7;
98            if x != 0 {
99                temp |= 0b1000_0000;
100            }
101
102            writer.write_u8(temp).map_err(MoshroomError::IoError)?;
103        }
104
105        Ok(())
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn varint_read() {
115        assert_eq!(
116            VarInt::read(&mut [0x0].as_ref(), ProtocolVersion::V1_20).unwrap(),
117            VarInt(0)
118        );
119        assert_eq!(
120            VarInt::read(&mut [0x1].as_ref(), ProtocolVersion::V1_20).unwrap(),
121            VarInt(1)
122        );
123        assert_eq!(
124            VarInt::read(&mut [0x2].as_ref(), ProtocolVersion::V1_20).unwrap(),
125            VarInt(2)
126        );
127        assert_eq!(
128            VarInt::read(&mut [0x7f].as_ref(), ProtocolVersion::V1_20).unwrap(),
129            VarInt(127)
130        );
131        assert_eq!(
132            VarInt::read(&mut [0x80, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
133            VarInt(128)
134        );
135        assert_eq!(
136            VarInt::read(&mut [0xff, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
137            VarInt(255)
138        );
139        assert_eq!(
140            VarInt::read(&mut [0xdd, 0xc7, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
141            VarInt(25565)
142        );
143        assert_eq!(
144            VarInt::read(&mut [0xff, 0xff, 0x7f].as_ref(), ProtocolVersion::V1_20).unwrap(),
145            VarInt(2097151)
146        );
147        assert_eq!(
148            VarInt::read(
149                &mut [0xff, 0xff, 0xff, 0xff, 0x07].as_ref(),
150                ProtocolVersion::V1_20
151            )
152            .unwrap(),
153            VarInt(2147483647)
154        );
155        assert_eq!(
156            VarInt::read(
157                &mut [0xff, 0xff, 0xff, 0xff, 0x0f].as_ref(),
158                ProtocolVersion::V1_20
159            )
160            .unwrap(),
161            VarInt(-1)
162        );
163        assert_eq!(
164            VarInt::read(
165                &mut [0x80, 0x80, 0x80, 0x80, 0x08].as_ref(),
166                ProtocolVersion::V1_20
167            )
168            .unwrap(),
169            VarInt(-2147483648)
170        );
171    }
172
173    #[test]
174    fn varint_write() {
175        fn check_varint<const N: usize>(value: i32, expected: [u8; N]) {
176            let mut buffer = Vec::new();
177            VarInt(value)
178                .write(&mut buffer, ProtocolVersion::V1_20)
179                .unwrap();
180            let out: [u8; N] = buffer.try_into().unwrap();
181
182            assert_eq!(expected, out);
183        }
184
185        check_varint(0, [0x0]);
186        check_varint(1, [0x1]);
187        check_varint(2, [0x2]);
188        check_varint(127, [0x7f]);
189        check_varint(128, [0x80, 0x01]);
190        check_varint(255, [0xff, 0x01]);
191        check_varint(25565, [0xdd, 0xc7, 0x01]);
192        check_varint(2097151, [0xff, 0xff, 0x7f]);
193        check_varint(2147483647, [0xff, 0xff, 0xff, 0xff, 0x07]);
194        check_varint(-1, [0xff, 0xff, 0xff, 0xff, 0x0f]);
195        check_varint(-2147483648, [0x80, 0x80, 0x80, 0x80, 0x08]);
196    }
197
198    #[test]
199    fn varint_write_read() {
200        let tests = [
201            0,
202            1,
203            2,
204            127,
205            128,
206            255,
207            25565,
208            2097151,
209            2147483647,
210            -1,
211            -2147483648,
212        ];
213        let mut buffer = Vec::new();
214        for i in tests {
215            buffer.clear();
216            let vi = VarInt(i);
217            vi.write(&mut buffer, ProtocolVersion::V1_20).unwrap();
218
219            let vo = VarInt::read(&mut buffer.as_slice(), ProtocolVersion::V1_20).unwrap();
220            assert_eq!(vi, vo);
221        }
222    }
223
224    #[test]
225    fn varlong_read() {
226        assert_eq!(
227            VarLong::read(&mut [0x0].as_ref(), ProtocolVersion::V1_20).unwrap(),
228            VarLong(0)
229        );
230        assert_eq!(
231            VarLong::read(&mut [0x1].as_ref(), ProtocolVersion::V1_20).unwrap(),
232            VarLong(1)
233        );
234        assert_eq!(
235            VarLong::read(&mut [0x2].as_ref(), ProtocolVersion::V1_20).unwrap(),
236            VarLong(2)
237        );
238        assert_eq!(
239            VarLong::read(&mut [0x7f].as_ref(), ProtocolVersion::V1_20).unwrap(),
240            VarLong(127)
241        );
242        assert_eq!(
243            VarLong::read(&mut [0x80, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
244            VarLong(128)
245        );
246        assert_eq!(
247            VarLong::read(&mut [0xff, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
248            VarLong(255)
249        );
250        assert_eq!(
251            VarLong::read(&mut [0xdd, 0xc7, 0x01].as_ref(), ProtocolVersion::V1_20).unwrap(),
252            VarLong(25565)
253        );
254        assert_eq!(
255            VarLong::read(&mut [0xff, 0xff, 0x7f].as_ref(), ProtocolVersion::V1_20).unwrap(),
256            VarLong(2097151)
257        );
258        assert_eq!(
259            VarLong::read(
260                &mut [0xff, 0xff, 0xff, 0xff, 0x07].as_ref(),
261                ProtocolVersion::V1_20
262            )
263            .unwrap(),
264            VarLong(2147483647)
265        );
266        assert_eq!(
267            VarLong::read(
268                &mut [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f].as_ref(),
269                ProtocolVersion::V1_20
270            )
271            .unwrap(),
272            VarLong(9223372036854775807)
273        );
274        assert_eq!(
275            VarLong::read(
276                &mut [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01].as_ref(),
277                ProtocolVersion::V1_20
278            )
279            .unwrap(),
280            VarLong(-1)
281        );
282        assert_eq!(
283            VarLong::read(
284                &mut [0x80, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01].as_ref(),
285                ProtocolVersion::V1_20
286            )
287            .unwrap(),
288            VarLong(-2147483648)
289        );
290        assert_eq!(
291            VarLong::read(
292                &mut [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01].as_ref(),
293                ProtocolVersion::V1_20
294            )
295            .unwrap(),
296            VarLong(-9223372036854775808)
297        );
298    }
299
300    #[test]
301    fn varlong_write() {
302        fn check_varlong<const N: usize>(value: i64, expected: [u8; N]) {
303            let mut buffer = Vec::new();
304            VarLong(value)
305                .write(&mut buffer, ProtocolVersion::V1_20)
306                .unwrap();
307            assert_eq!(buffer.len(), N, "Value: {}", value);
308            let out: [u8; N] = buffer.try_into().unwrap();
309
310            assert_eq!(expected, out);
311        }
312
313        check_varlong(0, [0x0]);
314        check_varlong(1, [0x1]);
315        check_varlong(2, [0x2]);
316        check_varlong(127, [0x7f]);
317        check_varlong(128, [0x80, 0x01]);
318        check_varlong(255, [0xff, 0x01]);
319        check_varlong(25565, [0xdd, 0xc7, 0x01]);
320        check_varlong(2097151, [0xff, 0xff, 0x7f]);
321        check_varlong(2147483647, [0xff, 0xff, 0xff, 0xff, 0x07]);
322        check_varlong(
323            9223372036854775807,
324            [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
325        );
326        check_varlong(
327            -1,
328            [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01],
329        );
330        check_varlong(
331            -2147483648,
332            [0x80, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01],
333        );
334        check_varlong(
335            -9223372036854775808,
336            [0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01],
337        );
338    }
339
340    #[test]
341    fn varlong_write_read() {
342        let tests = [
343            0,
344            1,
345            2,
346            127,
347            128,
348            255,
349            25565,
350            2097151,
351            2147483647,
352            9223372036854775807,
353            -1,
354            -2147483648,
355            -9223372036854775808,
356        ];
357        let mut buffer = Vec::new();
358        for i in tests {
359            buffer.clear();
360            let vi = VarLong(i);
361            vi.write(&mut buffer, ProtocolVersion::V1_20).unwrap();
362
363            let vo = VarLong::read(&mut buffer.as_slice(), ProtocolVersion::V1_20).unwrap();
364            assert_eq!(vi, vo);
365        }
366    }
367}