use tokio::io::AsyncReadExt;
use crate::Segment;
pub struct VarReader<'a, R: AsyncReadExt> {
reader: &'a mut R,
}
impl<'a, R: AsyncReadExt + Unpin> VarReader<'a, R> {
pub fn new(reader: &'a mut R) -> Self {
VarReader { reader }
}
async fn read_varint(&mut self) -> tokio::io::Result<usize> {
let mut value = 0usize;
let mut shift = 0;
loop {
let mut buf = [0; 1];
self.reader.read(&mut buf).await?;
let byte = buf[0];
value |= ((byte & 0x7F) as usize) << shift;
shift += 7;
if byte & 0x80 == 0 {
break;
}
}
Ok(value)
}
#[cfg(not(feature = "big-endian"))]
async fn read_u32(&mut self) -> tokio::io::Result<u32> {
let mut bytes = [0; 4];
self.reader.read_exact(&mut bytes).await?;
Ok(u32::from_le_bytes(bytes))
}
#[cfg(feature = "big-endian")]
async fn read_u32(&mut self) -> tokio::io::Result<u32> {
let mut bytes = [0; 4];
self.reader.read_exact(&mut bytes).await?;
Ok(u32::from_be_bytes(bytes))
}
pub async fn read_data(&mut self) -> tokio::io::Result<Vec<Segment>> {
let total_size = self.read_varint().await?;
let mut data = Vec::new();
while data.iter().map(|segment: &Segment| segment.len() + 4).sum::<usize>() < total_size {
let segment_size = self.read_u32().await? as usize;
let mut segment_data = vec![0u8; segment_size];
self.reader.read_exact(&mut segment_data).await?;
data.push(Segment::from(segment_data));
}
Ok(data)
}
}