use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use super::validate_read_count;
use crate::util::SliceRange;
pub trait Input {
type Item;
#[inline(always)]
#[must_use]
fn is_buffered(&self) -> bool {
false
}
unsafe fn read_unchecked(&mut self, output: &mut [Self::Item], index: usize, count: usize) -> Result<usize>;
#[inline(always)]
fn read(&mut self, output: &mut [Self::Item]) -> Result<usize> {
let read = unsafe { self.read_unchecked(output, 0, output.len()) }?;
validate_read_count(read, output.len())?;
Ok(read)
}
unsafe fn read_fully_unchecked(&mut self, output: &mut [Self::Item], index: usize, count: usize) -> Result<usize> {
debug_assert!(
SliceRange::range_fits(output.len(), index, count),
"unchecked read-fully range exceeds output buffer"
);
let mut total = 0;
while total < count {
let remaining = count - total;
match unsafe { self.read_unchecked(output, index + total, remaining) } {
Ok(0) => break,
Ok(read) => {
validate_read_count(read, remaining)?;
total += read;
}
Err(error) if error.kind() == ErrorKind::Interrupted => {}
Err(error) => return Err(error),
}
}
Ok(total)
}
#[inline(always)]
fn read_fully(&mut self, output: &mut [Self::Item]) -> Result<usize> {
unsafe { self.read_fully_unchecked(output, 0, output.len()) }
}
#[inline]
fn read_exactly(&mut self, output: &mut [Self::Item]) -> Result<()> {
if self.read_fully(output)? == output.len() {
Ok(())
} else {
Err(Error::new(
ErrorKind::UnexpectedEof,
"failed to fill whole input buffer",
))
}
}
}