aboutsummaryrefslogtreecommitdiff
path: root/matroska
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
parent56cf07697695dea747b1c62768999e6237c55448 (diff)
downloadjellything-e65619de86080d72bf81ba72311dce5325976478.tar
jellything-e65619de86080d72bf81ba72311dce5325976478.tar.bz2
jellything-e65619de86080d72bf81ba72311dce5325976478.tar.zst
stuff
Diffstat (limited to 'matroska')
-rw-r--r--matroska/src/block.rs43
-rw-r--r--matroska/src/lib.rs6
-rw-r--r--matroska/src/matroska.rs4
-rw-r--r--matroska/src/read.rs57
-rw-r--r--matroska/src/size.rs1
5 files changed, 103 insertions, 8 deletions
diff --git a/matroska/src/block.rs b/matroska/src/block.rs
index e69de29..b0d6f6b 100644
--- a/matroska/src/block.rs
+++ b/matroska/src/block.rs
@@ -0,0 +1,43 @@
+use crate::read::ReadExt;
+use anyhow::Result;
+use std::io::Cursor;
+
+pub enum LacingType {
+ FixedSize,
+ Ebml,
+ Xiph,
+}
+
+pub struct Block {
+ pub track: u64,
+ pub timestamp_off: i16,
+ pub invisible: bool,
+ pub lacing: Option<LacingType>,
+ pub data: Vec<u8>,
+}
+
+impl Block {
+ pub fn parse(buf: &[u8]) -> Result<Self> {
+ let (track, c) = Cursor::new(buf).read_vint_len()?;
+ let timestamp_off = i16::from_be_bytes(buf[c..c + 2].try_into().unwrap());
+ let flags = buf[c + 2];
+ let data = Vec::from(&buf[c + 3..]);
+
+ let invisible = (flags & 0b10000) == 0b10000;
+ let lacing = match flags & 0b1100 {
+ 0b0000 => None,
+ 0b0100 => Some(LacingType::Xiph),
+ 0b1000 => Some(LacingType::Ebml),
+ 0b1100 => Some(LacingType::FixedSize),
+ _ => unreachable!(),
+ };
+
+ Ok(Self {
+ track,
+ data,
+ invisible,
+ lacing,
+ timestamp_off,
+ })
+ }
+}
diff --git a/matroska/src/lib.rs b/matroska/src/lib.rs
index d1e0fba..0bc9cc3 100644
--- a/matroska/src/lib.rs
+++ b/matroska/src/lib.rs
@@ -1,11 +1,11 @@
+pub mod block;
pub mod matroska;
pub mod read;
pub mod size;
-pub mod write;
pub mod unflatten;
-pub mod block;
+pub mod write;
-use matroska::MatroskaTag;
+pub use matroska::MatroskaTag;
pub use read::ReadValue;
pub use write::WriteValue;
diff --git a/matroska/src/matroska.rs b/matroska/src/matroska.rs
index b4078ab..8d63d90 100644
--- a/matroska/src/matroska.rs
+++ b/matroska/src/matroska.rs
@@ -108,7 +108,7 @@ define_ebml! {
SimpleBlock[0xA3]: Binary,
Timestamp[0xE7]: Uint,
},
-
+
Cues[0x1C53BB6B]: {
CuePoint[0xBB]: {
CueTime[0xB3]: Uint,
@@ -327,4 +327,4 @@ define_ebml! {
},
},
},
-} \ No newline at end of file
+}
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)
+ }
+}
diff --git a/matroska/src/size.rs b/matroska/src/size.rs
index e774f0a..a2ca61d 100644
--- a/matroska/src/size.rs
+++ b/matroska/src/size.rs
@@ -1,4 +1,3 @@
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EbmlSize {
Exact(usize),