use crate::error::DecodeErrorKind;
use bytes::BufMut;
pub const MAX_LEN: usize = 10;
#[inline]
pub const fn zigzag(value: i64) -> u64 {
((value << 1) ^ (value >> 63)) as u64
}
#[inline]
pub const fn unzigzag(value: u64) -> i64 {
((value >> 1) as i64) ^ -((value & 1) as i64)
}
#[inline]
pub const fn uint_len(value: u64) -> usize {
let bits = 64 - (value | 1).leading_zeros() as usize;
bits.div_ceil(7)
}
#[inline]
pub const fn int_len(value: i64) -> usize {
uint_len(zigzag(value))
}
#[inline]
pub fn put_uint<B: BufMut + ?Sized>(out: &mut B, mut value: u64) {
let mut buf = [0u8; MAX_LEN];
let mut len = 0;
while value >= 0x80 {
buf[len] = (value as u8) | 0x80;
value >>= 7;
len += 1;
}
buf[len] = value as u8;
out.put_slice(&buf[..=len]);
}
#[inline]
pub fn put_int<B: BufMut + ?Sized>(out: &mut B, value: i64) {
put_uint(out, zigzag(value));
}
#[inline]
pub fn read_uint(input: &[u8]) -> Result<(u64, usize), DecodeErrorKind> {
let mut value = 0u64;
for (index, &byte) in input.iter().enumerate() {
if index == MAX_LEN - 1 && byte > 1 {
return Err(DecodeErrorKind::VarintOverflow);
}
value |= u64::from(byte & 0x7f) << (7 * index);
if byte & 0x80 == 0 {
if byte == 0 && index > 0 {
return Err(DecodeErrorKind::NonCanonicalVarint);
}
return Ok((value, index + 1));
}
}
Err(DecodeErrorKind::Truncated)
}
#[inline]
pub fn read_uint_lenient(input: &[u8]) -> (u64, usize) {
let mut value = 0u64;
for (index, &byte) in input.iter().take(MAX_LEN).enumerate() {
value |= u64::from(byte & 0x7f).wrapping_shl(7 * index as u32);
if byte & 0x80 == 0 {
return (value, index + 1);
}
}
(value, input.len().min(MAX_LEN))
}