@@ -9,16 +9,13 @@ const VARINT_MAX_BYTES: usize = 10;
9
9
/// A `BitReader` allows for efficiently reading bits from a byte buffer, up to a byte at a time.
10
10
///
11
11
/// It works by always storing at least the next 8 bits in `bits`, which lets us conveniently
12
- /// and efficiently read bits that cross a byte boundary. It's filled with the bits from `next_byte`
13
- /// after every read operation, which is in turn replaced by the next byte from `bytes` as soon
14
- /// as the next read might read bits from `next_byte`.
12
+ /// and efficiently read bits that cross a byte boundary.
15
13
pub struct BitReader < ' a > {
16
14
/// The bytes that have not been read from yet.
17
15
bytes : & ' a [ u8 ] ,
18
- /// The next byte from `bytes` to be added to `bits`.
19
- next_byte : u8 ,
20
16
/// The next bits to be read.
21
- bits : u16 ,
17
+ bits : u64 ,
18
+
22
19
/// The number of bits in `bits` from bytes that came before `next_byte` (at least 8, at most 15).
23
20
num_bits : u32 ,
24
21
}
@@ -31,51 +28,61 @@ impl<'a> BitReader<'a> {
31
28
if bytes. last ( ) == Some ( & 0 ) {
32
29
return Err ( Error :: NotMinimal ) ;
33
30
}
31
+ let mut bits = 0u64 ;
32
+ for i in 0 ..2 {
33
+ let byte = bytes. get ( i) . unwrap_or ( & 0 ) ;
34
+ bits |= ( * byte as u64 ) << ( 8 * i) ;
35
+ }
34
36
35
- let & byte1 = bytes. get ( 0 ) . unwrap_or ( & 0 ) ;
36
- let & byte2 = bytes. get ( 1 ) . unwrap_or ( & 0 ) ;
37
- let bytes = if bytes. len ( ) > 2 { & bytes[ 2 ..] } else { & [ ] } ;
37
+ let bytes = bytes. get ( 2 ..) . unwrap_or ( & [ ] ) ;
38
38
39
39
Ok ( Self {
40
40
bytes,
41
- bits : byte1 as u16 ,
42
- next_byte : byte2,
43
- num_bits : 8 ,
41
+ bits,
42
+ num_bits : 16 ,
44
43
} )
45
44
}
46
45
47
- /// Reads a given number of bits from the buffer. Will keep returning 0 once
46
+ /// Peeks a given number of bits from the buffer.Will keep returning 0 once
48
47
/// the buffer has been exhausted.
49
- pub fn read ( & mut self , num_bits : u32 ) -> u8 {
48
+ #[ inline( always) ]
49
+ pub fn peek ( & self , num_bits : u32 ) -> u8 {
50
50
debug_assert ! ( num_bits <= 8 ) ;
51
51
52
52
// creates a mask with a `num_bits` number of 1s in order
53
53
// to get only the bits we need from `self.bits`
54
54
let mask = ( 1 << num_bits) - 1 ;
55
- let res = ( self . bits & mask) as u8 ;
55
+ ( self . bits & mask) as u8
56
+ }
56
57
57
- // removes the bits we've just read from local storage
58
- // because we don't need them anymore
58
+ /// Drops a number of bits from the buffer
59
+ #[ inline( always) ]
60
+ pub fn drop ( & mut self , num_bits : u32 ) {
61
+ debug_assert ! ( num_bits <= 8 ) ;
62
+
63
+ // removes the bits
59
64
self . bits >>= num_bits;
60
65
self . num_bits -= num_bits;
61
66
62
- // this unconditionally adds the next byte to `bits`,
63
- // regardless of whether there's enough space or not. the
64
- // point is to make sure that `bits` always contains
65
- // at least the next 8 bits to be read
66
- self . bits |= ( self . next_byte as u16 ) << self . num_bits ;
67
+ // not sure why this being outside of the if improves the performance
68
+ // bit it does, probably related to keeping caches warm
69
+ let byte = self . bytes . first ( ) . unwrap_or ( & 0 ) ;
70
+ self . bits |= ( * byte as u64 ) << self . num_bits ;
67
71
68
- // if fewer than 8 bits remain, we increment `self.num_bits`
69
- // to include the bits from `next_byte` (which is already
70
- // contained in `bits`) and we update `next_byte` with the
71
- // data to be read after that
72
+ // if fewer than 8 bits remain, we skip to loading the next byte
72
73
if self . num_bits < 8 {
73
74
self . num_bits += 8 ;
74
-
75
- let ( & next_byte, bytes) = self . bytes . split_first ( ) . unwrap_or ( ( & 0 , & [ ] ) ) ;
76
- self . next_byte = next_byte;
77
- self . bytes = bytes;
75
+ self . bytes = self . bytes . get ( 1 ..) . unwrap_or ( & [ ] ) ;
78
76
}
77
+ }
78
+
79
+ /// Reads a given number of bits from the buffer. Will keep returning 0 once
80
+ /// the buffer has been exhausted.
81
+ pub fn read ( & mut self , num_bits : u32 ) -> u8 {
82
+ debug_assert ! ( num_bits <= 8 ) ;
83
+
84
+ let res = self . peek ( num_bits) ;
85
+ self . drop ( num_bits) ;
79
86
80
87
res
81
88
}
@@ -114,36 +121,36 @@ impl<'a> BitReader<'a> {
114
121
return Ok ( None ) ;
115
122
}
116
123
117
- let prefix_0 = self . read ( 1 ) ;
118
- let len = if prefix_0 == 1 {
124
+ let peek6 = self . peek ( 6 ) ;
125
+
126
+ let len = if peek6 & 0b01 != 0 {
119
127
// Block Single (prefix 1)
128
+ self . drop ( 1 ) ;
120
129
1
130
+ } else if peek6 & 0b10 != 0 {
131
+ // Block Short (prefix 01)
132
+ let val = ( ( peek6 >> 2 ) & 0x0f ) as u64 ;
133
+ self . drop ( 6 ) ;
134
+ if val < 2 {
135
+ return Err ( Error :: NotMinimal ) ;
136
+ }
137
+ val
121
138
} else {
122
- let prefix_1 = self . read ( 1 ) ;
123
-
124
- if prefix_1 == 1 {
125
- // Block Short (prefix 01)
126
- let val = self . read ( 4 ) as u64 ;
127
- if val < 2 {
128
- return Err ( Error :: NotMinimal ) ;
129
- }
130
- val
131
- } else {
132
- // Block Long (prefix 00)
133
- let val = self . read_varint ( ) ?;
134
- if val < 16 {
135
- return Err ( Error :: NotMinimal ) ;
136
- }
137
- val
139
+ // Block Long (prefix 00)
140
+ self . drop ( 2 ) ;
141
+ let val = self . read_varint ( ) ?;
142
+ if val < 16 {
143
+ return Err ( Error :: NotMinimal ) ;
138
144
}
145
+ val
139
146
} ;
140
147
141
148
Ok ( Some ( len) )
142
149
}
143
150
144
151
/// Returns true if there are more non-zero bits to be read.
145
152
pub fn has_more ( & self ) -> bool {
146
- self . bits > 0 || self . next_byte > 0 || !self . bytes . is_empty ( )
153
+ self . bits != 0 || !self . bytes . is_empty ( )
147
154
}
148
155
}
149
156
0 commit comments