/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2024 metamuffin */ use crate::write::vint_length; use crate::{read::ReadExt, write::write_vint}; use crate::{ReadValue, Result, WriteValue}; use std::io::{Cursor, Write}; #[derive(Debug, PartialEq, Clone, Copy)] pub enum LacingType { Xiph, FixedSize, Ebml, } #[derive(Debug, PartialEq, Clone)] pub struct Block { pub track: u64, pub keyframe: bool, pub discardable: bool, pub timestamp_off: i16, pub invisible: bool, pub lacing: Option, pub data: Vec, } impl ReadValue for Block { fn from_buf(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 & 0b1000) == 0b1000; let lacing = match flags & 0b110 { 0b000 => None, 0b010 => Some(LacingType::Xiph), 0b100 => Some(LacingType::FixedSize), 0b110 => Some(LacingType::Ebml), _ => unreachable!(), }; let keyframe = (flags & 0b10000000) == 0b10000000; let discardable = (flags & 0b1) == 0b1; Ok(Self { keyframe, discardable, track, data, invisible, lacing, timestamp_off, }) } } impl WriteValue for Block { fn write_to(&self, w: &mut impl Write) -> Result<()> { write_vint(w, self.inner_len() as u64)?; write_vint(w, self.track)?; w.write_all(&self.timestamp_off.to_be_bytes())?; w.write_all(&[match self.discardable { true => 0b1, false => 0b0, } | match self.keyframe { true => 0b10000000, false => 0b00000000, } | match self.invisible { true => 0b1000, false => 0b0000, } | match self.lacing { Some(LacingType::Xiph) => 0b010, Some(LacingType::Ebml) => 0b100, Some(LacingType::FixedSize) => 0b110, None => 0b0000, }])?; w.write_all(&self.data)?; Ok(()) } fn size(&self) -> usize { let il = self.inner_len(); vint_length(il as u64) + il } } impl Block { fn inner_len(&self) -> usize { vint_length(self.track) + 2 // timestamp + 1 // flags + self.data.len() } }