use anyhow::bail; pub mod matroska; pub mod read; pub mod write; #[derive(Debug, Clone)] pub enum Master { Start, End, } pub trait ValueFromBuf: Sized { fn from_buf(buf: &[u8]) -> anyhow::Result; } impl ValueFromBuf for u64 { fn from_buf(buf: &[u8]) -> anyhow::Result { if buf.len() > 8 { bail!("u64 too big") } let mut val = 0u64; for byte in buf { val <<= 8; val |= *byte as u64; } Ok(val) } } impl ValueFromBuf for i64 { fn from_buf(buf: &[u8]) -> anyhow::Result { if buf.len() > 8 { bail!("i64 too big") } Ok(if buf[0] > 127 { if buf.len() == 8 { i64::from_be_bytes(buf.try_into().unwrap()) } else { -((1 << (buf.len() * 8)) - (u64::from_buf(buf)? as i64)) } } else { u64::from_buf(buf)? as i64 }) } } impl ValueFromBuf for f64 { fn from_buf(buf: &[u8]) -> anyhow::Result { Ok(if buf.len() == 4 { f32::from_be_bytes(buf.try_into().unwrap()) as f64 } else if buf.len() == 8 { f64::from_be_bytes(buf.try_into().unwrap()) } else { bail!("float is not 4 or 8 bytes long"); }) } } impl ValueFromBuf for Vec { fn from_buf(buf: &[u8]) -> anyhow::Result { Ok(buf.to_vec()) } } impl ValueFromBuf for String { fn from_buf(buf: &[u8]) -> anyhow::Result { Ok(String::from_utf8(Vec::from(buf))?) } } impl ValueFromBuf for Master { /// this has an internal usage, where buf has len of 1, when an end should be constructed fn from_buf(buf: &[u8]) -> anyhow::Result { Ok(match buf.len() { 0 => Master::Start, 1 => Master::End, _ => unreachable!(), }) } }