Skip to content

Commit 5ddbdcb

Browse files
committed
EBML: Implement reader/Parse the header for properties
1 parent c264e49 commit 5ddbdcb

File tree

5 files changed

+376
-5
lines changed

5 files changed

+376
-5
lines changed

Diff for: src/ebml/element_reader.rs

+237
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
use crate::ebml::vint::VInt;
2+
use crate::error::Result;
3+
use crate::macros::decode_err;
4+
5+
use std::io::Read;
6+
7+
use byteorder::{BigEndian, ReadBytesExt};
8+
9+
pub struct ElementHeader {
10+
pub(crate) id: VInt,
11+
pub(crate) size: VInt,
12+
}
13+
14+
impl ElementHeader {
15+
fn read<R>(reader: &mut R, max_vint_length: u8) -> Result<Self>
16+
where
17+
R: Read,
18+
{
19+
Ok(Self {
20+
id: VInt::parse(reader, max_vint_length)?,
21+
size: VInt::parse(reader, max_vint_length)?,
22+
})
23+
}
24+
}
25+
26+
#[derive(Copy, Clone)]
27+
pub enum ElementDataType {
28+
SignedInt,
29+
UnsignedInt,
30+
Float,
31+
String,
32+
Utf8,
33+
Date,
34+
Master,
35+
Binary,
36+
}
37+
38+
#[derive(Copy, Clone)]
39+
struct MasterElement {
40+
id: ElementIdent,
41+
children: &'static [(VInt, ChildElementDescriptor)],
42+
}
43+
44+
#[derive(Copy, Clone)]
45+
pub(crate) struct ChildElementDescriptor {
46+
pub(crate) ident: ElementIdent,
47+
pub(crate) data_type: ElementDataType,
48+
}
49+
50+
macro_rules! define_master_elements {
51+
($(
52+
$_readable_ident:ident : {
53+
id: $vint_id:literal,
54+
children: [
55+
$($_readable_child_ident:ident : { $child_id:literal, $data_ty:ident }),* $(,)?
56+
] $(,)?
57+
}
58+
),+ $(,)?) => {
59+
#[derive(Copy, Clone, Eq, PartialEq)]
60+
pub(crate) enum ElementIdent {
61+
$(
62+
$_readable_ident,
63+
$($_readable_child_ident,)*
64+
)+
65+
}
66+
67+
static MASTER_ELEMENTS: once_cell::sync::Lazy<std::collections::HashMap<VInt, MasterElement>> = once_cell::sync::Lazy::new(|| {
68+
let mut m = std::collections::HashMap::new();
69+
$(
70+
m.insert(
71+
VInt($vint_id),
72+
MasterElement {
73+
id: ElementIdent::$_readable_ident,
74+
children: &[$((VInt($child_id), ChildElementDescriptor {
75+
ident: ElementIdent::$_readable_child_ident,
76+
data_type: ElementDataType::$data_ty,
77+
})),*][..]
78+
}
79+
);
80+
)+
81+
m
82+
});
83+
}
84+
}
85+
86+
define_master_elements! {
87+
EBML: {
88+
id: 0x1A45DFA3,
89+
children: [
90+
EBMLVersion: { 0x4286, UnsignedInt },
91+
EBMLReadVersion: { 0x42F7, UnsignedInt },
92+
EBMLMaxIDLength: { 0x42F2, UnsignedInt },
93+
EBMLMaxSizeLength: { 0x42F3, UnsignedInt },
94+
DocType: { 0x4282, String },
95+
DocTypeVersion: { 0x4287, UnsignedInt },
96+
DocTypeReadVersion: { 0x4285, UnsignedInt },
97+
],
98+
},
99+
DocTypeExtension: {
100+
id: 0x4281,
101+
children: [
102+
DocTypeExtensionName: { 0x4283, String },
103+
DocTypeExtensionVersion: { 0x4284, UnsignedInt },
104+
],
105+
},
106+
}
107+
108+
struct ElementReaderContext {
109+
/// Current master element
110+
current_master: Option<MasterElement>,
111+
/// Remaining length of the master element
112+
master_length: u64,
113+
/// Maximum size in octets of all element IDs
114+
max_id_length: u8,
115+
/// Maximum size in octets of all element data sizes
116+
max_size_length: u8,
117+
}
118+
119+
impl Default for ElementReaderContext {
120+
fn default() -> Self {
121+
Self {
122+
current_master: None,
123+
master_length: 0,
124+
// https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxidlength-element
125+
max_id_length: 4,
126+
// https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxsizelength-element
127+
max_size_length: 8,
128+
}
129+
}
130+
}
131+
132+
pub(crate) enum ElementReaderYield {
133+
Master((ElementIdent, u64)),
134+
Child((ChildElementDescriptor, u64)),
135+
Unknown(ElementHeader),
136+
Eof,
137+
}
138+
139+
pub struct ElementReader<R> {
140+
reader: R,
141+
ctx: ElementReaderContext,
142+
}
143+
144+
impl<R> ElementReader<R>
145+
where
146+
R: Read,
147+
{
148+
pub(crate) fn new(reader: R) -> Self {
149+
Self {
150+
reader,
151+
ctx: ElementReaderContext::default(),
152+
}
153+
}
154+
155+
pub(crate) fn set_max_id_length(&mut self, len: u8) {
156+
self.ctx.max_id_length = len
157+
}
158+
159+
pub(crate) fn set_max_size_length(&mut self, len: u8) {
160+
self.ctx.max_size_length = len
161+
}
162+
163+
fn next_master(&mut self) -> Result<ElementReaderYield> {
164+
let header = ElementHeader::read(&mut self.reader, self.ctx.max_size_length)?;
165+
let Some(master) = MASTER_ELEMENTS.get(&header.id) else {
166+
// We encountered an unknown master element
167+
return Ok(ElementReaderYield::Unknown(header));
168+
};
169+
170+
self.ctx.current_master = Some(*master);
171+
self.ctx.master_length = header.size.value();
172+
Ok(ElementReaderYield::Master((
173+
master.id,
174+
self.ctx.master_length,
175+
)))
176+
}
177+
178+
pub(crate) fn next(&mut self) -> Result<ElementReaderYield> {
179+
let Some(current_master) = self.ctx.current_master else {
180+
return self.next_master();
181+
};
182+
183+
if self.ctx.master_length == 0 {
184+
return self.next_master();
185+
}
186+
187+
let header = ElementHeader::read(&mut self.reader, self.ctx.max_size_length)?;
188+
189+
let Some((_, child)) = current_master
190+
.children
191+
.iter()
192+
.find(|(id, _)| *id == header.id)
193+
else {
194+
return Ok(ElementReaderYield::Unknown(header));
195+
};
196+
197+
Ok(ElementReaderYield::Child((*child, header.size.value())))
198+
}
199+
200+
pub(crate) fn skip(&mut self, length: u64) -> Result<()> {
201+
std::io::copy(&mut self.reader.by_ref().take(length), &mut std::io::sink())?;
202+
Ok(())
203+
}
204+
205+
pub(crate) fn read_signed_int(&mut self) -> Result<i64> {
206+
todo!()
207+
}
208+
209+
pub(crate) fn read_unsigned_int(&mut self) -> Result<u64> {
210+
todo!()
211+
}
212+
213+
pub(crate) fn read_float(&mut self, element_length: u64) -> Result<f64> {
214+
Ok(match element_length {
215+
0 => 0.0,
216+
4 => self.reader.read_f32::<BigEndian>()? as f64,
217+
8 => self.reader.read_f64::<BigEndian>()?,
218+
_ => decode_err!(@BAIL Ebml, "Invalid size for float element"),
219+
})
220+
}
221+
222+
pub(crate) fn read_string(&mut self) -> Result<String> {
223+
todo!()
224+
}
225+
226+
pub(crate) fn read_utf8(&mut self) -> Result<String> {
227+
todo!()
228+
}
229+
230+
pub(crate) fn read_date(&mut self) -> Result<String> {
231+
todo!()
232+
}
233+
234+
pub(crate) fn read_binary(&mut self) -> Result<Vec<u8>> {
235+
todo!()
236+
}
237+
}

