Skip to main content

nurtex_codec/
varint.rs

1use crate::{CONTINUE_BIT, SEGMENT_BITS, read_byte};
2use std::io::{self, Cursor, Write};
3
4/// Обёртка для типа `VarInt`
5pub trait VarInt {
6  /// Метод чтения `VarInt` из буффера
7  fn read_varint(buffer: &mut Cursor<&[u8]>) -> Option<i32>;
8
9  /// Метод записи `VarInt` в буффер
10  fn write_varint(&self, buffer: &mut impl Write) -> io::Result<()>;
11}
12
13impl VarInt for i32 {
14  fn read_varint(buffer: &mut Cursor<&[u8]>) -> Option<i32> {
15    let mut value = 0i32;
16    let mut position = 0u32;
17
18    loop {
19      let byte = read_byte(buffer)?;
20      value |= (((byte & SEGMENT_BITS) as u32) << position) as i32;
21
22      if (byte & CONTINUE_BIT) == 0 {
23        break;
24      }
25
26      position += 7;
27
28      if position >= 32 {
29        return None;
30      }
31    }
32
33    Some(value)
34  }
35
36  fn write_varint(&self, buffer: &mut impl Write) -> io::Result<()> {
37    let mut array = [0];
38    let mut value = *self;
39
40    if value == 0 {
41      buffer.write_all(&array)?;
42      return Ok(());
43    }
44
45    while value != 0 {
46      array[0] = (value & SEGMENT_BITS as i32) as u8;
47      value = (value >> 7) & (i32::MAX >> 6);
48
49      if value != 0 {
50        array[0] |= CONTINUE_BIT;
51      }
52
53      buffer.write_all(&array)?;
54    }
55
56    Ok(())
57  }
58}