@@ -377,17 +377,25 @@ impl StructAsBytes for EndTag {
377377 }
378378}
379379
380+ /// Iterates the MBI's tags from the first tag to the end tag.
380381#[ derive( Clone , Debug ) ]
381382pub struct TagIter < ' a > {
383+ /// Pointer to the next tag. Updated in each iteration.
382384 pub current : * const Tag ,
383- phantom : PhantomData < & ' a Tag > ,
385+ /// The pointer right after the MBI. Used for additional bounds checking.
386+ end_ptr_exclusive : * const u8 ,
387+ /// Lifetime capture of the MBI's memory.
388+ _mem : PhantomData < & ' a ( ) > ,
384389}
385390
386391impl < ' a > TagIter < ' a > {
387- pub fn new ( first : * const Tag ) -> Self {
392+ /// Creates a new iterator
393+ pub fn new ( mem : & ' a [ u8 ] ) -> Self {
394+ assert_eq ! ( mem. as_ptr( ) . align_offset( 8 ) , 0 ) ;
388395 TagIter {
389- current : first,
390- phantom : PhantomData ,
396+ current : mem. as_ptr ( ) . cast ( ) ,
397+ end_ptr_exclusive : unsafe { mem. as_ptr ( ) . add ( mem. len ( ) ) } ,
398+ _mem : PhantomData ,
391399 }
392400 }
393401}
@@ -396,17 +404,25 @@ impl<'a> Iterator for TagIter<'a> {
396404 type Item = & ' a Tag ;
397405
398406 fn next ( & mut self ) -> Option < & ' a Tag > {
399- match unsafe { & * self . current } {
407+ // This never failed so far. But better be safe.
408+ assert ! ( self . current. cast:: <u8 >( ) < self . end_ptr_exclusive) ;
409+
410+ let tag = unsafe { & * self . current } ;
411+ match tag {
400412 & Tag {
401413 // END-Tag
402414 typ : TagTypeId ( 0 ) ,
403415 size : 8 ,
404416 } => None , // end tag
405417 tag => {
418+ // We return the tag and update self.current already to the next
419+ // tag.
420+
421+ // next pointer (rounded up to 8-byte alignment)
422+ let ptr_offset = ( tag. size as usize + 7 ) & !7 ;
423+
406424 // go to next tag
407- let mut tag_addr = self . current as usize ;
408- tag_addr += ( ( tag. size + 7 ) & !7 ) as usize ; //align at 8 byte
409- self . current = tag_addr as * const _ ;
425+ self . current = unsafe { self . current . cast :: < u8 > ( ) . add ( ptr_offset) . cast :: < Tag > ( ) } ;
410426
411427 Some ( tag)
412428 }
0 commit comments