Packs multiple bytes into single bytes and writes them to `out`. This only works if `max - min < 16`, otherwise this just copies `bytes` to `out`. These particular tradeoffs were selected so input bytes don't span multiple output bytes to avoid confusing bytewise compression algorithms (e.g. Deflate). Mutates `bytes` to avoid copying them. The remaining `bytes` should be considered garbage.
(bytes: &mut [T], out: &mut Vec<u8>)
| 88 | /// |
| 89 | /// Mutates `bytes` to avoid copying them. The remaining `bytes` should be considered garbage. |
| 90 | pub fn pack_bytes<T: Byte>(bytes: &mut [T], out: &mut Vec<u8>) { |
| 91 | if skip_packing(bytes.len()) { |
| 92 | out.extend_from_slice(bytemuck::must_cast_slice(bytes)); |
| 93 | return; |
| 94 | } |
| 95 | let (min, max) = crate::pack_ints::minmax(bytes); |
| 96 | |
| 97 | // i8 packs as u8 if positive. |
| 98 | let basic_packing = if min >= T::default() { |
| 99 | Packing::new(bytemuck::must_cast(max)) |
| 100 | } else { |
| 101 | Packing::_256 // Any negative i8 as u8 is > 15 and can't be packed without offset_packing. |
| 102 | }; |
| 103 | |
| 104 | // u8::wrapping_sub == i8::wrapping_sub, so we can use u8s from here onward. |
| 105 | let min: u8 = bytemuck::must_cast(min); |
| 106 | let max: u8 = bytemuck::must_cast(max); |
| 107 | let bytes: &mut [u8] = bytemuck::must_cast_slice_mut(bytes); |
| 108 | pack_bytes_unsigned(bytes, out, basic_packing, min, max); |
| 109 | } |
| 110 | |
| 111 | /// [`pack_bytes`] but after i8s have been cast to u8s. |
| 112 | fn pack_bytes_unsigned( |