@@ -232,24 +232,30 @@ impl FixedSizeEncoding for Option<RawDefId> {
232232 type ByteArray = [ u8 ; 8 ] ;
233233
234234 #[ 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) ;
237238 if krate == 0 {
238239 return None ;
239240 }
240- let index = u32:: from_le_bytes ( b[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
241+ let index = u32:: from_le_bytes ( index) ;
242+
241243 Some ( RawDefId { krate : krate - 1 , index } )
242244 }
243245
244246 #[ inline]
245- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
247+ fn write_to_bytes ( self , dest : & mut [ u8 ; 8 ] ) {
246248 match self {
247249 None => unreachable ! ( ) ,
248250 Some ( RawDefId { krate, index } ) => {
249- // CrateNum is less than `CrateNum::MAX_AS_U32`.
250251 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) ;
253259 }
254260 }
255261 }
@@ -351,20 +357,11 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
351357
352358impl < T > LazyArray < T > {
353359 #[ inline]
354- fn write_to_bytes_impl ( self , b : & mut [ u8 ; 16 ] ) {
360+ fn write_to_bytes_impl ( self , dest : & mut [ u8 ; 16 ] ) {
355361 let position = ( self . position . get ( ) as u64 ) . to_le_bytes ( ) ;
356362 let len = ( self . num_elems as u64 ) . to_le_bytes ( ) ;
357363
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)
368365 }
369366
370367 fn from_bytes_impl ( position : & [ u8 ; 8 ] , meta : & [ u8 ; 8 ] ) -> Option < LazyArray < T > > {
@@ -374,20 +371,36 @@ impl<T> LazyArray<T> {
374371 }
375372}
376373
377- // Decoding helper for the encoding scheme used by `LazyArray`.
378374// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
379375// to the varint scheme that we use for tables.
380376#[ 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 {
385382 first[ i] = encoded[ 2 * i] ;
386383 second[ i] = encoded[ 2 * i + 1 ] ;
387384 }
388385 ( first, second)
389386}
390387
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+
391404impl < T > FixedSizeEncoding for LazyArray < T > {
392405 type ByteArray = [ u8 ; 16 ] ;
393406
0 commit comments