1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
use anyhow::{bail, Result};
use std::io::{Read, Seek};
use crate::matroska::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;
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))
}
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)))
}
pub fn read_tag_size(&mut self) -> Result<EbmlSize> {
Ok(EbmlSize::from_vint(self.read_vint_len()?))
}
pub fn read_tag(&mut self) -> Result<MatroskaTag> {
let id = self.read_tag_id()?;
let size = self.read_tag_size()?;
if MatroskaTag::is_master(id)? {
Ok(MatroskaTag::parse(id, &[])?)
} else {
let data = self.read_buf(size)?;
Ok(MatroskaTag::parse(id, &data)?)
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum EbmlSize {
Exact(usize),
Unknown,
}
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 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"),
}
}
}
|