raad/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![warn(
4    clippy::undocumented_unsafe_blocks,
5    clippy::missing_const_for_fn,
6    clippy::missing_safety_doc,
7    clippy::suboptimal_flops,
8    unsafe_op_in_unsafe_fn,
9    clippy::dbg_macro,
10    clippy::use_self,
11    missing_docs
12)]
13#![allow(
14    private_bounds,
15    clippy::zero_prefixed_literal,
16    mixed_script_confusables,
17    confusable_idents
18)]
19use std::mem::ManuallyDrop as MD;
20/// # Safety
21///
22/// this is a transmute. what do you want me to say. the types should, yknow, work? idk.
23const unsafe fn transmute_unchecked<T, U>(value: T) -> U {
24    // SAFETY: transmutation
25    unsafe {
26        #[repr(C)]
27        union Transmute<T, U> {
28            t: MD<T>,
29            u: MD<U>,
30        }
31        MD::into_inner(Transmute { t: MD::new(value) }.u)
32    }
33}
34
35macro_rules! trt {
36    (r $(#[doc = $x: expr])+ f $(#[doc = $z: expr])+ w $(#[doc = $y: expr])+) => {
37        use std::io::prelude::*;
38        use std::io::Result;
39        use std::mem::MaybeUninit as MU;
40
41        $(#[doc = $x])+
42        pub trait R: Read {
43            $(#[doc = $z])+
44            fn r<T: Readable>(&mut self) -> Result<T>;
45            /// Reads one byte out of a [`Reader`](Read).
46            /// ```
47            /// use raad::ne::*;
48            /// let mut d = &mut &[1u8, 2][..];
49            /// assert_eq!(d.b().unwrap(), 1);
50            /// assert_eq!(d.b().unwrap(), 2);
51            /// assert!(d.b().is_err());
52            /// ```
53            fn b(&mut self) -> Result<u8> {
54                self.r::<u8>()
55            }
56        }
57
58        #[doc(hidden)]
59        impl<D: Read> R for D {
60            fn r<T: Readable>(&mut self) -> Result<T> {
61                T::r(self)
62            }
63        }
64        #[diagnostic::on_unimplemented(
65            message = "this type is not suitable for reading into",
66            note = "read to [u8; N] first and then parse it",
67            label = "unreadable type"
68        )]
69        trait Readable
70        where
71            Self: Sized,
72        {
73            fn r(from: &mut impl Read) -> Result<Self>;
74        }
75
76        impl<const N: usize> Readable for [u8; N] {
77            fn r(from: &mut impl Read) -> Result<[u8; N]> {
78                let mut buf = [0; N];
79                from.read_exact(&mut buf).map(|()| buf)
80            }
81        }
82
83        impl<const N: usize> Writable for &[u8; N] {
84            fn _w(self, to: &mut impl Write) -> Result<()> {
85                to.w(&self[..])
86            }
87        }
88
89        $(#[doc = $y])+
90        pub trait W: Write {
91            /// Writes a type to a [`Writer`](Write)
92            fn w<T: Writable>(&mut self, data: T) -> Result<()>;
93        }
94
95        #[doc(hidden)]
96        impl<D: Write> W for D {
97            fn w<T: Writable>(&mut self, data: T) -> Result<()> {
98                data._w(self)
99            }
100        }
101        #[diagnostic::on_unimplemented(
102            message = "this type is not suitable for writing",
103            note = "turn it into a &[u8] first and then write that",
104            label = "unwritable type",
105        )]
106        trait Writable {
107            fn _w(self, to: &mut impl Write) -> Result<()>;
108        }
109
110        impl Writable for &[u8] {
111            fn _w(self, to: &mut impl Write) -> Result<()> {
112                to.write_all(self)
113            }
114        }
115    };
116}
117
118macro_rules! n {
119    (writes $bytes:ident $($n:ident)+) => {
120        $(
121            impl<const N: usize> Writable for &[$n; N] {
122                fn _w(self, to: &mut impl Write) -> Result<()> {
123                    to.w(&self[..])
124                }
125            }
126
127            impl Writable for &[$n] {
128                fn _w(self, to: &mut impl Write) -> Result<()> {
129                    if (cfg!(target_endian = "little") && stringify!($bytes) == "le") || (cfg!(target_endian = "big") && stringify!($bytes) == "be") {
130                        // SAFETY: len correct
131                        to.w(unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * ($n::BITS / 8) as usize) })
132                    } else {
133                        self.iter().try_for_each(|x| to.w(x))
134                    }
135                }
136            }
137            impl<const N: usize> Readable for [$n; N] {
138                fn r(from: &mut impl Read) -> Result<[$n; N]> {
139                    if (cfg!(target_endian = "little") && stringify!($bytes) == "le") || (cfg!(target_endian = "big") && stringify!($bytes) == "be") {
140                        let mut buf = [0; N];
141                        // SAFETY: len matches
142                        let mut u8s = unsafe { std::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, N * ($n::BITS / 8) as usize) };
143                        from.read_exact(&mut u8s).map(|()| buf)
144                    } else {
145                        let mut buf = [MU::<$n>::uninit(); N];
146                        for elem in &mut buf{
147                            elem.write(from.r::<$n>()?);
148                        }
149                        // SAFETY: array init
150                        Ok(unsafe { crate::transmute_unchecked(buf) })
151                    }
152                }
153            }
154        )+
155    };
156    (float $bytes:ident $([$n:ident <=> $int:ident])+) => {
157        $(
158        impl Readable for $n {
159            fn r(from: &mut impl Read) -> Result<$n> {
160                from.r::<$int>().map($n::from_bits)
161            }
162        }
163        )+
164
165        $(
166        impl Writable for $n {
167            fn _w(self, to: &mut impl Write) -> Result<()> {
168                to.w(self.to_bits())
169            }
170        }
171        impl Writable for &$n {
172            fn _w(self, to: &mut impl Write) -> Result<()> {
173                to.w(self.to_bits())
174            }
175        }
176        macro_rules! bytes {
177            ($t:ty) => {
178                impl Writable for $t {
179                    fn _w(self, to: &mut impl Write) -> Result<()> {
180                        to.w(&*self)
181                    }
182                }
183            }
184        }
185        bytes![Vec<$n>];
186        bytes![Box<[$n]>];
187        impl<const N: usize> Writable for [$n; N] {
188            fn _w(self, to: &mut impl Write) -> Result<()> {
189                to.w(&self[..])
190            }
191        }
192
193        impl<const N: usize> Writable for &[$n; N] {
194            fn _w(self, to: &mut impl Write) -> Result<()> {
195                to.w(&self[..])
196            }
197        }
198
199        impl Writable for &[$n] {
200            fn _w(self, to: &mut impl Write) -> Result<()> {
201                if (cfg!(target_endian = "little") && stringify!($bytes) == "le") || (cfg!(target_endian = "big") && stringify!($bytes) == "be") {
202                    // SAFETY: len correct
203                    to.w(unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * ($int::BITS / 8) as usize) })
204                } else {
205                    self.iter().try_for_each(|x| to.w(x))
206                }
207            }
208        }
209        impl<const N: usize> Readable for [$n; N] {
210            fn r(from: &mut impl Read) -> Result<[$n; N]> {
211                if (cfg!(target_endian = "little") && stringify!($bytes) == "le") || (cfg!(target_endian = "big") && stringify!($bytes) == "be") {
212                    let mut buf = [0.; N];
213                    // SAFETY: len matches
214                    let mut u8s = unsafe { std::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, N * ($int::BITS / 8) as usize) };
215                    from.read_exact(&mut u8s).map(|()| buf)
216                } else {
217                    let mut buf = [MU::<$n>::uninit(); N];
218                    for elem in &mut buf{
219                        elem.write(from.r::<$n>()?);
220                    }
221                    // SAFETY: array init
222                    Ok(unsafe { crate::transmute_unchecked(buf) })
223                }
224            }
225        }
226        )+
227    };
228    ($bytes:ident $($n:ident)+) => {
229        $(
230        impl Readable for $n {
231            fn r(from: &mut impl Read) -> Result<$n> {
232                from.r::<[u8; { std::mem::size_of::<$n>() }]>().map($n::from_ne_bytes).map($n::$bytes)
233            }
234        }
235        )+
236
237        $(
238        impl Writable for $n {
239            fn _w(self, to: &mut impl Write) -> Result<()> {
240                to.w(self.$bytes().to_ne_bytes())
241            }
242        }
243        impl Writable for &$n {
244            fn _w(self, to: &mut impl Write) -> Result<()> {
245                to.w(self.$bytes().to_ne_bytes())
246            }
247        }
248        macro_rules! bytes {
249            ($t:ty) => {
250                impl Writable for $t {
251                    fn _w(self, to: &mut impl Write) -> Result<()> {
252                        to.w(&*self)
253                    }
254                }
255            }
256        }
257        bytes![Vec<$n>];
258        bytes![Box<[$n]>];
259        impl<const N: usize> Writable for [$n; N] {
260            fn _w(self, to: &mut impl Write) -> Result<()> {
261                to.w(&self[..])
262            }
263        }
264        )+
265    };
266}
267
268macro_rules! test {
269    () => {
270        #[test]
271        fn x() {
272            let data = &mut &[0x12u8, 0x15][..];
273            let mut out = vec![];
274            out.w(data.r::<[u16; 1]>().unwrap()).unwrap();
275            assert_eq!(out, [0x12, 0x15]);
276
277            let mut out = vec![];
278            out.w([12.0_f32, 13.]).unwrap();
279            assert_eq!((&mut &*out).r::<[f32; 2]>().unwrap(), [12., 13.]);
280        }
281    };
282}
283pub mod le {
284    //! little endian readers and writers
285    trt!(
286        r /// Read little endian (commonly native) data.
287          /// This trait provides a [`r`](R::r) method for easy reading.
288          ///
289          /// Without this crate, you would have to do things such as:
290          /// ```
291          /// use std::io::Read;
292          /// let mut data = &mut &[0xff, 0xf1][..];
293          /// let mut two_bytes = [0; 2];
294          /// data.read(&mut two_bytes).unwrap();
295          /// assert_eq!(u16::from_le_bytes(two_bytes), 0xf1ff)
296          /// ```
297          /// Now, you can simply:
298          /// ```
299          /// use raad::le::*;
300          /// let mut data = &mut &[0xff, 0xf1][..];
301          /// assert_eq!(data.r::<u16>().unwrap(), 0xf1ff);
302          /// ```
303        f /// Read a little endian type.
304          /// ```
305          /// # #![allow(overflowing_literals)]
306          /// use raad::le::*;
307          /// let mut data = &mut &[0xc1, 0x00, 0x7c, 0xff][..];
308          /// assert_eq!(data.r::<[i16; 2]>().unwrap(), [0x00c1, 0xff7c]);
309          /// ```
310        w /// Write little endian (commonly native) data.
311          /// ```
312          /// # use raad::le::*;
313          /// let mut wtr = Vec::new();
314          /// wtr.w::<[u32; 2]>([267, 1205419366]).unwrap();
315          /// assert_eq!(wtr, [11, 1, 0, 0, 102, 61, 217, 71]);
316          /// ```
317    );
318    n![writes le u16 u32 u64 u128 i8 i16 i32 i64 i128];
319    n![float le [f32 <=> u32] [f64 <=> u64]];
320    n![to_le u8 u16 u32 u64 u128 i8 i16 i32 i64 i128];
321    test![];
322}
323
324#[doc(alias = "network")]
325pub mod be {
326    //! big endian readers and writers
327    trt!(
328        r /// Read big endian (network) data.
329          /// ```
330          /// use raad::be::*;
331          /// // this example doesnt actually care about endianness-- u8's dont have any.
332          /// let mut data = &mut &[2u8, 5, 1, 4, 3][..];
333          /// assert_eq!(data.r::<[u8; 5]>().unwrap(), [2, 5, 1, 4, 3]);
334          /// ```
335        f /// Read a big endian (network) type.
336          /// ```
337          /// use raad::be::*;
338          /// let mut data: &mut &[u8] = &mut &[
339          ///     0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
340          ///     0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
341          /// ][..];
342          /// assert_eq!(
343          ///     data.r::<u128>().unwrap(),
344          ///     16947640962301618749969007319746179
345          /// );
346          /// ```
347        w /// Write a big endian (network) type.
348          /// ```
349          /// use raad::be::*;
350          /// let mut wtr = Vec::new();
351          /// wtr.w::<[u16; 2]>([517, 768]).unwrap();
352          /// assert_eq!(wtr, b"\x02\x05\x03\x00");
353          /// ```
354    );
355    n![writes be u16 u32 u64 u128 i8 i16 i32 i64 i128];
356    n![float be [f32 <=> u32] [f64 <=> u64]];
357    n![to_be u8 u16 u32 u64 u128 i8 i16 i32 i64 i128];
358    test![];
359}
360
361pub mod ne {
362    //! native endian readers and writers
363    #[cfg(target_endian = "big")]
364    #[doc(inline)]
365    pub use super::be::{R, W};
366    #[cfg(target_endian = "little")]
367    #[doc(inline)]
368    pub use super::le::{R, W};
369}