Skip to content

Commit 409d482

Browse files
committed
EBML: Stub implement Segment parsing
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
1 parent ac4fc48 commit 409d482

File tree

3 files changed

+81
-17
lines changed

3 files changed

+81
-17
lines changed

lofty_attr/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub fn ebml_master_elements(input: TokenStream) -> TokenStream {
134134
});
135135

136136
TokenStream::from(quote! {
137-
#[derive(Copy, Clone, Eq, PartialEq)]
137+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
138138
pub(crate) enum ElementIdent {
139139
#( #identifiers_iter ),*
140140
}

src/ebml/read.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
mod segment;
2+
13
use super::EbmlFile;
2-
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
4+
use crate::ebml::element_reader::{ElementHeader, ElementIdent, ElementReader, ElementReaderYield};
5+
use crate::ebml::vint::VInt;
36
use crate::ebml::EbmlProperties;
47
use crate::error::Result;
58
use crate::macros::decode_err;
@@ -15,35 +18,38 @@ where
1518
// new ones all scattered throughout the file
1619
let mut properties = EbmlProperties::default();
1720

21+
let mut ebml_tag = None;
22+
1823
let mut element_reader = ElementReader::new(reader);
1924

2025
// First we need to go through the elements in the EBML master element
2126
read_ebml_header(&mut element_reader, parse_options, &mut properties)?;
2227

2328
loop {
24-
let ident;
25-
let data_ty;
26-
let size;
27-
2829
let res = element_reader.next()?;
2930
match res {
30-
ElementReaderYield::Master(_) => continue,
31-
ElementReaderYield::Child((child, size_)) => {
32-
ident = child.ident;
33-
data_ty = child.data_type;
34-
size = size_;
31+
ElementReaderYield::Master((ElementIdent::Segment, _)) => {
32+
ebml_tag = segment::read_from(&mut element_reader, parse_options, &mut properties)?;
33+
break;
3534
},
36-
ElementReaderYield::Unknown(element) => {
37-
log::debug!("Encountered unknown EBML element: {}", element.id.0);
38-
element_reader.skip(element.size.value())?;
35+
// CRC-32 (0xBF) and Void (0xEC) elements can occur at the top level.
36+
// This is valid, and we can just skip them.
37+
ElementReaderYield::Unknown(ElementHeader {
38+
id: VInt(id @ (0xBF | 0xEC)),
39+
size,
40+
}) => {
41+
log::debug!("Skipping global element: {:X}", id);
42+
element_reader.skip(size.value())?;
3943
continue;
4044
},
41-
ElementReaderYield::Eof => break,
45+
_ => {
46+
decode_err!(@BAIL Ebml, "File does not contain a segment element")
47+
},
4248
}
4349
}
4450

4551
Ok(EbmlFile {
46-
ebml_tag: None,
52+
ebml_tag,
4753
properties,
4854
})
4955
}
@@ -78,7 +84,7 @@ where
7884
},
7985
ElementReaderYield::Unknown(element) => {
8086
log::debug!(
81-
"Encountered unknown EBML element in header: {}",
87+
"Encountered unknown EBML element in header: {:X}",
8288
element.id.0
8389
);
8490
element_reader.skip(element.size.value())?;

src/ebml/read/segment.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
2+
use crate::ebml::properties::EbmlProperties;
3+
use crate::ebml::tag::EbmlTag;
4+
use crate::error::Result;
5+
use crate::macros::decode_err;
6+
use crate::probe::ParseOptions;
7+
8+
use std::io::{Read, Seek};
9+
10+
pub(super) fn read_from<R>(
11+
element_reader: &mut ElementReader<R>,
12+
_parse_options: ParseOptions,
13+
_properties: &mut EbmlProperties,
14+
) -> Result<Option<EbmlTag>>
15+
where
16+
R: Read + Seek,
17+
{
18+
element_reader.lock();
19+
20+
let mut tags = None;
21+
22+
loop {
23+
let res = element_reader.next()?;
24+
match res {
25+
ElementReaderYield::Master((id, size)) => match id {
26+
ElementIdent::Info => todo!("Support segment.Info"),
27+
ElementIdent::Cluster => todo!("Support segment.Cluster"),
28+
ElementIdent::Tracks => todo!("Support segment.Tracks"),
29+
ElementIdent::Tags => todo!("Support segment.Tags"),
30+
ElementIdent::Attachments => todo!("Support segment.Attachments"),
31+
ElementIdent::Chapters => todo!("Support segment.Chapters"),
32+
_ => {
33+
// We do not end up using information from all of the segment
34+
// elements, so we can just skip any useless ones.
35+
36+
log::debug!("Skipping EBML master element: {:?}", id);
37+
element_reader.skip(size)?;
38+
element_reader.goto_previous_master()?;
39+
continue;
40+
},
41+
},
42+
ElementReaderYield::Unknown(element) => {
43+
log::debug!("Skipping unknown EBML element: {:X}", element.id.0);
44+
element_reader.skip(element.size.value())?;
45+
continue;
46+
},
47+
ElementReaderYield::Eof => {
48+
element_reader.unlock();
49+
break;
50+
},
51+
_ => {
52+
decode_err!(@BAIL Ebml, "Segment element should only contain master elements")
53+
},
54+
}
55+
}
56+
57+
Ok(tags)
58+
}

0 commit comments

Comments
 (0)