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, 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_common!($name);
149 fields!($name {
150 $($field: ($ty, $offset),)*
151 });
152 buffer_check_length!($name $(, $buffer_len)?);
153 };
154
155 ($name:ident { $($field:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
156 buffer_common!($name);
157 buffer_no_length!($name);
158 fields!($name {
159 $($field: ($ty, $offset),)*
160 });
161 };
162
163 ($name:ident, buffer_len:expr) => {
164 buffer_common!($name);
165 buffer_check_length!($name, $buffer_len);
166 };
167
168 ($name:ident) => {
169 buffer_common!($name);
170 buffer_no_length!($name);
171 };
172}
173
174#[macro_export(local_inner_macros)]
175macro_rules! fields {
176 ($buffer:ident { $($name:ident : ($ty:tt, $offset:expr)),* $(,)? }) => {
177 $(
178 getter!($buffer, $name, $ty, $offset);
179 )*
180
181 $(
182 setter!($buffer, $name, $ty, $offset);
183 )*
184 }
185}
186
187#[macro_export]
188macro_rules! buffer_check_length {
189 ($name:ident) => {
190 impl<T: AsRef<[u8]>> $name<T> {
191 pub(crate) fn new_unchecked(buffer: T) -> Self {
192 Self { buffer }
193 }
194 }
195 };
196 ($name:ident, $buffer_len:expr) => {
197 impl<T: AsRef<[u8]>> $name<T> {
198 pub fn new(buffer: T) -> Result<Self, DecodeError> {
199 let packet = Self::new_unchecked(buffer);
200 packet.check_buffer_length()?;
201 Ok(packet)
202 }
203
204 pub(crate) fn new_unchecked(buffer: T) -> Self {
205 Self { buffer }
206 }
207
208 fn check_buffer_length(&self) -> Result<(), DecodeError> {
209 let len = self.buffer.as_ref().len();
210 if len < $buffer_len {
211 Err(DecodeError::InvalidBufferLength {
212 name: stringify!($name),
213 len,
214 buffer_len: $buffer_len,
215 })
216 } else {
217 Ok(())
218 }
219 }
220 }
221 };
222}
223
224#[macro_export]
225macro_rules! buffer_no_length {
226 ($name:ident) => {
227 impl<T: AsRef<[u8]>> $name<T> {
228 pub fn new(buffer: T) -> Self {
229 Self { buffer }
230 }
231 }
232 };
233}
234
235#[macro_export]
236macro_rules! buffer_common {
237 ($name:ident) => {
238 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
239 pub struct $name<T> {
240 buffer: T,
241 }
242
243 impl<T: AsRef<[u8]>> $name<T> {
244 pub fn into_inner(self) -> T {
245 self.buffer
246 }
247 }
248
249 impl<'a, T: AsRef<[u8]> + ?Sized> $name<&'a T> {
250 pub fn inner(&self) -> &'a [u8] {
251 &self.buffer.as_ref()[..]
252 }
253 }
254
255 impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> $name<&'a mut T> {
256 pub fn inner_mut(&mut self) -> &mut [u8] {
257 &mut self.buffer.as_mut()[..]
258 }
259 }
260 };
261}