@@ -240,24 +240,30 @@ impl FixedSizeEncoding for Option<RawDefId> {
240240 type ByteArray = [ u8 ; 8 ] ;
241241
242242 #[ 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) ;
245246 if krate == 0 {
246247 return None ;
247248 }
248- let index = u32:: from_le_bytes ( b[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
249+ let index = u32:: from_le_bytes ( index) ;
250+
249251 Some ( RawDefId { krate : krate - 1 , index } )
250252 }
251253
252254 #[ inline]
253- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
255+ fn write_to_bytes ( self , dest : & mut [ u8 ; 8 ] ) {
254256 match self {
255257 None => unreachable ! ( ) ,
256258 Some ( RawDefId { krate, index } ) => {
257- // CrateNum is less than `CrateNum::MAX_AS_U32`.
258259 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) ;
261267 }
262268 }
263269 }
@@ -359,20 +365,11 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
359365
360366impl < T > LazyArray < T > {
361367 #[ inline]
362- fn write_to_bytes_impl ( self , b : & mut [ u8 ; 16 ] ) {
368+ fn write_to_bytes_impl ( self , dest : & mut [ u8 ; 16 ] ) {
363369 let position = ( self . position . get ( ) as u64 ) . to_le_bytes ( ) ;
364370 let len = ( self . num_elems as u64 ) . to_le_bytes ( ) ;
365371
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)
376373 }
377374
378375 fn from_bytes_impl ( position : & [ u8 ; 8 ] , meta : & [ u8 ; 8 ] ) -> Option < LazyArray < T > > {
@@ -382,20 +379,36 @@ impl<T> LazyArray<T> {
382379 }
383380}
384381
385- // Decoding helper for the encoding scheme used by `LazyArray`.
386382// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
387383// to the varint scheme that we use for tables.
388384#[ 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 {
393390 first[ i] = encoded[ 2 * i] ;
394391 second[ i] = encoded[ 2 * i + 1 ] ;
395392 }
396393 ( first, second)
397394}
398395
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+
399412impl < T > FixedSizeEncoding for LazyArray < T > {
400413 type ByteArray = [ u8 ; 16 ] ;
401414
0 commit comments