data_view/
endian.rs

1#![allow(clippy::missing_safety_doc)]
2
3use super::*;
4use core::fmt::Debug;
5
6/// This trait contains unsafe methods for efficiently reading and writing data.
7///
8/// Those Methods are unsafe because they do not check the index bounds.
9///
10/// And safely used by internal. And shouldn't expect to be used by user.
11pub trait Endian: Copy + Default + Debug + PartialEq + PartialOrd + Sized + Send + Sync + Unpin {
12    unsafe fn __write_at__(self, dst: *mut u8);
13    unsafe fn __read_at__(src: *const u8) -> Self;
14}
15
16macro_rules! impl_endian_for {
17    [$($rty:ty)*] => ($(
18        // impl Endian for $rty {}
19        impl Endian for $rty {
20            unsafe fn __write_at__(self, dst: *mut u8) {
21                #[cfg(all(target_endian = "big", not(any(feature = "BE", feature = "NE"))))]
22                return write_unaligned(self.to_le_bytes().as_ptr(), dst, size_of::<$rty>());
23                #[cfg(all(target_endian = "little", feature = "BE"))]
24                return write_unaligned(self.to_be_bytes().as_ptr(), dst, size_of::<$rty>());
25                #[cfg(any(
26                    feature = "NE",
27                    all(target_endian = "big", feature = "BE"),
28                    all(target_endian = "little", not(any(feature = "BE", feature = "NE"))),
29                ))]
30                return write_unaligned(&self as *const Self as *const u8, dst, size_of::<$rty>());
31            }
32            unsafe fn __read_at__(src: *const u8) -> Self {
33                #[cfg(all(target_endian = "big", not(any(feature = "BE", feature = "NE"))))]
34                return Self::from_le_bytes(read_unaligned(src));
35                #[cfg(all(target_endian = "little", feature = "BE"))]
36                return Self::from_be_bytes(read_unaligned(src));
37                #[cfg(any(
38                    feature = "NE",
39                    all(target_endian = "big", feature = "BE"),
40                    all(target_endian = "little", not(any(feature = "BE", feature = "NE"))),
41                ))]
42                return read_unaligned(src);
43            }
44        }
45    )*);
46}
47
48impl_endian_for!(
49    u8 u16 u32 u64 u128
50    i8 i16 i32 i64 i128
51    usize isize
52    f32 f64
53);
54
55unsafe fn read_unaligned<T>(src: *const u8) -> T {
56    let mut tmp = core::mem::MaybeUninit::<T>::uninit();
57    ptr::copy_nonoverlapping(src, tmp.as_mut_ptr() as *mut u8, size_of::<T>());
58    tmp.assume_init()
59}
60unsafe fn write_unaligned(src: *const u8, dst: *mut u8, count: usize) {
61    ptr::copy_nonoverlapping(src, dst, count);
62}