Zerocopy - what to do with the body of a packet

Hi!
I am trying out zerocopy for parsing netflow aggregation data (version 8). I am reading the header OK but not sure what to do with the body

How do you deal with packets that have a fixed header and variable amount of records in the body? Basically I think it is going to look like:

#[derive(Debug, FromBytes, Unaligned)]
#[repr(C)]
pub struct NetflowV8Header {
    [...]
}

#[derive(Debug, FromBytes, Unaligned)]
#[repr(C)]
pub struct NetflowV8AsAggregationRecord {
   [...]
}

struct NetflowV8Packet<B> {
    header: LayoutVerified<B, NetflowV8Header>,
    records: Vec<NetflowV8AsAggregationPacket<B>>,
}

impl<B: ByteSlice> NetflowV8Packet<B> {
    pub fn parse(bytes: B) -> Option<NetflowV8Packet<B>> {
        let (header, remaining) = LayoutVerified::new_unaligned_from_prefix(bytes)?;

        let records = vec!();
        while let Some(aggregation_packet) = NetflowV8AsAggregationPacket::parse(&remaining[..]) {
            records.push(aggregation_packet);
        }

        Some(NetflowV8Packet { header, records })
    }
}

struct NetflowV8AsAggregationPacket<B> {
    records: LayoutVerified<B, NetflowV8AsAggregationRecord>,
    body: B,
}

impl<B: ByteSlice> NetflowV8AsAggregationPacket<B> {
     pub fn parse(bytes: B) -> Option<NetflowV8AsAggregationPacket<B>> {
        let (records, body) = LayoutVerified::new_unaligned_from_prefix(bytes)?;

        Some(NetflowV8AsAggregationPacket { records, body })
     }
}

I think I'm close but I get this error

error[E0308]: mismatched types
  --> src/netflow_v8_z.rs:67:40
   |
67 |         Some(NetflowV8Packet { header, records })
   |                                        ^^^^^^^ expected type parameter, found &[u8]
   |
   = note: expected type `std::vec::Vec<netflow_v8_z::NetflowV8AsAggregationPacket<B>>`
              found type `std::vec::Vec<netflow_v8_z::NetflowV8AsAggregationPacket<&[u8]>>`

Can someone please let me know if this is even the right approach? :slight_smile:

When you have a function with a type argument, such as B in your case, you don't choose that type. The type is forced on you by the caller of the function.

So you can't assign &[u8] to B, because the caller of the function could have demanded that B is some other type that implements ByteSlice.

If you write impl<'a> NetflowV8AsAggregationPacket<&'a [u8]>, you'll be able to return that, but you might run into limitations of specialization.

2 Likes

Thanks for the explanation. I wasn't able to wrangle the types so I've gone back to my nom implementation even though this way felt a bit nicer (at least for the header).