turbo_persistence/
compression.rs1use std::{mem::MaybeUninit, sync::Arc};
2
3use anyhow::{Context, Result};
4use lzzzz::lz4::{self, decompress};
5
6pub fn decompress_into_arc(uncompressed_length: u32, block: &[u8]) -> Result<Arc<[u8]>> {
11 debug_assert!(
12 uncompressed_length > 0,
13 "decompress_into_arc called with uncompressed_length=0; uncompressed blocks should use \
14 zero-copy mmap path"
15 );
16
17 let buffer: Arc<[MaybeUninit<u8>]> = Arc::new_uninit_slice(uncompressed_length as usize);
20 let mut buffer = unsafe { buffer.assume_init() };
22 let decompressed = Arc::get_mut(&mut buffer).expect("Arc refcount should be 1");
24 let bytes_written = decompress(block, decompressed).with_context(|| {
25 format!(
26 "Failed to decompress block ({} bytes compressed, {} bytes uncompressed)",
27 block.len(),
28 uncompressed_length
29 )
30 })?;
31 assert_eq!(
32 bytes_written, uncompressed_length as usize,
33 "Decompressed length does not match expected length"
34 );
35 Ok(buffer)
36}
37
38pub fn checksum_block(data: &[u8]) -> u32 {
40 crc32fast::hash(data)
41}
42
43#[tracing::instrument(level = "trace", skip_all)]
44pub fn compress_into_buffer(block: &[u8], buffer: &mut Vec<u8>) -> Result<()> {
45 lz4::compress_to_vec(block, buffer, lz4::ACC_LEVEL_DEFAULT).context("Compression failed")?;
46 Ok(())
47}