diff options
Diffstat (limited to 'ebml/src/read.rs')
-rw-r--r-- | ebml/src/read.rs | 127 |
1 files changed, 98 insertions, 29 deletions
diff --git a/ebml/src/read.rs b/ebml/src/read.rs index 3e02e18..3853782 100644 --- a/ebml/src/read.rs +++ b/ebml/src/read.rs @@ -1,11 +1,11 @@ -use anyhow::{bail, Result}; -use log::warn; +use anyhow::{anyhow, bail, Result}; +use log::{debug, warn}; use std::{ collections::VecDeque, - io::{Read, Seek}, + io::{Read, Seek, SeekFrom}, }; -use crate::matroska::MatroskaTag; +use crate::{matroska::MatroskaTag, size::EbmlSize, Master}; trait ReadAndSeek: Read + Seek {} impl<T: Read + Seek> ReadAndSeek for T {} @@ -83,10 +83,11 @@ impl EbmlReader { if let Some(end) = e.end { if self.position >= end { if self.position != end { - warn!("we missed the end") + warn!("we missed the end by {} bytes", self.position - end) } self.stack.pop(); - self.queue.push_back(MatroskaTag::parse(e.id, &[0])?); + self.queue + .push_back(MatroskaTag::construct_master(e.id, Master::End)?); } } } @@ -95,7 +96,7 @@ impl EbmlReader { let size = self.read_tag_size()?; let is_master = MatroskaTag::is_master(id)?; let tag = if is_master { - MatroskaTag::parse(id, &[])? + MatroskaTag::construct_master(id, Master::Start(size))? } else { let data = self.read_buf(size)?; MatroskaTag::parse(id, &data)? @@ -114,8 +115,11 @@ impl EbmlReader { if valid_child { break; } else { - self.queue - .push_back(MatroskaTag::parse(self.stack.pop().unwrap().id, &[0])?); + debug!("{id}"); + self.queue.push_back(MatroskaTag::construct_master( + self.stack.pop().unwrap().id, + Master::End, + )?); } } } @@ -129,6 +133,39 @@ impl EbmlReader { self.queue.push_back(tag); Ok(()) } + + /// context should be the next expected tag, such that the stack can be derived from its path. + pub fn seek(&mut self, position: usize, context: MatroskaTag) -> Result<()> { + let path = context + .path() + .ok_or(anyhow!("global tags dont give context"))?; + debug!( + "seeking to {position} with a context restored from path {:x?}", + path + ); + self.queue.clear(); + self.position = position; + self.inner.seek(SeekFrom::Start(position as u64))?; + self.stack = path + .iter() + .map(|id| StackTag { id: *id, end: None }) + .collect(); + Ok(()) + } + + pub fn collect_master(&mut self, master: MatroskaTag) -> Result<Vec<MatroskaTag>> { + let end = MatroskaTag::construct_master(master.id(), Master::End)?; + let mut out = vec![]; + while let Some(t) = self.next() { + let t = t?; + if t == end { + break; + } else { + out.push(t) + } + } + Ok(out) + } } impl Iterator for EbmlReader { @@ -146,31 +183,63 @@ impl Iterator for EbmlReader { } } -#[derive(Debug, Clone, Copy)] -pub enum EbmlSize { - Exact(usize), - Unknown, +pub trait ReadValue: Sized { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self>; } -impl EbmlSize { - pub fn from_vint((value, len): (u64, usize)) -> EbmlSize { - if value == ((1 << (7 * len)) - 1) { - Self::Unknown - } else { - Self::Exact(value as usize) + +impl ReadValue for u64 { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self> { + if buf.len() > 8 { + bail!("u64 too big") } - } - pub fn some(self) -> Option<usize> { - match self { - EbmlSize::Exact(s) => Some(s), - EbmlSize::Unknown => None, + let mut val = 0u64; + for byte in buf { + val <<= 8; + val |= *byte as u64; } + Ok(val) } } -impl Into<usize> for EbmlSize { - fn into(self) -> usize { - match self { - EbmlSize::Exact(s) => s, - EbmlSize::Unknown => panic!("unknown size, where it should have been known"), +impl ReadValue for i64 { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self> { + 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 ReadValue for f64 { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self> { + 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 ReadValue for Vec<u8> { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self> { + Ok(buf.to_vec()) + } +} +impl ReadValue for String { + fn from_buf(buf: &[u8]) -> anyhow::Result<Self> { + Ok(String::from_utf8(Vec::from(buf))?) + } +} +impl ReadValue for Master { + fn from_buf(_: &[u8]) -> anyhow::Result<Self> { + bail!("master cannot be parsed") } } |