use std::io::{self, Read, Result};
use encoding_rs::Encoding;
use zerocopy::{ByteOrder, FromBytes, I16, I32, I64, LE, LittleEndian, U16, U32, U64};
use crate::string::PascalString;
pub trait ReadBytesExt: Read {
#[inline]
fn read_t<T: FromBytes>(&mut self) -> Result<T> {
T::read_from_io(self)
}
#[inline]
fn read_u8(&mut self) -> Result<u8> {
u8::read_from_io(self)
}
#[inline]
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
U16::<T>::read_from_io(self).map(U16::get)
}
#[inline]
fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
I16::<T>::read_from_io(self).map(I16::get)
}
#[inline]
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
U32::<T>::read_from_io(self).map(U32::get)
}
#[inline]
fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
I32::<T>::read_from_io(self).map(I32::get)
}
#[inline]
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
U64::<T>::read_from_io(self).map(U64::get)
}
#[inline]
fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
I64::<T>::read_from_io(self).map(I64::get)
}
#[inline]
fn read_pascal_string(&mut self) -> Result<Option<PascalString>> {
PascalString::read(self)
}
fn read_decoded_pascal_string(
&mut self,
codepage: &'static Encoding,
) -> Result<Option<String>> {
Ok(self
.read_pascal_string()?
.map(|pascal_string| pascal_string.decoded(codepage).into_string()))
}
fn read_sized_decoded_pascal_string(
&mut self,
size: u32,
codepage: &'static Encoding,
) -> Result<Option<String>> {
Ok(PascalString::read_sized_decoded(self, size, codepage)?.map(PascalString::into_string))
}
fn read_raw_pascal_string(&mut self) -> Result<Vec<u8>> {
let length = self.read_u32::<LittleEndian>()?;
let mut buffer = vec![0; length as usize];
self.read_exact(&mut buffer)?;
Ok(buffer)
}
fn discard_pascal_string(&mut self) -> Result<()> {
let length = self.read_u32::<LE>()?;
io::copy(&mut self.take(length.into()), &mut io::sink())?;
Ok(())
}
}
impl<R: Read + ?Sized> ReadBytesExt for R {}