Skip to main content

futures_byteorder/
write.rs

1use std::borrow::Borrow;
2use std::ops::{Deref, DerefMut};
3
4use futures_lite::{AsyncWriteExt, io};
5
6use crate::{Endianness, NativeEndian, Representable};
7
8/// Wraps a type that implements [`AsyncWriteExt`] to extend its functionality with methods for
9/// writing 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 AsyncWriteBytes<'a, W>(&'a mut W)
16where
17    W: AsyncWriteExt + Unpin;
18
19impl<W> Deref for AsyncWriteBytes<'_, W>
20where
21    W: AsyncWriteExt + Unpin,
22{
23    type Target = W;
24
25    fn deref(&self) -> &Self::Target {
26        self.0
27    }
28}
29
30impl<W> DerefMut for AsyncWriteBytes<'_, W>
31where
32    W: AsyncWriteExt + Unpin,
33{
34    fn deref_mut(&mut self) -> &mut Self::Target {
35        self.0
36    }
37}
38
39impl<'a, W> AsyncWriteBytes<'a, W>
40where
41    W: AsyncWriteExt + 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(writer: &'a mut W) -> Self {
57        Self(writer)
58    }
59
60    /// # Errors
61    /// This method returns the same errors as [`AsyncWriteExt::write_all`].
62    pub async fn write_representable<E, Re>(&mut self, value: Re) -> io::Result<()>
63    where
64        E: Endianness,
65        Re: Representable,
66    {
67        let buffer = E::from_representable(&value);
68        self.write_all(buffer.borrow()).await
69    }
70
71    /// # Errors
72    /// This method returns the same errors as [`AsyncWriteExt::write_all`].
73    #[inline]
74    pub async fn write_u8(&mut self, value: u8) -> io::Result<()> {
75        self.write_all(&[value]).await
76    }
77
78    /// # Errors
79    /// This method returns the same errors as [`AsyncWriteExt::write_all`].
80    #[inline]
81    pub async fn write_i8(&mut self, value: i8) -> io::Result<()> {
82        self.write_all(&[value.cast_unsigned()]).await
83    }
84}
85
86macro_rules! impl_async_write_bytes {
87     ($(($num:ty, $write_name:ident, $write_name_ne:ident)),* $(,)?) => {
88        impl<W> AsyncWriteBytes<'_, W> where W: AsyncWriteExt + Unpin {
89            $(
90                    /// # Errors
91                    /// This method returns the same errors as [`AsyncWriteExt::write_all`].
92                    #[inline]
93                    pub async fn $write_name<E: Endianness>(&mut self, value: $num) -> io::Result<()> {
94                        self.write_representable::<E, $num>(value).await
95                    }
96
97                    /// # Errors
98                    /// This method returns the same errors as [`AsyncWriteExt::write_all`].
99                    ///
100                    /// Note: This writes using [`NativeEndian`], not `NetworkEndian`!
101                    #[inline]
102                    pub async fn $write_name_ne(&mut self, value: $num) -> io::Result<()> {
103                        self.write_representable::<NativeEndian, $num>(value).await
104                    }
105
106            )*
107        }
108    };
109}
110
111impl_async_write_bytes!(
112    (u16, write_u16, write_u16_ne),
113    (u32, write_u32, write_u32_ne),
114    (u64, write_u64, write_u64_ne),
115    (u128, write_u128, write_u128_ne),
116    (i16, write_i16, write_i16_ne),
117    (i32, write_i32, write_i32_ne),
118    (i64, write_i64, write_i64_ne),
119    (i128, write_i128, write_i128_ne),
120    (f32, write_f32, write_f32_ne),
121    (f64, write_f64, write_f64_ne),
122);
123
124impl<'a, W> From<&'a mut W> for AsyncWriteBytes<'a, W>
125where
126    W: AsyncWriteExt + Unpin,
127{
128    fn from(writer: &'a mut W) -> Self {
129        Self::new(writer)
130    }
131}