use crate::error::Error;
use crate::traits::{VarInt, VarIntOps};
pub fn encode<T: VarInt>(value: T, buf: &mut [u8]) -> Result<usize, Error> {
let mut val = value.to_unsigned();
let needed_size = value.varint_size();
if buf.len() < needed_size {
return Err(Error::BufferTooSmall {
needed: needed_size,
actual: buf.len(),
});
}
let mut i = 0;
while val.needs_another_byte() && i < buf.len() - 1 {
buf[i] = val.get_byte_with_continuation();
val = val.shift_right_7();
i += 1;
}
if i < buf.len() {
buf[i] = val.get_final_byte();
Ok(i + 1)
} else {
Err(Error::BufferTooSmall {
needed: i + 1,
actual: buf.len(),
})
}
}
pub fn decode<T: VarInt>(buf: &[u8]) -> Result<(T, usize), Error> {
let mut result = T::Unsigned::from_byte(0, 0);
let mut shift = 0;
let mut i = 0;
loop {
if i >= buf.len() {
return Err(Error::InputTooShort);
}
let byte = buf[i];
i += 1;
result = result.bitor(T::Unsigned::from_byte(byte & 0x7F, shift));
if byte & 0x80 == 0 {
break;
}
shift += 1;
if shift >= T::Unsigned::BITS / 7 + 1 {
return Err(Error::Overflow);
}
}
Ok((T::from_unsigned(result), i))
}
#[inline(always)]
pub fn varint_size<T: VarInt>(value: T) -> usize {
value.varint_size()
}