aboutsummaryrefslogtreecommitdiff
path: root/matroska/src/read.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-16 21:54:28 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-16 21:54:28 +0100
commite65619de86080d72bf81ba72311dce5325976478 (patch)
tree0296089fb71550169a896dfbc7de88e33e655f86 /matroska/src/read.rs
parent56cf07697695dea747b1c62768999e6237c55448 (diff)
downloadjellything-e65619de86080d72bf81ba72311dce5325976478.tar
jellything-e65619de86080d72bf81ba72311dce5325976478.tar.bz2
jellything-e65619de86080d72bf81ba72311dce5325976478.tar.zst
stuff
Diffstat (limited to 'matroska/src/read.rs')
-rw-r--r--matroska/src/read.rs57
1 files changed, 55 insertions, 2 deletions
diff --git a/matroska/src/read.rs b/matroska/src/read.rs
index 95a98b5..6849f11 100644
--- a/matroska/src/read.rs
+++ b/matroska/src/read.rs
@@ -1,6 +1,6 @@
use crate::{matroska::MatroskaTag, size::EbmlSize, Master};
use anyhow::{anyhow, bail, Result};
-use log::{debug, warn};
+use log::{debug, error, warn};
use std::{
collections::VecDeque,
io::{Read, Seek, SeekFrom},
@@ -22,6 +22,14 @@ pub struct EbmlReader {
pub position: usize,
}
+impl Read for EbmlReader {
+ fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
+ let r = self.inner.read(buf)?;
+ self.position += r;
+ Ok(r)
+ }
+}
+
impl EbmlReader {
pub fn new<T: Seek + Read + 'static>(inner: T) -> Self {
Self {
@@ -159,7 +167,22 @@ impl Iterator for EbmlReader {
} else {
match self.read_stuff() {
Ok(()) => self.next(),
- Err(e) => Some(Err(e)),
+ // in case we reached the end (error: failed to fill whole buffer),
+ // return the rest in the queue and pop all items of the stack
+ Err(e) => {
+ // TODO this is horrible, should use a custom error enum instead
+ if format!("{e}").as_str() == "failed to fill whole buffer" {
+ match self.queue.pop_front() {
+ Some(q) => Some(Ok(q)),
+ None => match self.stack.pop() {
+ Some(q) => Some(MatroskaTag::construct_master(q.id, Master::End)),
+ None => Some(Err(e)),
+ },
+ }
+ } else {
+ Some(Err(e))
+ }
+ }
}
}
}
@@ -225,3 +248,33 @@ impl ReadValue for Master {
panic!("master shall not be read like this")
}
}
+
+pub trait ReadExt: Read {
+ fn read_byte(&mut self) -> Result<u8>;
+ fn read_vint_len(&mut self) -> Result<(u64, usize)>;
+ fn read_vint(&mut self) -> Result<u64>;
+}
+impl<T: Read> ReadExt for T {
+ fn read_byte(&mut self) -> Result<u8> {
+ let mut b = [0u8];
+ self.read_exact(&mut b)?;
+ Ok(b[0])
+ }
+ fn read_vint_len(&mut self) -> Result<(u64, usize)> {
+ let s = self.read_byte()?;
+ let len = s.leading_zeros() + 1;
+ if len > 8 {
+ bail!("varint too long");
+ }
+ let mut value = s as u64;
+ value -= 1 << (8 - len);
+ for _ in 1..len {
+ value <<= 8;
+ value += self.read_byte()? as u64;
+ }
+ Ok((value, len as usize))
+ }
+ fn read_vint(&mut self) -> Result<u64> {
+ Ok(self.read_vint_len()?.0)
+ }
+}