diff options
author | metamuffin <metamuffin@disroot.org> | 2023-01-16 21:54:28 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-01-16 21:54:28 +0100 |
commit | e65619de86080d72bf81ba72311dce5325976478 (patch) | |
tree | 0296089fb71550169a896dfbc7de88e33e655f86 /matroska/src | |
parent | 56cf07697695dea747b1c62768999e6237c55448 (diff) | |
download | jellything-e65619de86080d72bf81ba72311dce5325976478.tar jellything-e65619de86080d72bf81ba72311dce5325976478.tar.bz2 jellything-e65619de86080d72bf81ba72311dce5325976478.tar.zst |
stuff
Diffstat (limited to 'matroska/src')
-rw-r--r-- | matroska/src/block.rs | 43 | ||||
-rw-r--r-- | matroska/src/lib.rs | 6 | ||||
-rw-r--r-- | matroska/src/matroska.rs | 4 | ||||
-rw-r--r-- | matroska/src/read.rs | 57 | ||||
-rw-r--r-- | matroska/src/size.rs | 1 |
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), |