@@ -107,7 +107,7 @@ ebml_master_elements! {
107107 Segment : {
108108 id: 0x1853_8067 ,
109109 children: [
110- SeekHead : { 0x114D_9B74 , Master } ,
110+ // SeekHead: { 0x114D_9B74, Master },
111111 Info : { 0x1549_A966 , Master } ,
112112 Cluster : { 0x1F43_B675 , Master } ,
113113 Tracks : { 0x1654_AE6B , Master } ,
@@ -118,12 +118,12 @@ ebml_master_elements! {
118118 } ,
119119
120120 // segment.seekHead
121- SeekHead : {
122- id: 0x114D_9B74 ,
123- children: [
124- Seek : { 0x4DBB , Master } ,
125- ] ,
126- } ,
121+ // SeekHead: {
122+ // id: 0x114D_9B74,
123+ // children: [
124+ // Seek: { 0x4DBB, Master },
125+ // ],
126+ // },
127127
128128 // segment.info
129129 Info : {
@@ -190,6 +190,33 @@ ebml_master_elements! {
190190 ] ,
191191 } ,
192192
193+ // segment.tags.tag.targets
194+ Targets : {
195+ id: 0x63C0 ,
196+ children: [
197+ TargetTypeValue : { 0x68CA , UnsignedInt } ,
198+ TargetType : { 0x63CA , String } ,
199+ TagTrackUID : { 0x63C5 , UnsignedInt } ,
200+ TagEditionUID : { 0x63C9 , UnsignedInt } ,
201+ TagChapterUID : { 0x63C4 , UnsignedInt } ,
202+ TagAttachmentUID : { 0x63C6 , UnsignedInt } ,
203+ ] ,
204+ } ,
205+
206+ // segment.tags.tag.simpleTag
207+ SimpleTag : {
208+ id: 0x67C8 ,
209+ children: [
210+ TagName : { 0x45A3 , Utf8 } ,
211+ TagLanguage : { 0x447A , String } ,
212+ TagLanguageBCP47 : { 0x447B , String } ,
213+ TagDefault : { 0x4484 , UnsignedInt } ,
214+ TagDefaultBogus : { 0x44B4 , UnsignedInt } ,
215+ TagString : { 0x4487 , Utf8 } ,
216+ TagBinary : { 0x4485 , Binary } ,
217+ ] ,
218+ } ,
219+
193220 // segment.attachments
194221 Attachments : {
195222 id: 0x1941_A469 ,
@@ -235,8 +262,13 @@ struct ElementReaderContext {
235262 /// This is set with [`ElementReader::lock`], and is used to prevent
236263 /// the reader from reading past the end of the current master element.
237264 locked : bool ,
238- /// The depth at which we are locked to
239- lock_depth : u8 ,
265+ /// The depths at which we are locked
266+ ///
267+ /// When we reach the end of one lock and unlock the reader, we need
268+ /// to know which depth to lock the reader at again (if any).
269+ ///
270+ /// This will **always** be sorted, so the current lock will be at the end.
271+ lock_depths : Vec < u8 > ,
240272 lock_len : VInt ,
241273}
242274
@@ -250,7 +282,7 @@ impl Default for ElementReaderContext {
250282 // https://www.rfc-editor.org/rfc/rfc8794.html#name-ebmlmaxsizelength-element
251283 max_size_length : 8 ,
252284 locked : false ,
253- lock_depth : 0 ,
285+ lock_depths : Vec :: with_capacity ( MAX_DEPTH as usize ) ,
254286 lock_len : VInt :: ZERO ,
255287 }
256288 }
@@ -285,6 +317,7 @@ impl ElementReaderYield {
285317 }
286318}
287319
320+ /// An EBML element reader.
288321pub struct ElementReader < R > {
289322 reader : R ,
290323 ctx : ElementReaderContext ,
@@ -308,6 +341,11 @@ where
308341 let ret = self . reader . read ( buf) ?;
309342 let len = self . current_master_length ( ) ;
310343 self . set_current_master_length ( len. saturating_sub ( ret as u64 ) ) ;
344+
345+ if self . ctx . locked {
346+ self . ctx . lock_len = self . ctx . lock_len . saturating_sub ( ret as u64 ) ;
347+ }
348+
311349 Ok ( ret)
312350 }
313351}
@@ -355,10 +393,6 @@ where
355393 return ;
356394 }
357395
358- if self . ctx . locked {
359- self . ctx . lock_len = length;
360- }
361-
362396 self . ctx . masters [ ( self . ctx . depth - 1 ) as usize ] . remaining_length = length;
363397 }
364398
@@ -405,7 +439,7 @@ where
405439 }
406440
407441 fn goto_previous_master ( & mut self ) -> Result < ( ) > {
408- if self . ctx . depth == 0 || self . ctx . depth == self . ctx . lock_depth {
442+ if self . ctx . depth == 0 || self . ctx . lock_depths . last ( ) == Some ( & self . ctx . depth ) {
409443 decode_err ! ( @BAIL Ebml , "Cannot go to previous master element, already at root" )
410444 }
411445
@@ -468,10 +502,22 @@ where
468502 pub ( crate ) fn lock ( & mut self ) {
469503 self . ctx . locked = true ;
470504 self . ctx . lock_len = self . current_master_length ( ) ;
505+ self . ctx . lock_depths . push ( self . ctx . depth ) ;
471506 }
472507
473508 pub ( crate ) fn unlock ( & mut self ) {
474- self . ctx . locked = false ;
509+ let _ = self . ctx . lock_depths . pop ( ) ;
510+
511+ let [ .., last] = & * self . ctx . lock_depths else {
512+ // We can only ever *truly* unlock if we are at the root level.
513+ log:: trace!( "Lock freed" ) ;
514+
515+ self . ctx . locked = false ;
516+ return ;
517+ } ;
518+
519+ log:: trace!( "Moving lock to depth: {}" , last) ;
520+ self . ctx . lock_len = self . ctx . masters [ ( * last - 1 ) as usize ] . remaining_length ;
475521 }
476522
477523 pub ( crate ) fn children ( & mut self ) -> ElementChildIterator < ' _ , R > {
@@ -595,6 +641,17 @@ where
595641 }
596642}
597643
644+ /// An iterator over the children of an EBML master element.
645+ ///
646+ /// This is created by calling [`ElementReader::children`].
647+ ///
648+ /// This is essentially a fancy wrapper around `ElementReader` that:
649+ ///
650+ /// * Automatically skips unknown elements ([`ElementReaderYield::Unknown`]).
651+ /// * [`Deref`]s to `ElementReader` so you can access the reader's methods.
652+ /// * Unlocks the reader when dropped.
653+ /// * If the reader is locked at multiple depths (meaning [`ElementReader::children`] was called
654+ /// multiple times), it will move the lock to the previously locked depth.
598655pub ( crate ) struct ElementChildIterator < ' a , R >
599656where
600657 R : Read ,
@@ -622,10 +679,15 @@ where
622679 }
623680
624681 pub ( crate ) fn master_exhausted ( & self ) -> bool {
625- let lock_depth = self . reader . ctx . lock_depth ;
626- assert ! ( lock_depth < self . reader. ctx. depth) ;
627-
628- self . reader . ctx . masters [ lock_depth as usize ] . remaining_length == 0
682+ let lock_depth = * self
683+ . reader
684+ . ctx
685+ . lock_depths
686+ . last ( )
687+ . expect ( "a child iterator should always have a lock depth" ) ;
688+ assert ! ( lock_depth <= self . reader. ctx. depth) ;
689+
690+ self . reader . ctx . masters [ ( lock_depth - 1 ) as usize ] . remaining_length == 0
629691 }
630692}
631693
0 commit comments