use crate::{read::ReadExt, write::write_vint}; use anyhow::Result; use std::io::Cursor; pub enum LacingType { FixedSize, Ebml, Xiph, } pub struct Block { pub track: u64, pub timestamp_off: i16, pub invisible: bool, pub lacing: Option, pub data: Vec, } impl Block { pub fn parse(buf: &[u8]) -> Result { let (track, c) = Cursor::new(buf).read_vint_len()?; let timestamp_off = i16::from_be_bytes(buf[c..c + 2].try_into().unwrap()); let flags = buf[c + 2]; let data = Vec::from(&buf[c + 3..]); let invisible = (flags & 0b10000) == 0b10000; let lacing = match flags & 0b1100 { 0b0000 => None, 0b0100 => Some(LacingType::Xiph), 0b1000 => Some(LacingType::Ebml), 0b1100 => Some(LacingType::FixedSize), _ => unreachable!(), }; Ok(Self { track, data, invisible, lacing, timestamp_off, }) } pub fn dump(&self) -> Vec { let mut out = vec![]; write_vint(&mut out, self.track).unwrap(); out.extend(self.timestamp_off.to_be_bytes().into_iter()); out.push( match self.invisible { true => 0b10000, false => 0b00000, } | match self.lacing { Some(LacingType::Xiph) => 0b0100, Some(LacingType::Ebml) => 0b1000, Some(LacingType::FixedSize) => 0b1100, None => 0b0000, }, ); out } }