Skip to main content

futures_byteorder/
read.rs

1use std::borrow::BorrowMut;
2use std::ops::{Deref, DerefMut};
3
4use futures_lite::{AsyncReadExt, io};
5
6use crate::{Endianness, NativeEndian, Representable};
7
8/// Wraps a type that implements [`AsyncReadExt`] to extend its functionality with methods for
9/// reading numbers (for [`futures_lite::io`]).
10///
11/// Note: This is a struct wrapper instead of a trait like in the original `byteorder` crate because
12/// it would require for either extremely painful code or to import the heavy proc-macro crate that
13/// is `async-trait`
14#[repr(transparent)]
15pub struct AsyncReadBytes<'a, R>(&'a mut R)
16where
17    R: AsyncReadExt + Unpin;
18
19impl<R> Deref for AsyncReadBytes<'_, R>
20where
21    R: AsyncReadExt + Unpin,
22{
23    type Target = R;
24
25    fn deref(&self) -> &Self::Target {
26        self.0
27    }
28}
29
30impl<R> DerefMut for AsyncReadBytes<'_, R>
31where
32    R: AsyncReadExt + Unpin,
33{
34    fn deref_mut(&mut self) -> &mut Self::Target {
35        self.0
36    }
37}
38
39impl<'a, R> AsyncReadBytes<'a, R>
40where
41    R: AsyncReadExt + Unpin,
42{
43    /// Creates a new `AsyncReadBytes` wrapper around the given reader.
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use futures_byteorder::AsyncReadBytes;
49    /// use futures_lite::io::Cursor;
50    ///
51    /// let data = vec![0x12, 0x34];
52    /// let mut reader = Cursor::new(data);
53    /// let reader = AsyncReadBytes::new(&mut reader);
54    /// ```
55    #[must_use]
56    pub const fn new(reader: &'a mut R) -> Self {
57        Self(reader)
58    }
59
60    /// # Errors
61    /// This method returns the same errors as [`AsyncReadExt::read_exact`].
62    pub async fn read_representable<E, Re>(&mut self) -> io::Result<Re>
63    where
64        E: Endianness,
65        Re: Representable,
66    {
67        let mut buffer = Re::Representation::default();
68        self.read_exact(buffer.borrow_mut()).await?;
69        Ok(E::to_representable(&buffer))
70    }
71
72    /// # Errors
73    /// This method returns the same errors as [`AsyncReadExt::read_exact`].
74    #[inline]
75    pub async fn read_u8(&mut self) -> io::Result<u8> {
76        self.read_representable::<NativeEndian, u8>().await
77    }
78
79    /// # Errors
80    /// This method returns the same errors as [`AsyncReadExt::read_exact`].
81    #[inline]
82    pub async fn read_i8(&mut self) -> io::Result<i8> {
83        self.read_representable::<NativeEndian, i8>().await
84    }
85}
86
87macro_rules! impl_async_read_bytes {
88    ($(($num:ty, $read_name:ident, $read_name_ne:ident)),* $(,)?) => {
89        impl<R> AsyncReadBytes<'_, R> where R: AsyncReadExt + Unpin {
90            $(
91                /// # Errors
92                /// This method returns the same errors as [`AsyncReadExt::read_exact`].
93                #[inline]
94                pub async fn $read_name<E: Endianness>(&mut self) -> io::Result<$num> {
95                    self.read_representable::<E, $num>().await
96                }
97
98                /// # Errors
99                /// This method returns the same errors as [`AsyncReadExt::read_exact`].
100                #[inline]
101                pub async fn $read_name_ne(&mut self) -> io::Result<$num> {
102                    self.read_representable::<NativeEndian, $num>().await
103                }
104            )*
105        }
106    };
107}
108
109impl_async_read_bytes!(
110    (u16, read_u16, read_u16_ne),
111    (u32, read_u32, read_u32_ne),
112    (u64, read_u64, read_u64_ne),
113    (u128, read_u128, read_u128_ne),
114    (i16, read_i16, read_i16_ne),
115    (i32, read_i32, read_i32_ne),
116    (i64, read_i64, read_i64_ne),
117    (i128, read_i128, read_i128_ne),
118    (f32, read_f32, read_f32_ne),
119    (f64, read_f64, read_f64_ne),
120);
121
122impl<'a, R> From<&'a mut R> for AsyncReadBytes<'a, R>
123where
124    R: AsyncReadExt + Unpin,
125{
126    fn from(reader: &'a mut R) -> Self {
127        Self::new(reader)
128    }
129}