refactor(compress): move advanced CDict wrapper policy to Rust

Move advanced CDict parameter preparation and construction ordering into the Rust
policy layer while keeping advanced2 allocation, workspace, and private context
layout in C. Preserve the existing allocator and callback ABI at the seam.

Test Plan:
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets (782 passed)
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/cli/Cargo.toml --all-targets -- -D warnings
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/cli/Cargo.toml --all-targets (179 passed)
- ulimit -v 41943040; make -j1
- ulimit -v 41943040; make -j1 -C tests test (all tests completed successfully)
This commit is contained in:
2026-07-20 06:43:45 +02:00
parent 25428b8cef
commit f7c04292d4
2 changed files with 301 additions and 9 deletions
+222
View File
@@ -2224,6 +2224,100 @@ pub unsafe extern "C" fn ZSTD_rust_createCCtx(
cctx
}
type CreateCDictAdvancedWrapperInitParamsFn = unsafe extern "C" fn(
*mut c_void,
*mut c_void,
*const ZSTD_compressionParameters,
*const c_void,
usize,
c_int,
);
type CreateCDictAdvancedWrapperCreateFn = unsafe extern "C" fn(
*mut c_void,
*const c_void,
usize,
c_int,
c_int,
*const c_void,
*const c_void,
) -> *mut c_void;
/// Explicit projection for the public heap-CDict wrapper.
///
/// Rust owns the wrapper's preparation-to-construction ordering and forwards
/// the dictionary scalars. C retains the private `ZSTD_CCtx_params` setup and
/// the advanced-CDict implementation behind callbacks; allocation and
/// workspace ownership stay in the existing advanced2 path.
#[repr(C)]
pub struct ZSTD_rust_createCDictAdvancedWrapperState {
callback_context: *mut c_void,
cctx_params: *mut c_void,
c_params: *const ZSTD_compressionParameters,
custom_mem: *const c_void,
init_params: CreateCDictAdvancedWrapperInitParamsFn,
create: CreateCDictAdvancedWrapperCreateFn,
}
const _: () = {
assert!(offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, callback_context) == 0);
assert!(
offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, cctx_params) == size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, c_params) == 2 * size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, custom_mem) == 3 * size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, init_params)
== 4 * size_of::<usize>()
);
assert!(
offset_of!(ZSTD_rust_createCDictAdvancedWrapperState, create) == 5 * size_of::<usize>()
);
assert!(size_of::<ZSTD_rust_createCDictAdvancedWrapperState>() == size_of::<[usize; 6]>());
};
/// Prepare a heap-CDict parameter object, then enter the existing advanced
/// construction path in the original callback order.
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_createCDictAdvancedWrapper(
state: *const ZSTD_rust_createCDictAdvancedWrapperState,
dict: *const c_void,
dict_size: usize,
dict_load_method: c_int,
dict_content_type: c_int,
) -> *mut c_void {
if state.is_null() {
return ptr::null_mut();
}
let state = unsafe { &*state };
if state.cctx_params.is_null() || state.c_params.is_null() || state.custom_mem.is_null() {
return ptr::null_mut();
}
unsafe {
(state.init_params)(
state.callback_context,
state.cctx_params,
state.c_params,
state.custom_mem,
dict_size,
dict_content_type,
);
(state.create)(
state.callback_context,
dict,
dict_size,
dict_load_method,
dict_content_type,
state.cctx_params,
state.custom_mem,
)
}
}
type InitStaticCCtxFn = unsafe extern "C" fn(*mut c_void) -> *mut c_void;
const ZSTD_STATIC_WORKSPACE_ALIGNMENT: usize = 8;
@@ -17800,6 +17894,134 @@ mod tests {
assert!(context.initialized.is_null());
}
#[derive(Default)]
struct CreateCDictAdvancedWrapperTestContext {
events: Vec<&'static str>,
init_context: *mut c_void,
init_cctx_params: *mut c_void,
init_c_params: *const ZSTD_compressionParameters,
init_custom_mem: *const c_void,
init_dict_size: usize,
init_dict_content_type: c_int,
create_context: *mut c_void,
create_dict: *const c_void,
create_dict_size: usize,
create_dict_load_method: c_int,
create_dict_content_type: c_int,
create_cctx_params: *const c_void,
create_custom_mem: *const c_void,
result: *mut c_void,
}
unsafe extern "C" fn create_cdict_advanced_wrapper_test_init(
context: *mut c_void,
cctx_params: *mut c_void,
c_params: *const ZSTD_compressionParameters,
custom_mem: *const c_void,
dict_size: usize,
dict_content_type: c_int,
) {
let context = unsafe { &mut *context.cast::<CreateCDictAdvancedWrapperTestContext>() };
context.events.push("init");
context.init_context = context as *mut _ as *mut c_void;
context.init_cctx_params = cctx_params;
context.init_c_params = c_params;
context.init_custom_mem = custom_mem;
context.init_dict_size = dict_size;
context.init_dict_content_type = dict_content_type;
}
unsafe extern "C" fn create_cdict_advanced_wrapper_test_create(
context: *mut c_void,
dict: *const c_void,
dict_size: usize,
dict_load_method: c_int,
dict_content_type: c_int,
cctx_params: *const c_void,
custom_mem: *const c_void,
) -> *mut c_void {
let context = unsafe { &mut *context.cast::<CreateCDictAdvancedWrapperTestContext>() };
context.events.push("create");
context.create_context = context as *mut _ as *mut c_void;
context.create_dict = dict;
context.create_dict_size = dict_size;
context.create_dict_load_method = dict_load_method;
context.create_dict_content_type = dict_content_type;
context.create_cctx_params = cctx_params;
context.create_custom_mem = custom_mem;
context.result
}
fn create_cdict_advanced_wrapper_test_state(
context: &mut CreateCDictAdvancedWrapperTestContext,
cctx_params: *mut c_void,
c_params: *const ZSTD_compressionParameters,
custom_mem: *const c_void,
) -> ZSTD_rust_createCDictAdvancedWrapperState {
ZSTD_rust_createCDictAdvancedWrapperState {
callback_context: context as *mut _ as *mut c_void,
cctx_params,
c_params,
custom_mem,
init_params: create_cdict_advanced_wrapper_test_init,
create: create_cdict_advanced_wrapper_test_create,
}
}
#[test]
fn create_cdict_advanced_wrapper_preserves_prepare_then_create_order() {
let mut context = CreateCDictAdvancedWrapperTestContext {
result: ptr::dangling_mut(),
..Default::default()
};
let cctx_params = ptr::dangling_mut::<c_void>();
let c_params = ptr::dangling::<ZSTD_compressionParameters>();
let custom_mem = ptr::dangling::<c_void>();
let dict = ptr::dangling::<u8>().cast::<c_void>();
let state = create_cdict_advanced_wrapper_test_state(
&mut context,
cctx_params,
c_params,
custom_mem,
);
let result = unsafe { ZSTD_rust_createCDictAdvancedWrapper(&state, dict, 123, 1, 2) };
assert_eq!(result, context.result);
assert_eq!(context.events, ["init", "create"]);
assert_eq!(context.init_context, state.callback_context);
assert_eq!(context.init_cctx_params, cctx_params);
assert_eq!(context.init_c_params, c_params);
assert_eq!(context.init_custom_mem, custom_mem);
assert_eq!(context.init_dict_size, 123);
assert_eq!(context.init_dict_content_type, 2);
assert_eq!(context.create_context, state.callback_context);
assert_eq!(context.create_dict, dict);
assert_eq!(context.create_dict_size, 123);
assert_eq!(context.create_dict_load_method, 1);
assert_eq!(context.create_dict_content_type, 2);
assert_eq!(context.create_cctx_params, cctx_params);
assert_eq!(context.create_custom_mem, custom_mem);
}
#[test]
fn create_cdict_advanced_wrapper_rejects_missing_parameter_storage() {
let mut context = CreateCDictAdvancedWrapperTestContext::default();
let c_params = ptr::dangling::<ZSTD_compressionParameters>();
let custom_mem = ptr::dangling::<c_void>();
let state = create_cdict_advanced_wrapper_test_state(
&mut context,
ptr::null_mut(),
c_params,
custom_mem,
);
let result = unsafe { ZSTD_rust_createCDictAdvancedWrapper(&state, ptr::null(), 0, 0, 0) };
assert!(result.is_null());
assert!(context.events.is_empty());
}
#[derive(Default)]
struct InitCCtxTestContext {
events: Vec<&'static str>,