tiny_varint/
encoding.rs

1
2use crate::error::Error;
3use crate::traits::{VarInt, VarIntOps};
4
5/// Encodes arbitrary VarInt type to varint format
6///
7/// Returns the number of bytes written
8///
9/// # Parameters
10/// * `value` - The value to encode
11/// * `buf` - Output buffer
12///
13/// # Errors
14/// Returns `Error::BufferTooSmall` if the buffer is too small
15pub fn encode<T: VarInt>(value: T, buf: &mut [u8]) -> Result<usize, Error> {
16    let mut val = value.to_unsigned();
17    let needed_size = value.varint_size();
18    
19    if buf.len() < needed_size {
20        return Err(Error::BufferTooSmall {
21            needed: needed_size,
22            actual: buf.len(),
23        });
24    }
25    
26    let mut i = 0;
27    while val.needs_another_byte() && i < buf.len() - 1 {
28        buf[i] = val.get_byte_with_continuation();
29        val = val.shift_right_7();
30        i += 1;
31    }
32    
33    if i < buf.len() {
34        buf[i] = val.get_final_byte();
35        Ok(i + 1)
36    } else {
37        Err(Error::BufferTooSmall {
38            needed: i + 1,
39            actual: buf.len(),
40        })
41    }
42}
43
44/// Decodes arbitrary VarInt type from varint format
45///
46/// Returns the decoded value and the number of bytes read
47///
48/// # Parameters
49/// * `buf` - Input buffer containing varint encoding
50///
51/// # Errors
52/// * Returns `Error::InputTooShort` if the input buffer is insufficient
53/// * Returns `Error::InvalidEncoding` if the varint encoding is invalid
54/// * Returns `Error::Overflow` if overflow occurs during decoding
55pub fn decode<T: VarInt>(buf: &[u8]) -> Result<(T, usize), Error> {
56    let mut result = T::Unsigned::from_byte(0, 0);
57    let mut shift = 0;
58    let mut i = 0;
59    
60    loop {
61        if i >= buf.len() {
62            return Err(Error::InputTooShort);
63        }
64        
65        let byte = buf[i];
66        i += 1;
67        
68        result = result.bitor(T::Unsigned::from_byte(byte & 0x7F, shift));
69        
70        // Check if done
71        if byte & 0x80 == 0 {
72            break;
73        }
74        
75        shift += 1;
76        
77        // Prevent too large varint
78        if shift >= T::Unsigned::BITS / 7 + 1 {
79            return Err(Error::Overflow);
80        }
81    }
82    
83    Ok((T::from_unsigned(result), i))
84}
85
86/// Calculates the number of bytes needed to encode a VarInt value
87///
88/// # Parameters
89/// * `value` - The value to calculate the size for
90#[inline(always)]
91pub fn varint_size<T: VarInt>(value: T) -> usize {
92    value.varint_size()
93}