aboutsummaryrefslogtreecommitdiff
path: root/ebml/src
diff options
context:
space:
mode:
Diffstat (limited to 'ebml/src')
-rw-r--r--ebml/src/unflatten.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/ebml/src/unflatten.rs b/ebml/src/unflatten.rs
new file mode 100644
index 0000000..e1dd0a2
--- /dev/null
+++ b/ebml/src/unflatten.rs
@@ -0,0 +1,64 @@
+use crate::{matroska::MatroskaTag, Master};
+use anyhow::Result;
+
+pub struct Unflat<'a> {
+ pub item: MatroskaTag,
+ pub children: Option<Unflatten<'a>>,
+}
+
+pub struct Unflatten<'a> {
+ inner: &'a mut dyn Iterator<Item = Result<MatroskaTag>>,
+ stop: bool,
+ end: Option<MatroskaTag>,
+}
+
+impl<'a> Unflatten<'a> {
+ pub fn new(inner: &'a mut dyn Iterator<Item = Result<MatroskaTag>>) -> Self {
+ Self {
+ inner,
+ stop: false,
+ end: None,
+ }
+ }
+
+ pub fn next(&mut self) -> Option<Result<Unflat>> {
+ if self.stop {
+ return None;
+ }
+ match self.inner.next() {
+ None => None,
+ Some(Err(e)) => Some(Err(e)),
+ Some(Ok(item)) => {
+ let master = MatroskaTag::is_master(item.id()).unwrap();
+ if Some(&item) == self.end.as_ref() {
+ self.stop = true;
+ None
+ } else {
+ Some(Ok(Unflat {
+ children: if master {
+ let end =
+ MatroskaTag::construct_master(item.id(), Master::End).unwrap();
+ if end == item {
+ return None;
+ }
+ Some(Unflatten {
+ inner: self.inner,
+ stop: false,
+ end: Some(end),
+ })
+ } else {
+ None
+ },
+ item,
+ }))
+ }
+ }
+ }
+ }
+}
+
+impl Drop for Unflatten<'_> {
+ fn drop(&mut self) {
+ while let Some(_) = self.next() {}
+ }
+}