feat(decompress): move DCtx prefix copy into Rust
Move the `ZSTD_copyDCtx` prefix-copy leaf into the Rust decompression module. Rust uses the C-projected address of `inBuff` to preserve the exact private context cutoff, while C retains the configuration-dependent context layout and shallow-pointer ownership semantics. Add a focused boundary test and remove the now-unused C copy helper. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo fmt --manifest-path rust/Cargo.toml -- --check - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml copy_prefix -- --nocapture - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - ulimit -v 41943040 make -B -C programs -j1 zstd - ulimit -v 41943040 make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s
This commit is contained in:
@@ -117,7 +117,6 @@ ZSTD_DDict* ZSTD_rust_create_ddict(const void* dict, size_t dictSize,
|
|||||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||||
ZSTD_dictContentType_e dictContentType,
|
ZSTD_dictContentType_e dictContentType,
|
||||||
ZSTD_customMem customMem);
|
ZSTD_customMem customMem);
|
||||||
void ZSTD_rust_dctx_copy_prefix(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx);
|
|
||||||
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx);
|
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx);
|
||||||
void ZSTD_rust_dctx_trace_end(ZSTD_DCtx* dctx, U64 uncompressedSize,
|
void ZSTD_rust_dctx_trace_end(ZSTD_DCtx* dctx, U64 uncompressedSize,
|
||||||
U64 compressedSize, int streaming);
|
U64 compressedSize, int streaming);
|
||||||
@@ -261,12 +260,6 @@ ZSTD_DDict* ZSTD_rust_create_ddict(const void* dict, size_t dictSize,
|
|||||||
dictContentType, customMem);
|
dictContentType, customMem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZSTD_rust_dctx_copy_prefix(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
||||||
{
|
|
||||||
size_t const toCopy = (size_t)((const char*)(&dstDCtx->inBuff) - (const char*)dstDCtx);
|
|
||||||
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx)
|
void ZSTD_rust_dctx_trace_begin(ZSTD_DCtx* dctx)
|
||||||
{
|
{
|
||||||
#if ZSTD_TRACE
|
#if ZSTD_TRACE
|
||||||
|
|||||||
+3
-2
@@ -119,8 +119,9 @@ zstd ABI:
|
|||||||
- `zstd_decompress` owns the public decompression context, one-shot,
|
- `zstd_decompress` owns the public decompression context, one-shot,
|
||||||
dictionary, parameter, and streaming state machines. Its C shim retains
|
dictionary, parameter, and streaming state machines. Its C shim retains
|
||||||
the configuration-dependent context layout and platform details, plus
|
the configuration-dependent context layout and platform details, plus
|
||||||
legacy and trace leaves; Rust owns decoder storage allocation and custom
|
legacy and trace leaves; Rust owns decoder storage allocation, custom
|
||||||
memory dispatch.
|
memory dispatch, and the `ZSTD_copyDCtx` prefix copy up to the projected
|
||||||
|
`inBuff` field.
|
||||||
- Command-line frontend
|
- Command-line frontend
|
||||||
- `zstd_cli` owns the Rust parser, safety policy, and dispatch. It is built
|
- `zstd_cli` owns the Rust parser, safety policy, and dispatch. It is built
|
||||||
by the separate `cli/` static-library package only for program archives,
|
by the separate `cli/` static-library package only for program archives,
|
||||||
|
|||||||
@@ -326,7 +326,6 @@ unsafe extern "C" {
|
|||||||
streaming: c_int,
|
streaming: c_int,
|
||||||
);
|
);
|
||||||
fn ZSTD_rust_dctx_trace_begin(dctx: *mut ZSTD_DCtx);
|
fn ZSTD_rust_dctx_trace_begin(dctx: *mut ZSTD_DCtx);
|
||||||
fn ZSTD_rust_dctx_copy_prefix(dst: *mut ZSTD_DCtx, src: *const ZSTD_DCtx);
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(test),
|
not(test),
|
||||||
any(
|
any(
|
||||||
@@ -367,6 +366,12 @@ unsafe fn dctx_view(dctx: *mut ZSTD_DCtx) -> ZSTD_rustDctxView {
|
|||||||
unsafe { view.assume_init() }
|
unsafe { view.assume_init() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn copy_dctx_prefix(dst: *mut u8, src: *const u8, in_buff: *const c_void) {
|
||||||
|
let to_copy = (in_buff as usize).wrapping_sub(dst as usize);
|
||||||
|
unsafe { ptr::copy_nonoverlapping(src, dst, to_copy) };
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn legacy_empty_const_ptr() -> *const c_void {
|
fn legacy_empty_const_ptr() -> *const c_void {
|
||||||
ptr::addr_of!(LEGACY_EMPTY_BYTE).cast()
|
ptr::addr_of!(LEGACY_EMPTY_BYTE).cast()
|
||||||
@@ -2574,7 +2579,32 @@ pub unsafe extern "C" fn ZSTD_freeDCtx(dctx: *mut ZSTD_DCtx) -> usize {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn ZSTD_copyDCtx(dst: *mut ZSTD_DCtx, src: *const ZSTD_DCtx) {
|
pub unsafe extern "C" fn ZSTD_copyDCtx(dst: *mut ZSTD_DCtx, src: *const ZSTD_DCtx) {
|
||||||
unsafe { ZSTD_rust_dctx_copy_prefix(dst, src) }
|
if dst.is_null() || src.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let view = unsafe { dctx_view(dst) };
|
||||||
|
unsafe {
|
||||||
|
copy_dctx_prefix(dst.cast(), src.cast(), view.in_buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod dctx_copy_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_prefix_stops_before_the_input_buffer_field() {
|
||||||
|
let source = [1u8, 2, 3, 4, 5];
|
||||||
|
let mut destination = [0xAAu8; 8];
|
||||||
|
let in_buff = unsafe { destination.as_mut_ptr().add(5).cast::<c_void>() };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
copy_dctx_prefix(destination.as_mut_ptr(), source.as_ptr(), in_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(&destination[..5], &source);
|
||||||
|
assert_eq!(&destination[5..], &[0xAA; 3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn select_frame_ddict(view: &ZSTD_rustDctxView) {
|
unsafe fn select_frame_ddict(view: &ZSTD_rustDctxView) {
|
||||||
|
|||||||
Reference in New Issue
Block a user