brec 0.5.0

A flexible binary format for storing and streaming structured data as packets with CRC protection and recoverability from corruption. Built for extensibility and robustness.
Documentation
use std::marker::PhantomData;

use crate::*;

/// A lightweight representation of a parsed packet with block references and optional raw payload.
///
/// This structure is used when:
/// - You want to keep references to already-decoded blocks (`BR`)
/// - You don’t need to immediately decode the payload (it can remain as a raw slice)
///
/// Useful in zero-copy parsing scenarios or when working with external buffers.
///
/// # Type Parameters
/// - `B`: The original block type, implementing [`BlockDef`].
/// - `BR`: The referred/parsed block type, implementing [`BlockReferredDef<B>`].
///
/// # Fields
/// - `blocks`: A vector of referred block objects.
/// - `header`: The parsed packet header.
/// - `payload`: Optional raw payload slice (usually borrowed from a buffer).
/// - `_b`: Phantom marker to retain the `B` type.
pub struct PacketReferred<'a, B: BlockDef, BR: BlockReferredDef<B>> {
    /// Blocks represented in referred or zero-copy form.
    pub blocks: Vec<BR>,
    /// Parsed packet header.
    pub header: PacketHeader,
    /// Optional raw payload body borrowed from the source buffer.
    pub payload: Option<&'a [u8]>,
    _b: PhantomData<B>,
}

impl<B: BlockDef, BR: BlockReferredDef<B>> PacketReferred<'_, B, BR> {
    /// Constructs a new `PacketReferred` with the given blocks and header.
    ///
    /// The payload is not set by default and must be attached manually if needed.
    ///
    /// # Arguments
    /// - `blocks` - A list of parsed or referred blocks.
    /// - `header` - The parsed packet header associated with the packet.
    ///
    /// # Returns
    /// A new `PacketReferred` instance with `payload = None`.
    pub fn new(blocks: Vec<BR>, header: PacketHeader) -> Self {
        Self {
            blocks,
            header,
            payload: None,
            _b: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn packet_referred_new_initializes_fields() {
        let header = PacketHeader {
            size: 123,
            blocks_len: 45,
            payload: true,
            crc: 7,
        };
        let packet = PacketReferred::<crate::tests::TestBlock, crate::tests::TestBlock>::new(
            Vec::new(),
            header,
        );

        assert!(packet.blocks.is_empty());
        assert!(packet.payload.is_none());
        assert_eq!(packet.header.size, 123);
        assert_eq!(packet.header.blocks_len, 45);
        assert!(packet.header.payload);
        assert_eq!(packet.header.crc, 7);
    }
}