use speedy::{Context, Endianness, Readable, Reader, Writable, Writer};
use crate::messages::submessages::{submessage_flag::*, submessage_kind::SubmessageKind};
#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct SubmessageHeader {
pub kind: SubmessageKind,
pub flags: u8, pub content_length: u16, }
impl<'a, C: Context> Readable<'a, C> for SubmessageHeader {
#[inline]
fn read_from<R: Reader<'a, C>>(reader: &mut R) -> Result<Self, C::Error> {
let kind: SubmessageKind = reader.read_value()?;
let flags: u8 = reader.read_value()?;
let content_length = match endianness_flag(flags) {
Endianness::LittleEndian => u16::from_le_bytes([reader.read_u8()?, reader.read_u8()?]),
Endianness::BigEndian => u16::from_be_bytes([reader.read_u8()?, reader.read_u8()?]),
};
Ok(Self {
kind,
flags,
content_length,
})
}
#[inline]
fn minimum_bytes_needed() -> usize {
std::mem::size_of::<Self>()
}
}
impl<C: Context> Writable<C> for SubmessageHeader {
#[inline]
fn write_to<T: ?Sized + Writer<C>>(&self, writer: &mut T) -> Result<(), C::Error> {
writer.write_value(&self.kind)?;
writer.write_value(&self.flags)?;
match endianness_flag(self.flags) {
speedy::Endianness::LittleEndian => {
writer.write_u8(self.content_length as u8)?;
writer.write_u8((self.content_length >> 8) as u8)?;
}
speedy::Endianness::BigEndian => {
writer.write_u8((self.content_length >> 8) as u8)?;
writer.write_u8(self.content_length as u8)?;
}
};
Ok(())
}
}
#[cfg(test)]
mod tests {
use enumflags2::BitFlags;
use super::*;
serialization_test!( type = SubmessageHeader,
{
submessage_header_big_endian_flag,
SubmessageHeader {
kind: SubmessageKind::ACKNACK,
flags: BitFlags::<ACKNACK_Flags>::from_endianness(Endianness::BigEndian).bits(),
content_length: 42,
},
le = [0x06, 0x00, 0x00, 0x2A],
be = [0x06, 0x00, 0x00, 0x2A]
},
{
submessage_header_little_endian_flag,
SubmessageHeader {
kind: SubmessageKind::ACKNACK,
flags: BitFlags::<ACKNACK_Flags>::from_endianness(Endianness::LittleEndian).bits(),
content_length: 42,
},
le = [0x06, 0x01, 0x2A, 0x00],
be = [0x06, 0x01, 0x2A, 0x00]
},
{
submessage_header_big_endian_2_bytes_length,
SubmessageHeader {
kind: SubmessageKind::ACKNACK,
flags: BitFlags::<ACKNACK_Flags>::from_endianness(Endianness::BigEndian).bits(),
content_length: 258,
},
le = [0x06, 0x00, 0x01, 0x02],
be = [0x06, 0x00, 0x01, 0x02]
},
{
submessage_header_little_endian_2_bytes_length,
SubmessageHeader {
kind: SubmessageKind::ACKNACK,
flags: BitFlags::<ACKNACK_Flags>::from_endianness(Endianness::LittleEndian).bits(),
content_length: 258,
},
le = [0x06, 0x01, 0x02, 0x01],
be = [0x06, 0x01, 0x02, 0x01]
},
{
submessage_header_wireshark,
SubmessageHeader {
kind: SubmessageKind::INFO_TS,
flags: BitFlags::<INFOTIMESTAMP_Flags>::from_endianness(Endianness::LittleEndian).bits(),
content_length: 8,
},
le = [0x09, 0x01, 0x08, 0x00],
be = [0x09, 0x01, 0x08, 0x00]
},
{
submessage_header_gap,
SubmessageHeader {
kind: SubmessageKind::GAP,
flags: BitFlags::<GAP_Flags>::from_endianness(Endianness::LittleEndian).bits(),
content_length: 7,
},
le = [0x08, 0x01, 0x07, 0x00],
be = [0x08, 0x01, 0x07, 0x00]
});
}