Skip to content

Commit

Permalink
EBML: Stub implement Segment parsing
Browse files Browse the repository at this point in the history
Signed-off-by: Serial <[email protected]>
  • Loading branch information
Serial-ATA committed Nov 25, 2023
1 parent ac4fc48 commit 409d482
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 17 deletions.
2 changes: 1 addition & 1 deletion lofty_attr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,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 ),*
}
Expand Down
38 changes: 22 additions & 16 deletions src/ebml/read.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
})
}
Expand Down Expand Up @@ -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())?;
Expand Down
58 changes: 58 additions & 0 deletions src/ebml/read/segment.rs
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 409d482

Please sign in to comment.