Skip to main content

nurtex_codec/
varlong.rs

1use crate::{CONTINUE_BIT, SEGMENT_BITS, read_byte};
2use std::io::{self, Cursor, Write};
3
4/// Обёртка для типа `VarLong`
5pub trait VarLong {
6  /// Метод чтения `VarLong` из буффера
7  fn read_varlong(buffer: &mut Cursor<&[u8]>) -> Option<i64>;
8
9  /// Метод записи `VarLong` в буффер
10  fn write_varlong(&self, buffer: &mut impl Write) -> io::Result<()>;
11}
12
13impl VarLong for i64 {
14  fn read_varlong(buffer: &mut Cursor<&[u8]>) -> Option<i64> {
15    let mut value = 0i64;
16    let mut position = 0u32;
17
18    loop {
19      let byte = read_byte(buffer)?;
20      value |= (((byte & SEGMENT_BITS) as u32) << position) as i64;
21
22      if (byte & CONTINUE_BIT) == 0 {
23        break;
24      }
25
26      position += 7;
27
28      if position >= 64 {
29        return None;
30      }
31    }
32
33    Some(value)
34  }
35
36  fn write_varlong(&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 i64) as u8;
47      value = (value >> 7) & (i64::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}