feat(compress): move frame chunk checksum into Rust
Project the frame-chunk XXH64 state as a typed pointer so Rust owns the checksum update while preserving the existing pre-block ordering and error behavior. Remove the now-redundant C checksum callback and shrink the cross-language frame-chunk state layout assertions. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --all -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --lib zstd_compress::tests::frame_chunk -- --nocapture - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --all-targets -- -D warnings - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test - ulimit -v 41943040; make -j1 - ulimit -v 41943040; make -j1 -C tests test-zstream ZSTREAM_TESTTIME=-T2s - ulimit -v 41943040; make -j1 -C tests test-fuzzer FUZZERTEST=-T3s FUZZER_FLAGS=--no-big-tests
This commit is contained in:
@@ -821,13 +821,10 @@ typedef size_t (*ZSTD_rust_frameChunkCompress_f)(void* context,
|
|||||||
const void* src,
|
const void* src,
|
||||||
size_t srcSize,
|
size_t srcSize,
|
||||||
U32 lastBlock);
|
U32 lastBlock);
|
||||||
typedef void (*ZSTD_rust_frameChunkChecksum_f)(void* state,
|
|
||||||
const void* src,
|
|
||||||
size_t srcSize);
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* callbackContext;
|
void* callbackContext;
|
||||||
void* tmpWorkspace;
|
void* tmpWorkspace;
|
||||||
void* checksumState;
|
XXH64_state_t* checksumState;
|
||||||
int* isFirstBlock;
|
int* isFirstBlock;
|
||||||
ZSTD_compressionStage_e* stage;
|
ZSTD_compressionStage_e* stage;
|
||||||
size_t tmpWkspSize;
|
size_t tmpWkspSize;
|
||||||
@@ -843,7 +840,6 @@ typedef struct {
|
|||||||
ZSTD_rust_frameChunkCompress_f compressTarget;
|
ZSTD_rust_frameChunkCompress_f compressTarget;
|
||||||
ZSTD_rust_frameChunkCompress_f compressSplit;
|
ZSTD_rust_frameChunkCompress_f compressSplit;
|
||||||
ZSTD_rust_frameChunkCompress_f compressInternal;
|
ZSTD_rust_frameChunkCompress_f compressInternal;
|
||||||
ZSTD_rust_frameChunkChecksum_f updateChecksum;
|
|
||||||
} ZSTD_rust_frameChunkState;
|
} ZSTD_rust_frameChunkState;
|
||||||
size_t ZSTD_rust_compressFrameChunk(
|
size_t ZSTD_rust_compressFrameChunk(
|
||||||
const ZSTD_rust_frameChunkState* state,
|
const ZSTD_rust_frameChunkState* state,
|
||||||
@@ -874,7 +870,7 @@ typedef char ZSTD_rust_frame_chunk_state_layout[
|
|||||||
&& offsetof(ZSTD_rust_frameChunkState, prepareState)
|
&& offsetof(ZSTD_rust_frameChunkState, prepareState)
|
||||||
== 7 * sizeof(void*) + sizeof(S64) + 6 * sizeof(int)
|
== 7 * sizeof(void*) + sizeof(S64) + 6 * sizeof(int)
|
||||||
&& sizeof(ZSTD_rust_frameChunkState)
|
&& sizeof(ZSTD_rust_frameChunkState)
|
||||||
== 12 * sizeof(void*) + sizeof(S64) + 6 * sizeof(int))
|
== 11 * sizeof(void*) + sizeof(S64) + 6 * sizeof(int))
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
|
|
||||||
/* The high-level continue/block entry points are Rust-owned. This projection
|
/* The high-level continue/block entry points are Rust-owned. This projection
|
||||||
@@ -5575,12 +5571,6 @@ static size_t ZSTD_rust_frameChunk_compressInternal(
|
|||||||
1 /* frame */);
|
1 /* frame */);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ZSTD_rust_frameChunk_updateChecksum(
|
|
||||||
void* state, const void* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
(void)XXH64_update((XXH64_state_t*)state, src, srcSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! ZSTD_compress_frameChunk() :
|
/*! ZSTD_compress_frameChunk() :
|
||||||
* Compress a chunk of data into one or multiple blocks.
|
* Compress a chunk of data into one or multiple blocks.
|
||||||
* All blocks will be terminated, all input will be consumed.
|
* All blocks will be terminated, all input will be consumed.
|
||||||
@@ -5623,7 +5613,6 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
|
|||||||
state.compressTarget = ZSTD_rust_frameChunk_compressTarget;
|
state.compressTarget = ZSTD_rust_frameChunk_compressTarget;
|
||||||
state.compressSplit = ZSTD_rust_frameChunk_compressSplit;
|
state.compressSplit = ZSTD_rust_frameChunk_compressSplit;
|
||||||
state.compressInternal = ZSTD_rust_frameChunk_compressInternal;
|
state.compressInternal = ZSTD_rust_frameChunk_compressInternal;
|
||||||
state.updateChecksum = ZSTD_rust_frameChunk_updateChecksum;
|
|
||||||
return ZSTD_rust_compressFrameChunk(
|
return ZSTD_rust_compressFrameChunk(
|
||||||
&state, dst, dstCapacity, src, srcSize, lastFrameChunk);
|
&state, dst, dstCapacity, src, srcSize, lastFrameChunk);
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-22
@@ -16,6 +16,8 @@
|
|||||||
use crate::common::MINMATCH;
|
use crate::common::MINMATCH;
|
||||||
use crate::errors::{ERR_isError, ZstdErrorCode, ERROR};
|
use crate::errors::{ERR_isError, ZstdErrorCode, ERROR};
|
||||||
use crate::mem::MEM_writeLE32;
|
use crate::mem::MEM_writeLE32;
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::xxhash::XXH64_reset;
|
||||||
use crate::xxhash::{XXH64_digest, XXH64_state_t, XXH64_update};
|
use crate::xxhash::{XXH64_digest, XXH64_state_t, XXH64_update};
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use crate::zstd_compress_api::ZSTD_compressBound;
|
use crate::zstd_compress_api::ZSTD_compressBound;
|
||||||
@@ -178,7 +180,6 @@ type FrameChunkPrepareOverflowFn = unsafe extern "C" fn(*mut c_void, *const c_vo
|
|||||||
type FrameChunkPrepareWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize, c_uint);
|
type FrameChunkPrepareWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize, c_uint);
|
||||||
type FrameChunkCompressFn =
|
type FrameChunkCompressFn =
|
||||||
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
|
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
|
||||||
type FrameChunkChecksumFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
|
|
||||||
|
|
||||||
type BuildSeqStoreSkipFn = unsafe extern "C" fn(*mut c_void, usize);
|
type BuildSeqStoreSkipFn = unsafe extern "C" fn(*mut c_void, usize);
|
||||||
type BuildSeqStorePrepareFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
|
type BuildSeqStorePrepareFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
|
||||||
@@ -550,7 +551,7 @@ const _: () = {
|
|||||||
pub struct ZSTD_rust_frameChunkState {
|
pub struct ZSTD_rust_frameChunkState {
|
||||||
callback_context: *mut c_void,
|
callback_context: *mut c_void,
|
||||||
tmp_workspace: *mut c_void,
|
tmp_workspace: *mut c_void,
|
||||||
checksum_state: *mut c_void,
|
checksum_state: *mut XXH64_state_t,
|
||||||
is_first_block: *mut c_int,
|
is_first_block: *mut c_int,
|
||||||
stage: *mut c_int,
|
stage: *mut c_int,
|
||||||
tmp_wksp_size: usize,
|
tmp_wksp_size: usize,
|
||||||
@@ -566,7 +567,6 @@ pub struct ZSTD_rust_frameChunkState {
|
|||||||
compress_target: FrameChunkCompressFn,
|
compress_target: FrameChunkCompressFn,
|
||||||
compress_split: FrameChunkCompressFn,
|
compress_split: FrameChunkCompressFn,
|
||||||
compress_internal: FrameChunkCompressFn,
|
compress_internal: FrameChunkCompressFn,
|
||||||
update_checksum: FrameChunkChecksumFn,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _: () = {
|
const _: () = {
|
||||||
@@ -608,7 +608,7 @@ const _: () = {
|
|||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
size_of::<ZSTD_rust_frameChunkState>()
|
size_of::<ZSTD_rust_frameChunkState>()
|
||||||
== 12 * size_of::<usize>() + size_of::<c_longlong>() + 6 * size_of::<c_int>()
|
== 11 * size_of::<usize>() + size_of::<c_longlong>() + 6 * size_of::<c_int>()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -659,7 +659,9 @@ unsafe fn compress_frame_chunk_body_with(
|
|||||||
if state.checksum_state.is_null() {
|
if state.checksum_state.is_null() {
|
||||||
return ERROR(ZstdErrorCode::Generic);
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
}
|
}
|
||||||
unsafe { (state.update_checksum)(state.checksum_state, src, src_size) };
|
unsafe {
|
||||||
|
let _ = XXH64_update(state.checksum_state, src, src_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut remaining = src_size;
|
let mut remaining = src_size;
|
||||||
@@ -10844,8 +10846,7 @@ mod tests {
|
|||||||
split_calls: usize,
|
split_calls: usize,
|
||||||
internal_calls: usize,
|
internal_calls: usize,
|
||||||
last_blocks: [c_uint; 4],
|
last_blocks: [c_uint; 4],
|
||||||
checksum_calls: usize,
|
checksum_state: Option<XXH64_state_t>,
|
||||||
checksum_size: usize,
|
|
||||||
target_result: usize,
|
target_result: usize,
|
||||||
split_result: usize,
|
split_result: usize,
|
||||||
internal_result: usize,
|
internal_result: usize,
|
||||||
@@ -10945,16 +10946,6 @@ mod tests {
|
|||||||
context.internal_result
|
context.internal_result
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn frame_chunk_test_checksum(
|
|
||||||
context: *mut c_void,
|
|
||||||
_src: *const c_void,
|
|
||||||
src_size: usize,
|
|
||||||
) {
|
|
||||||
let context = unsafe { frame_chunk_test_context(context) };
|
|
||||||
context.checksum_calls += 1;
|
|
||||||
context.checksum_size = context.checksum_size.wrapping_add(src_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn frame_chunk_test_state(
|
fn frame_chunk_test_state(
|
||||||
context: &mut FrameChunkTestContext,
|
context: &mut FrameChunkTestContext,
|
||||||
is_first_block: &mut c_int,
|
is_first_block: &mut c_int,
|
||||||
@@ -10965,6 +10956,18 @@ mod tests {
|
|||||||
) -> ZSTD_rust_frameChunkState {
|
) -> ZSTD_rust_frameChunkState {
|
||||||
let context_ptr = context as *mut FrameChunkTestContext;
|
let context_ptr = context as *mut FrameChunkTestContext;
|
||||||
let callback_context = context_ptr.cast::<c_void>();
|
let callback_context = context_ptr.cast::<c_void>();
|
||||||
|
context.checksum_state = Some(XXH64_state_t {
|
||||||
|
total_len: 0,
|
||||||
|
v: [0; 4],
|
||||||
|
mem64: [0; 4],
|
||||||
|
memsize: 0,
|
||||||
|
reserved32: 0,
|
||||||
|
reserved64: 0,
|
||||||
|
});
|
||||||
|
let checksum_state = context.checksum_state.as_mut().unwrap();
|
||||||
|
unsafe {
|
||||||
|
let _ = XXH64_reset(checksum_state, 0);
|
||||||
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
(*context_ptr).clamp_state = Some(ZSTD_rust_frameChunkClampState {
|
(*context_ptr).clamp_state = Some(ZSTD_rust_frameChunkClampState {
|
||||||
next_to_update: &mut (*context_ptr).clamp_next_to_update,
|
next_to_update: &mut (*context_ptr).clamp_next_to_update,
|
||||||
@@ -10991,7 +10994,7 @@ mod tests {
|
|||||||
ZSTD_rust_frameChunkState {
|
ZSTD_rust_frameChunkState {
|
||||||
callback_context,
|
callback_context,
|
||||||
tmp_workspace: ptr::null_mut(),
|
tmp_workspace: ptr::null_mut(),
|
||||||
checksum_state: callback_context,
|
checksum_state,
|
||||||
is_first_block,
|
is_first_block,
|
||||||
stage,
|
stage,
|
||||||
tmp_wksp_size: 0,
|
tmp_wksp_size: 0,
|
||||||
@@ -11007,7 +11010,6 @@ mod tests {
|
|||||||
compress_target: frame_chunk_test_target,
|
compress_target: frame_chunk_test_target,
|
||||||
compress_split: frame_chunk_test_split,
|
compress_split: frame_chunk_test_split,
|
||||||
compress_internal: frame_chunk_test_internal,
|
compress_internal: frame_chunk_test_internal,
|
||||||
update_checksum: frame_chunk_test_checksum,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11044,8 +11046,10 @@ mod tests {
|
|||||||
assert_eq!(context.clamp_next_to_update, 4);
|
assert_eq!(context.clamp_next_to_update, 4);
|
||||||
assert_eq!(context.internal_calls, 2);
|
assert_eq!(context.internal_calls, 2);
|
||||||
assert_eq!(context.last_blocks[..2], [0, 1]);
|
assert_eq!(context.last_blocks[..2], [0, 1]);
|
||||||
assert_eq!(context.checksum_calls, 1);
|
assert_eq!(
|
||||||
assert_eq!(context.checksum_size, source.len());
|
context.checksum_state.as_ref().unwrap().total_len,
|
||||||
|
source.len() as u64
|
||||||
|
);
|
||||||
assert_eq!(is_first_block, 0);
|
assert_eq!(is_first_block, 0);
|
||||||
assert_eq!(stage, 77);
|
assert_eq!(stage, 77);
|
||||||
assert_ne!(output[..3], [0xa5; 3]);
|
assert_ne!(output[..3], [0xa5; 3]);
|
||||||
@@ -11141,7 +11145,10 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(result, ERROR(ZstdErrorCode::DstSizeTooSmall));
|
assert_eq!(result, ERROR(ZstdErrorCode::DstSizeTooSmall));
|
||||||
assert_eq!(context.checksum_calls, 1);
|
assert_eq!(
|
||||||
|
context.checksum_state.as_ref().unwrap().total_len,
|
||||||
|
source.len() as u64
|
||||||
|
);
|
||||||
assert_eq!(context.prepare_calls, 0);
|
assert_eq!(context.prepare_calls, 0);
|
||||||
assert_eq!(context.internal_calls, 0);
|
assert_eq!(context.internal_calls, 0);
|
||||||
assert_eq!(is_first_block, 1);
|
assert_eq!(is_first_block, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user