aboutsummaryrefslogtreecommitdiff
path: root/ebml/src/read.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-14 18:04:16 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-14 18:04:16 +0100
commitf452df18749b13f9d83a6ea679361d195b4a9ae1 (patch)
tree04897eef044ebed319949a0cdbd04232f0dce98c /ebml/src/read.rs
parent6c023ddeaa0894813fc74038af7568c2d867c052 (diff)
downloadjellything-f452df18749b13f9d83a6ea679361d195b4a9ae1.tar
jellything-f452df18749b13f9d83a6ea679361d195b4a9ae1.tar.bz2
jellything-f452df18749b13f9d83a6ea679361d195b4a9ae1.tar.zst
seeking and broken writing
Diffstat (limited to 'ebml/src/read.rs')
-rw-r--r--ebml/src/read.rs127
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")
}
}