1#[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, u128, $offset:expr) => {
41 pub fn $name(&self) -> u128 {
42 use $crate::byteorder::{ByteOrder, NativeEndian};
43 NativeEndian::read_u128(&self.buffer.as_ref()[$offset])
44 }
45 };
46 ($name:ident, i8, $offset:expr) => {
47 pub fn $name(&self) -> i8 {
48 self.buffer.as_ref()[$offset]
49 }
50 };
51 ($name:ident, i16, $offset:expr) => {
52 pub fn $name(&self) -> i16 {
53 use $crate::byteorder::{ByteOrder, NativeEndian};
54 NativeEndian::read_i16(&self.buffer.as_ref()[$offset])
55 }
56 };
57 ($name:ident, i32, $offset:expr) => {
58 pub fn $name(&self) -> i32 {
59 use $crate::byteorder::{ByteOrder, NativeEndian};
60 NativeEndian::read_i32(&self.buffer.as_ref()[$offset])
61 }
62 };
63 ($name:ident, i64, $offset:expr) => {
64 pub fn $name(&self) -> i64 {
65 use $crate::byteorder::{ByteOrder, NativeEndian};
66 NativeEndian::read_i64(&self.buffer.as_ref()[$offset])
67 }
68 };
69 ($name:ident, i128, $offset:expr) => {
70 pub fn $name(&self) -> i128 {
71 use $crate::byteorder::{ByteOrder, NativeEndian};
72 NativeEndian::read_i128(&self.buffer.as_ref()[$offset])
73 }
74 };
75}
76
77#[macro_export(local_inner_macros)]
78macro_rules! setter {
79 ($buffer: ident, $name:ident, slice, $offset:expr) => {
80 impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> $buffer<&'a mut T> {
81 $crate::paste::item! {
82 pub fn [<$name _mut>](&mut self) -> &mut [u8] {
83 &mut self.buffer.as_mut()[$offset]
84 }
85 }
86 }
87 };
88 ($buffer: ident, $name:ident, $ty:tt, $offset:expr) => {
89 impl<'a, T: AsRef<[u8]> + AsMut<[u8]>> $buffer<T> {
90 setter!($name, $ty, $offset);
91 }
92 };
93 ($name:ident, u8, $offset:expr) => {
94 $crate::paste::item! {
95 pub fn [<set_ $name>](&mut self, value: u8) {
96 self.buffer.as_mut()[$offset] = value;
97 }
98 }
99 };
100 ($name:ident, u16, $offset:expr) => {
101 $crate::paste::item! {
102 pub fn [<set_ $name>](&mut self, value: u16) {
103 use $crate::byteorder::{ByteOrder, NativeEndian};
104 NativeEndian::write_u16(&mut self.buffer.as_mut()[$offset], value)
105 }
106 }
107 };
108 ($name:ident, u32, $offset:expr) => {
109 $crate::paste::item! {
110 pub fn [<set_ $name>](&mut self, value: u32) {
111 use $crate::byteorder::{ByteOrder, NativeEndian};
112 NativeEndian::write_u32(&mut self.buffer.as_mut()[$offset], value)
113 }
114 }
115 };
116 ($name:ident, u64, $offset:expr) => {
117 $crate::paste::item! {
118 pub fn [<set_ $name>](&mut self, value: u64) {
119 use $crate::byteorder::{ByteOrder, NativeEndian};
120 NativeEndian::write_u64(&mut self.buffer.as_mut()[$offset], value)
121 }
122 }
123 };
124 ($name:ident, u128, $offset:expr) => {
125 $crate::paste::item! {
126 pub fn [<set_ $name>](&mut self, value: u128) {
127 use $crate::byteorder::{ByteOrder, NativeEndian};
128 NativeEndian::write_u128(&mut self.buffer.as_mut()[$offset], value)
129 }
130 }
131 };
132 ($name:ident, i8, $offset:expr) => {
133 $crate::paste::item! {
134 pub fn [<set_ $name>](&mut self, value: i8) {
135 self.buffer.as_mut()[$offset] = value;
136 }
137 }
138 };
139 ($name:ident, i16, $offset:expr) => {
140 $crate::paste::item! {
141 pub fn [<set_ $name>](&mut self, value: i16) {
142 use $crate::byteorder::{ByteOrder, NativeEndian};
143 NativeEndian::write_i16(&mut self.buffer.as_mut()[$offset], value)
144 }
145 }
146 };
147 ($name:ident, i32, $offset:expr) => {
148 $crate::paste::item! {
149 pub fn [<set_ $name>](&mut self, value: i32) {
150 use $crate::byteorder::{ByteOrder, NativeEndian};
151 NativeEndian::write_i32(&mut self.buffer.as_mut()[$offset], value)
152 }
153 }
154 };
155 ($name:ident, i64, $offset:expr) => {
156 $crate::paste::item! {
157 pub fn [<set_ $name>](&mut self, value: i64) {
158 use $crate::byteorder::{ByteOrder, NativeEndian};
159 NativeEndian::write_i64(&mut self.buffer.as_mut()[$offset], value)
160 }
161 }
162 };
163 ($name:ident, i128, $offset:expr) => {
164 $crate::paste::item! {
165 pub fn [<set_ $name>](&mut self, value: i128) {
166 use $crate::byteorder::{ByteOrder, NativeEndian};
167 NativeEndian::write_i128(&mut self.buffer.as_mut()[$offset], value)
168 }
169 }
170 };
171}
172
173#[macro_export(local_inner_macros)]
174macro_rules! buffer {
175 ($name:ident($($buffer_len:expr)?) { $($field:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
176 buffer_common!($name);
177 fields!($name {
178 $($field: ($ty, $offset),)*
179 });
180 buffer_check_length!($name $(, $buffer_len)?);
181 };
182
183 ($name:ident { $($field:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
184 buffer_common!($name);
185 buffer_no_length!($name);
186 fields!($name {
187 $($field: ($ty, $offset),)*
188 });
189 };
190
191 ($name:ident, buffer_len:expr) => {
192 buffer_common!($name);
193 buffer_check_length!($name, $buffer_len);
194 };
195
196 ($name:ident) => {
197 buffer_common!($name);
198 buffer_no_length!($name);
199 };
200}
201
202#[macro_export(local_inner_macros)]
203macro_rules! fields {
204 ($buffer:ident { $($name:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
205 $(
206 getter!($buffer, $name, $ty, $offset);
207 )*
208
209 $(
210 setter!($buffer, $name, $ty, $offset);
211 )*
212 }
213}
214
215#[macro_export]
216macro_rules! buffer_check_length {
217 ($name:ident) => {
218 impl<T: AsRef<[u8]>> $name<T> {
219 pub(crate) fn new_unchecked(buffer: T) -> Self {
220 Self { buffer }
221 }
222 }
223 };
224 ($name:ident, $buffer_len:expr) => {
225 impl<T: AsRef<[u8]>> $name<T> {
226 pub fn new(buffer: T) -> Result<Self, DecodeError> {
227 let packet = Self::new_unchecked(buffer);
228 packet.check_buffer_length()?;
229 Ok(packet)
230 }
231
232 pub(crate) fn new_unchecked(buffer: T) -> Self {
233 Self { buffer }
234 }
235
236 fn check_buffer_length(&self) -> Result<(), DecodeError> {
237 let len = self.buffer.as_ref().len();
238 if len < $buffer_len {
239 Err(DecodeError::InvalidBufferLength {
240 name: stringify!($name),
241 len,
242 buffer_len: $buffer_len,
243 })
244 } else {
245 Ok(())
246 }
247 }
248 }
249 };
250}
251
252#[macro_export]
253macro_rules! buffer_no_length {
254 ($name:ident) => {
255 impl<T: AsRef<[u8]>> $name<T> {
256 pub fn new(buffer: T) -> Self {
257 Self { buffer }
258 }
259 }
260 };
261}
262
263#[macro_export]
264macro_rules! buffer_common {
265 ($name:ident) => {
266 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
267 pub struct $name<T> {
268 buffer: T,
269 }
270
271 impl<T: AsRef<[u8]>> $name<T> {
272 pub fn into_inner(self) -> T {
273 self.buffer
274 }
275 }
276
277 impl<'a, T: AsRef<[u8]> + ?Sized> $name<&'a T> {
278 pub fn inner(&self) -> &'a [u8] {
279 &self.buffer.as_ref()[..]
280 }
281 }
282
283 impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> $name<&'a mut T> {
284 pub fn inner_mut(&mut self) -> &mut [u8] {
285 &mut self.buffer.as_mut()[..]
286 }
287 }
288 };
289}