use std::io;
use std::io::{ErrorKind, Read};
macro_rules! from_reader_impl {
($($t:ty),*) => {
$(
impl FromReader for $t {
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
let mut buf = [0; std::mem::size_of::<$t>()];
r.read_exact(&mut buf).map(|_| <$t>::from_le_bytes(buf))
}
}
)*
};
}
#[derive(Default)]
pub struct PaddedReader {
padding: usize,
}
impl PaddedReader {
pub fn reads_then_set_padding<T, R>(&mut self, r: &mut R, new_padding: usize) -> io::Result<T>
where
T: FromReader,
R: Read,
{
let data = self.reads(r)?;
self.padding = new_padding;
Ok(data)
}
pub fn reads<T, R>(&self, r: &mut R) -> io::Result<T>
where
T: FromReader,
R: Read,
{
let mut temp = vec![0; self.padding];
r.read_exact(&mut temp)?;
r.reads()
}
pub fn set_padding(&mut self, padding: usize) -> &mut Self {
self.padding = padding;
self
}
pub const fn with_padding(padding: usize) -> Self {
Self { padding }
}
pub const fn padding(&self) -> usize {
self.padding
}
}
pub trait FromReader: Sized {
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read;
}
from_reader_impl!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64, usize);
impl FromReader for bool {
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
r.reads::<u8>().map(|x| x != 0)
}
}
impl FromReader for char {
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
r.reads::<u32>().and_then(|c| {
char::from_u32(c)
.ok_or_else(|| io::Error::new(ErrorKind::InvalidData, "Not a character"))
})
}
}
impl FromReader for String {
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
let mut buf = Vec::new();
loop {
let b = r.reads::<u8>()?;
if b == 0 {
break String::from_utf8(buf)
.map_err(|_| io::Error::new(ErrorKind::InvalidData, "Invalid UTF-8"));
}
buf.push(b);
}
}
}
impl<T> FromReader for Option<T>
where
T: FromReader,
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
if r.reads::<bool>()? {
return Ok(Some(r.reads()?));
}
Ok(None)
}
}
#[cfg(feature = "dyn_impl")]
impl<T> FromReader for Vec<T>
where
T: FromReader,
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
let len = r.reads::<u32>()? as usize;
let mut buf = Vec::with_capacity(len);
for _ in 0..len {
buf.push(r.reads()?);
}
Ok(buf)
}
}
impl<T, const N: usize> FromReader for [T; N]
where
T: FromReader + Copy + Default,
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
let mut arr = [T::default(); N];
for value in arr.iter_mut() {
*value = r.reads()?;
}
Ok(arr)
}
}
impl<T, E> FromReader for Result<T, E>
where
T: FromReader,
E: FromReader,
{
fn from_reader<R>(r: &mut R) -> io::Result<Result<T, E>>
where
R: Read,
{
if r.reads()? {
return Ok(Err(r.reads()?));
}
Ok(Ok(r.reads()?))
}
}
impl FromReader for () {
fn from_reader<R>(_r: &mut R) -> io::Result<Self>
where
R: Read,
{
Ok(())
}
}
impl<T, Z> FromReader for (T, Z)
where
T: FromReader,
Z: FromReader,
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
Ok((r.reads()?, r.reads()?))
}
}
impl<T, Z, H> FromReader for (T, Z, H)
where
T: FromReader,
Z: FromReader,
H: FromReader,
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
Ok((r.reads()?, r.reads()?, r.reads()?))
}
}
impl<T> FromReader for Box<T>
where T: FromReader
{
fn from_reader<R>(r: &mut R) -> io::Result<Self>
where
R: Read,
{
Ok(Box::new(r.reads()?))
}
}
pub trait ToraRead {
fn reads<T>(&mut self) -> io::Result<T>
where
T: FromReader;
}
#[cfg(feature = "read_impl")]
impl<R> ToraRead for R
where
R: Read,
{
fn reads<T>(&mut self) -> io::Result<T>
where
T: FromReader,
{
T::from_reader(self)
}
}