Diff for: src/ebml/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! EBML specific items
2+
mod element_reader;
23
mod properties;
34
mod read;
45
mod tag;

Diff for: src/ebml/properties.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
11
use crate::properties::FileProperties;
22

3+
#[derive(Debug, Clone, PartialEq, Default)]
4+
pub struct EbmlHeaderProperties {
5+
pub(crate) version: u64,
6+
pub(crate) read_version: u64,
7+
pub(crate) max_id_length: u8,
8+
pub(crate) max_size_length: u8,
9+
pub(crate) doc_type: String,
10+
pub(crate) doc_type_version: u64,
11+
pub(crate) doc_type_read_version: u64,
12+
}
13+
14+
#[derive(Debug, Clone, PartialEq, Default)]
15+
pub struct EbmlExtension {
16+
pub(crate) name: String,
17+
pub(crate) version: u64,
18+
}
19+
320
/// EBML audio properties
421
#[derive(Debug, Clone, PartialEq, Default)]
5-
pub struct EbmlProperties {}
22+
pub struct EbmlProperties {
23+
pub(crate) header: EbmlHeaderProperties,
24+
pub(crate) extensions: Vec<EbmlExtension>,
25+
}
626

727
impl From<EbmlProperties> for FileProperties {
828
fn from(_input: EbmlProperties) -> Self {

0 commit comments

Comments
 (0)