[`pack_ints`] but after isize has been converted to i64.
(ints: &mut [T], out: &mut Vec<u8>)
| 348 | |
| 349 | /// [`pack_ints`] but after isize has been converted to i64. |
| 350 | fn pack_ints_sized<T: SizedInt>(ints: &mut [T], out: &mut Vec<u8>) { |
| 351 | // Handle i8 right away since pack_bytes needs to know that it's signed. |
| 352 | // If we didn't have this special case [0i8, -1, 0, -1, 0, -1] couldn't be packed. |
| 353 | // Doesn't affect larger signed ints because they're made positive before pack_bytes::<u8> is called. |
| 354 | if std::mem::size_of::<T>() == 1 && T::MIN < T::default() { |
| 355 | let ints: &mut [i8] = bytemuck::must_cast_slice_mut(ints); |
| 356 | pack_bytes(ints, out); |
| 357 | return; |
| 358 | }; |
| 359 | |
| 360 | let (basic_packing, min_max) = if skip_packing::<T>(ints.len()) { |
| 361 | (Packing::new(T::Unsigned::MAX), None) |
| 362 | } else { |
| 363 | // Take a small sample to avoid wastefully scanning the whole slice. |
| 364 | let (sample, remaining) = ints.split_at(ints.len().min(16)); |
| 365 | let (min, max) = minmax(sample); |
| 366 | |
| 367 | // Only have to check packing(max - min) since it's always as good as packing(max). |
| 368 | let none = Packing::new(T::Unsigned::MAX); |
| 369 | if Packing::new(max.to_unsigned().wrapping_sub(min.to_unsigned())) == none { |
| 370 | none.write::<T::Unsigned>(out, false); |
| 371 | (none, None) |
| 372 | } else { |
| 373 | let (remaining_min, remaining_max) = minmax(remaining); |
| 374 | let min = min.min(remaining_min); |
| 375 | let max = max.max(remaining_max); |
| 376 | |
| 377 | // Signed ints pack as unsigned ints if positive. |
| 378 | let basic_packing = if min >= T::default() { |
| 379 | Packing::new(max.to_unsigned()) |
| 380 | } else { |
| 381 | none // Any negative can't be packed without offset_packing. |
| 382 | }; |
| 383 | (basic_packing, Some((min, max))) |
| 384 | } |
| 385 | }; |
| 386 | let ints = bytemuck::must_cast_slice_mut(ints); |
| 387 | let min_max = min_max.map(|(min, max)| (min.to_unsigned(), max.to_unsigned())); |
| 388 | pack_ints_sized_unsigned::<T::Unsigned>(ints, out, basic_packing, min_max); |
| 389 | } |
| 390 | |
| 391 | /// [`pack_ints_sized`] but after signed integers have been cast to unsigned. |
| 392 | fn pack_ints_sized_unsigned<T: SizedUInt>( |
no test coverage detected