Opposite of `pack_arithmetic`. `out` will be overwritten with the unpacked bytes.
(
input: &mut &[u8],
unpacked_len: usize,
out: &mut Vec<u8>,
)
| 434 | |
| 435 | /// Opposite of `pack_arithmetic`. `out` will be overwritten with the unpacked bytes. |
| 436 | fn unpack_arithmetic<const FACTOR: usize>( |
| 437 | input: &mut &[u8], |
| 438 | unpacked_len: usize, |
| 439 | out: &mut Vec<u8>, |
| 440 | ) -> Result<()> { |
| 441 | let divisor = factor_to_divisor::<FACTOR>(); |
| 442 | |
| 443 | // TODO STRICT: check that packed.all(|&b| b < FACTOR.powi(divisor)). |
| 444 | let floor = unpacked_len / divisor; |
| 445 | let ceil = crate::nightly::div_ceil_usize(unpacked_len, divisor); |
| 446 | let packed = consume_bytes(input, ceil)?; |
| 447 | |
| 448 | debug_assert!(out.is_empty()); |
| 449 | out.reserve(unpacked_len); |
| 450 | let unpacked = &mut out.spare_capacity_mut()[..unpacked_len]; |
| 451 | |
| 452 | for i in 0..floor { |
| 453 | unsafe { |
| 454 | let mut packed = *packed.get_unchecked(i); |
| 455 | if FACTOR == 2 && BMI2 { |
| 456 | #[cfg(not(all(target_arch = "x86_64", target_feature = "bmi2")))] |
| 457 | unreachable!(); |
| 458 | #[cfg(all(target_arch = "x86_64", target_feature = "bmi2"))] |
| 459 | { |
| 460 | // Could use on any pow2 FACTOR, but only 2 is faster (target-cpu=native). |
| 461 | let chunk = std::arch::x86_64::_pdep_u64(packed as u64, 0x0101010101010101); |
| 462 | *(unpacked.as_mut_ptr() as *mut [u8; 8]).add(i) = chunk.to_le_bytes(); |
| 463 | } |
| 464 | } else { |
| 465 | for byte in unpacked.get_unchecked_mut(i * divisor..i * divisor + divisor) { |
| 466 | byte.write(packed % FACTOR as u8); |
| 467 | packed /= FACTOR as u8; |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | } |
| 472 | if floor < ceil { |
| 473 | let mut packed = packed[floor]; |
| 474 | for byte in unpacked[floor * divisor..].iter_mut() { |
| 475 | byte.write(packed % FACTOR as u8); |
| 476 | packed /= FACTOR as u8; |
| 477 | } |
| 478 | } |
| 479 | // Safety: `unpacked_len` elements were initialized by the loops above. |
| 480 | unsafe { out.set_len(unpacked_len) }; |
| 481 | Ok(()) |
| 482 | } |
| 483 | |
| 484 | #[cfg(test)] |
| 485 | mod tests { |
nothing calls this directly
no test coverage detected