When "Finalizing" the bitpack to an allocation, I multiply the array by u32, and check the size of the increment to figure out how many bytes are in the "in-progress" pack.
functionbitpack_arr_bytes(bitpack:Bitpacker):numberlocalarr_length=bitpack.arr/2returnarr_length*U32_SIZEendfunctionbitpack_remainder_bytes(bitpack:Bitpacker):number-- divide by 2 since increment represents the next number to addlocalcurrent_size=bitpack.increment/2localnum_bits=math.log(current_size,2)localnum_bytes=math.ceil(num_bits/8)returnnum_bytesendfunctionbitpack_bytes(bitpack:Bitpacker):numberlocalarr_bytes=bitpack_arr_bytes(bitpack)localremainder_bytes=bitpack_remainder_bytes(bitpack)returnarr_bytes+remainder_bytesend
Deserialization
To deserialize a table of bitpacks (booleans), I used a constant lookup table moving 8 booleans at a time to an output
bool table with table.move(). Here's
how the constant lookup table is generated:
A luau value takes up 16 bytes of memory, so this table should occupy 31-33kb (16*2^8*8) of memory statically. For
reference — last I checked, this is a bit less than roblox's voice chat ui assets take up.