use crate::{ErrorKind, Result, SeekFrom};
pub trait Read {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
async 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..]).await {
Ok(0) => return Err(ErrorKind::UnexpectedEof.into()),
Ok(n) => total_read += n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
Ok(())
}
}
pub trait Write {
async fn write(&mut self, buf: &[u8]) -> Result<usize>;
async fn flush(&mut self) -> Result<()>;
async fn write_all(&mut self, buf: &[u8]) -> Result<()> {
let mut written = 0;
while written < buf.len() {
match self.write(&buf[written..]).await {
Ok(0) => return Err(ErrorKind::WriteZero.into()),
Ok(n) => written += n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
}
}
Ok(())
}
}
pub trait Seek {
async fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
async fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0)).await
}
async fn seek_relative(&mut self, offset: i64) -> Result<()> {
self.seek(SeekFrom::Current(offset)).await?;
Ok(())
}
}
impl<T: Read> Read for &mut T {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
T::read(self, buf).await
}
async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
T::read_exact(self, buf).await
}
}
impl<T: Write> Write for &mut T {
async fn write(&mut self, buf: &[u8]) -> Result<usize> {
T::write(self, buf).await
}
async fn flush(&mut self) -> Result<()> {
T::flush(self).await
}
async fn write_all(&mut self, buf: &[u8]) -> Result<()> {
T::write_all(self, buf).await
}
}
impl<T: Seek> Seek for &mut T {
async fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
T::seek(self, pos).await
}
async fn stream_position(&mut self) -> Result<u64> {
T::stream_position(self).await
}
async fn seek_relative(&mut self, offset: i64) -> Result<()> {
T::seek_relative(self, offset).await
}
}
pub trait ReadExt {
async fn read_struct<T: bytemuck::Zeroable + bytemuck::NoUninit + bytemuck::AnyBitPattern>(
&mut self,
) -> Result<T>;
async fn parse<T: Parsable>(&mut self) -> Result<T>;
}
impl<T: Read> ReadExt for T {
async 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)).await?;
Ok(temp)
}
async fn parse<S: Parsable>(&mut self) -> Result<S> {
S::parse(self).await
}
}
pub trait Parsable: Sized {
async fn parse<R: Read>(reader: &mut R) -> Result<Self>;
}
pub trait Writable: Sized {
async fn write<W: Write>(&self, writer: &mut W) -> Result<()>;
}