#[derive(Debug, Clone, Copy)]
pub struct Header {
pub property: super::Property,
pub sequence: Option<u16>,
pub fragment: Option<super::Fragment>,
}
impl Header {
pub fn with_prop(property: super::Property) -> Self {
Self {
property,
sequence: None,
fragment: None,
}
}
pub fn len(&self) -> usize {
if self.fragment.is_some() {
9
} else if self.is_sequenced() {
3
} else {
1
}
}
pub fn is_sequenced(&self) -> bool {
self.property.is_sequenced()
}
pub fn is_client_data(&self) -> bool {
self.property.is_client_data()
}
pub(crate) fn parse(slice: &[u8]) -> std::io::Result<Self> {
if !slice.is_empty() {
let flags = slice[0];
let property = super::Property::try_from(flags & 0x7F)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
let sequence = if property.is_sequenced() {
if slice.len() >= 3 {
Some(u16::from_le_bytes([slice[1], slice[2]]))
} else {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Data to parse is not long enough for sequence number"));
}
} else {
None
};
let fragment = if (flags & 0x80) != 0 {
Some(super::Fragment::parse(slice)?)
} else {
None
};
Ok(Self {
property,
sequence,
fragment,
})
} else {
Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Data to parse is empty"))
}
}
pub(crate) fn dump<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
let mut total_bytes = 1;
let flags = (self.property as u8) | if self.fragment.is_some() { 0x80 } else { 0x00 };
writer.write_all(&[flags])?;
if let Some(seq) = self.sequence {
writer.write_all(&seq.to_le_bytes())?;
total_bytes += 2;
} else if self.fragment.is_some() {
writer.write_all(&0u16.to_le_bytes())?;
total_bytes += 2;
}
if let Some(frag) = self.fragment {
total_bytes += frag.dump(writer)?;
}
Ok(total_bytes)
}
}