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!($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}