feat(compress): move block header serialization to Rust
Keep the private writeBlockHeader signature and its debug logging in C while moving the pure block-type, size, and 24-bit little-endian encoding behind a narrow Rust ABI. The Rust leaf preserves the RLE blockSize path for cSize == 1 and the compressed cSize path for every other value. Test Plan: - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression block_header -- --nocapture` -- passed - `make -B -C lib -j2 lib` -- passed - `make -C tests -j2 fuzzer` -- passed - `./tests/fuzzer -s4560 -t47 -i48 -v` -- passed - Required clippy, nightly fmt, and diff checks -- passed
This commit is contained in:
@@ -37,6 +37,8 @@ size_t ZSTD_rust_writeFrameHeader(void* dst, size_t dstCapacity,
|
|||||||
int contentSizeFlag, int format,
|
int contentSizeFlag, int format,
|
||||||
U32 windowLog, U64 pledgedSrcSize,
|
U32 windowLog, U64 pledgedSrcSize,
|
||||||
U32 dictID);
|
U32 dictID);
|
||||||
|
void ZSTD_rust_writeBlockHeader(void* op, size_t cSize, size_t blockSize,
|
||||||
|
U32 lastBlock);
|
||||||
size_t ZSTD_rust_writeEpilogue(void* dst, size_t dstCapacity, int* stage,
|
size_t ZSTD_rust_writeEpilogue(void* dst, size_t dstCapacity, int* stage,
|
||||||
int noDictIDFlag, int checksumFlag,
|
int noDictIDFlag, int checksumFlag,
|
||||||
int contentSizeFlag, int format, U32 windowLog,
|
int contentSizeFlag, int format, U32 windowLog,
|
||||||
@@ -2592,10 +2594,7 @@ ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)
|
|||||||
static void
|
static void
|
||||||
writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock)
|
writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock)
|
||||||
{
|
{
|
||||||
U32 const cBlockHeader = cSize == 1 ?
|
ZSTD_rust_writeBlockHeader(op, cSize, blockSize, lastBlock);
|
||||||
lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
|
|
||||||
lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
|
|
||||||
MEM_writeLE24(op, cBlockHeader);
|
|
||||||
DEBUGLOG(5, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock);
|
DEBUGLOG(5, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const ZSTD_F_ZSTD1: c_int = 0;
|
|||||||
const ZSTD_BLOCK_SIZE: usize = 128 << 10;
|
const ZSTD_BLOCK_SIZE: usize = 128 << 10;
|
||||||
const ZSTD_FAST: c_int = 1;
|
const ZSTD_FAST: c_int = 1;
|
||||||
const ZSTD_BTULTRA2: c_int = 9;
|
const ZSTD_BTULTRA2: c_int = 9;
|
||||||
|
const ZSTD_BT_COMPRESSED: u32 = 2;
|
||||||
const SPLIT_LEVELS: [c_int; 10] = [0, 0, 1, 2, 2, 3, 3, 4, 4, 4];
|
const SPLIT_LEVELS: [c_int; 10] = [0, 0, 1, 2, 2, 3, 3, 4, 4, 4];
|
||||||
const ZSTD_BT_RLE: u32 = 1;
|
const ZSTD_BT_RLE: u32 = 1;
|
||||||
const ZSTDCS_CREATED: c_int = 0;
|
const ZSTDCS_CREATED: c_int = 0;
|
||||||
@@ -83,6 +84,31 @@ pub(crate) unsafe fn write_raw_block(
|
|||||||
needed
|
needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rust implementation of the private compressed-block header serializer.
|
||||||
|
///
|
||||||
|
/// The C wrapper retains the original static helper signature and keeps its
|
||||||
|
/// debug logging at the call site. The helper itself only needs scalar
|
||||||
|
/// values and writes the low 24 bits in little-endian order, as `MEM_writeLE24`
|
||||||
|
/// does.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_writeBlockHeader(
|
||||||
|
op: *mut c_void,
|
||||||
|
c_size: usize,
|
||||||
|
block_size: usize,
|
||||||
|
last_block: c_uint,
|
||||||
|
) {
|
||||||
|
let block_type = if c_size == 1 {
|
||||||
|
ZSTD_BT_RLE
|
||||||
|
} else {
|
||||||
|
ZSTD_BT_COMPRESSED
|
||||||
|
};
|
||||||
|
let size = if c_size == 1 { block_size } else { c_size };
|
||||||
|
let header = last_block
|
||||||
|
.wrapping_add(block_type << 1)
|
||||||
|
.wrapping_add((size as u32).wrapping_shl(3));
|
||||||
|
unsafe { write_le24(op.cast(), header) };
|
||||||
|
}
|
||||||
|
|
||||||
/// Rust implementation of the private `ZSTD_writeFrameHeader()` leaf.
|
/// Rust implementation of the private `ZSTD_writeFrameHeader()` leaf.
|
||||||
///
|
///
|
||||||
/// `no_dict_id_flag`, `checksum_flag`, `content_size_flag`, `format`, and
|
/// `no_dict_id_flag`, `checksum_flag`, `content_size_flag`, `format`, and
|
||||||
@@ -604,6 +630,24 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_rle_block_header() {
|
||||||
|
let mut output = [0u8; ZSTD_BLOCKHEADERSIZE];
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_writeBlockHeader(output.as_mut_ptr().cast(), 1, 0x12345, 1);
|
||||||
|
}
|
||||||
|
assert_eq!(output, [0x2b, 0x1a, 0x09]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn writes_compressed_block_header() {
|
||||||
|
let mut output = [0u8; ZSTD_BLOCKHEADERSIZE];
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_writeBlockHeader(output.as_mut_ptr().cast(), 0x23456, 0x54321, 1);
|
||||||
|
}
|
||||||
|
assert_eq!(output, [0xb5, 0xa2, 0x11]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn optimal_block_size_keeps_small_blocks_intact() {
|
fn optimal_block_size_keeps_small_blocks_intact() {
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
|
|||||||
Reference in New Issue
Block a user