bitfield-serialize 0.1.0

A Rust library for defining and serializing bitfield structures with macro support
Documentation
//! Bitfield serializer for converting between bitfield values and byte arrays.

use crate::types::{BitfieldStruct, BitfieldValue, FieldType};
use crate::utils::{BitReader, BitWriter};
use std::collections::HashMap;

/// A serializer for bitfield structures.
#[derive(Debug, Clone)]
pub struct BitfieldSerializer {
    /// Registered bitfield structure definitions.
    pub structs: HashMap<String, BitfieldStruct>,
}

impl BitfieldSerializer {
    /// Create a new BitfieldSerializer.
    pub fn new() -> Self {
        Self {
            structs: HashMap::new(),
        }
    }

    /// Register a bitfield structure definition.
    pub fn register_struct(&mut self, bitfield_struct: BitfieldStruct) {
        self.structs
            .insert(bitfield_struct.name.clone(), bitfield_struct);
    }

    /// Serialize a bitfield value to bytes.
    pub fn serialize(&self, value: &BitfieldValue) -> Result<Vec<u8>, String> {
        let struct_def = self
            .structs
            .get(&value.struct_name)
            .ok_or_else(|| format!("Unknown struct: {}", value.struct_name))?;

        let mut writer = BitWriter::new();
        self.serialize_struct(&mut writer, struct_def, value)?;
        Ok(writer.finish())
    }

    /// Deserialize bytes to a bitfield value.
    pub fn deserialize(&self, struct_name: &str, data: &[u8]) -> Result<BitfieldValue, String> {
        let struct_def = self
            .structs
            .get(struct_name)
            .ok_or_else(|| format!("Unknown struct: {}", struct_name))?;

        let mut reader = BitReader::new(data);
        self.deserialize_struct(&mut reader, struct_def)
    }

    /// Serialize to a hexadecimal string.
    pub fn to_hex(&self, value: &BitfieldValue) -> Result<String, String> {
        let bytes = self.serialize(value)?;
        Ok(hex::encode(bytes))
    }

    /// Deserialize from a hexadecimal string.
    pub fn from_hex(&self, struct_name: &str, hex_str: &str) -> Result<BitfieldValue, String> {
        let bytes = hex::decode(hex_str).map_err(|e| format!("Invalid hex string: {}", e))?;
        self.deserialize(struct_name, &bytes)
    }

    /// Get the expected byte size for a structure.
    pub fn byte_size(&self, struct_name: &str) -> Option<usize> {
        let struct_def = self.structs.get(struct_name)?;
        Some(struct_def.byte_size(&self.structs))
    }

    /// Get the expected bit size for a structure.
    pub fn bit_size(&self, struct_name: &str) -> Option<usize> {
        let struct_def = self.structs.get(struct_name)?;
        Some(struct_def.bit_size(&self.structs))
    }

    /// Serialize a single structure.
    fn serialize_struct(
        &self,
        writer: &mut BitWriter,
        struct_def: &BitfieldStruct,
        value: &BitfieldValue,
    ) -> Result<(), String> {
        for field in &struct_def.fields {
            match &field.field_type {
                FieldType::U8 => {
                    let val = value
                        .get_u8(&field.name)
                        .ok_or_else(|| format!("Missing field: {}", field.name))?;
                    writer.write_bits(val as u64, field.bits);
                }
                FieldType::U16 => {
                    let val = value
                        .get_u16(&field.name)
                        .ok_or_else(|| format!("Missing field: {}", field.name))?;
                    writer.write_bits(val as u64, field.bits);
                }
                FieldType::U32 => {
                    let val = value
                        .get_u32(&field.name)
                        .ok_or_else(|| format!("Missing field: {}", field.name))?;
                    writer.write_bits(val as u64, field.bits);
                }
                FieldType::U64 => {
                    let val = value
                        .get_u64(&field.name)
                        .ok_or_else(|| format!("Missing field: {}", field.name))?;
                    writer.write_bits(val, field.bits);
                }
                FieldType::Nested(nested_struct_name) => {
                    let nested_value = value
                        .get_nested(&field.name)
                        .ok_or_else(|| format!("Missing nested field: {}", field.name))?;
                    let nested_struct_def = self
                        .structs
                        .get(nested_struct_name)
                        .ok_or_else(|| format!("Unknown nested struct: {}", nested_struct_name))?;
                    self.serialize_struct(writer, nested_struct_def, nested_value)?;
                }
            }
        }
        Ok(())
    }

