use core::marker::PhantomData;
use std::io::{
Error,
ErrorKind,
Read,
Result,
Seek,
SeekFrom,
};
use crate::codec::{
DecodePolicy,
Leb128DecodeError,
NonStrict,
Strict,
ZigZagCodec,
};
use crate::stream::BufferedInput;
pub struct BufferedZigZagReader<R, P = NonStrict> {
input: BufferedInput<R>,
marker: PhantomData<fn() -> P>,
}
impl<R, P> BufferedZigZagReader<R, P>
where
P: DecodePolicy,
{
#[must_use]
#[inline]
pub fn new(inner: R) -> Self {
Self {
input: BufferedInput::new(inner),
marker: PhantomData,
}
}
#[must_use]
#[inline]
pub fn with_capacity(inner: R, capacity: usize) -> Self {
Self {
input: BufferedInput::with_capacity(inner, capacity),
marker: PhantomData,
}
}
#[must_use]
#[inline]
pub const fn is_strict(&self) -> bool {
P::STRICT
}
#[must_use]
#[inline]
pub const fn inner(&self) -> &R {
self.input.inner()
}
#[must_use]
#[inline]
pub fn inner_mut(&mut self) -> &mut R {
self.input.inner_mut()
}
#[must_use]
#[inline]
pub fn into_inner(self) -> R {
self.input.into_inner()
}
}
macro_rules! impl_read_value {
($policy:ty, $method:ident, $ty:ty, $doc:literal) => {
#[doc = $doc]
#[inline]
pub fn $method(&mut self) -> Result<$ty> {
type Codec = ZigZagCodec<$ty, $policy>;
self.input
.read_variable_decoded::<{ Codec::REQUIRED_MIN_BUFFER_LEN }, _, _, _, _>(
|bytes, index, available| {
unsafe { Codec::read_available_unchecked(bytes, index, available) }
},
map_leb128_decode_error,
)
}
};
}
macro_rules! impl_for_policy {
($policy:ty) => {
impl<R> BufferedZigZagReader<R, $policy>
where
R: Read,
{
impl_read_value!($policy, read_i8, i8, "Reads a ZigZag `i8`.");
impl_read_value!($policy, read_i16, i16, "Reads a ZigZag `i16`.");
impl_read_value!($policy, read_i32, i32, "Reads a ZigZag `i32`.");
impl_read_value!($policy, read_i64, i64, "Reads a ZigZag `i64`.");
impl_read_value!($policy, read_i128, i128, "Reads a ZigZag `i128`.");
impl_read_value!($policy, read_isize, isize, "Reads a ZigZag `isize`.");
}
};
}
impl_for_policy!(NonStrict);
impl_for_policy!(Strict);
impl<R, P> Read for BufferedZigZagReader<R, P>
where
R: Read,
{
#[inline]
fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
self.input.read_raw(buffer)
}
}
impl<R, P> Seek for BufferedZigZagReader<R, P>
where
R: Read + Seek,
{
#[inline]
fn seek(&mut self, position: SeekFrom) -> Result<u64> {
self.input.seek_raw(position)
}
}
#[inline]
fn map_leb128_decode_error(error: Leb128DecodeError) -> Error {
Error::new(ErrorKind::InvalidData, error)
}