use crate::bitstream::{BitReader, BitWriter};
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Header {
pub version: u8,
pub divergent_paths: bool,
}
impl Header {
pub const WF_REDESIGN_VERSION: u8 = 4;
pub fn write(&self, w: &mut BitWriter) {
let bits = (u64::from(self.divergent_paths) << 4) | u64::from(self.version & 0b1111);
w.write_bits(bits, 5);
}
pub fn read(r: &mut BitReader) -> Result<Self, Error> {
let bits = r.read_bits(5)?;
let divergent_paths = (bits >> 4) & 1 != 0;
let version = (bits & 0b1111) as u8;
if version != Self::WF_REDESIGN_VERSION {
return Err(Error::WireVersionMismatch { got: version });
}
Ok(Self {
version,
divergent_paths,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn header_round_trip_shared() {
let h = Header {
version: Header::WF_REDESIGN_VERSION,
divergent_paths: false,
};
let mut w = BitWriter::new();
h.write(&mut w);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
assert_eq!(Header::read(&mut r).unwrap(), h);
}
#[test]
fn header_round_trip_divergent() {
let h = Header {
version: Header::WF_REDESIGN_VERSION,
divergent_paths: true,
};
let mut w = BitWriter::new();
h.write(&mut w);
let bytes = w.into_bytes();
let mut r = BitReader::new(&bytes);
assert_eq!(Header::read(&mut r).unwrap(), h);
}
#[test]
fn header_rejects_version_mismatch() {
let bytes = vec![0x00];
let mut r = BitReader::new(&bytes);
assert!(matches!(
Header::read(&mut r),
Err(Error::WireVersionMismatch { got: 0 })
));
let bytes = vec![0x10];
let mut r = BitReader::new(&bytes);
assert!(matches!(
Header::read(&mut r),
Err(Error::WireVersionMismatch { got: 2 })
));
}
#[test]
fn header_common_case_byte_value() {
let h = Header {
version: Header::WF_REDESIGN_VERSION,
divergent_paths: false,
};
let mut w = BitWriter::new();
h.write(&mut w);
assert_eq!(w.into_bytes(), vec![0x20]);
}
}