use super::error::IoError;
pub trait IoBase {
type Error: IoError;
}
pub trait Read: IoBase {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Self::Error> {
while !buf.is_empty() {
match self.read(buf) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.is_interrupted() => {}
Err(e) => return Err(e),
}
}
if buf.is_empty() {
Ok(())
} else {
debug!("failed to fill whole buffer in read_exact");
Err(Self::Error::new_unexpected_eof_error())
}
}
}
pub trait Write: IoBase {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Self::Error> {
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => {
debug!("failed to write whole buffer in write_all");
return Err(Self::Error::new_write_zero_error());
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.is_interrupted() => {}
Err(e) => return Err(e),
}
}
Ok(())
}
fn flush(&mut self) -> Result<(), Self::Error>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
pub trait Seek: IoBase {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error>;
}
impl From<SeekFrom> for std::io::SeekFrom {
fn from(from: SeekFrom) -> Self {
match from {
SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
SeekFrom::End(n) => std::io::SeekFrom::End(n),
SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
}
}
}
impl From<std::io::SeekFrom> for SeekFrom {
fn from(from: std::io::SeekFrom) -> Self {
match from {
std::io::SeekFrom::Start(n) => SeekFrom::Start(n),
std::io::SeekFrom::End(n) => SeekFrom::End(n),
std::io::SeekFrom::Current(n) => SeekFrom::Current(n),
}
}
}
pub struct StdIoWrapper<T> {
inner: T,
}
impl<T> StdIoWrapper<T> {
pub fn new(inner: T) -> Self {
Self { inner }
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T> IoBase for StdIoWrapper<T> {
type Error = std::io::Error;
}
impl<T: std::io::Read> Read for StdIoWrapper<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.inner.read(buf)
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.inner.read_exact(buf)
}
}
impl<T: std::io::Write> Write for StdIoWrapper<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.inner.write(buf)
}
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
self.inner.write_all(buf)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.inner.flush()
}
}
impl<T: std::io::Seek> Seek for StdIoWrapper<T> {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
self.inner.seek(pos.into())
}
}
impl<T> From<T> for StdIoWrapper<T> {
fn from(from: T) -> Self {
Self::new(from)
}
}
pub(super) trait ReadLeExt {
type Error;
fn read_u8(&mut self) -> Result<u8, Self::Error>;
fn read_u16_le(&mut self) -> Result<u16, Self::Error>;
fn read_u32_le(&mut self) -> Result<u32, Self::Error>;
}
impl<T: Read> ReadLeExt for T {
type Error = <Self as IoBase>::Error;
fn read_u8(&mut self) -> Result<u8, Self::Error> {
let mut buf = [0_u8; 1];
self.read_exact(&mut buf)?;
Ok(buf[0])
}
fn read_u16_le(&mut self) -> Result<u16, Self::Error> {
let mut buf = [0_u8; 2];
self.read_exact(&mut buf)?;
Ok(u16::from_le_bytes(buf))
}
fn read_u32_le(&mut self) -> Result<u32, Self::Error> {
let mut buf = [0_u8; 4];
self.read_exact(&mut buf)?;
Ok(u32::from_le_bytes(buf))
}
}
pub(super) trait WriteLeExt {
type Error;
fn write_u8(&mut self, n: u8) -> Result<(), Self::Error>;
fn write_u16_le(&mut self, n: u16) -> Result<(), Self::Error>;
fn write_u32_le(&mut self, n: u32) -> Result<(), Self::Error>;
}
impl<T: Write> WriteLeExt for T {
type Error = <Self as IoBase>::Error;
fn write_u8(&mut self, n: u8) -> Result<(), Self::Error> {
self.write_all(&[n])
}
fn write_u16_le(&mut self, n: u16) -> Result<(), Self::Error> {
self.write_all(&n.to_le_bytes())
}
fn write_u32_le(&mut self, n: u32) -> Result<(), Self::Error> {
self.write_all(&n.to_le_bytes())
}
}