@@ -346,6 +346,12 @@ impl<T> LazyArray<T> {
346346 let position = ( self . position . get ( ) as u64 ) . to_le_bytes ( ) ;
347347 let len = ( self . num_elems as u64 ) . to_le_bytes ( ) ;
348348
349+ // Element width is selected at runtime on a per-table basis by omitting trailing
350+ // zero bytes in table elements. This works very naturally when table elements are
351+ // simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
352+ // element would shield the trailing zeroes in the first. Interleaving the bytes
353+ // of the position and length exposes trailing zeroes in both to the optimization.
354+ // We encode length second because we generally expect it to be smaller.
349355 for i in 0 ..8 {
350356 b[ 2 * i] = position[ i] ;
351357 b[ 2 * i + 1 ] = len[ i] ;
@@ -359,18 +365,26 @@ impl<T> LazyArray<T> {
359365 }
360366}
361367
368+ // Decoding helper for the encoding scheme used by `LazyArray`.
369+ // Interleaving the bytes of the two integers exposes trailing bytes in the first integer
370+ // to the varint scheme that we use for tables.
371+ #[ inline]
372+ fn decode_interleaved ( encoded : & [ u8 ; 16 ] ) -> ( [ u8 ; 8 ] , [ u8 ; 8 ] ) {
373+ let mut first = [ 0u8 ; 8 ] ;
374+ let mut second = [ 0u8 ; 8 ] ;
375+ for i in 0 ..8 {
376+ first[ i] = encoded[ 2 * i] ;
377+ second[ i] = encoded[ 2 * i + 1 ] ;
378+ }
379+ ( first, second)
380+ }
381+
362382impl < T > FixedSizeEncoding for LazyArray < T > {
363383 type ByteArray = [ u8 ; 16 ] ;
364384
365385 #[ inline]
366386 fn from_bytes ( b : & [ u8 ; 16 ] ) -> Self {
367- let mut position = [ 0u8 ; 8 ] ;
368- let mut meta = [ 0u8 ; 8 ] ;
369-
370- for i in 0 ..8 {
371- position[ i] = b[ 2 * i] ;
372- meta[ i] = b[ 2 * i + 1 ] ;
373- }
387+ let ( position, meta) = decode_interleaved ( b) ;
374388
375389 if meta == [ 0 ; 8 ] {
376390 return Default :: default ( ) ;
@@ -390,13 +404,7 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
390404
391405 #[ inline]
392406 fn from_bytes ( b : & [ u8 ; 16 ] ) -> Self {
393- let mut position = [ 0u8 ; 8 ] ;
394- let mut meta = [ 0u8 ; 8 ] ;
395-
396- for i in 0 ..8 {
397- position[ i] = b[ 2 * i] ;
398- meta[ i] = b[ 2 * i + 1 ] ;
399- }
407+ let ( position, meta) = decode_interleaved ( b) ;
400408
401409 LazyArray :: from_bytes_impl ( & position, & meta)
402410 }
0 commit comments