@@ -255,24 +255,30 @@ impl FixedSizeEncoding for Option<RawDefId> {
255
255
type ByteArray = [ u8 ; 8 ] ;
256
256
257
257
#[ inline]
258
- fn from_bytes ( b : & [ u8 ; 8 ] ) -> Self {
259
- let krate = u32:: from_le_bytes ( b[ 0 ..4 ] . try_into ( ) . unwrap ( ) ) ;
258
+ fn from_bytes ( encoded : & [ u8 ; 8 ] ) -> Self {
259
+ let ( index, krate) = decode_interleaved ( encoded) ;
260
+ let krate = u32:: from_le_bytes ( krate) ;
260
261
if krate == 0 {
261
262
return None ;
262
263
}
263
- let index = u32:: from_le_bytes ( b[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
264
+ let index = u32:: from_le_bytes ( index) ;
265
+
264
266
Some ( RawDefId { krate : krate - 1 , index } )
265
267
}
266
268
267
269
#[ inline]
268
- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
270
+ fn write_to_bytes ( self , dest : & mut [ u8 ; 8 ] ) {
269
271
match self {
270
272
None => unreachable ! ( ) ,
271
273
Some ( RawDefId { krate, index } ) => {
272
- // CrateNum is less than `CrateNum::MAX_AS_U32`.
273
274
debug_assert ! ( krate < u32 :: MAX ) ;
274
- b[ 0 ..4 ] . copy_from_slice ( & ( 1 + krate) . to_le_bytes ( ) ) ;
275
- b[ 4 ..8 ] . copy_from_slice ( & index. to_le_bytes ( ) ) ;
275
+ // CrateNum is less than `CrateNum::MAX_AS_U32`.
276
+ let krate = ( krate + 1 ) . to_le_bytes ( ) ;
277
+ let index = index. to_le_bytes ( ) ;
278
+
279
+ // CrateNum is usually much smaller than the index within the crate, so put it in
280
+ // the second slot.
281
+ encode_interleaved ( index, krate, dest) ;
276
282
}
277
283
}
278
284
}
@@ -374,20 +380,11 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
374
380
375
381
impl < T > LazyArray < T > {
376
382
#[ inline]
377
- fn write_to_bytes_impl ( self , b : & mut [ u8 ; 16 ] ) {
383
+ fn write_to_bytes_impl ( self , dest : & mut [ u8 ; 16 ] ) {
378
384
let position = ( self . position . get ( ) as u64 ) . to_le_bytes ( ) ;
379
385
let len = ( self . num_elems as u64 ) . to_le_bytes ( ) ;
380
386
381
- // Element width is selected at runtime on a per-table basis by omitting trailing
382
- // zero bytes in table elements. This works very naturally when table elements are
383
- // simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
384
- // element would shield the trailing zeroes in the first. Interleaving the bytes
385
- // of the position and length exposes trailing zeroes in both to the optimization.
386
- // We encode length second because we generally expect it to be smaller.
387
- for i in 0 ..8 {
388
- b[ 2 * i] = position[ i] ;
389
- b[ 2 * i + 1 ] = len[ i] ;
390
- }
387
+ encode_interleaved ( position, len, dest)
391
388
}
392
389
393
390
fn from_bytes_impl ( position : & [ u8 ; 8 ] , meta : & [ u8 ; 8 ] ) -> Option < LazyArray < T > > {
@@ -397,20 +394,36 @@ impl<T> LazyArray<T> {
397
394
}
398
395
}
399
396
400
- // Decoding helper for the encoding scheme used by `LazyArray`.
401
397
// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
402
398
// to the varint scheme that we use for tables.
403
399
#[ inline]
404
- fn decode_interleaved ( encoded : & [ u8 ; 16 ] ) -> ( [ u8 ; 8 ] , [ u8 ; 8 ] ) {
405
- let mut first = [ 0u8 ; 8 ] ;
406
- let mut second = [ 0u8 ; 8 ] ;
407
- for i in 0 ..8 {
400
+ fn decode_interleaved < const N : usize , const M : usize > ( encoded : & [ u8 ; N ] ) -> ( [ u8 ; M ] , [ u8 ; M ] ) {
401
+ assert_eq ! ( M * 2 , N ) ;
402
+ let mut first = [ 0u8 ; M ] ;
403
+ let mut second = [ 0u8 ; M ] ;
404
+ for i in 0 ..M {
408
405
first[ i] = encoded[ 2 * i] ;
409
406
second[ i] = encoded[ 2 * i + 1 ] ;
410
407
}
411
408
( first, second)
412
409
}
413
410
411
+ // Element width is selected at runtime on a per-table basis by omitting trailing
412
+ // zero bytes in table elements. This works very naturally when table elements are
413
+ // simple numbers but sometimes we have a pair of integers. If naively encoded, the second element
414
+ // would shield the trailing zeroes in the first. Interleaving the bytes exposes trailing zeroes in
415
+ // both to the optimization.
416
+ //
417
+ // Prefer passing a and b such that `b` is usually smaller.
418
+ #[ inline]
419
+ fn encode_interleaved < const N : usize , const M : usize > ( a : [ u8 ; M ] , b : [ u8 ; M ] , dest : & mut [ u8 ; N ] ) {
420
+ assert_eq ! ( M * 2 , N ) ;
421
+ for i in 0 ..M {
422
+ dest[ 2 * i] = a[ i] ;
423
+ dest[ 2 * i + 1 ] = b[ i] ;
424
+ }
425
+ }
426
+
414
427
impl < T > FixedSizeEncoding for LazyArray < T > {
415
428
type ByteArray = [ u8 ; 16 ] ;
416
429
0 commit comments