use super::{ByteWriter, LoadError, read_u32_at};
pub(crate) const TAG_PYLD: [u8; 4] = *b"PYLD";
pub(crate) const PYLD_DESC_LEN: usize = 8;
pub(crate) const PYLD_DESC_LEN_FIXED: usize = 12;
pub(crate) struct PyldDesc {
#[cfg_attr(not(feature = "stream"), allow(dead_code))]
pub(crate) desc_len: usize,
pub(crate) record_stride: usize,
}
pub(crate) fn parse_pyld_chunk(chunk: &[u8]) -> Result<(PyldDesc, &[u8]), LoadError> {
if chunk.len() < PYLD_DESC_LEN {
return Err(LoadError::Truncated);
}
let desc_len = read_u32_at(chunk, 0)? as usize;
if desc_len < PYLD_DESC_LEN || desc_len > chunk.len() {
return Err(LoadError::InvalidTree);
}
let ordering = chunk[4];
let compression = chunk[5];
if ordering != 0 || compression != 0 {
return Err(LoadError::UnsupportedVersion);
}
let record_stride = if desc_len >= PYLD_DESC_LEN_FIXED {
read_u32_at(chunk, 8)? as usize
} else {
0
};
Ok((
PyldDesc {
desc_len,
record_stride,
},
&chunk[desc_len..],
))
}
impl ByteWriter<'_> {
pub(crate) fn write_pyld_desc(&mut self, record_stride: Option<u32>) {
let desc_len = match record_stride {
Some(_) => PYLD_DESC_LEN_FIXED,
None => PYLD_DESC_LEN,
};
self.write_u32(desc_len as u32);
self.write_u8(0); self.write_u8(0); self.write_u16(0); if let Some(stride) = record_stride {
self.write_u32(stride);
}
}
}