use crate::Result;
#[cfg(not(feature = "std"))]
use crate::{Error, ErrorKind, SeekFrom};
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
pub use std::io::Read;
pub use std::io::Write;
pub use std::io::Seek;
} else {
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
let mut total_read = 0;
while total_read < buf.len() {
match self.read(&mut buf[total_read..]) {
Ok(0) => return Err(Error::from_kind(ErrorKind::UnexpectedEof)),
Ok(n) => total_read += n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
Ok(())
}
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize>;
fn flush(&mut self) -> Result<()>;
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
let mut written = 0;
while written < buf.len() {
match self.write(&buf[written..]) {
Ok(0) => return Err(Error::from_kind(ErrorKind::WriteZero)),
Ok(n) => written += n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
Ok(())
}
}
pub trait Seek {
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0))
}
fn seek_relative(&mut self, offset: i64) -> Result<()> {
self.seek(SeekFrom::Current(offset))?;
Ok(())
}
}
}
}
pub trait ReadExt {
fn read_struct<T: bytemuck::Zeroable + bytemuck::NoUninit + bytemuck::AnyBitPattern>(
&mut self,
) -> Result<T>;
fn parse<T: Parsable>(&mut self) -> Result<T>;
}
impl<T: Read> ReadExt for T {
fn read_struct<S: bytemuck::Zeroable + bytemuck::NoUninit + bytemuck::AnyBitPattern>(
&mut self,
) -> Result<S> {
let mut temp = S::zeroed();
self.read_exact(bytemuck::bytes_of_mut(&mut temp))?;
Ok(temp)
}
fn parse<S: Parsable>(&mut self) -> Result<S> {
S::parse(self)
}
}
pub trait Parsable: Sized {
fn parse<R: Read>(reader: &mut R) -> Result<Self>;
}
pub trait Writable: Sized {
fn write<W: Write>(&self, writer: &mut W) -> Result<()>;
}