netlink_packet_utils/
macros.rs

1// SPDX-License-Identifier: MIT
2
3#[macro_export(local_inner_macros)]
4macro_rules! getter {
5    ($buffer: ident, $name:ident, slice, $offset:expr) => {
6        impl<'a, T: AsRef<[u8]> + ?Sized> $buffer<&'a T> {
7            pub fn $name(&self) -> &'a [u8] {
8                &self.buffer.as_ref()[$offset]
9            }
10        }
11    };
12    ($buffer: ident, $name:ident, $ty:tt, $offset:expr) => {
13        impl<'a, T: AsRef<[u8]>> $buffer<T> {
14            getter!($name, $ty, $offset);
15        }
16    };
17    ($name:ident, u8, $offset:expr) => {
18        pub fn $name(&self) -> u8 {
19            self.buffer.as_ref()[$offset]
20        }
21    };
22    ($name:ident, u16, $offset:expr) => {
23        pub fn $name(&self) -> u16 {
24            use $crate::byteorder::{ByteOrder, NativeEndian};
25            NativeEndian::read_u16(&self.buffer.as_ref()[$offset])
26        }
27    };
28    ($name:ident, u32, $offset:expr) => {
29        pub fn $name(&self) -> u32 {
30            use $crate::byteorder::{ByteOrder, NativeEndian};
31            NativeEndian::read_u32(&self.buffer.as_ref()[$offset])
32        }
33    };
34    ($name:ident, u64, $offset:expr) => {
35        pub fn $name(&self) -> u64 {
36            use $crate::byteorder::{ByteOrder, NativeEndian};
37            NativeEndian::read_u64(&self.buffer.as_ref()[$offset])
38        }
39    };
40    ($name:ident, i8, $offset:expr) => {
41        pub fn $name(&self) -> i8 {
42            self.buffer.as_ref()[$offset]
43        }
44    };
45    ($name:ident, i16, $offset:expr) => {
46        pub fn $name(&self) -> i16 {
47            use $crate::byteorder::{ByteOrder, NativeEndian};
48            NativeEndian::read_i16(&self.buffer.as_ref()[$offset])
49        }
50    };
51    ($name:ident, i32, $offset:expr) => {
52        pub fn $name(&self) -> i32 {
53            use $crate::byteorder::{ByteOrder, NativeEndian};
54            NativeEndian::read_i32(&self.buffer.as_ref()[$offset])
55        }
56    };
57    ($name:ident, i64, $offset:expr) => {
58        pub fn $name(&self) -> i64 {
59            use $crate::byteorder::{ByteOrder, NativeEndian};
60            NativeEndian::read_i64(&self.buffer.as_ref()[$offset])
61        }
62    };
63}
64
65#[macro_export(local_inner_macros)]
66macro_rules! setter {
67    ($buffer: ident, $name:ident, slice, $offset:expr) => {
68        impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> $buffer<&'a mut T> {
69            $crate::paste::item! {
70                pub fn [<$name _mut>](&mut self) -> &mut [u8] {
71                    &mut self.buffer.as_mut()[$offset]
72                }
73            }
74        }
75    };
76    ($buffer: ident, $name:ident, $ty:tt, $offset:expr) => {
77        impl<'a, T: AsRef<[u8]> + AsMut<[u8]>> $buffer<T> {
78            setter!($name, $ty, $offset);
79        }
80    };
81    ($name:ident, u8, $offset:expr) => {
82        $crate::paste::item! {
83            pub fn [<set_ $name>](&mut self, value: u8) {
84                self.buffer.as_mut()[$offset] = value;
85            }
86        }
87    };
88    ($name:ident, u16, $offset:expr) => {
89        $crate::paste::item! {
90            pub fn [<set_ $name>](&mut self, value: u16) {
91                use $crate::byteorder::{ByteOrder, NativeEndian};
92                NativeEndian::write_u16(&mut self.buffer.as_mut()[$offset], value)
93            }
94        }
95    };
96    ($name:ident, u32, $offset:expr) => {
97        $crate::paste::item! {
98            pub fn [<set_ $name>](&mut self, value: u32) {
99                use $crate::byteorder::{ByteOrder, NativeEndian};
100                NativeEndian::write_u32(&mut self.buffer.as_mut()[$offset], value)
101            }
102        }
103    };
104    ($name:ident, u64, $offset:expr) => {
105        $crate::paste::item! {
106            pub fn [<set_ $name>](&mut self, value: u64) {
107                use $crate::byteorder::{ByteOrder, NativeEndian};
108                NativeEndian::write_u64(&mut self.buffer.as_mut()[$offset], value)
109            }
110        }
111    };
112    ($name:ident, i8, $offset:expr) => {
113        $crate::paste::item! {
114            pub fn [<set_ $name>](&mut self, value: i8) {
115                self.buffer.as_mut()[$offset] = value;
116            }
117        }
118    };
119    ($name:ident, i16, $offset:expr) => {
120        $crate::paste::item! {
121            pub fn [<set_ $name>](&mut self, value: i16) {
122                use $crate::byteorder::{ByteOrder, NativeEndian};
123                NativeEndian::write_i16(&mut self.buffer.as_mut()[$offset], value)
124            }
125        }
126    };
127    ($name:ident, i32, $offset:expr) => {
128        $crate::paste::item! {
129            pub fn [<set_ $name>](&mut self, value: i32) {
130                use $crate::byteorder::{ByteOrder, NativeEndian};
131                NativeEndian::write_i32(&mut self.buffer.as_mut()[$offset], value)
132            }
133        }
134    };
135    ($name:ident, i64, $offset:expr) => {
136        $crate::paste::item! {
137            pub fn [<set_ $name>](&mut self, value: i64) {
138                use $crate::byteorder::{ByteOrder, NativeEndian};
139                NativeEndian::write_i64(&mut self.buffer.as_mut()[$offset], value)
140            }
141        }
142    };
143}
144
145#[macro_export(local_inner_macros)]
146macro_rules! buffer {
147    ($name:ident($buffer_len:expr) { $($field:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
148        buffer!($name { $($field: ($ty, $offset),)* });
149        buffer_check_length!($name($buffer_len));
150    };
151
152    ($name:ident { $($field:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
153        buffer_common!($name);
154        fields!($name {
155            $($field: ($ty, $offset),)*
156        });
157    };
158
159    ($name:ident, $buffer_len:expr) => {
160        buffer_common!($name);
161        buffer_check_length!($name($buffer_len));
162    };
163
164    ($name:ident) => {
165        buffer_common!($name);
166    };
167}
168
169#[macro_export(local_inner_macros)]
170macro_rules! fields {
171    ($buffer:ident { $($name:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
172        $(
173            getter!($buffer, $name, $ty, $offset);
174        )*
175
176            $(
177                setter!($buffer, $name, $ty, $offset);
178            )*
179    }
180}
181
182#[macro_export]
183macro_rules! buffer_check_length {
184    ($name:ident($buffer_len:expr)) => {
185        impl<T: AsRef<[u8]>> $name<T> {
186            pub fn new_checked(buffer: T) -> Result<Self, DecodeError> {
187                let packet = Self::new(buffer);
188                packet.check_buffer_length()?;
189                Ok(packet)
190            }
191
192            fn check_buffer_length(&self) -> Result<(), DecodeError> {
193                let len = self.buffer.as_ref().len();
194                if len < $buffer_len {
195                    Err(DecodeError::InvalidBufferLength {
196                        name: stringify!($name),
197                        len,
198                        buffer_len: $buffer_len,
199                    })
200                } else {
201                    Ok(())
202                }
203            }
204        }
205    };
206}
207
208#[macro_export]
209macro_rules! buffer_common {
210    ($name:ident) => {
211        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
212        pub struct $name<T> {
213            buffer: T,
214        }
215
216        impl<T: AsRef<[u8]>> $name<T> {
217            pub fn new(buffer: T) -> Self {
218                Self { buffer }
219            }
220
221            pub fn into_inner(self) -> T {
222                self.buffer
223            }
224        }
225
226        impl<'a, T: AsRef<[u8]> + ?Sized> $name<&'a T> {
227            pub fn inner(&self) -> &'a [u8] {
228                &self.buffer.as_ref()[..]
229            }
230        }
231
232        impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> $name<&'a mut T> {
233            pub fn inner_mut(&mut self) -> &mut [u8] {
234                &mut self.buffer.as_mut()[..]
235            }
236        }
237    };
238}