use std::io::{self, Read};
const U64_LEN: usize = 10;
pub(crate) fn read_varint_u64<R: Read>(stream: &mut R) -> Result<Option<(u64, usize)>, io::Error> {
let mut result: u64 = 0;
for i in 0..U64_LEN {
let mut buf = [0u8; 1];
stream.read_exact(&mut buf)?;
let byte = buf[0];
result |= u64::from(byte & 0b0111_1111) << (i * 7);
if byte & 0b1000_0000 == 0 {
return Ok(Some((result, i + 1)));
}
}
Ok(None)
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use quickcheck_macros::quickcheck;
use super::U64_LEN;
use crate::varint::read_varint_u64;
fn encode_varint_u64(input: u64, buf: &mut [u8; U64_LEN]) -> (&[u8], usize) {
let mut n = input;
let mut i = 0;
for b in buf.iter_mut() {
*b = n as u8 | 0b1000_0000;
n >>= 7;
if n == 0 {
*b &= 0b0111_1111;
break;
}
i += 1
}
debug_assert_eq!(n, 0);
(&buf[0..=i], i + 1)
}
#[quickcheck]
fn varint_u64_identity(input: u64) -> bool {
let mut buf = [0u8; U64_LEN];
let (buf_ref, input_len) = encode_varint_u64(input, &mut buf);
let mut input_stream = Cursor::new(buf_ref);
let output = read_varint_u64(&mut input_stream);
(input, input_len) == output.unwrap().unwrap()
}
}