use crate::check::Check;
use crate::error::{Error, Result};
use crate::io::Reader;
pub const LAYR_HEADER_LEN: usize = 4;
pub const LAYR_VERSION: u32 = 1;
pub fn parse(payload: &[u8]) -> Result<(&[u8], u32)> {
let mut r = Reader::checked(payload, Check::LayrVersion);
let layr_version = r.u32()?;
if layr_version != LAYR_VERSION {
return Err(Error::new(
Check::LayrVersion,
format!("unsupported layr_version {layr_version}"),
));
}
Ok((&payload[LAYR_HEADER_LEN..], layr_version))
}
pub fn frame(payload: &[u8]) -> Result<&[u8]> {
parse(payload).map(|(frame, _)| frame)
}
pub fn to_bytes(frame: &[u8]) -> Vec<u8> {
let mut out = crate::io::Writer::with_capacity(LAYR_HEADER_LEN + frame.len());
out.u32(LAYR_VERSION);
out.bytes(frame);
out.into_vec()
}
pub fn container_len(frame_len: usize) -> u64 {
(LAYR_HEADER_LEN + frame_len) as u64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_payload_is_a_version_then_the_frame() {
let payload = to_bytes(b"a zstd frame");
assert_eq!(payload.len(), LAYR_HEADER_LEN + 12);
assert_eq!(&payload[..4], &1u32.to_le_bytes());
assert_eq!(frame(&payload).unwrap(), b"a zstd frame");
assert_eq!(parse(&payload).unwrap().1, 1);
assert_eq!(container_len(12), payload.len() as u64);
}
#[test]
fn a_bad_version_or_a_short_payload_is_rejected() {
let mut bad = to_bytes(b"frame");
bad[0..4].copy_from_slice(&2u32.to_le_bytes());
assert_eq!(frame(&bad).unwrap_err().check(), Check::LayrVersion);
assert_eq!(
frame(&[1, 0, 0]).unwrap_err().check(),
Check::LayrVersion,
"a payload shorter than the version field"
);
assert_eq!(frame(&to_bytes(b"")).unwrap(), b"");
}
}