EBML: Stub implement Segment parsing

Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
Serial 2023-11-25 12:10:54 -05:00
parent 4ff820c9da
commit ca7e3fe237
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
3 changed files with 81 additions and 17 deletions

View file

@ -106,7 +106,7 @@ pub fn ebml_master_elements(input: TokenStream) -> TokenStream {
});
TokenStream::from(quote! {
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub(crate) enum ElementIdent {
#( #identifiers_iter ),*
}

View file

@ -1,5 +1,8 @@
mod segment;
use super::EbmlFile;
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
use crate::ebml::element_reader::{ElementHeader, ElementIdent, ElementReader, ElementReaderYield};
use crate::ebml::vint::VInt;
use crate::ebml::EbmlProperties;
use crate::error::Result;
use crate::macros::decode_err;
@ -15,35 +18,38 @@ where
// new ones all scattered throughout the file
let mut properties = EbmlProperties::default();
let mut ebml_tag = None;
let mut element_reader = ElementReader::new(reader);
// First we need to go through the elements in the EBML master element
read_ebml_header(&mut element_reader, parse_options, &mut properties)?;
loop {
let ident;
let data_ty;
let size;
let res = element_reader.next()?;
match res {
ElementReaderYield::Master(_) => continue,
ElementReaderYield::Child((child, size_)) => {
ident = child.ident;
data_ty = child.data_type;
size = size_;
ElementReaderYield::Master((ElementIdent::Segment, _)) => {
ebml_tag = segment::read_from(&mut element_reader, parse_options, &mut properties)?;
break;
},
ElementReaderYield::Unknown(element) => {
log::debug!("Encountered unknown EBML element: {}", element.id.0);
element_reader.skip(element.size.value())?;
// CRC-32 (0xBF) and Void (0xEC) elements can occur at the top level.
// This is valid, and we can just skip them.
ElementReaderYield::Unknown(ElementHeader {
id: VInt(id @ (0xBF | 0xEC)),
size,
}) => {
log::debug!("Skipping global element: {:X}", id);
element_reader.skip(size.value())?;
continue;
},
ElementReaderYield::Eof => break,
_ => {
decode_err!(@BAIL Ebml, "File does not contain a segment element")
},
}
}
Ok(EbmlFile {
ebml_tag: None,
ebml_tag,
properties,
})
}
@ -78,7 +84,7 @@ where
},
ElementReaderYield::Unknown(element) => {
log::debug!(
"Encountered unknown EBML element in header: {}",
"Encountered unknown EBML element in header: {:X}",
element.id.0
);
element_reader.skip(element.size.value())?;

58
src/ebml/read/segment.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::ebml::element_reader::{ElementIdent, ElementReader, ElementReaderYield};
use crate::ebml::properties::EbmlProperties;
use crate::ebml::tag::EbmlTag;
use crate::error::Result;
use crate::macros::decode_err;
use crate::probe::ParseOptions;
use std::io::{Read, Seek};
pub(super) fn read_from<R>(
element_reader: &mut ElementReader<R>,
_parse_options: ParseOptions,
_properties: &mut EbmlProperties,
) -> Result<Option<EbmlTag>>
where
R: Read + Seek,
{
element_reader.lock();
let mut tags = None;
loop {
let res = element_reader.next()?;
match res {
ElementReaderYield::Master((id, size)) => match id {
ElementIdent::Info => todo!("Support segment.Info"),
ElementIdent::Cluster => todo!("Support segment.Cluster"),
ElementIdent::Tracks => todo!("Support segment.Tracks"),
ElementIdent::Tags => todo!("Support segment.Tags"),
ElementIdent::Attachments => todo!("Support segment.Attachments"),
ElementIdent::Chapters => todo!("Support segment.Chapters"),
_ => {
// We do not end up using information from all of the segment
// elements, so we can just skip any useless ones.
log::debug!("Skipping EBML master element: {:?}", id);
element_reader.skip(size)?;
element_reader.goto_previous_master()?;
continue;
},
},
ElementReaderYield::Unknown(element) => {
log::debug!("Skipping unknown EBML element: {:X}", element.id.0);
element_reader.skip(element.size.value())?;
continue;
},
ElementReaderYield::Eof => {
element_reader.unlock();
break;
},
_ => {
decode_err!(@BAIL Ebml, "Segment element should only contain master elements")
},
}
}
Ok(tags)
}