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! { TokenStream::from(quote! {
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub(crate) enum ElementIdent { pub(crate) enum ElementIdent {
#( #identifiers_iter ),* #( #identifiers_iter ),*
} }

View file

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