awdl-frame-parser 0.4.1

A parser for AWDL data and action frames.
Documentation
use ether_type::EtherType;
use scroll::{
    ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
    Endian, Pread, Pwrite,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AWDLDataFrame<P> {
    pub sequence_number: u16,
    pub ether_type: EtherType,
    pub payload: P,
}
impl<P: MeasureWith<()>> MeasureWith<()> for AWDLDataFrame<P> {
    fn measure_with(&self, ctx: &()) -> usize {
        8 + self.payload.measure_with(ctx)
    }
}
impl<'a> TryFromCtx<'a> for AWDLDataFrame<&'a [u8]> {
    type Error = scroll::Error;
    fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
        let mut offset = 0;
        let header_data = from.gread::<[u8; 2]>(&mut offset)?;
        if header_data != [0x03, 0x04] {
            return Err(scroll::Error::BadInput {
                size: offset,
                msg: "Unknown header format.",
            });
        }
        let sequence_number = from.gread_with(&mut offset, Endian::Little)?;
        offset += 2;
        let ether_type = EtherType::from_bits(from.gread_with(&mut offset, Endian::Big)?);
        let payload_len = from.len() - offset;
        let payload = from.gread_with(&mut offset, payload_len)?;
        Ok((
            Self {
                sequence_number,
                ether_type,
                payload,
            },
            offset,
        ))
    }
}
impl<P: TryIntoCtx<Error = scroll::Error>> TryIntoCtx for AWDLDataFrame<P> {
    type Error = scroll::Error;
    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
        let mut offset = 0;

        buf.gwrite::<[u8; 2]>([0x03, 0x04], &mut offset)?;
        buf.gwrite_with(self.sequence_number, &mut offset, Endian::Little)?;
        offset += 2;
        buf.gwrite_with(
            self.ether_type.into_bits(),
            &mut offset,
            Endian::Big,
        )?;
        buf.gwrite(self.payload, &mut offset)?;

        Ok(offset)
    }
}
#[test]
fn test_data_frame() {
    use alloc::vec;
    let bytes = include_bytes!("../test_bins/data_frame.bin");
    let data_frame = bytes.pread::<AWDLDataFrame<&[u8]>>(0).unwrap();
    assert_eq!(
        data_frame,
        AWDLDataFrame {
            sequence_number: 2981,
            ether_type: EtherType::IPv6,
            payload: &bytes[8..]
        }
    );
    let mut buf = vec![0x00u8; data_frame.measure_with(&())];
    buf.pwrite(data_frame, 0).unwrap();
    assert_eq!(bytes, buf.as_slice());
}