feat(compress): move continue window updates into Rust
Project the match-state and optional LDM window fields directly through the compressContinue ABI so Rust can reuse the existing window-update leaf. Keep forceNonContiguous and nextToUpdate updates visible to the following C callbacks, preserve the match-before-LDM ordering, and remove the C window update callback while retaining context-sensitive overflow and block calls. 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::compress_continue -- --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:
@@ -878,8 +878,20 @@ typedef char ZSTD_rust_frame_chunk_state_layout[
|
|||||||
? 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
|
||||||
* carries frame-header scalars, mutable state, and C callbacks; the private
|
* carries frame-header scalars, mutable state, and C callbacks. Window
|
||||||
* CCtx and match-state layout never crosses the ABI. */
|
* advancement uses direct pointers to the C-owned fields; the private CCtx
|
||||||
|
* and match-state layout never crosses the ABI. */
|
||||||
|
typedef struct {
|
||||||
|
void* nextSrc;
|
||||||
|
void* base;
|
||||||
|
void* dictBase;
|
||||||
|
void* dictLimit;
|
||||||
|
void* lowLimit;
|
||||||
|
void* forceNonContiguous;
|
||||||
|
void* nextToUpdate;
|
||||||
|
} ZSTD_rust_compressContinueWindowState;
|
||||||
|
typedef char ZSTD_rust_compress_continue_window_state_layout[
|
||||||
|
(sizeof(ZSTD_rust_compressContinueWindowState) == 7 * sizeof(void*)) ? 1 : -1];
|
||||||
typedef void (*ZSTD_rust_compressContinueWindow_f)(void* context,
|
typedef void (*ZSTD_rust_compressContinueWindow_f)(void* context,
|
||||||
const void* src,
|
const void* src,
|
||||||
size_t srcSize);
|
size_t srcSize);
|
||||||
@@ -891,7 +903,8 @@ typedef size_t (*ZSTD_rust_compressContinueBlock_f)(void* context,
|
|||||||
U32 lastFrameChunk);
|
U32 lastFrameChunk);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* callbackContext;
|
void* callbackContext;
|
||||||
ZSTD_rust_compressContinueWindow_f updateWindow;
|
ZSTD_rust_compressContinueWindowState* windowState;
|
||||||
|
ZSTD_rust_compressContinueWindowState* ldmWindowState;
|
||||||
ZSTD_rust_compressContinueWindow_f correctOverflow;
|
ZSTD_rust_compressContinueWindow_f correctOverflow;
|
||||||
ZSTD_rust_compressContinueBlock_f compressFrameChunk;
|
ZSTD_rust_compressContinueBlock_f compressFrameChunk;
|
||||||
ZSTD_rust_compressContinueBlock_f compressBlock;
|
ZSTD_rust_compressContinueBlock_f compressBlock;
|
||||||
@@ -907,6 +920,7 @@ typedef struct {
|
|||||||
int format;
|
int format;
|
||||||
U32 windowLog;
|
U32 windowLog;
|
||||||
U32 dictID;
|
U32 dictID;
|
||||||
|
int ldmEnabled;
|
||||||
} ZSTD_rust_compressContinueState;
|
} ZSTD_rust_compressContinueState;
|
||||||
size_t ZSTD_rust_compressContinue(
|
size_t ZSTD_rust_compressContinue(
|
||||||
const ZSTD_rust_compressContinueState* state,
|
const ZSTD_rust_compressContinueState* state,
|
||||||
@@ -915,32 +929,35 @@ size_t ZSTD_rust_compressContinue(
|
|||||||
U32 frame, U32 lastFrameChunk);
|
U32 frame, U32 lastFrameChunk);
|
||||||
typedef char ZSTD_rust_compress_continue_state_layout[
|
typedef char ZSTD_rust_compress_continue_state_layout[
|
||||||
(offsetof(ZSTD_rust_compressContinueState, callbackContext) == 0
|
(offsetof(ZSTD_rust_compressContinueState, callbackContext) == 0
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, updateWindow) == sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, windowState) == sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, correctOverflow) == 2 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, ldmWindowState) == 2 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 3 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, correctOverflow) == 3 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, compressBlock) == 4 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, compressFrameChunk) == 4 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, stage) == 5 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, compressBlock) == 5 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, consumedSrcSize) == 6 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, stage) == 6 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, producedCSize) == 7 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, consumedSrcSize) == 7 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, pledgedSrcSizePlusOne) == 8 * sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, producedCSize) == 8 * sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_compressContinueState, pledgedSrcSizePlusOne) == 9 * sizeof(void*)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, blockSizeMax)
|
&& offsetof(ZSTD_rust_compressContinueState, blockSizeMax)
|
||||||
== 8 * sizeof(void*) + sizeof(U64)
|
== 9 * sizeof(void*) + sizeof(U64)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, checkBlockSize)
|
&& offsetof(ZSTD_rust_compressContinueState, checkBlockSize)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, noDictIDFlag)
|
&& offsetof(ZSTD_rust_compressContinueState, noDictIDFlag)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + sizeof(int)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + sizeof(int)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, checksumFlag)
|
&& offsetof(ZSTD_rust_compressContinueState, checksumFlag)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 2 * sizeof(int)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 2 * sizeof(int)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, contentSizeFlag)
|
&& offsetof(ZSTD_rust_compressContinueState, contentSizeFlag)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 3 * sizeof(int)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 3 * sizeof(int)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, format)
|
&& offsetof(ZSTD_rust_compressContinueState, format)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 4 * sizeof(int)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 4 * sizeof(int)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, windowLog)
|
&& offsetof(ZSTD_rust_compressContinueState, windowLog)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int)
|
||||||
&& offsetof(ZSTD_rust_compressContinueState, dictID)
|
&& offsetof(ZSTD_rust_compressContinueState, dictID)
|
||||||
== 8 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + sizeof(U32)
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + sizeof(U32)
|
||||||
|
&& offsetof(ZSTD_rust_compressContinueState, ldmEnabled)
|
||||||
|
== 9 * sizeof(void*) + sizeof(U64) + sizeof(size_t) + 5 * sizeof(int) + 2 * sizeof(U32)
|
||||||
&& sizeof(ZSTD_rust_compressContinueState)
|
&& sizeof(ZSTD_rust_compressContinueState)
|
||||||
== (sizeof(void*) == 8 ? 112 : 72))
|
== (sizeof(void*) == 8 ? 120 : 80))
|
||||||
? 1 : -1];
|
? 1 : -1];
|
||||||
|
|
||||||
/* Rust owns the end-of-frame orchestration. The callbacks retain the
|
/* Rust owns the end-of-frame orchestration. The callbacks retain the
|
||||||
@@ -5612,22 +5629,6 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ZSTD_rust_compressContinue_updateWindow(
|
|
||||||
void* context, const void* src, size_t srcSize)
|
|
||||||
{
|
|
||||||
ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context;
|
|
||||||
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
|
|
||||||
|
|
||||||
if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) {
|
|
||||||
ms->forceNonContiguous = 0;
|
|
||||||
ms->nextToUpdate = ms->window.dictLimit;
|
|
||||||
}
|
|
||||||
if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
||||||
ZSTD_window_update(&cctx->ldmState.window, src, srcSize,
|
|
||||||
/* forceNonContiguous */ 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ZSTD_rust_compressContinue_correctOverflow(
|
static void ZSTD_rust_compressContinue_correctOverflow(
|
||||||
void* context, const void* src, size_t srcSize)
|
void* context, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
@@ -5665,8 +5666,30 @@ static size_t ZSTD_compressContinue_dispatch(
|
|||||||
size_t blockSizeMax, int checkBlockSize)
|
size_t blockSizeMax, int checkBlockSize)
|
||||||
{
|
{
|
||||||
ZSTD_rust_compressContinueState state;
|
ZSTD_rust_compressContinueState state;
|
||||||
|
ZSTD_rust_compressContinueWindowState windowState;
|
||||||
|
ZSTD_rust_compressContinueWindowState ldmWindowState;
|
||||||
|
ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;
|
||||||
|
ZSTD_window_t* const window = &ms->window;
|
||||||
|
ZSTD_window_t* const ldmWindow = &cctx->ldmState.window;
|
||||||
|
|
||||||
|
windowState.nextSrc = &window->nextSrc;
|
||||||
|
windowState.base = &window->base;
|
||||||
|
windowState.dictBase = &window->dictBase;
|
||||||
|
windowState.dictLimit = &window->dictLimit;
|
||||||
|
windowState.lowLimit = &window->lowLimit;
|
||||||
|
windowState.forceNonContiguous = &ms->forceNonContiguous;
|
||||||
|
windowState.nextToUpdate = &ms->nextToUpdate;
|
||||||
|
ldmWindowState.nextSrc = &ldmWindow->nextSrc;
|
||||||
|
ldmWindowState.base = &ldmWindow->base;
|
||||||
|
ldmWindowState.dictBase = &ldmWindow->dictBase;
|
||||||
|
ldmWindowState.dictLimit = &ldmWindow->dictLimit;
|
||||||
|
ldmWindowState.lowLimit = &ldmWindow->lowLimit;
|
||||||
|
ldmWindowState.forceNonContiguous = NULL;
|
||||||
|
ldmWindowState.nextToUpdate = NULL;
|
||||||
|
|
||||||
state.callbackContext = cctx;
|
state.callbackContext = cctx;
|
||||||
state.updateWindow = ZSTD_rust_compressContinue_updateWindow;
|
state.windowState = &windowState;
|
||||||
|
state.ldmWindowState = &ldmWindowState;
|
||||||
state.correctOverflow = ZSTD_rust_compressContinue_correctOverflow;
|
state.correctOverflow = ZSTD_rust_compressContinue_correctOverflow;
|
||||||
state.compressFrameChunk = ZSTD_rust_compressContinue_frameChunk;
|
state.compressFrameChunk = ZSTD_rust_compressContinue_frameChunk;
|
||||||
state.compressBlock = ZSTD_rust_compressContinue_block;
|
state.compressBlock = ZSTD_rust_compressContinue_block;
|
||||||
@@ -5682,6 +5705,7 @@ static size_t ZSTD_compressContinue_dispatch(
|
|||||||
state.format = (int)cctx->appliedParams.format;
|
state.format = (int)cctx->appliedParams.format;
|
||||||
state.windowLog = cctx->appliedParams.cParams.windowLog;
|
state.windowLog = cctx->appliedParams.cParams.windowLog;
|
||||||
state.dictID = cctx->dictID;
|
state.dictID = cctx->dictID;
|
||||||
|
state.ldmEnabled = cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable;
|
||||||
return ZSTD_rust_compressContinue(
|
return ZSTD_rust_compressContinue(
|
||||||
&state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk);
|
&state, dst, dstCapacity, src, srcSize, frame, lastFrameChunk);
|
||||||
}
|
}
|
||||||
|
|||||||
+200
-33
@@ -795,17 +795,59 @@ type CompressContinueWindowFn = unsafe extern "C" fn(*mut c_void, *const c_void,
|
|||||||
type CompressContinueBlockFn =
|
type CompressContinueBlockFn =
|
||||||
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;
|
||||||
|
|
||||||
|
/// Pointer projection for one C-owned `ZSTD_window_t` and the match-state
|
||||||
|
/// fields which follow its update. Each field points directly at the C
|
||||||
|
/// storage so later callbacks observe the updated window immediately.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Default)]
|
||||||
|
struct ZSTD_rust_compressContinueWindowProjection {
|
||||||
|
next_src: *mut *const c_void,
|
||||||
|
base: *mut *const c_void,
|
||||||
|
dict_base: *mut *const c_void,
|
||||||
|
dict_limit: *mut c_uint,
|
||||||
|
low_limit: *mut c_uint,
|
||||||
|
force_non_contiguous: *mut c_int,
|
||||||
|
next_to_update: *mut c_uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(offset_of!(ZSTD_rust_compressContinueWindowProjection, next_src) == 0);
|
||||||
|
assert!(offset_of!(ZSTD_rust_compressContinueWindowProjection, base) == size_of::<usize>());
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueWindowProjection, dict_base) == 2 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueWindowProjection, dict_limit)
|
||||||
|
== 3 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueWindowProjection, low_limit) == 4 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
offset_of!(
|
||||||
|
ZSTD_rust_compressContinueWindowProjection,
|
||||||
|
force_non_contiguous
|
||||||
|
) == 5 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueWindowProjection, next_to_update)
|
||||||
|
== 6 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(size_of::<ZSTD_rust_compressContinueWindowProjection>() == 7 * size_of::<usize>());
|
||||||
|
};
|
||||||
|
|
||||||
/// Explicit projection for the high-level continue and deprecated block APIs.
|
/// Explicit projection for the high-level continue and deprecated block APIs.
|
||||||
///
|
///
|
||||||
/// Rust owns stage transitions, frame-header sequencing, input progression,
|
/// Rust owns stage transitions, frame-header sequencing, input progression,
|
||||||
/// and dispatch between the already-migrated frame-chunk/block bodies. The
|
/// and dispatch between the already-migrated frame-chunk/block bodies. The
|
||||||
/// frame-header parameters are projected as scalars, while the opaque callback
|
/// frame-header parameters are projected as scalars. The opaque callback
|
||||||
/// context remains in C, where callbacks update the private match-state
|
/// context remains in C for overflow correction and context-sensitive block
|
||||||
/// windows and invoke the C-owned context-sensitive operations.
|
/// operations; window advancement is projected directly into Rust.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ZSTD_rust_compressContinueState {
|
pub struct ZSTD_rust_compressContinueState {
|
||||||
callback_context: *mut c_void,
|
callback_context: *mut c_void,
|
||||||
update_window: CompressContinueWindowFn,
|
window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
|
ldm_window_state: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
correct_overflow: CompressContinueWindowFn,
|
correct_overflow: CompressContinueWindowFn,
|
||||||
compress_frame_chunk: CompressContinueBlockFn,
|
compress_frame_chunk: CompressContinueBlockFn,
|
||||||
compress_block: CompressContinueBlockFn,
|
compress_block: CompressContinueBlockFn,
|
||||||
@@ -821,36 +863,40 @@ pub struct ZSTD_rust_compressContinueState {
|
|||||||
format: c_int,
|
format: c_int,
|
||||||
window_log: c_uint,
|
window_log: c_uint,
|
||||||
dict_id: c_uint,
|
dict_id: c_uint,
|
||||||
|
ldm_enabled: c_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
const COMPRESS_CONTINUE_SCALARS_OFFSET: usize =
|
const COMPRESS_CONTINUE_SCALARS_OFFSET: usize =
|
||||||
size_of::<[usize; 8]>() + size_of::<u64>() + size_of::<usize>();
|
size_of::<[usize; 9]>() + size_of::<u64>() + size_of::<usize>();
|
||||||
|
|
||||||
const _: () = {
|
const _: () = {
|
||||||
assert!(offset_of!(ZSTD_rust_compressContinueState, callback_context) == 0);
|
assert!(offset_of!(ZSTD_rust_compressContinueState, callback_context) == 0);
|
||||||
assert!(offset_of!(ZSTD_rust_compressContinueState, update_window) == size_of::<usize>());
|
assert!(offset_of!(ZSTD_rust_compressContinueState, window_state) == size_of::<usize>());
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 2 * size_of::<usize>()
|
offset_of!(ZSTD_rust_compressContinueState, ldm_window_state) == 2 * size_of::<usize>()
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 3 * size_of::<usize>()
|
offset_of!(ZSTD_rust_compressContinueState, correct_overflow) == 3 * size_of::<usize>()
|
||||||
);
|
);
|
||||||
assert!(offset_of!(ZSTD_rust_compressContinueState, compress_block) == 4 * size_of::<usize>());
|
|
||||||
assert!(offset_of!(ZSTD_rust_compressContinueState, stage) == 5 * size_of::<usize>());
|
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, consumed_src_size) == 6 * size_of::<usize>()
|
offset_of!(ZSTD_rust_compressContinueState, compress_frame_chunk) == 4 * size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(offset_of!(ZSTD_rust_compressContinueState, compress_block) == 5 * size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_compressContinueState, stage) == 6 * size_of::<usize>());
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueState, consumed_src_size) == 7 * size_of::<usize>()
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, produced_c_size)
|
offset_of!(ZSTD_rust_compressContinueState, produced_c_size)
|
||||||
== 7 * (usize::BITS as usize / 8)
|
== 8 * (usize::BITS as usize / 8)
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, pledged_src_size_plus_one)
|
offset_of!(ZSTD_rust_compressContinueState, pledged_src_size_plus_one)
|
||||||
== size_of::<[usize; 8]>()
|
== size_of::<[usize; 9]>()
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, block_size_max)
|
offset_of!(ZSTD_rust_compressContinueState, block_size_max)
|
||||||
== size_of::<[usize; 8]>() + size_of::<u64>()
|
== size_of::<[usize; 9]>() + size_of::<u64>()
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
offset_of!(ZSTD_rust_compressContinueState, check_block_size)
|
offset_of!(ZSTD_rust_compressContinueState, check_block_size)
|
||||||
@@ -880,9 +926,13 @@ const _: () = {
|
|||||||
offset_of!(ZSTD_rust_compressContinueState, dict_id)
|
offset_of!(ZSTD_rust_compressContinueState, dict_id)
|
||||||
== COMPRESS_CONTINUE_SCALARS_OFFSET + size_of::<[c_int; 5]>() + size_of::<c_uint>()
|
== COMPRESS_CONTINUE_SCALARS_OFFSET + size_of::<[c_int; 5]>() + size_of::<c_uint>()
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueState, ldm_enabled)
|
||||||
|
== COMPRESS_CONTINUE_SCALARS_OFFSET + size_of::<[c_int; 5]>() + 2 * size_of::<c_uint>()
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
size_of::<ZSTD_rust_compressContinueState>()
|
size_of::<ZSTD_rust_compressContinueState>()
|
||||||
== if size_of::<usize>() == 8 { 112 } else { 72 }
|
== if size_of::<usize>() == 8 { 120 } else { 80 }
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -890,6 +940,56 @@ const ZSTD_COMPRESSION_STAGE_CREATED: c_int = 0;
|
|||||||
const ZSTD_COMPRESSION_STAGE_INIT: c_int = 1;
|
const ZSTD_COMPRESSION_STAGE_INIT: c_int = 1;
|
||||||
const ZSTD_COMPRESSION_STAGE_ONGOING: c_int = 2;
|
const ZSTD_COMPRESSION_STAGE_ONGOING: c_int = 2;
|
||||||
|
|
||||||
|
unsafe fn compress_continue_update_window(
|
||||||
|
projection: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
|
src: *const c_void,
|
||||||
|
src_size: usize,
|
||||||
|
force_non_contiguous: c_int,
|
||||||
|
update_match_state: bool,
|
||||||
|
) -> Result<(), usize> {
|
||||||
|
if projection.is_null() {
|
||||||
|
return Err(ERROR(ZstdErrorCode::Generic));
|
||||||
|
}
|
||||||
|
let projection = unsafe { &*projection };
|
||||||
|
if projection.next_src.is_null()
|
||||||
|
|| projection.base.is_null()
|
||||||
|
|| projection.dict_base.is_null()
|
||||||
|
|| projection.dict_limit.is_null()
|
||||||
|
|| projection.low_limit.is_null()
|
||||||
|
{
|
||||||
|
return Err(ERROR(ZstdErrorCode::Generic));
|
||||||
|
}
|
||||||
|
if update_match_state
|
||||||
|
&& (projection.force_non_contiguous.is_null() || projection.next_to_update.is_null())
|
||||||
|
{
|
||||||
|
return Err(ERROR(ZstdErrorCode::Generic));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut window_state = ZSTD_rust_windowUpdateState {
|
||||||
|
nextSrc: unsafe { *projection.next_src },
|
||||||
|
base: unsafe { *projection.base },
|
||||||
|
dictBase: unsafe { *projection.dict_base },
|
||||||
|
dictLimit: unsafe { *projection.dict_limit },
|
||||||
|
lowLimit: unsafe { *projection.low_limit },
|
||||||
|
};
|
||||||
|
let contiguous =
|
||||||
|
unsafe { ZSTD_rust_windowUpdate(&mut window_state, src, src_size, force_non_contiguous) };
|
||||||
|
unsafe {
|
||||||
|
*projection.next_src = window_state.nextSrc;
|
||||||
|
*projection.base = window_state.base;
|
||||||
|
*projection.dict_base = window_state.dictBase;
|
||||||
|
*projection.dict_limit = window_state.dictLimit;
|
||||||
|
*projection.low_limit = window_state.lowLimit;
|
||||||
|
}
|
||||||
|
if update_match_state && contiguous == 0 {
|
||||||
|
unsafe {
|
||||||
|
*projection.force_non_contiguous = 0;
|
||||||
|
*projection.next_to_update = window_state.dictLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
unsafe fn compress_continue_body_with(
|
unsafe fn compress_continue_body_with(
|
||||||
state: &ZSTD_rust_compressContinueState,
|
state: &ZSTD_rust_compressContinueState,
|
||||||
@@ -947,7 +1047,32 @@ unsafe fn compress_continue_body_with(
|
|||||||
return frame_header_size;
|
return frame_header_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { (state.update_window)(state.callback_context, src, src_size) };
|
if state.window_state.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let match_window = unsafe { &*state.window_state };
|
||||||
|
if match_window.force_non_contiguous.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let force_non_contiguous = unsafe { *match_window.force_non_contiguous };
|
||||||
|
if let Err(result) = unsafe {
|
||||||
|
compress_continue_update_window(
|
||||||
|
state.window_state,
|
||||||
|
src,
|
||||||
|
src_size,
|
||||||
|
force_non_contiguous,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
} {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if state.ldm_enabled != 0 {
|
||||||
|
if let Err(result) = unsafe {
|
||||||
|
compress_continue_update_window(state.ldm_window_state, src, src_size, 0, false)
|
||||||
|
} {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
if frame == 0 {
|
if frame == 0 {
|
||||||
unsafe { (state.correct_overflow)(state.callback_context, src, src_size) };
|
unsafe { (state.correct_overflow)(state.callback_context, src, src_size) };
|
||||||
}
|
}
|
||||||
@@ -7610,7 +7735,7 @@ const HASH_READ_SIZE: u32 = 8;
|
|||||||
/// Pointer arithmetic is intentionally performed as wrapping address math to
|
/// Pointer arithmetic is intentionally performed as wrapping address math to
|
||||||
/// mirror the original C implementation's pointer-overflow contract.
|
/// mirror the original C implementation's pointer-overflow contract.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
pub struct ZSTD_rust_windowUpdateState {
|
pub struct ZSTD_rust_windowUpdateState {
|
||||||
pub nextSrc: *const c_void,
|
pub nextSrc: *const c_void,
|
||||||
pub base: *const c_void,
|
pub base: *const c_void,
|
||||||
@@ -11026,13 +11151,18 @@ mod tests {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct CompressContinueTestContext {
|
struct CompressContinueTestContext {
|
||||||
update_window_calls: usize,
|
|
||||||
overflow_calls: usize,
|
overflow_calls: usize,
|
||||||
frame_calls: usize,
|
frame_calls: usize,
|
||||||
block_calls: usize,
|
block_calls: usize,
|
||||||
last_frame_chunk: c_uint,
|
last_frame_chunk: c_uint,
|
||||||
frame_result: usize,
|
frame_result: usize,
|
||||||
block_result: usize,
|
block_result: usize,
|
||||||
|
window: ZSTD_rust_windowUpdateState,
|
||||||
|
ldm_window: ZSTD_rust_windowUpdateState,
|
||||||
|
force_non_contiguous: c_int,
|
||||||
|
next_to_update: c_uint,
|
||||||
|
window_projection: ZSTD_rust_compressContinueWindowProjection,
|
||||||
|
ldm_window_projection: ZSTD_rust_compressContinueWindowProjection,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn compress_continue_test_context(
|
unsafe fn compress_continue_test_context(
|
||||||
@@ -11041,15 +11171,6 @@ mod tests {
|
|||||||
unsafe { &mut *context.cast::<CompressContinueTestContext>() }
|
unsafe { &mut *context.cast::<CompressContinueTestContext>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn compress_continue_test_window(
|
|
||||||
context: *mut c_void,
|
|
||||||
_src: *const c_void,
|
|
||||||
_src_size: usize,
|
|
||||||
) {
|
|
||||||
let context = unsafe { compress_continue_test_context(context) };
|
|
||||||
context.update_window_calls += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "C" fn compress_continue_test_overflow(
|
unsafe extern "C" fn compress_continue_test_overflow(
|
||||||
context: *mut c_void,
|
context: *mut c_void,
|
||||||
_src: *const c_void,
|
_src: *const c_void,
|
||||||
@@ -11095,9 +11216,40 @@ mod tests {
|
|||||||
block_size_max: usize,
|
block_size_max: usize,
|
||||||
check_block_size: c_int,
|
check_block_size: c_int,
|
||||||
) -> ZSTD_rust_compressContinueState {
|
) -> ZSTD_rust_compressContinueState {
|
||||||
|
let base = WINDOW_INIT_SENTINEL.as_ptr().cast::<c_void>();
|
||||||
|
let next_src = unsafe { base.cast::<u8>().add(2).cast::<c_void>() };
|
||||||
|
context.window = ZSTD_rust_windowUpdateState {
|
||||||
|
nextSrc: next_src,
|
||||||
|
base,
|
||||||
|
dictBase: base,
|
||||||
|
dictLimit: ZSTD_WINDOW_START_INDEX,
|
||||||
|
lowLimit: ZSTD_WINDOW_START_INDEX,
|
||||||
|
};
|
||||||
|
context.ldm_window = context.window;
|
||||||
|
context.force_non_contiguous = 0;
|
||||||
|
context.next_to_update = ZSTD_WINDOW_START_INDEX;
|
||||||
|
context.window_projection = ZSTD_rust_compressContinueWindowProjection {
|
||||||
|
next_src: ptr::addr_of_mut!(context.window.nextSrc),
|
||||||
|
base: ptr::addr_of_mut!(context.window.base),
|
||||||
|
dict_base: ptr::addr_of_mut!(context.window.dictBase),
|
||||||
|
dict_limit: ptr::addr_of_mut!(context.window.dictLimit),
|
||||||
|
low_limit: ptr::addr_of_mut!(context.window.lowLimit),
|
||||||
|
force_non_contiguous: ptr::addr_of_mut!(context.force_non_contiguous),
|
||||||
|
next_to_update: ptr::addr_of_mut!(context.next_to_update),
|
||||||
|
};
|
||||||
|
context.ldm_window_projection = ZSTD_rust_compressContinueWindowProjection {
|
||||||
|
next_src: ptr::addr_of_mut!(context.ldm_window.nextSrc),
|
||||||
|
base: ptr::addr_of_mut!(context.ldm_window.base),
|
||||||
|
dict_base: ptr::addr_of_mut!(context.ldm_window.dictBase),
|
||||||
|
dict_limit: ptr::addr_of_mut!(context.ldm_window.dictLimit),
|
||||||
|
low_limit: ptr::addr_of_mut!(context.ldm_window.lowLimit),
|
||||||
|
force_non_contiguous: ptr::null_mut(),
|
||||||
|
next_to_update: ptr::null_mut(),
|
||||||
|
};
|
||||||
ZSTD_rust_compressContinueState {
|
ZSTD_rust_compressContinueState {
|
||||||
callback_context: (context as *mut CompressContinueTestContext).cast(),
|
callback_context: (context as *mut CompressContinueTestContext).cast(),
|
||||||
update_window: compress_continue_test_window,
|
window_state: &context.window_projection,
|
||||||
|
ldm_window_state: &context.ldm_window_projection,
|
||||||
correct_overflow: compress_continue_test_overflow,
|
correct_overflow: compress_continue_test_overflow,
|
||||||
compress_frame_chunk: compress_continue_test_frame,
|
compress_frame_chunk: compress_continue_test_frame,
|
||||||
compress_block: compress_continue_test_block,
|
compress_block: compress_continue_test_block,
|
||||||
@@ -11113,6 +11265,7 @@ mod tests {
|
|||||||
format: 0,
|
format: 0,
|
||||||
window_log: 10,
|
window_log: 10,
|
||||||
dict_id: 0,
|
dict_id: 0,
|
||||||
|
ldm_enabled: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11153,7 +11306,12 @@ mod tests {
|
|||||||
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING);
|
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING);
|
||||||
assert_eq!(consumed, 12);
|
assert_eq!(consumed, 12);
|
||||||
assert_eq!(produced, 23);
|
assert_eq!(produced, 23);
|
||||||
assert_eq!(context.update_window_calls, 1);
|
assert_eq!(context.window.nextSrc, unsafe {
|
||||||
|
source.as_ptr().add(source.len()).cast()
|
||||||
|
});
|
||||||
|
assert_eq!(context.ldm_window.nextSrc, context.window.nextSrc);
|
||||||
|
assert_eq!(context.force_non_contiguous, 0);
|
||||||
|
assert_eq!(context.next_to_update, context.window.dictLimit);
|
||||||
assert_eq!(context.overflow_calls, 0);
|
assert_eq!(context.overflow_calls, 0);
|
||||||
assert_eq!(context.frame_calls, 1);
|
assert_eq!(context.frame_calls, 1);
|
||||||
assert_eq!(context.block_calls, 0);
|
assert_eq!(context.block_calls, 0);
|
||||||
@@ -11192,7 +11350,6 @@ mod tests {
|
|||||||
assert_eq!(result, 6);
|
assert_eq!(result, 6);
|
||||||
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING);
|
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_ONGOING);
|
||||||
assert_eq!((consumed, produced), (7, 11));
|
assert_eq!((consumed, produced), (7, 11));
|
||||||
assert_eq!(context.update_window_calls, 0);
|
|
||||||
assert_eq!(context.frame_calls, 0);
|
assert_eq!(context.frame_calls, 0);
|
||||||
assert_eq!(&output[..6], &[0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x00]);
|
assert_eq!(&output[..6], &[0x28, 0xb5, 0x2f, 0xfd, 0x00, 0x00]);
|
||||||
assert_eq!(&output[6..], &[0xa5; 12]);
|
assert_eq!(&output[6..], &[0xa5; 12]);
|
||||||
@@ -11215,6 +11372,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let source = [0x22u8; 5];
|
let source = [0x22u8; 5];
|
||||||
let mut output = [0xa5u8; 16];
|
let mut output = [0xa5u8; 16];
|
||||||
|
let initial_window = context.window;
|
||||||
|
let initial_ldm_window = context.ldm_window;
|
||||||
|
|
||||||
let oversized = unsafe {
|
let oversized = unsafe {
|
||||||
ZSTD_rust_compressContinue(
|
ZSTD_rust_compressContinue(
|
||||||
@@ -11230,7 +11389,8 @@ mod tests {
|
|||||||
assert_eq!(oversized, ERROR(ZstdErrorCode::SrcSizeWrong));
|
assert_eq!(oversized, ERROR(ZstdErrorCode::SrcSizeWrong));
|
||||||
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_INIT);
|
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_INIT);
|
||||||
assert_eq!((consumed, produced), (4, 9));
|
assert_eq!((consumed, produced), (4, 9));
|
||||||
assert_eq!(context.update_window_calls, 0);
|
assert_eq!(context.window, initial_window);
|
||||||
|
assert_eq!(context.ldm_window, initial_ldm_window);
|
||||||
assert_eq!(context.block_calls, 0);
|
assert_eq!(context.block_calls, 0);
|
||||||
|
|
||||||
state.check_block_size = 0;
|
state.check_block_size = 0;
|
||||||
@@ -11248,7 +11408,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
assert_eq!(created, ERROR(ZstdErrorCode::StageWrong));
|
assert_eq!(created, ERROR(ZstdErrorCode::StageWrong));
|
||||||
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_CREATED);
|
assert_eq!(stage, ZSTD_COMPRESSION_STAGE_CREATED);
|
||||||
assert_eq!(context.update_window_calls, 0);
|
assert_eq!(context.window, initial_window);
|
||||||
|
assert_eq!(context.ldm_window, initial_ldm_window);
|
||||||
assert_eq!(context.block_calls, 0);
|
assert_eq!(context.block_calls, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11290,7 +11451,10 @@ mod tests {
|
|||||||
(stage, consumed, produced),
|
(stage, consumed, produced),
|
||||||
(ZSTD_COMPRESSION_STAGE_ONGOING, 4, 9)
|
(ZSTD_COMPRESSION_STAGE_ONGOING, 4, 9)
|
||||||
);
|
);
|
||||||
assert_eq!(context.update_window_calls, 1);
|
assert_eq!(context.window.nextSrc, unsafe {
|
||||||
|
source.as_ptr().add(source.len()).cast()
|
||||||
|
});
|
||||||
|
assert_eq!(context.ldm_window.nextSrc, context.window.nextSrc);
|
||||||
assert_eq!(context.overflow_calls, 1);
|
assert_eq!(context.overflow_calls, 1);
|
||||||
assert_eq!(context.block_calls, 1);
|
assert_eq!(context.block_calls, 1);
|
||||||
}
|
}
|
||||||
@@ -11330,6 +11494,9 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(result, ERROR(ZstdErrorCode::SrcSizeWrong));
|
assert_eq!(result, ERROR(ZstdErrorCode::SrcSizeWrong));
|
||||||
assert_eq!((consumed, produced), (6, 3));
|
assert_eq!((consumed, produced), (6, 3));
|
||||||
|
assert_eq!(context.window.nextSrc, unsafe {
|
||||||
|
source.as_ptr().add(source.len()).cast()
|
||||||
|
});
|
||||||
assert_eq!(context.block_calls, 1);
|
assert_eq!(context.block_calls, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user