use std::borrow::BorrowMut;
use std::ops::{Deref, DerefMut};
use futures_lite::{AsyncReadExt, io};
use crate::{Endianness, NativeEndian, Representable};
#[repr(transparent)]
pub struct AsyncReadBytes<'a, R>(&'a mut R)
where
R: AsyncReadExt + Unpin;
impl<R> Deref for AsyncReadBytes<'_, R>
where
R: AsyncReadExt + Unpin,
{
type Target = R;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<R> DerefMut for AsyncReadBytes<'_, R>
where
R: AsyncReadExt + Unpin,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl<'a, R> AsyncReadBytes<'a, R>
where
R: AsyncReadExt + Unpin,
{
#[must_use]
pub const fn new(reader: &'a mut R) -> Self {
Self(reader)
}
pub async fn read_representable<E, Re>(&mut self) -> io::Result<Re>
where
E: Endianness,
Re: Representable,
{
let mut buffer = Re::Representation::default();
self.read_exact(buffer.borrow_mut()).await?;
Ok(E::to_representable(&buffer))
}
#[inline]
pub async fn read_u8(&mut self) -> io::Result<u8> {
self.read_representable::<NativeEndian, u8>().await
}
#[inline]
pub async fn read_i8(&mut self) -> io::Result<i8> {
self.read_representable::<NativeEndian, i8>().await
}
}
macro_rules! impl_async_read_bytes {
($(($num:ty, $read_name:ident, $read_name_ne:ident)),* $(,)?) => {
impl<R> AsyncReadBytes<'_, R> where R: AsyncReadExt + Unpin {
$(
/// # Errors
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
#[inline]
pub async fn $read_name<E: Endianness>(&mut self) -> io::Result<$num> {
self.read_representable::<E, $num>().await
}
#[inline]
pub async fn $read_name_ne(&mut self) -> io::Result<$num> {
self.read_representable::<NativeEndian, $num>().await
}
)*
}
};
}
impl_async_read_bytes!(
(u16, read_u16, read_u16_ne),
(u32, read_u32, read_u32_ne),
(u64, read_u64, read_u64_ne),
(u128, read_u128, read_u128_ne),
(i16, read_i16, read_i16_ne),
(i32, read_i32, read_i32_ne),
(i64, read_i64, read_i64_ne),
(i128, read_i128, read_i128_ne),
(f32, read_f32, read_f32_ne),
(f64, read_f64, read_f64_ne),
);
impl<'a, R> From<&'a mut R> for AsyncReadBytes<'a, R>
where
R: AsyncReadExt + Unpin,
{
fn from(reader: &'a mut R) -> Self {
Self::new(reader)
}
}