Document in the code how this scheme works

This commit is contained in:
Ben Kimock 2023-08-29 20:16:57 -04:00
parent e0103a7b3c
commit 225b3c0556
2 changed files with 25 additions and 14 deletions

View File

@ -136,7 +136,10 @@ impl<T> LazyArray<T> {
/// eagerly and in-order.
struct LazyTable<I, T> {
position: NonZeroUsize,
/// The encoded size of the elements of a table is selected at runtime to drop
/// trailing zeroes. This is the number of bytes used for each table element.
width: usize,
/// How many elements are in the table.
len: usize,
_marker: PhantomData<fn(I) -> T>,
}

View File

@ -346,6 +346,12 @@ impl<T> LazyArray<T> {
let position = (self.position.get() as u64).to_le_bytes();
let len = (self.num_elems as u64).to_le_bytes();
// Element width is selected at runtime on a per-table basis by omitting trailing
// zero bytes in table elements. This works very naturally when table elements are
// simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
// element would shield the trailing zeroes in the first. Interleaving the bytes
// of the position and length exposes trailing zeroes in both to the optimization.
// We encode length second because we generally expect it to be smaller.
for i in 0..8 {
b[2 * i] = position[i];
b[2 * i + 1] = len[i];
@ -359,18 +365,26 @@ impl<T> LazyArray<T> {
}
}
// Decoding helper for the encoding scheme used by `LazyArray`.
// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
// to the varint scheme that we use for tables.
#[inline]
fn decode_interleaved(encoded: &[u8; 16]) -> ([u8; 8], [u8; 8]) {
let mut first = [0u8; 8];
let mut second = [0u8; 8];
for i in 0..8 {
first[i] = encoded[2 * i];
second[i] = encoded[2 * i + 1];
}
(first, second)
}
impl<T> FixedSizeEncoding for LazyArray<T> {
type ByteArray = [u8; 16];
#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
let mut position = [0u8; 8];
let mut meta = [0u8; 8];
for i in 0..8 {
position[i] = b[2 * i];
meta[i] = b[2 * i + 1];
}
let (position, meta) = decode_interleaved(b);
if meta == [0; 8] {
return Default::default();
@ -390,13 +404,7 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
let mut position = [0u8; 8];
let mut meta = [0u8; 8];
for i in 0..8 {
position[i] = b[2 * i];
meta[i] = b[2 * i + 1];
}
let (position, meta) = decode_interleaved(b);
LazyArray::from_bytes_impl(&position, &meta)
}