rust_bitfield_serializer/
macros.rs1#![allow(unused_imports)]
3#![allow(unused_assignments)]
4#![allow(dead_code)]
5
6#[macro_export]
98macro_rules! bitfield {
99 (
101 $(
102 struct $name:ident {
103 $(
104 $field_name:ident: $field_type:ty $(, $bits:literal)?
105 ),* $(,)?
106 }
107 )+
108 ) => {
109 $(
110 bitfield!(@single $name { $($field_name: $field_type $(, $bits)?),* });
111 )+
112 };
113
114 (
116 struct $name:ident {
117 $(
118 $field_name:ident: $field_type:ty $(, $bits:literal)?
119 ),* $(,)?
120 }
121 ) => {
122 bitfield!(@single $name { $($field_name: $field_type $(, $bits)?),* });
123 };
124
125 (@single $name:ident { $($field_name:ident: $field_type:ty $(, $bits:literal)?),* }) => {
127 #[derive(Debug, Clone, PartialEq)]
128 pub struct $name {
129 $(
130 pub $field_name: bitfield!(@field_type $field_type $(, $bits)?),
131 )*
132 _internal_data: Vec<u8>,
133 }
134
135 impl $name {
136 pub fn new() -> Self {
138 Self {
139 $(
140 $field_name: Default::default(),
141 )*
142 _internal_data: vec![0; Self::byte_size()],
143 }
144 }
145
146 pub fn sync_to_data(&mut self) {
148 self._internal_data = vec![0; Self::byte_size()];
149 let mut current_bit = 0;
150 $(
151 bitfield!(@write_field_to_data self, $field_name, $field_type, current_bit $(, $bits)?);
152 )*
153 }
154
155 pub fn sync_from_data(&mut self) {
157 let mut current_bit = 0;
158 $(
159 bitfield!(@read_field_from_data self, $field_name, $field_type, current_bit $(, $bits)?);
160 )*
161 }
162
163 pub fn field_bit_size(field_name: &str) -> Option<usize> {
165 match field_name {
166 $(
167 stringify!($field_name) => Some(bitfield!(@size $field_type $(, $bits)?)),
168 )*
169 _ => None,
170 }
171 }
172
173 pub fn field_bit_offset(field_name: &str) -> Option<usize> {
175 let mut current_bit = 0;
176 $(
177 if field_name == stringify!($field_name) {
178 return Some(current_bit);
179 }
180 current_bit += bitfield!(@size $field_type $(, $bits)?);
181 )*
182 None
183 }
184
185 fn read_bits_from_data(data: &[u8], start_bit: usize, num_bits: usize) -> u64 {
187 $crate::utils::BitReader::read_bits_at(data, start_bit, num_bits)
188 }
189
190 fn write_bits_to_data(data: &mut [u8], start_bit: usize, value: u64, num_bits: usize) {
192 $crate::utils::BitWriter::write_bits_to(data, start_bit, value, num_bits);
193 }
194 }
195
196 impl $crate::traits::BitfieldSize for $name {
197 fn bit_size() -> usize {
198 0 $(+ bitfield!(@size $field_type $(, $bits)?))*
199 }
200 }
201
202 impl $crate::traits::BitfieldSerialize for $name {
203 fn serialize(&self) -> Vec<u8> {
204 let mut instance = self.clone();
205 instance.sync_to_data();
206 instance._internal_data
207 }
208
209 fn deserialize(data: &[u8]) -> Result<Self, String> {
210 if data.len() != Self::byte_size() {
211 return Err(format!(
212 "Data size mismatch: expected {} bytes, got {}",
213 Self::byte_size(),
214 data.len()
215 ));
216 }
217 let mut instance = Self::new();
218 instance._internal_data = data.to_vec();
219 instance.sync_from_data();
220 Ok(instance)
221 }
222 }
223
224 impl Default for $name {
225 fn default() -> Self {
226 Self::new()
227 }
228 }
229 };
230
231 (@field_type $field_type:ty, $bits:literal) => {
233 $field_type
234 };
235
236 (@field_type $field_type:ty) => {
237 $field_type
238 };
239
240 (@write_field_to_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident, $bits:literal) => {
242 {
243 let value = $self.$field_name as u64;
244 Self::write_bits_to_data(&mut $self._internal_data, $current_bit, value, $bits);
245 $current_bit += $bits;
246 }
247 };
248
249 (@write_field_to_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident) => {
250 {
251 let serialized = $self.$field_name.serialize();
252 let bit_size = <$field_type>::bit_size();
253 for (i, &byte) in serialized.iter().enumerate() {
254 let byte_start_bit = $current_bit + i * 8;
255 let remaining_bits = bit_size.saturating_sub(i * 8).min(8);
256 Self::write_bits_to_data(&mut $self._internal_data, byte_start_bit, byte as u64, remaining_bits);
257 }
258 $current_bit += bit_size;
259 }
260 };
261
262 (@read_field_from_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident, $bits:literal) => {
264 {
265 let value = Self::read_bits_from_data(&$self._internal_data, $current_bit, $bits);
266 $self.$field_name = value as $field_type;
267 $current_bit += $bits;
268 }
269 };
270
271 (@read_field_from_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident) => {
272 {
273 let bit_size = <$field_type>::bit_size();
274 let byte_size = bit_size.div_ceil(8);
275 let mut field_data = vec![0u8; byte_size];
276
277 for i in 0..byte_size {
278 let byte_start_bit = $current_bit + i * 8;
279 let remaining_bits = bit_size.saturating_sub(i * 8).min(8);
280 let byte_value = Self::read_bits_from_data(&$self._internal_data, byte_start_bit, remaining_bits);
281 field_data[i] = byte_value as u8;
282 }
283
284 match <$field_type>::deserialize(&field_data) {
285 Ok(value) => $self.$field_name = value,
286 Err(_) => $self.$field_name = Default::default(),
287 }
288 $current_bit += bit_size;
289 }
290 };
291
292 (@size $field_type:ty, $bits:literal) => {
294 $bits
295 };
296
297 (@size $field_type:ty) => {
298 <$field_type>::bit_size()
299 };
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305 use crate::traits::{BitfieldSerialize, BitfieldSize};
306
307 bitfield! {
308 struct TestStruct {
309 field1: u8, 4,
310 field2: u8, 4,
311 }
312 }
313
314 bitfield! {
315 struct SimpleHeader {
316 version: u8, 4,
317 flags: u8, 4,
318 }
319
320 struct ComplexPacket {
321 header: SimpleHeader,
322 payload_len: u16, 12,
323 checksum: u8, 8,
324 }
325 }
326
327 #[test]
328 fn test_basic_bitfield() {
329 let mut test_struct = TestStruct::new();
330 test_struct.field1 = 0xA;
331 test_struct.field2 = 0xB;
332
333 assert_eq!(TestStruct::bit_size(), 8);
334 assert_eq!(TestStruct::byte_size(), 1);
335
336 let serialized = test_struct.serialize();
337 assert_eq!(serialized.len(), 1);
338
339 let deserialized = TestStruct::deserialize(&serialized).unwrap();
340 assert_eq!(deserialized.field1, 0xA);
341 assert_eq!(deserialized.field2, 0xB);
342 }
343
344 #[test]
345 fn test_nested_bitfield() {
346 let mut packet = ComplexPacket::new();
347 packet.header.version = 2;
348 packet.header.flags = 0xF;
349 packet.payload_len = 1024;
350 packet.checksum = 0xFF;
351
352 let serialized = packet.serialize();
353 let deserialized = ComplexPacket::deserialize(&serialized).unwrap();
354
355 assert_eq!(deserialized.header.version, 2);
356 assert_eq!(deserialized.header.flags, 0xF);
357 assert_eq!(deserialized.payload_len, 1024);
358 assert_eq!(deserialized.checksum, 0xFF);
359 }
360
361 #[test]
362 fn test_field_metadata() {
363 assert_eq!(TestStruct::field_bit_size("field1"), Some(4));
364 assert_eq!(TestStruct::field_bit_size("field2"), Some(4));
365 assert_eq!(TestStruct::field_bit_size("nonexistent"), None);
366
367 assert_eq!(TestStruct::field_bit_offset("field1"), Some(0));
368 assert_eq!(TestStruct::field_bit_offset("field2"), Some(4));
369 assert_eq!(TestStruct::field_bit_offset("nonexistent"), None);
370 }
371
372 #[test]
373 fn test_hex_serialization() {
374 let mut test_struct = TestStruct::new();
375 test_struct.field1 = 0xA;
376 test_struct.field2 = 0xB;
377
378 let hex = test_struct.to_hex();
379 let from_hex = TestStruct::from_hex(&hex).unwrap();
380
381 assert_eq!(from_hex.field1, 0xA);
382 assert_eq!(from_hex.field2, 0xB);
383 }
384}