userspace/macros/structs/
default.rs

1#[macro_export]
2macro_rules! r#struct {
3    ($vis:vis $struct_identifier:ident {$($field_visibility:vis $field_identifier:ident: $field_type:ty),*$(,)?}) => {
4
5        // #[repr(C,packed)]
6        #[derive(Debug, Clone, Copy)]
7        $vis struct $struct_identifier {
8            $($field_visibility $field_identifier: $field_type),*
9        }
10
11        impl $crate::traits::Bytes<crate::Origin,crate::Origin> for $struct_identifier {
12            const BYTES_SIZE : usize = $(<$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE +)* 0;
13
14            fn to_bytes(&self, endianness: bool) -> [u8; Self::BYTES_SIZE] {
15                let mut b = [0u8; Self::BYTES_SIZE];
16                let mut o = 0;
17                $(
18                    b[o..(o+<$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE)].copy_from_slice(
19                        &if endianness {
20                            <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::to_le_bytes(&self.$field_identifier)
21                        } else {
22                            <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::to_be_bytes(&self.$field_identifier)
23                        }
24                    );
25                    o = o + <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
26                )*
27                b
28            }
29
30            fn from_bytes(bytes : [u8; Self::BYTES_SIZE], endianness: bool) -> Self {
31                let mut o = 0;
32                $(
33                    let mut field_bytes = [0u8; <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE];
34                    field_bytes.copy_from_slice(&bytes[o..(o+<$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE)]);
35                    let $field_identifier = if endianness {
36                        <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_le_bytes(field_bytes)
37                    } else {
38                        <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_be_bytes(field_bytes)
39                    };
40                    o = o + <$field_type as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
41                )*
42                Self {
43                    $($field_identifier,)*
44                }
45            }
46        }
47
48        type OptionDiscriminant = u8;
49        impl $crate::traits::Bytes<crate::Origin,crate::Origin> for Option<$struct_identifier> {
50            const BYTES_SIZE: usize = <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE + <$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
51            fn from_bytes(bytes: [u8; Self::BYTES_SIZE], endianness: bool) -> Self {
52                let mut option_bytes = [0u8; <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE];
53                let mut o = 0;
54                let mut l = <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
55                option_bytes.copy_from_slice(&bytes[o..l]);
56                let option = if endianness {
57                    <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_le_bytes(option_bytes)
58                } else {
59                    <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_be_bytes(option_bytes)
60                };
61                if option == 0 {
62                    None
63                } else {
64                    o = l;
65                    l = l + <$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
66                    let mut value_bytes = [0u8; <$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE];
67                    value_bytes.copy_from_slice(&bytes[o..l]);
68                    if endianness {
69                        Some(<$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_le_bytes(value_bytes))
70                    } else {
71                        Some(<$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::from_be_bytes(value_bytes))
72                    }
73                }
74            }
75
76            fn to_bytes(&self, endianness: bool) -> [u8; Self::BYTES_SIZE] {
77                let mut bytes = [0u8; Self::BYTES_SIZE];
78                if let Some(v) = self {
79                    let mut o = 0;
80                    let mut l = <OptionDiscriminant as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
81                    bytes[o..l].copy_from_slice(&(1 as OptionDiscriminant).to_le_bytes());
82                    o = l;
83                    l = l + <$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::BYTES_SIZE;
84                    if endianness {
85                        bytes[o..l].copy_from_slice(&<$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::to_le_bytes(v));
86                    } else {
87                        bytes[o..l].copy_from_slice(&<$struct_identifier as $crate::traits::Bytes<crate::Origin,crate::Origin>>::to_be_bytes(v));
88                    }
89                    bytes
90                } else {
91                    bytes
92                }
93            }
94        }
95    }
96}
97pub use r#struct;