use crate::error::Error;
use crate::traits::VarInt;
use crate::encoding::{encode, decode};
use crate::zigzag::{ZigZag, encode_zigzag, decode_zigzag};
use core::marker::PhantomData;
pub struct VarIntEncoder<'a, T: VarInt = u64> {
buf: &'a mut [u8],
pos: usize,
_marker: PhantomData<T>,
}
impl<'a, T: VarInt> VarIntEncoder<'a, T> {
pub fn new(buf: &'a mut [u8]) -> Self {
VarIntEncoder {
buf,
pos: 0,
_marker: PhantomData,
}
}
pub fn position(&self) -> usize {
self.pos
}
pub fn remaining(&self) -> usize {
self.buf.len() - self.pos
}
pub fn write(&mut self, value: T) -> Result<usize, Error> {
if self.pos >= self.buf.len() {
return Err(Error::BufferTooSmall {
needed: self.pos + 1,
actual: self.buf.len(),
});
}
let bytes_written = encode(value, &mut self.buf[self.pos..])?;
self.pos += bytes_written;
Ok(bytes_written)
}
pub fn write_batch(&mut self, values: &[T]) -> Result<usize, Error> {
let start_pos = self.pos;
for &value in values {
self.write(value)?;
}
Ok(self.pos - start_pos)
}
#[inline]
pub fn write_u64(&mut self, value: u64) -> Result<usize, Error>
where T: From<u64> {
self.write(T::from(value))
}
#[inline]
pub fn write_u128(&mut self, value: u128) -> Result<usize, Error>
where T: From<u128> {
self.write(T::from(value))
}
pub fn write_zigzag<S>(&mut self, value: S) -> Result<usize, Error>
where
S: ZigZag,
S::Unsigned: VarInt {
if self.pos >= self.buf.len() {
return Err(Error::BufferTooSmall {
needed: self.pos + 1,
actual: self.buf.len(),
});
}
let bytes_written = encode_zigzag(value, &mut self.buf[self.pos..])?;
self.pos += bytes_written;
Ok(bytes_written)
}
pub fn write_zigzag_batch<S>(&mut self, values: &[S]) -> Result<usize, Error>
where
S: ZigZag,
S::Unsigned: VarInt {
let start_pos = self.pos;
for &value in values {
self.write_zigzag(value)?;
}
Ok(self.pos - start_pos)
}
}
pub struct VarIntDecoder<'a, T: VarInt = u64> {
buf: &'a [u8],
pos: usize,
_marker: PhantomData<T>,
}
impl<'a, T: VarInt> VarIntDecoder<'a, T> {
pub fn new(buf: &'a [u8]) -> Self {
VarIntDecoder {
buf,
pos: 0,
_marker: PhantomData,
}
}
pub fn position(&self) -> usize {
self.pos
}
pub fn remaining(&self) -> &'a [u8] {
&self.buf[self.pos..]
}
pub fn read(&mut self) -> Result<T, Error> {
if self.pos >= self.buf.len() {
return Err(Error::InputTooShort);
}
let (value, bytes_read) = decode(&self.buf[self.pos..])?;
self.pos += bytes_read;
Ok(value)
}
pub fn read_batch(&mut self, values: &mut [T]) -> Result<usize, Error> {
let mut count = 0;
while count < values.len() && self.pos < self.buf.len() {
match self.read() {
Ok(value) => {
values[count] = value;
count += 1;
}
Err(Error::InputTooShort) => break,
Err(e) => return Err(e),
}
}
Ok(count)
}
#[inline]
pub fn read_u64(&mut self) -> Result<u64, Error>
where u64: From<T> {
Ok(u64::from(self.read()?))
}
#[inline]
pub fn read_u128(&mut self) -> Result<u128, Error>
where u128: From<T> {
Ok(u128::from(self.read()?))
}
pub fn read_zigzag<S>(&mut self) -> Result<S, Error>
where
S: ZigZag,
S::Unsigned: VarInt {
if self.pos >= self.buf.len() {
return Err(Error::InputTooShort);
}
let (value, bytes_read) = decode_zigzag(&self.buf[self.pos..])?;
self.pos += bytes_read;
Ok(value)
}
pub fn read_zigzag_batch<S>(&mut self, values: &mut [S]) -> Result<usize, Error>
where
S: ZigZag,
S::Unsigned: VarInt {
let mut count = 0;
while count < values.len() && self.pos < self.buf.len() {
match self.read_zigzag() {
Ok(value) => {
values[count] = value;
count += 1;
}
Err(Error::InputTooShort) => break,
Err(e) => return Err(e),
}
}
Ok(count)
}
}
#[inline]
pub fn encode_batch(values: &[u64], buf: &mut [u8]) -> Result<usize, Error> {
let mut encoder = VarIntEncoder::new(buf);
encoder.write_batch(values)
}
#[inline]
pub fn decode_batch(buf: &[u8], values: &mut [u64]) -> Result<usize, Error> {
let mut decoder = VarIntDecoder::new(buf);
decoder.read_batch(values)
}