@@ -535,34 +535,55 @@ impl Encoder for FileEncoder {
535
535
// -----------------------------------------------------------------------------
536
536
537
537
pub struct MemDecoder < ' a > {
538
+ // Previously this type stored `position: usize`, but because it's staying
539
+ // safe code, that meant that reading `n` bytes meant a bounds check both
540
+ // for `position + n` *and* `position`, since there's nothing saying that
541
+ // the additions didn't wrap. Storing an iterator like this instead means
542
+ // there's no offsetting needed to get to the data, and the iterator instead
543
+ // of a slice means only increasing the start pointer on reads, rather than
544
+ // also needing to decrease the count in a slice.
545
+ // This field is first because it's touched more than `data`.
546
+ reader : std:: slice:: Iter < ' a , u8 > ,
538
547
pub data : & ' a [ u8 ] ,
539
- position : usize ,
540
548
}
541
549
542
550
impl < ' a > MemDecoder < ' a > {
543
551
#[ inline]
544
552
pub fn new ( data : & ' a [ u8 ] , position : usize ) -> MemDecoder < ' a > {
545
- MemDecoder { data, position }
553
+ let reader = data[ position..] . iter ( ) ;
554
+ MemDecoder { data, reader }
546
555
}
547
556
548
557
#[ inline]
549
558
pub fn position ( & self ) -> usize {
550
- self . position
559
+ self . data . len ( ) - self . reader . len ( )
551
560
}
552
561
553
562
#[ inline]
554
563
pub fn set_position ( & mut self , pos : usize ) {
555
- self . position = pos
564
+ self . reader = self . data [ pos.. ] . iter ( ) ;
556
565
}
557
566
558
567
#[ inline]
559
568
pub fn advance ( & mut self , bytes : usize ) {
560
- self . position += bytes;
569
+ self . reader . advance_by ( bytes) . unwrap ( ) ;
570
+ }
571
+
572
+ #[ cold]
573
+ fn panic_insufficient_data ( & self ) -> ! {
574
+ let pos = self . position ( ) ;
575
+ let len = self . data . len ( ) ;
576
+ panic ! ( "Insufficient remaining data at position {pos} (length {len})" ) ;
561
577
}
562
578
}
563
579
564
580
macro_rules! read_leb128 {
565
- ( $dec: expr, $fun: ident) => { { leb128:: $fun( $dec. data, & mut $dec. position) } } ;
581
+ ( $dec: expr, $fun: ident) => { {
582
+ let mut position = 0_usize ;
583
+ let val = leb128:: $fun( $dec. reader. as_slice( ) , & mut position) ;
584
+ let _ = $dec. reader. advance_by( position) ;
585
+ val
586
+ } } ;
566
587
}
567
588
568
589
impl < ' a > Decoder for MemDecoder < ' a > {
@@ -583,17 +604,14 @@ impl<'a> Decoder for MemDecoder<'a> {
583
604
584
605
#[ inline]
585
606
fn read_u16 ( & mut self ) -> u16 {
586
- let bytes = [ self . data [ self . position ] , self . data [ self . position + 1 ] ] ;
587
- let value = u16:: from_le_bytes ( bytes) ;
588
- self . position += 2 ;
589
- value
607
+ let bytes = self . read_raw_bytes_array :: < 2 > ( ) ;
608
+ u16:: from_le_bytes ( * bytes)
590
609
}
591
610
592
611
#[ inline]
593
612
fn read_u8 ( & mut self ) -> u8 {
594
- let value = self . data [ self . position ] ;
595
- self . position += 1 ;
596
- value
613
+ let bytes = self . read_raw_bytes_array :: < 1 > ( ) ;
614
+ u8:: from_le_bytes ( * bytes)
597
615
}
598
616
599
617
#[ inline]
@@ -618,17 +636,14 @@ impl<'a> Decoder for MemDecoder<'a> {
618
636
619
637
#[ inline]
620
638
fn read_i16 ( & mut self ) -> i16 {
621
- let bytes = [ self . data [ self . position ] , self . data [ self . position + 1 ] ] ;
622
- let value = i16:: from_le_bytes ( bytes) ;
623
- self . position += 2 ;
624
- value
639
+ let bytes = self . read_raw_bytes_array :: < 2 > ( ) ;
640
+ i16:: from_le_bytes ( * bytes)
625
641
}
626
642
627
643
#[ inline]
628
644
fn read_i8 ( & mut self ) -> i8 {
629
- let value = self . data [ self . position ] ;
630
- self . position += 1 ;
631
- value as i8
645
+ let bytes = self . read_raw_bytes_array :: < 1 > ( ) ;
646
+ i8:: from_le_bytes ( * bytes)
632
647
}
633
648
634
649
#[ inline]
@@ -663,20 +678,26 @@ impl<'a> Decoder for MemDecoder<'a> {
663
678
#[ inline]
664
679
fn read_str ( & mut self ) -> & ' a str {
665
680
let len = self . read_usize ( ) ;
666
- let sentinel = self . data [ self . position + len] ;
667
- assert ! ( sentinel == STR_SENTINEL ) ;
668
- let s = unsafe {
669
- std:: str:: from_utf8_unchecked ( & self . data [ self . position ..self . position + len] )
670
- } ;
671
- self . position += len + 1 ;
672
- s
681
+
682
+ // This cannot reuse `read_raw_bytes` as that runs into lifetime issues
683
+ // where the slice gets tied to `'b` instead of just to `'a`.
684
+ if self . reader . len ( ) <= len {
685
+ self . panic_insufficient_data ( ) ;
686
+ }
687
+ let slice = self . reader . as_slice ( ) ;
688
+ assert ! ( slice[ len] == STR_SENTINEL ) ;
689
+ self . reader . advance_by ( len + 1 ) . unwrap ( ) ;
690
+ unsafe { std:: str:: from_utf8_unchecked ( & slice[ ..len] ) }
673
691
}
674
692
675
693
#[ inline]
676
694
fn read_raw_bytes ( & mut self , bytes : usize ) -> & ' a [ u8 ] {
677
- let start = self . position ;
678
- self . position += bytes;
679
- & self . data [ start..self . position ]
695
+ if self . reader . len ( ) < bytes {
696
+ self . panic_insufficient_data ( ) ;
697
+ }
698
+ let slice = self . reader . as_slice ( ) ;
699
+ self . reader . advance_by ( bytes) . unwrap ( ) ;
700
+ & slice[ ..bytes]
680
701
}
681
702
}
682
703
0 commit comments