1#![allow(clippy::missing_safety_doc)]
2
3use super::*;
4use core::fmt::Debug;
5
6pub 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 {
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}