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