use nom::{
number::streaming::{be_u32, be_u64},
Err, IResult, Needed,
};
use crate::Error;
use super::*;
#[derive(Debug, Default, PartialEq)]
pub struct VrtPacket<'a> {
pub header: Header,
pub stream_id: Option<u32>,
pub class_id: Option<ClassId>,
pub tsi: Option<u32>,
pub tsf: Option<u64>,
pub payload: &'a [u8],
pub trailer: Option<Trailer>,
}
impl VrtPacket<'_> {
pub fn parse(i: &[u8]) -> IResult<&[u8], VrtPacket<'_>> {
let (i, header) = Header::parse(i)?;
let expected_size = header.packet_size as usize * size_of::<u32>();
let actual_size = i.len() + size_of::<u32>();
if actual_size < expected_size {
return Err(Err::Incomplete(Needed::new(expected_size)));
}
let mut payload_len = expected_size;
payload_len -= size_of::<u32>(); if header.t {
payload_len -= size_of::<u32>(); }
let (i, stream_id) = if matches!(
header.packet_type,
PktType::IfDataWithStream | PktType::ExtDataWithStream
) {
let (i, stream_id) = be_u32(i)?;
payload_len -= size_of_val(&stream_id);
(i, Some(stream_id))
} else {
(i, None)
};
let (i, class_id) = if header.c {
let (i, class_id) = ClassId::parse(i)?;
payload_len -= size_of_val(&class_id);
(i, Some(class_id))
} else {
(i, None)
};
let (i, tsi) = if header.tsi == Tsi::None {
(i, None)
} else {
let (i, tsi) = be_u32(i)?;
payload_len -= size_of_val(&tsi);
(i, Some(tsi))
};
let (i, tsf) = if header.tsf == Tsf::None {
(i, None)
} else {
let (i, tsf) = be_u64(i)?;
payload_len -= size_of_val(&tsf);
(i, Some(tsf))
};
let (data_payload, i) = i.split_at(payload_len);
let (i, trailer) = if header.t {
let (i, trailer) = Trailer::parse(i)?;
(i, Some(trailer))
} else {
(i, None)
};
let packet = VrtPacket {
header,
stream_id,
class_id,
tsi,
tsf,
payload: data_payload,
trailer,
};
Ok((i, packet))
}
pub fn serialize(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
let mut offset = 0;
offset += self.header.serialize(&mut buffer[offset..])?;
if let Some(stream_id) = self.stream_id {
if buffer.len() < offset + size_of::<u32>() {
return Err(Error::BufferFull);
}
buffer[offset..offset + size_of::<u32>()].copy_from_slice(&stream_id.to_be_bytes());
offset += size_of::<u32>();
}
if let Some(class_id) = self.class_id {
offset += class_id.serialize(&mut buffer[offset..])?;
}
if let Some(tsi) = self.tsi {
if buffer.len() < offset + size_of_val(&tsi) {
return Err(Error::BufferFull);
}
buffer[offset..offset + size_of_val(&tsi)].copy_from_slice(&tsi.to_be_bytes());
offset += size_of_val(&tsi);
}
if let Some(tsf) = self.tsf {
if buffer.len() < offset + size_of_val(&tsf) {
return Err(Error::BufferFull);
}
buffer[offset..offset + size_of_val(&tsf)].copy_from_slice(&tsf.to_be_bytes());
offset += size_of_val(&tsf);
}
if buffer.len() < offset + self.payload.len() {
return Err(Error::BufferFull);
}
buffer[offset..offset + self.payload.len()].copy_from_slice(self.payload);
offset += self.payload.len();
if let Some(trailer) = self.trailer {
offset += trailer.serialize(&mut buffer[offset..])?;
}
self.header.packet_size = (offset / size_of::<u32>()).try_into()?;
let _ = self.header.serialize(&mut buffer[0..])?;
Ok(offset)
}
}