1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::*;

impl Encoder for bool {
    #[inline]
    fn encoder(self, c: &mut Cursor<impl Bytes>) {
        u8::encoder(self.into(), c);
    }
}
impl<E: Error> Decoder<'_, E> for bool {
    #[inline]
    fn decoder(c: &mut Cursor<&[u8]>) -> Result<Self, E> {
        u8::decoder(c).map(|b| b != 0)
    }
}

impl Encoder for char {
    #[inline]
    fn encoder(self, c: &mut Cursor<impl Bytes>) {
        u32::encoder(self.into(), c);
    }
}
impl<E: Error> Decoder<'_, E> for char {
    #[inline]
    fn decoder(c: &mut Cursor<&[u8]>) -> Result<Self, E> {
        char::from_u32(u32::decoder(c)?).ok_or_else(E::invalid_data)
    }
}

macro_rules! impl_data_type_for {
    [$($rty:ty)*] => ($(
        impl Encoder for $rty {
            // const IS_DYNAMIC: bool = false;
            #[inline]
            fn encoder(self, c: &mut Cursor<impl Bytes>) {
                unsafe {
                    let data = c.data.as_mut();
                    let dst = data.as_mut_ptr().add(c.offset);

                    let total_len = c.offset + size_of::<Self>();
                    if total_len > c.data.as_ref().len() {
                        c.data.reserve(size_of::<Self>());
                        #[allow(clippy::uninit_vec)]
                        c.data.set_len(total_len);
                    }
                    c.offset = total_len;
                    write_num!(self, dst);
                }
            }
        }
        impl<E: Error> Decoder<'_, E> for $rty {
            #[inline]
            fn decoder(c: &mut Cursor<&[u8]>) -> Result<Self, E> {
                unsafe {
                    let total_len = c.offset + size_of::<Self>();
                    if total_len > c.data.len() { return Err(E::insufficient_bytes()); }

                    let src = c.data.as_ptr().add(c.offset);
                    c.offset = total_len;
                    read_num!(src);
                };
            }
        }
    )*);
}
macro_rules! read_num {
    [$src: expr] => {
        #[cfg(all(target_endian = "big", not(any(feature = "BE", feature = "NE"))))]
        return Ok(Self::from_le_bytes(read_unaligned($src)));
        #[cfg(all(target_endian = "little", feature = "BE"))]
        return Ok(Self::from_be_bytes(read_unaligned($src)));
        #[cfg(any(
            feature = "NE",
            all(target_endian = "big", feature = "BE"),
            all(target_endian = "little", not(any(feature = "BE", feature = "NE"))),
        ))]
        return Ok(read_unaligned($src));
    };
}
macro_rules! write_num {
    [$val:tt, $dst: expr] => (
        #[cfg(all(target_endian = "big", not(any(feature = "BE", feature = "NE"))))]
        write_unaligned($val.to_le_bytes().as_ptr() , $dst, size_of::<Self>());
        #[cfg(all(target_endian = "little", feature = "BE"))]
        write_unaligned($val.to_be_bytes().as_ptr() , $dst, size_of::<Self>());
        #[cfg(any(
            feature = "NE",
            all(target_endian = "big", feature = "BE"),
            all(target_endian = "little", not(any(feature = "BE", feature = "NE"))),
        ))]
        write_unaligned(&$val as *const Self as *const u8, $dst, size_of::<Self>());
    )
}
impl_data_type_for!(
    u8 u16 u32 u64 u128
    i8 i16 i32 i64 i128
    usize isize
    f32 f64
);

//---------------------------------------------------------------------------------

unsafe fn read_unaligned<T>(src: *const u8) -> T {
    let mut tmp = MaybeUninit::<T>::uninit();
    ptr::copy_nonoverlapping(src, tmp.as_mut_ptr() as *mut u8, size_of::<T>());
    tmp.assume_init()
}
unsafe fn write_unaligned(src: *const u8, dst: *mut u8, count: usize) {
    ptr::copy_nonoverlapping(src, dst, count);
}