refactor(compress): move sequence generation policy to Rust
ZSTD_generateSequences() previously mixed public parameter validation, temporary-output allocation, sequence-collector setup, compression, and cleanup inside the C translation unit. Move that ordering into Rust behind callbacks so private ZSTD_CCtx and SeqCollector layouts remain C-owned. The adapter retains C allocation, context access, and the existing ZSTD_compress2 operation, while Rust guarantees temporary-output cleanup after collector setup failures and compression errors and preserves the original target-block-size and worker parameter checks. Focused callback tests cover validation-before-allocation, cleanup on setup failure, and successful callback ordering/count publication. Test Plan: - `cargo fmt --manifest-path rust/Cargo.toml --all -- --check` -- passed - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml generate_sequences --lib` -- passed (3 tests) - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --all-targets` -- passed (762 tests) - `ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings` -- passed - `ulimit -v 41943040; make -j1` -- passed
This commit is contained in:
@@ -5454,39 +5454,104 @@ static void ZSTD_initBuildSeqStoreState(
|
|||||||
|
|
||||||
/* ZSTD_sequenceBound() lives in rust/src/zstd_compress_api.rs. */
|
/* ZSTD_sequenceBound() lives in rust/src/zstd_compress_api.rs. */
|
||||||
|
|
||||||
|
typedef size_t (*ZSTD_rust_generateSequencesGetParameter_f)(
|
||||||
|
void* context, int param, int* value);
|
||||||
|
typedef void* (*ZSTD_rust_generateSequencesAllocate_f)(
|
||||||
|
void* context, size_t size);
|
||||||
|
typedef void (*ZSTD_rust_generateSequencesFree_f)(
|
||||||
|
void* context, void* pointer);
|
||||||
|
typedef size_t (*ZSTD_rust_generateSequencesSetCollector_f)(
|
||||||
|
void* context, ZSTD_Sequence* outSeqs, size_t outSeqsSize);
|
||||||
|
typedef size_t (*ZSTD_rust_generateSequencesCompress2_f)(
|
||||||
|
void* context, void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize);
|
||||||
|
typedef size_t (*ZSTD_rust_generateSequencesGetCount_f)(void* context);
|
||||||
|
typedef struct {
|
||||||
|
void* callbackContext;
|
||||||
|
ZSTD_rust_generateSequencesGetParameter_f getParameter;
|
||||||
|
ZSTD_rust_generateSequencesAllocate_f allocate;
|
||||||
|
ZSTD_rust_generateSequencesFree_f free;
|
||||||
|
ZSTD_rust_generateSequencesSetCollector_f setCollector;
|
||||||
|
ZSTD_rust_generateSequencesCompress2_f compress2;
|
||||||
|
ZSTD_rust_generateSequencesGetCount_f getCount;
|
||||||
|
} ZSTD_rust_generateSequencesState;
|
||||||
|
typedef char ZSTD_rust_generate_sequences_state_layout[
|
||||||
|
(offsetof(ZSTD_rust_generateSequencesState, callbackContext) == 0
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, getParameter)
|
||||||
|
== sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, allocate)
|
||||||
|
== 2 * sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, free)
|
||||||
|
== 3 * sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, setCollector)
|
||||||
|
== 4 * sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, compress2)
|
||||||
|
== 5 * sizeof(void*)
|
||||||
|
&& offsetof(ZSTD_rust_generateSequencesState, getCount)
|
||||||
|
== 6 * sizeof(void*)
|
||||||
|
&& sizeof(ZSTD_rust_generateSequencesState) == 7 * sizeof(void*))
|
||||||
|
? 1 : -1];
|
||||||
|
size_t ZSTD_rust_generateSequences(
|
||||||
|
const ZSTD_rust_generateSequencesState* state,
|
||||||
|
ZSTD_Sequence* outSeqs, size_t outSeqsSize,
|
||||||
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
static size_t ZSTD_rust_generateSequences_getParameter(
|
||||||
|
void* context, int param, int* value)
|
||||||
|
{
|
||||||
|
return ZSTD_CCtx_getParameter(
|
||||||
|
(const ZSTD_CCtx*)context, (ZSTD_cParameter)param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* ZSTD_rust_generateSequences_allocate(void* context, size_t size)
|
||||||
|
{
|
||||||
|
(void)context;
|
||||||
|
return ZSTD_customMalloc(size, ZSTD_defaultCMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ZSTD_rust_generateSequences_free(void* context, void* pointer)
|
||||||
|
{
|
||||||
|
(void)context;
|
||||||
|
ZSTD_customFree(pointer, ZSTD_defaultCMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ZSTD_rust_generateSequences_setCollector(
|
||||||
|
void* context, ZSTD_Sequence* outSeqs, size_t outSeqsSize)
|
||||||
|
{
|
||||||
|
ZSTD_CCtx* const zc = (ZSTD_CCtx*)context;
|
||||||
|
zc->seqCollector.collectSequences = 1;
|
||||||
|
zc->seqCollector.seqStart = outSeqs;
|
||||||
|
zc->seqCollector.seqIndex = 0;
|
||||||
|
zc->seqCollector.maxSequences = outSeqsSize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ZSTD_rust_generateSequences_compress2(
|
||||||
|
void* context, void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize)
|
||||||
|
{
|
||||||
|
return ZSTD_compress2((ZSTD_CCtx*)context, dst, dstCapacity, src, srcSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ZSTD_rust_generateSequences_getCount(void* context)
|
||||||
|
{
|
||||||
|
return ((const ZSTD_CCtx*)context)->seqCollector.seqIndex;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
||||||
size_t outSeqsSize, const void* src, size_t srcSize)
|
size_t outSeqsSize, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
const size_t dstCapacity = ZSTD_compressBound(srcSize);
|
ZSTD_rust_generateSequencesState const state = {
|
||||||
void* dst; /* Make C90 happy. */
|
zc,
|
||||||
SeqCollector seqCollector;
|
ZSTD_rust_generateSequences_getParameter,
|
||||||
{
|
ZSTD_rust_generateSequences_allocate,
|
||||||
int targetCBlockSize;
|
ZSTD_rust_generateSequences_free,
|
||||||
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), "");
|
ZSTD_rust_generateSequences_setCollector,
|
||||||
RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, "targetCBlockSize != 0");
|
ZSTD_rust_generateSequences_compress2,
|
||||||
}
|
ZSTD_rust_generateSequences_getCount
|
||||||
{
|
};
|
||||||
int nbWorkers;
|
return ZSTD_rust_generateSequences(
|
||||||
FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), "");
|
&state, outSeqs, outSeqsSize, src, srcSize);
|
||||||
RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
|
|
||||||
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
|
|
||||||
|
|
||||||
seqCollector.collectSequences = 1;
|
|
||||||
seqCollector.seqStart = outSeqs;
|
|
||||||
seqCollector.seqIndex = 0;
|
|
||||||
seqCollector.maxSequences = outSeqsSize;
|
|
||||||
zc->seqCollector = seqCollector;
|
|
||||||
|
|
||||||
{
|
|
||||||
const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
|
|
||||||
ZSTD_customFree(dst, ZSTD_defaultCMem);
|
|
||||||
FORWARD_IF_ERROR(ret, "ZSTD_compress2 failed");
|
|
||||||
}
|
|
||||||
assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));
|
|
||||||
return zc->seqCollector.seqIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ZSTD_mergeBlockDelimiters() lives in rust/src/zstd_compress_api.rs. */
|
/* ZSTD_mergeBlockDelimiters() lives in rust/src/zstd_compress_api.rs. */
|
||||||
|
|||||||
@@ -1275,6 +1275,105 @@ 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;
|
||||||
|
|
||||||
|
type GenerateSequencesGetParameterFn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, c_int, *mut c_int) -> usize;
|
||||||
|
type GenerateSequencesAllocateFn = unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void;
|
||||||
|
type GenerateSequencesFreeFn = unsafe extern "C" fn(*mut c_void, *mut c_void);
|
||||||
|
type GenerateSequencesSetCollectorFn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, *mut ZSTD_Sequence, usize) -> usize;
|
||||||
|
type GenerateSequencesCompress2Fn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize) -> usize;
|
||||||
|
type GenerateSequencesGetCountFn = unsafe extern "C" fn(*mut c_void) -> usize;
|
||||||
|
|
||||||
|
/// C-owned context projection for `ZSTD_generateSequences()`.
|
||||||
|
///
|
||||||
|
/// Rust owns the public policy and temporary-buffer lifetime. C callbacks keep
|
||||||
|
/// the private `ZSTD_CCtx` and `SeqCollector` layouts out of this module.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ZSTD_rust_generateSequencesState {
|
||||||
|
callback_context: *mut c_void,
|
||||||
|
get_parameter: GenerateSequencesGetParameterFn,
|
||||||
|
allocate: GenerateSequencesAllocateFn,
|
||||||
|
free: GenerateSequencesFreeFn,
|
||||||
|
set_collector: GenerateSequencesSetCollectorFn,
|
||||||
|
compress2: GenerateSequencesCompress2Fn,
|
||||||
|
get_count: GenerateSequencesGetCountFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, callback_context) == 0);
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, get_parameter) == size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, allocate) == 2 * size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, free) == 3 * size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, set_collector) == 4 * size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, compress2) == 5 * size_of::<usize>());
|
||||||
|
assert!(offset_of!(ZSTD_rust_generateSequencesState, get_count) == 6 * size_of::<usize>());
|
||||||
|
assert!(size_of::<ZSTD_rust_generateSequencesState>() == 7 * size_of::<usize>());
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Own the validation, allocation, collection setup, compression call, and
|
||||||
|
/// cleanup ordering for the public sequence-generation API.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_generateSequences(
|
||||||
|
state: *const ZSTD_rust_generateSequencesState,
|
||||||
|
out_seqs: *mut ZSTD_Sequence,
|
||||||
|
out_seqs_size: usize,
|
||||||
|
src: *const c_void,
|
||||||
|
src_size: usize,
|
||||||
|
) -> usize {
|
||||||
|
if state.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::Generic);
|
||||||
|
}
|
||||||
|
let state = unsafe { &*state };
|
||||||
|
let dst_capacity = crate::zstd_compress_api::ZSTD_compressBound(src_size);
|
||||||
|
let mut parameter = 0;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
(state.get_parameter)(
|
||||||
|
state.callback_context,
|
||||||
|
ZSTD_C_TARGET_C_BLOCK_SIZE,
|
||||||
|
&mut parameter,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if ERR_isError(result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if parameter != 0 {
|
||||||
|
return ERROR(ZstdErrorCode::ParameterUnsupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { (state.get_parameter)(state.callback_context, ZSTD_C_NB_WORKERS, &mut parameter) };
|
||||||
|
if ERR_isError(result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if parameter != 0 {
|
||||||
|
return ERROR(ZstdErrorCode::ParameterUnsupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dst = unsafe { (state.allocate)(state.callback_context, dst_capacity) };
|
||||||
|
if dst.is_null() {
|
||||||
|
return ERROR(ZstdErrorCode::MemoryAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = unsafe { (state.set_collector)(state.callback_context, out_seqs, out_seqs_size) };
|
||||||
|
if ERR_isError(result) {
|
||||||
|
unsafe { (state.free)(state.callback_context, dst) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { (state.compress2)(state.callback_context, dst, dst_capacity, src, src_size) };
|
||||||
|
unsafe { (state.free)(state.callback_context, dst) };
|
||||||
|
if ERR_isError(result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sequence_count = unsafe { (state.get_count)(state.callback_context) };
|
||||||
|
debug_assert!(sequence_count <= crate::zstd_compress_api::ZSTD_sequenceBound(src_size));
|
||||||
|
sequence_count
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn compress_continue_block_body_with(
|
unsafe fn compress_continue_block_body_with(
|
||||||
state: &ZSTD_rust_compressContinueBlockState,
|
state: &ZSTD_rust_compressContinueBlockState,
|
||||||
@@ -9663,6 +9762,172 @@ mod tests {
|
|||||||
const ZSTD_BTOPT: c_int = 7;
|
const ZSTD_BTOPT: c_int = 7;
|
||||||
const ZSTD_BTULTRA2: c_int = 9;
|
const ZSTD_BTULTRA2: c_int = 9;
|
||||||
|
|
||||||
|
struct GenerateSequencesTestContext {
|
||||||
|
events: Vec<&'static str>,
|
||||||
|
target_c_block_size: c_int,
|
||||||
|
nb_workers: c_int,
|
||||||
|
allocation_fails: bool,
|
||||||
|
collector_result: usize,
|
||||||
|
compress_result: usize,
|
||||||
|
sequence_count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_get_parameter_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
parameter: c_int,
|
||||||
|
value: *mut c_int,
|
||||||
|
) -> usize {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
let (event, result) = match parameter {
|
||||||
|
ZSTD_C_TARGET_C_BLOCK_SIZE => ("target", context.target_c_block_size),
|
||||||
|
ZSTD_C_NB_WORKERS => ("workers", context.nb_workers),
|
||||||
|
_ => ("other", 0),
|
||||||
|
};
|
||||||
|
context.events.push(event);
|
||||||
|
unsafe { *value = result };
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_allocate_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_size: usize,
|
||||||
|
) -> *mut c_void {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
context.events.push("allocate");
|
||||||
|
if context.allocation_fails {
|
||||||
|
ptr::null_mut()
|
||||||
|
} else {
|
||||||
|
Box::into_raw(Box::new(0_u8)).cast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_free_test(context: *mut c_void, pointer: *mut c_void) {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
context.events.push("free");
|
||||||
|
if !pointer.is_null() {
|
||||||
|
unsafe { drop(Box::from_raw(pointer.cast::<u8>())) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_set_collector_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_out_seqs: *mut ZSTD_Sequence,
|
||||||
|
_out_seqs_size: usize,
|
||||||
|
) -> usize {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
context.events.push("collector");
|
||||||
|
context.collector_result
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_compress2_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_dst: *mut c_void,
|
||||||
|
_dst_capacity: usize,
|
||||||
|
_src: *const c_void,
|
||||||
|
_src_size: usize,
|
||||||
|
) -> usize {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
context.events.push("compress2");
|
||||||
|
context.compress_result
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn generate_sequences_get_count_test(context: *mut c_void) -> usize {
|
||||||
|
let context = unsafe { &mut *context.cast::<GenerateSequencesTestContext>() };
|
||||||
|
context.events.push("count");
|
||||||
|
context.sequence_count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_sequences_test_state(
|
||||||
|
context: &mut GenerateSequencesTestContext,
|
||||||
|
) -> ZSTD_rust_generateSequencesState {
|
||||||
|
ZSTD_rust_generateSequencesState {
|
||||||
|
callback_context: context as *mut GenerateSequencesTestContext as *mut c_void,
|
||||||
|
get_parameter: generate_sequences_get_parameter_test,
|
||||||
|
allocate: generate_sequences_allocate_test,
|
||||||
|
free: generate_sequences_free_test,
|
||||||
|
set_collector: generate_sequences_set_collector_test,
|
||||||
|
compress2: generate_sequences_compress2_test,
|
||||||
|
get_count: generate_sequences_get_count_test,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_sequences_rejects_unsupported_parameters_before_allocation() {
|
||||||
|
let mut context = GenerateSequencesTestContext {
|
||||||
|
events: Vec::new(),
|
||||||
|
target_c_block_size: 1,
|
||||||
|
nb_workers: 0,
|
||||||
|
allocation_fails: false,
|
||||||
|
collector_result: 0,
|
||||||
|
compress_result: 0,
|
||||||
|
sequence_count: 0,
|
||||||
|
};
|
||||||
|
let state = generate_sequences_test_state(&mut context);
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { ZSTD_rust_generateSequences(&state, ptr::null_mut(), 0, ptr::null(), 0) };
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ERR_getErrorCode(result),
|
||||||
|
ZstdErrorCode::ParameterUnsupported as i32
|
||||||
|
);
|
||||||
|
assert_eq!(context.events, ["target"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_sequences_frees_temporary_output_on_setup_failure() {
|
||||||
|
let mut context = GenerateSequencesTestContext {
|
||||||
|
events: Vec::new(),
|
||||||
|
target_c_block_size: 0,
|
||||||
|
nb_workers: 0,
|
||||||
|
allocation_fails: false,
|
||||||
|
collector_result: ERROR(ZstdErrorCode::Generic),
|
||||||
|
compress_result: 0,
|
||||||
|
sequence_count: 0,
|
||||||
|
};
|
||||||
|
let state = generate_sequences_test_state(&mut context);
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { ZSTD_rust_generateSequences(&state, ptr::null_mut(), 0, ptr::null(), 0) };
|
||||||
|
|
||||||
|
assert_eq!(ERR_getErrorCode(result), ZstdErrorCode::Generic as i32);
|
||||||
|
assert_eq!(
|
||||||
|
context.events,
|
||||||
|
["target", "workers", "allocate", "collector", "free"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generate_sequences_runs_callbacks_in_order_and_returns_count() {
|
||||||
|
let mut context = GenerateSequencesTestContext {
|
||||||
|
events: Vec::new(),
|
||||||
|
target_c_block_size: 0,
|
||||||
|
nb_workers: 0,
|
||||||
|
allocation_fails: false,
|
||||||
|
collector_result: 0,
|
||||||
|
compress_result: 0,
|
||||||
|
sequence_count: 2,
|
||||||
|
};
|
||||||
|
let state = generate_sequences_test_state(&mut context);
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { ZSTD_rust_generateSequences(&state, ptr::null_mut(), 0, ptr::null(), 0) };
|
||||||
|
|
||||||
|
assert_eq!(result, 2);
|
||||||
|
assert_eq!(
|
||||||
|
context.events,
|
||||||
|
[
|
||||||
|
"target",
|
||||||
|
"workers",
|
||||||
|
"allocate",
|
||||||
|
"collector",
|
||||||
|
"compress2",
|
||||||
|
"free",
|
||||||
|
"count"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn select_block_compressor_test_default(
|
unsafe extern "C" fn select_block_compressor_test_default(
|
||||||
_match_state: *mut c_void,
|
_match_state: *mut c_void,
|
||||||
_seq_store: *mut SeqStore_t,
|
_seq_store: *mut SeqStore_t,
|
||||||
|
|||||||
Reference in New Issue
Block a user