| 21 | /// Written as a tight loop over bytes for auto-vectorization. |
| 22 | #[inline] |
| 23 | pub(super) fn pack_bits(packed: &mut [u8], bit_offset: usize, value: u64, bit_width: u8) { |
| 24 | let bw = bit_width as usize; |
| 25 | if bw == 0 { |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | let byte_idx = bit_offset / 8; |
| 30 | let bit_idx = bit_offset % 8; |
| 31 | |
| 32 | // How many bits fit in the first byte. |
| 33 | let first_bits = (8 - bit_idx).min(bw); |
| 34 | |
| 35 | // Write first partial byte. |
| 36 | packed[byte_idx] |= ((value & low_mask_u64(first_bits)) as u8) << bit_idx; |
| 37 | |
| 38 | let mut remaining = bw - first_bits; |
| 39 | let mut val = value >> first_bits; |
| 40 | let mut bi = byte_idx + 1; |
| 41 | |
| 42 | // Write full bytes. |
| 43 | while remaining >= 8 { |
| 44 | packed[bi] = (val & 0xFF) as u8; |
| 45 | val >>= 8; |
| 46 | remaining -= 8; |
| 47 | bi += 1; |
| 48 | } |
| 49 | |
| 50 | // Write last partial byte. |
| 51 | if remaining > 0 { |
| 52 | packed[bi] |= (val & low_mask_u64(remaining)) as u8; |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | /// Unpack a value from a byte array at the given bit offset. |
| 57 | #[inline] |