@@ -240,24 +240,30 @@ impl FixedSizeEncoding for Option<RawDefId> {
240
240
type ByteArray = [ u8 ; 8 ] ;
241
241
242
242
#[ inline]
243
- fn from_bytes ( b : & [ u8 ; 8 ] ) -> Self {
244
- let krate = u32:: from_le_bytes ( b[ 0 ..4 ] . try_into ( ) . unwrap ( ) ) ;
243
+ fn from_bytes ( encoded : & [ u8 ; 8 ] ) -> Self {
244
+ let ( index, krate) = decode_interleaved ( encoded) ;
245
+ let krate = u32:: from_le_bytes ( krate) ;
245
246
if krate == 0 {
246
247
return None ;
247
248
}
248
- let index = u32:: from_le_bytes ( b[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
249
+ let index = u32:: from_le_bytes ( index) ;
250
+
249
251
Some ( RawDefId { krate : krate - 1 , index } )
250
252
}
251
253
252
254
#[ inline]
253
- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
255
+ fn write_to_bytes ( self , dest : & mut [ u8 ; 8 ] ) {
254
256
match self {
255
257
None => unreachable ! ( ) ,
256
258
Some ( RawDefId { krate, index } ) => {
257
- // CrateNum is less than `CrateNum::MAX_AS_U32`.
258
259
debug_assert ! ( krate < u32 :: MAX ) ;
259
- b[ 0 ..4 ] . copy_from_slice ( & ( 1 + krate) . to_le_bytes ( ) ) ;
260
- b[ 4 ..8 ] . copy_from_slice ( & index. to_le_bytes ( ) ) ;
260
+ // CrateNum is less than `CrateNum::MAX_AS_U32`.
261
+ let krate = ( krate + 1 ) . to_le_bytes ( ) ;
262
+ let index = index. to_le_bytes ( ) ;
263
+
264
+ // CrateNum is usually much smaller than the index within the crate, so put it in
265
+ // the second slot.
266
+ encode_interleaved ( index, krate, dest) ;
261
267
}
262
268
}
263
269
}
@@ -359,20 +365,11 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
359
365
360
366
impl < T > LazyArray < T > {
361
367
#[ inline]
362
- fn write_to_bytes_impl ( self , b : & mut [ u8 ; 16 ] ) {
368
+ fn write_to_bytes_impl ( self , dest : & mut [ u8 ; 16 ] ) {
363
369
let position = ( self . position . get ( ) as u64 ) . to_le_bytes ( ) ;
364
370
let len = ( self . num_elems as u64 ) . to_le_bytes ( ) ;
365
371
366
- // Element width is selected at runtime on a per-table basis by omitting trailing
367
- // zero bytes in table elements. This works very naturally when table elements are
368
- // simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
369
- // element would shield the trailing zeroes in the first. Interleaving the bytes
370
- // of the position and length exposes trailing zeroes in both to the optimization.
371
- // We encode length second because we generally expect it to be smaller.
372
- for i in 0 ..8 {
373
- b[ 2 * i] = position[ i] ;
374
- b[ 2 * i + 1 ] = len[ i] ;
375
- }
372
+ encode_interleaved ( position, len, dest)
376
373
}
377
374
378
375
fn from_bytes_impl ( position : & [ u8 ; 8 ] , meta : & [ u8 ; 8 ] ) -> Option < LazyArray < T > > {
@@ -382,20 +379,36 @@ impl<T> LazyArray<T> {
382
379
}
383
380
}
384
381
385
- // Decoding helper for the encoding scheme used by `LazyArray`.
386
382
// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
387
383
// to the varint scheme that we use for tables.
388
384
#[ inline]
389
- fn decode_interleaved ( encoded : & [ u8 ; 16 ] ) -> ( [ u8 ; 8 ] , [ u8 ; 8 ] ) {
390
- let mut first = [ 0u8 ; 8 ] ;
391
- let mut second = [ 0u8 ; 8 ] ;
392
- for i in 0 ..8 {
385
+ fn decode_interleaved < const N : usize , const M : usize > ( encoded : & [ u8 ; N ] ) -> ( [ u8 ; M ] , [ u8 ; M ] ) {
386
+ assert_eq ! ( M * 2 , N ) ;
387
+ let mut first = [ 0u8 ; M ] ;
388
+ let mut second = [ 0u8 ; M ] ;
389
+ for i in 0 ..M {
393
390
first[ i] = encoded[ 2 * i] ;
394
391
second[ i] = encoded[ 2 * i + 1 ] ;
395
392
}
396
393
( first, second)
397
394
}
398
395
396
+ // Element width is selected at runtime on a per-table basis by omitting trailing
397
+ // zero bytes in table elements. This works very naturally when table elements are
398
+ // simple numbers but sometimes we have a pair of integers. If naively encoded, the second element
399
+ // would shield the trailing zeroes in the first. Interleaving the bytes exposes trailing zeroes in
400
+ // both to the optimization.
401
+ //
402
+ // Prefer passing a and b such that `b` is usually smaller.
403
+ #[ inline]
404
+ fn encode_interleaved < const N : usize , const M : usize > ( a : [ u8 ; M ] , b : [ u8 ; M ] , dest : & mut [ u8 ; N ] ) {
405
+ assert_eq ! ( M * 2 , N ) ;
406
+ for i in 0 ..M {
407
+ dest[ 2 * i] = a[ i] ;
408
+ dest[ 2 * i + 1 ] = b[ i] ;
409
+ }
410
+ }
411
+
399
412
impl < T > FixedSizeEncoding for LazyArray < T > {
400
413
type ByteArray = [ u8 ; 16 ] ;
401
414
0 commit comments