bitfield-serialize 0.1.0

A Rust library for defining and serializing bitfield structures with macro support
Documentation
// Macros for defining bitfield structures.
#![allow(unused_imports)]
#![allow(unused_assignments)]
#![allow(dead_code)]

/// Macro for defining bitfield structures with automatic serialization support.
///
/// # Usage
///
/// ```
/// use rust_bitfield_serializer::*;
///
/// bitfield! {
///     struct MyBitfield {
///         field1: u8, 4,
///         field2: u8, 4,
///     }
/// }
/// ```
///
/// # Examples
///
/// ```
/// use rust_bitfield_serializer::*;
/// bitfield! {
///     struct MyBitfield {
///         field1: u8, 4,
///         field2: u8, 4,
///     }
/// }
/// let mut bf = MyBitfield::new();
/// bf.field1 = 0xA;
/// bf.field2 = 0xB;
/// let bytes = bf.serialize();
/// assert_eq!(bytes, vec![0xAB]);
/// let bf2 = MyBitfield::deserialize(&bytes).unwrap();
/// assert_eq!(bf2.field1, 0xA);
/// assert_eq!(bf2.field2, 0xB);
/// ```
///
/// Nested structures example:
///
/// ```
/// use rust_bitfield_serializer::*;
/// bitfield! {
///     struct NestedHeader {
///         version: u8, 4,
///         flags: u8, 4,
///     }
///
///     struct NestedPacket {
///         header: NestedHeader,
///         payload_len: u16, 12,
///         checksum: u8, 8,
///     }
/// }
/// let mut p = NestedPacket::new();
/// p.header.version = 2;
/// p.header.flags = 0xF;
/// p.payload_len = 0xABC;
/// p.checksum = 0x1;
/// let bytes = p.serialize();
/// let p2 = NestedPacket::deserialize(&bytes).unwrap();
/// assert_eq!(p2.header.version, 2);
/// assert_eq!(p2.header.flags, 0xF);
/// assert_eq!(p2.payload_len, 0xABC);
/// assert_eq!(p2.checksum, 0x1);
/// ```
///
/// This creates a struct `MyBitfield` with fields that can be accessed directly,
/// along with serialization and deserialization capabilities.
///
/// # Multiple Structures
///
/// You can define multiple structures in a single macro invocation:
///
/// ```
/// use rust_bitfield_serializer::*;
/// bitfield! {
///     struct Header {
///         version: u8, 4,
///         flags: u8, 4,
///     }
///
///     struct Packet {
///         header: Header,
///         payload_len: u16, 12,
///         checksum: u8, 8,
///     }
/// }
/// ```
///
/// # Nested Structures
///
/// Bitfield structures can contain other bitfield structures as fields.
/// When no bit count is specified, the entire nested structure is used.
#[macro_export]
macro_rules! bitfield {
    // Multiple structures
    (
        $(
            struct $name:ident {
                $(
                    $field_name:ident: $field_type:ty $(, $bits:literal)?
                ),* $(,)?
            }
        )+
    ) => {
        $(
            bitfield!(@single $name { $($field_name: $field_type $(, $bits)?),* });
        )+
    };

    // Single structure
    (
        struct $name:ident {
            $(
                $field_name:ident: $field_type:ty $(, $bits:literal)?
            ),* $(,)?
        }
    ) => {
        bitfield!(@single $name { $($field_name: $field_type $(, $bits)?),* });
    };

    // Generate single structure implementation
    (@single $name:ident { $($field_name:ident: $field_type:ty $(, $bits:literal)?),* }) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name {
            $(
                pub $field_name: bitfield!(@field_type $field_type $(, $bits)?),
            )*
            _internal_data: Vec<u8>,
        }

        impl $name {
            /// Create a new instance with default values.
            pub fn new() -> Self {
                Self {
                    $(
                        $field_name: Default::default(),
                    )*
                    _internal_data: vec![0; Self::byte_size()],
                }
            }

            /// Synchronize field values to internal data for serialization.
            pub fn sync_to_data(&mut self) {
                self._internal_data = vec![0; Self::byte_size()];
                let mut current_bit = 0;
                $(
                    bitfield!(@write_field_to_data self, $field_name, $field_type, current_bit $(, $bits)?);
                )*
            }

            /// Synchronize internal data to field values after deserialization.
            pub fn sync_from_data(&mut self) {
                let mut current_bit = 0;
                $(
                    bitfield!(@read_field_from_data self, $field_name, $field_type, current_bit $(, $bits)?);
                )*
            }

            /// Get the bit size of a specific field.
            pub fn field_bit_size(field_name: &str) -> Option<usize> {
                match field_name {
                    $(
                        stringify!($field_name) => Some(bitfield!(@size $field_type $(, $bits)?)),
                    )*
                    _ => None,
                }
            }

            /// Get the bit offset of a specific field.
            pub fn field_bit_offset(field_name: &str) -> Option<usize> {
                let mut current_bit = 0;
                $(
                    if field_name == stringify!($field_name) {
                        return Some(current_bit);
                    }
                    current_bit += bitfield!(@size $field_type $(, $bits)?);
                )*
                None
            }

            /// Read bits from data at a specific position.
            fn read_bits_from_data(data: &[u8], start_bit: usize, num_bits: usize) -> u64 {
                $crate::utils::BitReader::read_bits_at(data, start_bit, num_bits)
            }

            /// Write bits to data at a specific position.
            fn write_bits_to_data(data: &mut [u8], start_bit: usize, value: u64, num_bits: usize) {
                $crate::utils::BitWriter::write_bits_to(data, start_bit, value, num_bits);
            }
        }

        impl $crate::traits::BitfieldSize for $name {
            fn bit_size() -> usize {
                0 $(+ bitfield!(@size $field_type $(, $bits)?))*
            }
        }

        impl $crate::traits::BitfieldSerialize for $name {
            fn serialize(&self) -> Vec<u8> {
                let mut instance = self.clone();
                instance.sync_to_data();
                instance._internal_data
            }

            fn deserialize(data: &[u8]) -> Result<Self, String> {
                if data.len() != Self::byte_size() {
                    return Err(format!(
                        "Data size mismatch: expected {} bytes, got {}",
                        Self::byte_size(),
                        data.len()
                    ));
                }
                let mut instance = Self::new();
                instance._internal_data = data.to_vec();
                instance.sync_from_data();
                Ok(instance)
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self::new()
            }
        }
    };

    // Determine field type
    (@field_type $field_type:ty, $bits:literal) => {
        $field_type
    };

    (@field_type $field_type:ty) => {
        $field_type
    };

    // Write field value to internal data
    (@write_field_to_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident, $bits:literal) => {
        {
            let value = $self.$field_name as u64;
            Self::write_bits_to_data(&mut $self._internal_data, $current_bit, value, $bits);
            $current_bit += $bits;
        }
    };

    (@write_field_to_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident) => {
        {
            let serialized = $self.$field_name.serialize();
            let bit_size = <$field_type>::bit_size();
            for (i, &byte) in serialized.iter().enumerate() {
                let byte_start_bit = $current_bit + i * 8;
                let remaining_bits = bit_size.saturating_sub(i * 8).min(8);
                Self::write_bits_to_data(&mut $self._internal_data, byte_start_bit, byte as u64, remaining_bits);
            }
            $current_bit += bit_size;
        }
    };

    // Read field value from internal data
    (@read_field_from_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident, $bits:literal) => {
        {
            let value = Self::read_bits_from_data(&$self._internal_data, $current_bit, $bits);
            $self.$field_name = value as $field_type;
            $current_bit += $bits;
        }
    };

    (@read_field_from_data $self:ident, $field_name:ident, $field_type:ty, $current_bit:ident) => {
        {
            let bit_size = <$field_type>::bit_size();
            let byte_size = bit_size.div_ceil(8);
            let mut field_data = vec![0u8; byte_size];

            for i in 0..byte_size {
                let byte_start_bit = $current_bit + i * 8;
                let remaining_bits = bit_size.saturating_sub(i * 8).min(8);
                let byte_value = Self::read_bits_from_data(&$self._internal_data, byte_start_bit, remaining_bits);
                field_data[i] = byte_value as u8;
            }

            match <$field_type>::deserialize(&field_data) {
                Ok(value) => $self.$field_name = value,
                Err(_) => $self.$field_name = Default::default(),
            }
            $current_bit += bit_size;
        }
    };

    // Calculate field size
    (@size $field_type:ty, $bits:literal) => {
        $bits
    };

    (@size $field_type:ty) => {
        <$field_type>::bit_size()
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::traits::{BitfieldSerialize, BitfieldSize};

    bitfield! {
        struct TestStruct {
            field1: u8, 4,
            field2: u8, 4,
        }
    }

    bitfield! {
        struct SimpleHeader {
            version: u8, 4,
            flags: u8, 4,
        }

        struct ComplexPacket {
            header: SimpleHeader,
            payload_len: u16, 12,
            checksum: u8, 8,
        }
    }

    #[test]
    fn test_basic_bitfield() {
        let mut test_struct = TestStruct::new();
        test_struct.field1 = 0xA;
        test_struct.field2 = 0xB;

        assert_eq!(TestStruct::bit_size(), 8);
        assert_eq!(TestStruct::byte_size(), 1);

        let serialized = test_struct.serialize();
        assert_eq!(serialized.len(), 1);

        let deserialized = TestStruct::deserialize(&serialized).unwrap();
        assert_eq!(deserialized.field1, 0xA);
        assert_eq!(deserialized.field2, 0xB);
    }

    #[test]
    fn test_nested_bitfield() {
        let mut packet = ComplexPacket::new();
        packet.header.version = 2;
        packet.header.flags = 0xF;
        packet.payload_len = 1024;
        packet.checksum = 0xFF;

        let serialized = packet.serialize();
        let deserialized = ComplexPacket::deserialize(&serialized).unwrap();

        assert_eq!(deserialized.header.version, 2);
        assert_eq!(deserialized.header.flags, 0xF);
        assert_eq!(deserialized.payload_len, 1024);
        assert_eq!(deserialized.checksum, 0xFF);
    }

    #[test]
    fn test_field_metadata() {
        assert_eq!(TestStruct::field_bit_size("field1"), Some(4));
        assert_eq!(TestStruct::field_bit_size("field2"), Some(4));
        assert_eq!(TestStruct::field_bit_size("nonexistent"), None);

        assert_eq!(TestStruct::field_bit_offset("field1"), Some(0));
        assert_eq!(TestStruct::field_bit_offset("field2"), Some(4));
        assert_eq!(TestStruct::field_bit_offset("nonexistent"), None);
    }

    #[test]
    fn test_hex_serialization() {
        let mut test_struct = TestStruct::new();
        test_struct.field1 = 0xA;
        test_struct.field2 = 0xB;

        let hex = test_struct.to_hex();
        let from_hex = TestStruct::from_hex(&hex).unwrap();

        assert_eq!(from_hex.field1, 0xA);
        assert_eq!(from_hex.field2, 0xB);
    }
}