feat(compress): move deprecated block adapter into Rust
Project the existing sequence-store and block-internal states through the continue context so Rust builds deprecated blocks and enters the migrated block leaf directly. Remove the C forwarding adapter while retaining the private matchfinder and CCtx callbacks behind the existing build projection. 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:
@@ -921,6 +921,9 @@ size_t ZSTD_rust_compressContinue(
|
|||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
U32 frame, U32 lastFrameChunk);
|
U32 frame, U32 lastFrameChunk);
|
||||||
|
size_t ZSTD_rust_compressContinueBlock(
|
||||||
|
void* context, void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize, 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, windowState) == sizeof(void*)
|
&& offsetof(ZSTD_rust_compressContinueState, windowState) == sizeof(void*)
|
||||||
@@ -5422,6 +5425,13 @@ typedef struct {
|
|||||||
const ZSTD_CCtx_params* params;
|
const ZSTD_CCtx_params* params;
|
||||||
} ZSTD_rust_overflowCorrectContext;
|
} ZSTD_rust_overflowCorrectContext;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const ZSTD_rust_buildSeqStoreState* buildSeqStoreState;
|
||||||
|
const ZSTD_rust_blockInternalState* blockInternalState;
|
||||||
|
} ZSTD_rust_compressContinueBlockState;
|
||||||
|
typedef char ZSTD_rust_compress_continue_block_state_layout[
|
||||||
|
(sizeof(ZSTD_rust_compressContinueBlockState) == 2 * sizeof(void*)) ? 1 : -1];
|
||||||
|
|
||||||
/* All continue entry points use this synchronous stack projection. The
|
/* All continue entry points use this synchronous stack projection. The
|
||||||
* private CCtx and match-state layouts remain behind the direct field
|
* private CCtx and match-state layouts remain behind the direct field
|
||||||
* projections and context-sensitive leaf callbacks. */
|
* projections and context-sensitive leaf callbacks. */
|
||||||
@@ -5434,6 +5444,9 @@ typedef struct {
|
|||||||
ZSTD_rust_frameChunkClampState frameChunkClampState;
|
ZSTD_rust_frameChunkClampState frameChunkClampState;
|
||||||
ZSTD_rust_overflowCorrectContext overflowContext;
|
ZSTD_rust_overflowCorrectContext overflowContext;
|
||||||
ZSTD_rust_overflowCorrectState overflowState;
|
ZSTD_rust_overflowCorrectState overflowState;
|
||||||
|
ZSTD_rust_buildSeqStoreState buildSeqStoreState;
|
||||||
|
ZSTD_rust_blockInternalState blockInternalState;
|
||||||
|
ZSTD_rust_compressContinueBlockState blockState;
|
||||||
} ZSTD_rust_compressContinueContext;
|
} ZSTD_rust_compressContinueContext;
|
||||||
|
|
||||||
static int ZSTD_rust_overflowCorrect_need(
|
static int ZSTD_rust_overflowCorrect_need(
|
||||||
@@ -5573,16 +5586,6 @@ static size_t ZSTD_rust_frameChunk_compressInternal(
|
|||||||
1 /* frame */);
|
1 /* frame */);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ZSTD_rust_compressContinue_block(
|
|
||||||
void* context, void* dst, size_t dstCapacity,
|
|
||||||
const void* src, size_t srcSize, U32 lastFrameChunk)
|
|
||||||
{
|
|
||||||
(void)lastFrameChunk;
|
|
||||||
return ZSTD_compressBlock_internal(
|
|
||||||
(ZSTD_CCtx*)context, dst, dstCapacity, src, srcSize,
|
|
||||||
0 /* frame */);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ZSTD_compressContinue_prepare(
|
static void ZSTD_compressContinue_prepare(
|
||||||
ZSTD_CCtx* cctx, size_t blockSizeMax, int checkBlockSize,
|
ZSTD_CCtx* cctx, size_t blockSizeMax, int checkBlockSize,
|
||||||
ZSTD_rust_compressContinueContext* context)
|
ZSTD_rust_compressContinueContext* context)
|
||||||
@@ -5633,6 +5636,21 @@ static void ZSTD_compressContinue_prepare(
|
|||||||
context->frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit;
|
context->frameChunkState.compressSplit = ZSTD_rust_frameChunk_compressSplit;
|
||||||
context->frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal;
|
context->frameChunkState.compressInternal = ZSTD_rust_frameChunk_compressInternal;
|
||||||
|
|
||||||
|
ZSTD_initBuildSeqStoreState(cctx, &context->buildSeqStoreState);
|
||||||
|
context->blockInternalState.seqStore = &cctx->seqStore;
|
||||||
|
context->blockInternalState.prevCBlock = &cctx->blockState.prevCBlock;
|
||||||
|
context->blockInternalState.nextCBlock = &cctx->blockState.nextCBlock;
|
||||||
|
context->blockInternalState.tmpWorkspace = cctx->tmpWorkspace;
|
||||||
|
context->blockInternalState.tmpWkspSize = cctx->tmpWkspSize;
|
||||||
|
context->blockInternalState.seqCollector = &cctx->seqCollector;
|
||||||
|
context->blockInternalState.strategy = (int)cctx->appliedParams.cParams.strategy;
|
||||||
|
context->blockInternalState.disableLiteralCompression =
|
||||||
|
ZSTD_literalsCompressionIsDisabled(&cctx->appliedParams);
|
||||||
|
context->blockInternalState.bmi2 = cctx->bmi2;
|
||||||
|
context->blockInternalState.isFirstBlock = cctx->isFirstBlock;
|
||||||
|
context->blockState.buildSeqStoreState = &context->buildSeqStoreState;
|
||||||
|
context->blockState.blockInternalState = &context->blockInternalState;
|
||||||
|
|
||||||
context->overflowContext.matchState = ms;
|
context->overflowContext.matchState = ms;
|
||||||
context->overflowContext.workspace = &cctx->workspace;
|
context->overflowContext.workspace = &cctx->workspace;
|
||||||
context->overflowContext.params = &cctx->appliedParams;
|
context->overflowContext.params = &cctx->appliedParams;
|
||||||
@@ -5646,12 +5664,12 @@ static void ZSTD_compressContinue_prepare(
|
|||||||
context->overflowState.loadedDictEnd = &ms->loadedDictEnd;
|
context->overflowState.loadedDictEnd = &ms->loadedDictEnd;
|
||||||
context->overflowState.dictMatchState = &ms->dictMatchState;
|
context->overflowState.dictMatchState = &ms->dictMatchState;
|
||||||
|
|
||||||
context->state.callbackContext = cctx;
|
context->state.callbackContext = &context->blockState;
|
||||||
context->state.windowState = &context->windowState;
|
context->state.windowState = &context->windowState;
|
||||||
context->state.ldmWindowState = &context->ldmWindowState;
|
context->state.ldmWindowState = &context->ldmWindowState;
|
||||||
context->state.overflowState = &context->overflowState;
|
context->state.overflowState = &context->overflowState;
|
||||||
context->state.frameChunkState = &context->frameChunkState;
|
context->state.frameChunkState = &context->frameChunkState;
|
||||||
context->state.compressBlock = ZSTD_rust_compressContinue_block;
|
context->state.compressBlock = ZSTD_rust_compressContinueBlock;
|
||||||
context->state.stage = &cctx->stage;
|
context->state.stage = &cctx->stage;
|
||||||
context->state.consumedSrcSize = &cctx->consumedSrcSize;
|
context->state.consumedSrcSize = &cctx->consumedSrcSize;
|
||||||
context->state.producedCSize = &cctx->producedCSize;
|
context->state.producedCSize = &cctx->producedCSize;
|
||||||
|
|||||||
+108
-4
@@ -796,6 +796,24 @@ pub unsafe extern "C" fn ZSTD_rust_compressFrameChunk(
|
|||||||
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;
|
||||||
|
|
||||||
|
/// Explicit projection for the deprecated block adapter. Rust builds the
|
||||||
|
/// sequence store and then enters the already-Rust-owned block body; the
|
||||||
|
/// projected states retain only the matchfinder and CCtx storage callbacks.
|
||||||
|
#[repr(C)]
|
||||||
|
struct ZSTD_rust_compressContinueBlockState {
|
||||||
|
build_seq_store_state: *const ZSTD_rust_buildSeqStoreState,
|
||||||
|
block_internal_state: *const ZSTD_rust_blockInternalState,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(offset_of!(ZSTD_rust_compressContinueBlockState, build_seq_store_state) == 0);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rust_compressContinueBlockState, block_internal_state)
|
||||||
|
== size_of::<usize>()
|
||||||
|
);
|
||||||
|
assert!(size_of::<ZSTD_rust_compressContinueBlockState>() == 2 * size_of::<usize>());
|
||||||
|
};
|
||||||
|
|
||||||
/// Pointer projection for one C-owned `ZSTD_window_t` and the match-state
|
/// 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
|
/// fields which follow its update. Each field points directly at the C
|
||||||
/// storage so later callbacks observe the updated window immediately.
|
/// storage so later callbacks observe the updated window immediately.
|
||||||
@@ -942,6 +960,39 @@ const ZSTD_COMPRESSION_STAGE_ONGOING: c_int = 2;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
const ZSTD_COMPRESSION_STAGE_ENDING: c_int = 3;
|
const ZSTD_COMPRESSION_STAGE_ENDING: c_int = 3;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_compressContinueBlock(
|
||||||
|
context: *mut c_void,
|
||||||
|
dst: *mut c_void,
|
||||||
|
dst_capacity: usize,
|
||||||
|
src: *const c_void,
|
||||||
|
src_size: usize,
|
||||||
|
_last_frame_chunk: c_uint,
|
||||||
|
) -> usize {
|
||||||
|
if context.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let state = unsafe { &*context.cast::<ZSTD_rust_compressContinueBlockState>() };
|
||||||
|
if state.build_seq_store_state.is_null() || state.block_internal_state.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let bss = unsafe { ZSTD_rust_buildSeqStore(state.build_seq_store_state, src, src_size) };
|
||||||
|
if ERR_isError(bss) {
|
||||||
|
return bss;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
ZSTD_rust_compressBlockInternalAfterBuild(
|
||||||
|
state.block_internal_state,
|
||||||
|
dst,
|
||||||
|
dst_capacity,
|
||||||
|
src,
|
||||||
|
src_size,
|
||||||
|
0,
|
||||||
|
bss as c_int,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn compress_continue_update_window(
|
unsafe fn compress_continue_update_window(
|
||||||
projection: *const ZSTD_rust_compressContinueWindowProjection,
|
projection: *const ZSTD_rust_compressContinueWindowProjection,
|
||||||
src: *const c_void,
|
src: *const c_void,
|
||||||
@@ -4097,10 +4148,10 @@ const _: () = {
|
|||||||
|
|
||||||
/// Explicit projection of the state used by `ZSTD_compressBlock_internal`.
|
/// Explicit projection of the state used by `ZSTD_compressBlock_internal`.
|
||||||
///
|
///
|
||||||
/// Sequence-store construction and the no-compress fallback remain in C.
|
/// Sequence-store construction enters through an explicit build-state
|
||||||
/// Rust owns sequence collection, entropy emission, the legacy first-block
|
/// projection. Rust owns sequence collection, entropy emission, the legacy
|
||||||
/// RLE gate, and the compressed-block state transitions after the store is
|
/// first-block RLE gate, and the compressed-block state transitions after the
|
||||||
/// ready.
|
/// store is ready.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ZSTD_rust_blockInternalState {
|
pub struct ZSTD_rust_blockInternalState {
|
||||||
seq_store: *const SeqStore_t,
|
seq_store: *const SeqStore_t,
|
||||||
@@ -11525,6 +11576,59 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compress_continue_block_builds_small_block_through_projected_states() {
|
||||||
|
let mut probe = BuildSeqStoreSelectProbe::default();
|
||||||
|
let mut seq_store = unsafe { MaybeUninit::<SeqStore_t>::zeroed().assume_init() };
|
||||||
|
let mut build_state = build_seq_store_select_test_state(&mut probe, 0, 0, 0, 0);
|
||||||
|
build_state.seq_store = &mut seq_store;
|
||||||
|
|
||||||
|
let mut prev_block = zeroed_state();
|
||||||
|
let mut next_block = zeroed_state();
|
||||||
|
let mut prev_c_block = &mut prev_block as *mut _;
|
||||||
|
let mut next_c_block = &mut next_block as *mut _;
|
||||||
|
let mut seq_collector = SeqCollector {
|
||||||
|
collectSequences: 0,
|
||||||
|
seqStart: ptr::null_mut(),
|
||||||
|
seqIndex: 0,
|
||||||
|
maxSequences: 0,
|
||||||
|
};
|
||||||
|
let block_state = ZSTD_rust_blockInternalState {
|
||||||
|
seq_store: &seq_store,
|
||||||
|
prev_c_block: &mut prev_c_block,
|
||||||
|
next_c_block: &mut next_c_block,
|
||||||
|
tmp_workspace: ptr::null_mut(),
|
||||||
|
tmp_wksp_size: 0,
|
||||||
|
seq_collector: &mut seq_collector,
|
||||||
|
strategy: 0,
|
||||||
|
disable_literal_compression: 0,
|
||||||
|
bmi2: 0,
|
||||||
|
is_first_block: 1,
|
||||||
|
};
|
||||||
|
let state = ZSTD_rust_compressContinueBlockState {
|
||||||
|
build_seq_store_state: &build_state,
|
||||||
|
block_internal_state: &block_state,
|
||||||
|
};
|
||||||
|
let source = [0u8; 1];
|
||||||
|
let mut output = [0xa5u8; 8];
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ZSTD_rust_compressContinueBlock(
|
||||||
|
(&state as *const ZSTD_rust_compressContinueBlockState)
|
||||||
|
.cast_mut()
|
||||||
|
.cast(),
|
||||||
|
output.as_mut_ptr().cast(),
|
||||||
|
output.len(),
|
||||||
|
source.as_ptr().cast(),
|
||||||
|
source.len(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
assert_eq!(output, [0xa5; 8]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compress_continue_starts_frame_and_updates_progression() {
|
fn compress_continue_starts_frame_and_updates_progression() {
|
||||||
let mut context = CompressContinueTestContext {
|
let mut context = CompressContinueTestContext {
|
||||||
|
|||||||
Reference in New Issue
Block a user