use std::io::{
Result,
SeekFrom,
};
use crate::{
BufferedInput,
Input,
Seekable,
SeekableInput,
};
pub enum EnsuredBufferedInput<I>
where
I: Input,
I::Item: Copy + Default,
{
AlreadyBuffered(I),
Buffered(BufferedInput<I>),
}
impl<I> Input for EnsuredBufferedInput<I>
where
I: Input,
I::Item: Copy + Default,
{
type Item = I::Item;
#[inline(always)]
fn is_buffered(&self) -> bool {
true
}
#[inline(always)]
unsafe fn read_unchecked(
&mut self,
output: &mut [Self::Item],
index: usize,
count: usize,
) -> Result<usize> {
match self {
Self::AlreadyBuffered(input) => {
unsafe { input.read_unchecked(output, index, count) }
}
Self::Buffered(input) => {
unsafe { input.read_unchecked(output, index, count) }
}
}
}
#[inline(always)]
fn read(&mut self, output: &mut [Self::Item]) -> Result<usize> {
match self {
Self::AlreadyBuffered(input) => input.read(output),
Self::Buffered(input) => input.read(output),
}
}
#[inline(always)]
unsafe fn read_fully_unchecked(
&mut self,
output: &mut [Self::Item],
index: usize,
count: usize,
) -> Result<usize> {
match self {
Self::AlreadyBuffered(input) => {
unsafe { input.read_fully_unchecked(output, index, count) }
}
Self::Buffered(input) => {
unsafe { input.read_fully_unchecked(output, index, count) }
}
}
}
#[inline(always)]
fn read_fully(&mut self, output: &mut [Self::Item]) -> Result<usize> {
match self {
Self::AlreadyBuffered(input) => input.read_fully(output),
Self::Buffered(input) => input.read_fully(output),
}
}
}
impl<I> Seekable for EnsuredBufferedInput<I>
where
I: SeekableInput,
<I as Input>::Item: Copy + Default,
{
type Item = <I as Input>::Item;
#[inline(always)]
fn seek_to(&mut self, position: SeekFrom) -> Result<u64> {
match self {
Self::AlreadyBuffered(input) => input.seek_to(position),
Self::Buffered(input) => input.seek_to(position),
}
}
}