use std::io::Cursor; use std::sync::Arc; use webm::*; #[derive(Clone)] pub enum Chunk = Vec> { Headers { bytes: Arc }, ClusterHead { keyframe: bool, start: u64, end: u64, // space for a Cluster tag and a Timecode tag bytes: [u8;16], bytes_used: u8 }, ClusterBody { bytes: Arc } } impl> Chunk { pub fn new_cluster_head(timecode: u64) -> Chunk { let mut chunk = Chunk::ClusterHead { keyframe: false, start: 0, end: 0, bytes: [0;16], bytes_used: 0 }; chunk.update_timecode(timecode); chunk } pub fn update_timecode(&mut self, timecode: u64) { if let &mut Chunk::ClusterHead {ref mut start, ref mut end, ref mut bytes, ref mut bytes_used, ..} = self { let delta = *end - *start; *start = timecode; *end = *start + delta; let mut cursor = Cursor::new(bytes as &mut [u8]); // buffer is sized so these should never fail encode_webm_element(&WebmElement::Cluster, &mut cursor).unwrap(); encode_webm_element(&WebmElement::Timecode(timecode), &mut cursor).unwrap(); *bytes_used = cursor.position() as u8; } } pub fn extend_timespan(&mut self, timecode: u64) { if let &mut Chunk::ClusterHead {start, ref mut end, ..} = self { if timecode > start { *end = timecode; } } } pub fn mark_keyframe(&mut self, new_keyframe: bool) { if let &mut Chunk::ClusterHead {ref mut keyframe, ..} = self { *keyframe = new_keyframe; } } } impl> AsRef<[u8]> for Chunk { fn as_ref(&self) -> &[u8] { match self { &Chunk::Headers {ref bytes, ..} => bytes.as_ref().as_ref(), &Chunk::ClusterHead {ref bytes, bytes_used, ..} => bytes[..bytes_used as usize].as_ref(), &Chunk::ClusterBody {ref bytes, ..} => bytes.as_ref().as_ref() } } } #[cfg(test)] mod tests { use chunk::*; #[test] fn enough_space_for_header() { let mut chunk: Chunk = Chunk::ClusterHead { keyframe: false, start: 0, end: 0, bytes: [0;16] }; chunk.update_timecode(u64::max_value()); } }