diff options
Diffstat (limited to 'ebml/src/read.rs')
-rw-r--r-- | ebml/src/read.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/ebml/src/read.rs b/ebml/src/read.rs new file mode 100644 index 0000000..0ffb24c --- /dev/null +++ b/ebml/src/read.rs @@ -0,0 +1,96 @@ +use std::io::{Read, Seek}; + +use anyhow::{bail, Result}; +use log::debug; +use webm_iterable::matroska_spec::MatroskaSpec; + +use crate::format::matroska::{Master, MatroskaTag}; + +trait ReadAndSeek: Read + Seek {} +impl<T: Read + Seek> ReadAndSeek for T {} + +pub struct EbmlReader { + inner: Box<dyn ReadAndSeek>, + pub position: usize, +} + +pub trait EbmlRead: Sized { + fn read(r: &mut EbmlReader) -> Result<Self>; +} + +impl EbmlReader { + pub fn new<T: Seek + Read + 'static>(inner: T) -> Self { + Self { + inner: Box::new(inner), + position: 0, + } + } + + pub fn read_byte(&mut self) -> Result<u8> { + let mut b = [0u8]; + self.inner.read_exact(&mut b)?; + self.position += 1; + Ok(b[0]) + } + pub fn read_buf(&mut self, size: impl Into<usize>) -> Result<Vec<u8>> { + let size = size.into(); + let mut b = vec![0u8; size]; + self.inner.read_exact(&mut b)?; + self.position += size; + Ok(b) + } + pub fn read_vint_len(&mut self) -> Result<(u64, usize)> { + let s = self.read_byte()?; + let len = s.leading_zeros() + 1; + let mut value = s as u64; + value -= 1 << (8 - len); + for _ in 0..(len - 1) { + value <<= 8; + value += self.read_byte()? as u64; + } + Ok((value, len as usize)) + } + pub fn read_vint(&mut self) -> Result<u64> { + Ok(self.read_vint_len()?.0) + } + pub fn read_utf8(&mut self, size: impl Into<usize>) -> Result<String> { + let b = self.read_buf(size)?; + Ok(String::from_utf8(b)?) + } + + pub fn read_tag_id(&mut self) -> Result<u64> { + let (value, len) = self.read_vint_len()?; + Ok(value + (1 << (7 * len))) + } +} + +#[derive(Debug, Clone, Copy)] +pub enum EbmlSize { + Exact(usize), + Unknown, +} +impl EbmlSize { + #[rustfmt::skip] + pub fn from_vint((value, len): (u64, usize)) -> EbmlSize { + match len { + 1 => if value == ((1 << (7)) - 1) { return Self::Unknown; }, + 2 => if value == ((1 << (7 * 2)) - 1) { return Self::Unknown; }, + 3 => if value == ((1 << (7 * 3)) - 1) { return Self::Unknown; }, + 4 => if value == ((1 << (7 * 4)) - 1) { return Self::Unknown; }, + 5 => if value == ((1 << (7 * 5)) - 1) { return Self::Unknown; }, + 6 => if value == ((1 << (7 * 6)) - 1) { return Self::Unknown; }, + 7 => if value == ((1 << (7 * 7)) - 1) { return Self::Unknown; }, + 8 => if value == ((1 << (7 * 8)) - 1) { return Self::Unknown; }, + _ => {}, + } + Self::Exact(len) + } +} +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"), + } + } +} |