    /// Deserialize a single structure.
    fn deserialize_struct(
        &self,
        reader: &mut BitReader,
        struct_def: &BitfieldStruct,
    ) -> Result<BitfieldValue, String> {
        let mut result = BitfieldValue::new(&struct_def.name);

        for field in &struct_def.fields {
            match &field.field_type {
                FieldType::U8 => {
                    let val = reader.read_bits(field.bits)? as u8;
                    result.set_u8(&field.name, val);
                }
                FieldType::U16 => {
                    let val = reader.read_bits(field.bits)? as u16;
                    result.set_u16(&field.name, val);
                }
                FieldType::U32 => {
                    let val = reader.read_bits(field.bits)? as u32;
                    result.set_u32(&field.name, val);
                }
                FieldType::U64 => {
                    let val = reader.read_bits(field.bits)?;
                    result.set_u64(&field.name, val);
                }
                FieldType::Nested(nested_struct_name) => {
                    let nested_struct_def = self
                        .structs
                        .get(nested_struct_name)
                        .ok_or_else(|| format!("Unknown nested struct: {}", nested_struct_name))?;
                    let nested_value = self.deserialize_struct(reader, nested_struct_def)?;
                    result.set_nested(&field.name, nested_value);
                }
            }
        }

        Ok(result)
    }
}

impl Default for BitfieldSerializer {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::{BitfieldStruct, FieldType};

    #[test]
    fn test_simple_serialization() {
        let mut serializer = BitfieldSerializer::new();

        // Define a simple structure
        let mut struct_def = BitfieldStruct::new("SimpleStruct");
        struct_def.add_field("field1", 4, FieldType::U8);
        struct_def.add_field("field2", 4, FieldType::U8);

        serializer.register_struct(struct_def);

        // Create a value
        let mut value = BitfieldValue::new("SimpleStruct");
        value.set_u8("field1", 0xA);
        value.set_u8("field2", 0xB);

        // Serialize
        let serialized = serializer.serialize(&value).unwrap();
        assert_eq!(serialized, vec![0xAB]); // 0xB in upper 4 bits, 0xA in lower 4 bits

        // Deserialize
        let deserialized = serializer.deserialize("SimpleStruct", &serialized).unwrap();
        assert_eq!(deserialized.get_u8("field1"), Some(0xA));
        assert_eq!(deserialized.get_u8("field2"), Some(0xB));
    }

    #[test]
    fn test_nested_serialization() {
        let mut serializer = BitfieldSerializer::new();

        // Define nested structure
        let mut inner_struct = BitfieldStruct::new("InnerStruct");
        inner_struct.add_field("inner_field", 8, FieldType::U8);

        let mut outer_struct = BitfieldStruct::new("OuterStruct");
        outer_struct.add_field("outer_field", 4, FieldType::U8);
        outer_struct.add_field("nested", 8, FieldType::Nested("InnerStruct".to_string()));

        serializer.register_struct(inner_struct);
        serializer.register_struct(outer_struct);

        // Create nested value
        let mut inner_value = BitfieldValue::new("InnerStruct");
        inner_value.set_u8("inner_field", 0xFF);

        let mut outer_value = BitfieldValue::new("OuterStruct");
        outer_value.set_u8("outer_field", 0xA);
        outer_value.set_nested("nested", inner_value);

        // Serialize
        let serialized = serializer.serialize(&outer_value).unwrap();

        // Deserialize
        let deserialized = serializer.deserialize("OuterStruct", &serialized).unwrap();
        assert_eq!(deserialized.get_u8("outer_field"), Some(0xA));

        let nested = deserialized.get_nested("nested").unwrap();
        assert_eq!(nested.get_u8("inner_field"), Some(0xFF));
    }

    #[test]
    fn test_hex_conversion() {
        let mut serializer = BitfieldSerializer::new();

        let mut struct_def = BitfieldStruct::new("HexStruct");
        struct_def.add_field("field", 8, FieldType::U8);

        serializer.register_struct(struct_def);

        let mut value = BitfieldValue::new("HexStruct");
        value.set_u8("field", 0xAB);

        let hex = serializer.to_hex(&value).unwrap();
        assert_eq!(hex, "ab");

        let from_hex = serializer.from_hex("HexStruct", &hex).unwrap();
        assert_eq!(from_hex.get_u8("field"), Some(0xAB));
    }

    #[test]
    fn test_size_calculation() {
        let mut serializer = BitfieldSerializer::new();

        let mut struct_def = BitfieldStruct::new("SizeStruct");
        struct_def.add_field("field1", 4, FieldType::U8);
        struct_def.add_field("field2", 12, FieldType::U16);

        serializer.register_struct(struct_def);

        assert_eq!(serializer.bit_size("SizeStruct"), Some(16));
        assert_eq!(serializer.byte_size("SizeStruct"), Some(2));
    }

    #[test]
    fn test_error_handling() {
        let serializer = BitfieldSerializer::new();

        // Test unknown struct
        let mut value = BitfieldValue::new("UnknownStruct");
        value.set_u8("field", 42);

        assert!(serializer.serialize(&value).is_err());
        assert!(serializer.deserialize("UnknownStruct", &[0]).is_err());
    }
}