use crate::SUPPORTED_VERSIONS; #[derive(Debug)] pub struct CBTHeader { pub version: u8, pub width: u16, pub height: u16, pub frame_count: u16, pub flags: CBTFlags, } #[derive(Debug)] pub struct CBTFlags { pub has_alpha_channel: bool, } #[derive(Debug)] pub enum HeaderError { TooShort, UnsupportedVersion, NotACBT, } impl CBTHeader { pub fn get_from_bytes(bytes: &[u8]) -> Result { if bytes.len() < 16 { return Err(HeaderError::TooShort); } let magic_valid = b"CBTSEX"; if &bytes[0..6] != magic_valid { return Err(HeaderError::NotACBT); } let version = bytes[6]; if !SUPPORTED_VERSIONS.contains(&version) { return Err(HeaderError::UnsupportedVersion); } let width = u16::from_le_bytes(bytes[7..9].try_into().unwrap()); let height = u16::from_le_bytes(bytes[9..11].try_into().unwrap()); let frame_count = u16::from_le_bytes(bytes[11..13].try_into().unwrap()); let flags = CBTFlags { has_alpha_channel: bytes[13] == 1, }; Ok(CBTHeader { version, width, height, frame_count, flags, }) } pub fn to_bytes(&self) -> [u8; 16] { let mut bytes = [0; 16]; // add magic let magic = b"CBTSEX"; bytes[0..magic.len()].copy_from_slice(magic); bytes[magic.len()] = self.version; bytes[magic.len() + 1..magic.len() + 3].copy_from_slice(&self.width.to_le_bytes()); bytes[magic.len() + 3..magic.len() + 5].copy_from_slice(&self.height.to_le_bytes()); bytes[magic.len() + 5..magic.len() + 7].copy_from_slice(&self.frame_count.to_le_bytes()); bytes[magic.len() + 7] = if self.flags.has_alpha_channel { 1 } else { 0 }; bytes } } impl PartialEq for CBTHeader { fn eq(&self, other: &Self) -> bool { self.version == other.version && self.width == other.width && self.height == other.height && self.frame_count == other.frame_count && self.flags == other.flags } } impl PartialEq for CBTFlags { fn eq(&self, other: &Self) -> bool { self.has_alpha_channel == other.has_alpha_channel } }