Skip to main content

mcproto_codec/
varlong.rs

1use std::io::{Read, Write};
2use crate::CodecError;
3
4pub trait VarLongWrite: Write {
5    #[inline]
6    fn write_varlong(&mut self, value: i64) -> Result<(), CodecError> {
7        let mut value = value as u64;
8        for i in 0..10 {
9            let byte = (value & 0x7F) as u8;
10            value >>= 7;
11            let has_next = value != 0 && i < 9;
12            let byte = if has_next { byte | 0x80 } else { byte };
13
14            self.write_all(&[byte])?;
15
16            if !has_next {
17                return Ok(());
18            }
19        }
20        Err(CodecError::VarLongOverflow)
21    }
22}
23
24pub trait VarLongRead: Read {
25    #[inline]
26    fn read_varlong(&mut self) -> Result<i64, CodecError> {
27        let mut result = 0u64;
28        let mut shift = 0;
29
30        for _ in 0..10 {
31            let mut buf = [0u8; 1];
32            self.read_exact(&mut buf)?;
33            let byte = buf[0];
34
35            let value = (byte & 0x7F) as u64;
36            result |= value << shift;
37
38            if (byte & 0x80) == 0 {
39                return Ok(result as i64);
40            }
41
42            shift += 7;
43        }
44        Err(CodecError::VarLongOverflow)
45    }
46}
47
48impl<R: Read> VarLongRead for R {}
49impl<W: Write> VarLongWrite for W {}