use std::io::{
Error,
ErrorKind,
Result,
};
use crate::Output;
use crate::util::UncheckedSlice;
pub trait OutputExt: Output {
#[inline(always)]
fn write_all(&mut self, input: &[Self::Item]) -> Result<()> {
unsafe { self.write_all_unchecked(input, 0, input.len()) }
}
unsafe fn write_all_unchecked(
&mut self,
input: &[Self::Item],
index: usize,
count: usize,
) -> Result<()> {
debug_assert!(
UncheckedSlice::range_fits(input.len(), index, count),
"unchecked write-all range exceeds input buffer"
);
let mut written = 0;
while written < count {
let remaining = count - written;
match unsafe {
self.write_unchecked(input, index + written, remaining)
} {
Ok(0) => {
return Err(Error::new(
ErrorKind::WriteZero,
"failed to write whole output range",
));
}
Ok(progress) => {
if progress > remaining {
return Err(Error::new(
ErrorKind::InvalidData,
format!(
"writer reported {progress} items for a {remaining}-item range"
),
));
}
written += progress;
}
Err(error) if error.kind() == ErrorKind::Interrupted => {}
Err(error) => return Err(error),
}
}
Ok(())
}
}
impl<T> OutputExt for T where T: Output + ?Sized {}