netlink_packet_core/
macros.rs

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