feat(cli): move decompression resource orchestration to Rust
Move the decompression resource creation order into the Rust CLI policy layer: dictionary stat and patch-memory preparation, decoder allocation, window/checksum configuration, dictionary reset/attachment, and asynchronous pool creation now run through one Rust-owned sequence. Keep dRess_t, stat_t, dictionary buffers, decoder context, pools, and exact allocation errors in C callbacks. Preserve the original patch-from and dictionary-reference behavior while adding ABI layout assertions, scalar policy coverage, and error short-circuit tests for the new boundary. Test Plan: - ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo +nightly fmt --manifest-path rust/cli/Cargo.toml --all - 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 (207 passed) - ulimit -v 41943040; CARGO_BUILD_JOBS=1 make -j1
This commit is contained in:
+147
-34
@@ -3820,11 +3820,62 @@ int FIO_compressMultipleFilenames(FIO_ctx_t* const fCtx,
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FIO_Dict_t dict;
|
FIO_Dict_t dict;
|
||||||
|
stat_t dictFileStat;
|
||||||
ZSTD_DStream* dctx;
|
ZSTD_DStream* dctx;
|
||||||
WritePoolCtx_t *writeCtx;
|
WritePoolCtx_t *writeCtx;
|
||||||
ReadPoolCtx_t *readCtx;
|
ReadPoolCtx_t *readCtx;
|
||||||
} dRess_t;
|
} dRess_t;
|
||||||
|
|
||||||
|
typedef void (*FIO_rust_createDResourcesPrepareDictionaryCallback_f)(
|
||||||
|
void* context, FIO_prefs_t* prefs, const char* dictFileName);
|
||||||
|
typedef void (*FIO_rust_createDResourcesCreateDctxCallback_f)(void* context);
|
||||||
|
typedef size_t (*FIO_rust_createDResourcesSetMaxWindowSizeCallback_f)(
|
||||||
|
void* context, unsigned memLimit);
|
||||||
|
typedef size_t (*FIO_rust_createDResourcesSetParameterCallback_f)(
|
||||||
|
void* context, int value);
|
||||||
|
typedef size_t (*FIO_rust_createDResourcesLoadDictionaryCallback_f)(
|
||||||
|
void* context, FIO_prefs_t* prefs, const char* dictFileName);
|
||||||
|
typedef void (*FIO_rust_createDResourcesCreatePoolCallback_f)(
|
||||||
|
void* context, const FIO_prefs_t* prefs);
|
||||||
|
typedef int (*FIO_rust_createDResourcesIsErrorCallback_f)(size_t result);
|
||||||
|
typedef struct {
|
||||||
|
void* callbackContext;
|
||||||
|
FIO_prefs_t* prefs;
|
||||||
|
const char* dictFileName;
|
||||||
|
FIO_rust_createDResourcesPrepareDictionaryCallback_f prepareDictionary;
|
||||||
|
FIO_rust_createDResourcesCreateDctxCallback_f createDctx;
|
||||||
|
FIO_rust_createDResourcesSetMaxWindowSizeCallback_f setMaxWindowSize;
|
||||||
|
FIO_rust_createDResourcesSetParameterCallback_f setParameter;
|
||||||
|
FIO_rust_createDResourcesLoadDictionaryCallback_f loadDictionary;
|
||||||
|
FIO_rust_createDResourcesCreatePoolCallback_f createWritePool;
|
||||||
|
FIO_rust_createDResourcesCreatePoolCallback_f createReadPool;
|
||||||
|
FIO_rust_createDResourcesIsErrorCallback_f isError;
|
||||||
|
} FIO_rust_createDResourcesState;
|
||||||
|
typedef char FIO_rust_create_d_resources_state_layout[
|
||||||
|
(offsetof(FIO_rust_createDResourcesState, callbackContext) == 0
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, prefs) == sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, dictFileName)
|
||||||
|
== 2 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, prepareDictionary)
|
||||||
|
== 3 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, createDctx)
|
||||||
|
== 4 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, setMaxWindowSize)
|
||||||
|
== 5 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, setParameter)
|
||||||
|
== 6 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, loadDictionary)
|
||||||
|
== 7 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, createWritePool)
|
||||||
|
== 8 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, createReadPool)
|
||||||
|
== 9 * sizeof(void*)
|
||||||
|
&& offsetof(FIO_rust_createDResourcesState, isError)
|
||||||
|
== 10 * sizeof(void*)
|
||||||
|
&& sizeof(FIO_rust_createDResourcesState) == 11 * sizeof(void*))
|
||||||
|
? 1 : -1];
|
||||||
|
size_t FIO_rust_createDResources(const FIO_rust_createDResourcesState* state);
|
||||||
|
|
||||||
typedef void (*FIO_rust_freeDResourcesCallback_f)(void* context);
|
typedef void (*FIO_rust_freeDResourcesCallback_f)(void* context);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* callbackContext;
|
void* callbackContext;
|
||||||
@@ -3870,45 +3921,107 @@ static void FIO_rust_freeDResources_readPool(void* context)
|
|||||||
AIO_ReadPool_free(ress->readCtx);
|
AIO_ReadPool_free(ress->readCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FIO_rust_createDResources_prepareDictionary(
|
||||||
|
void* context, FIO_prefs_t* prefs, const char* dictFileName)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
FIO_getDictFileStat(dictFileName, &ress->dictFileStat);
|
||||||
|
if (prefs->patchFromMode) {
|
||||||
|
unsigned long long const dictSize =
|
||||||
|
(unsigned long long)UTIL_getFileSizeStat(&ress->dictFileStat);
|
||||||
|
FIO_adjustMemLimitForPatchFromMode(
|
||||||
|
prefs, dictSize, 0 /* just use the dict size */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FIO_rust_createDResources_createDctx(void* context)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
ress->dctx = ZSTD_createDStream();
|
||||||
|
if (ress->dctx == NULL)
|
||||||
|
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t FIO_rust_createDResources_setMaxWindowSize(
|
||||||
|
void* context, unsigned memLimit)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
return ZSTD_DCtx_setMaxWindowSize(ress->dctx, memLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t FIO_rust_createDResources_setParameter(void* context, int value)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
return ZSTD_DCtx_setParameter(
|
||||||
|
ress->dctx, ZSTD_d_forceIgnoreChecksum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t FIO_rust_createDResources_loadDictionary(
|
||||||
|
void* context, FIO_prefs_t* prefs, const char* dictFileName)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
unsigned long long const dictSize = prefs->patchFromMode
|
||||||
|
? (unsigned long long)UTIL_getFileSizeStat(&ress->dictFileStat)
|
||||||
|
: 0;
|
||||||
|
FIO_dictBufferType_t const dictBufferType =
|
||||||
|
(FIO_dictBufferType_t)FIO_rust_selectDictBufferType(
|
||||||
|
prefs->mmapDict, prefs->patchFromMode, dictSize,
|
||||||
|
prefs->memLimit);
|
||||||
|
|
||||||
|
FIO_initDict(&ress->dict, dictFileName, prefs, &ress->dictFileStat,
|
||||||
|
dictBufferType);
|
||||||
|
|
||||||
|
{ size_t const result = ZSTD_DCtx_reset(
|
||||||
|
ress->dctx, ZSTD_reset_session_only);
|
||||||
|
if (ZSTD_isError(result)) return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefs->patchFromMode) {
|
||||||
|
return ZSTD_DCtx_refPrefix(
|
||||||
|
ress->dctx, ress->dict.dictBuffer, ress->dict.dictBufferSize);
|
||||||
|
}
|
||||||
|
return ZSTD_DCtx_loadDictionary_byReference(
|
||||||
|
ress->dctx, ress->dict.dictBuffer, ress->dict.dictBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FIO_rust_createDResources_createWritePool(
|
||||||
|
void* context, const FIO_prefs_t* prefs)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
ress->writeCtx = AIO_WritePool_create(prefs, ZSTD_DStreamOutSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FIO_rust_createDResources_createReadPool(
|
||||||
|
void* context, const FIO_prefs_t* prefs)
|
||||||
|
{
|
||||||
|
dRess_t* const ress = (dRess_t*)context;
|
||||||
|
ress->readCtx = AIO_ReadPool_create(prefs, ZSTD_DStreamInSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FIO_rust_createDResources_isError(size_t result)
|
||||||
|
{
|
||||||
|
return ZSTD_isError(result);
|
||||||
|
}
|
||||||
|
|
||||||
static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)
|
static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFileName)
|
||||||
{
|
{
|
||||||
unsigned long long dictSize = 0;
|
|
||||||
stat_t statbuf;
|
|
||||||
dRess_t ress;
|
dRess_t ress;
|
||||||
memset(&statbuf, 0, sizeof(statbuf));
|
|
||||||
memset(&ress, 0, sizeof(ress));
|
memset(&ress, 0, sizeof(ress));
|
||||||
|
|
||||||
FIO_getDictFileStat(dictFileName, &statbuf);
|
FIO_rust_createDResourcesState const state = {
|
||||||
|
&ress,
|
||||||
if (prefs->patchFromMode){
|
prefs,
|
||||||
dictSize = (unsigned long long)UTIL_getFileSizeStat(&statbuf);
|
dictFileName,
|
||||||
FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, 0 /* just use the dict size */);
|
FIO_rust_createDResources_prepareDictionary,
|
||||||
}
|
FIO_rust_createDResources_createDctx,
|
||||||
|
FIO_rust_createDResources_setMaxWindowSize,
|
||||||
/* Allocation */
|
FIO_rust_createDResources_setParameter,
|
||||||
ress.dctx = ZSTD_createDStream();
|
FIO_rust_createDResources_loadDictionary,
|
||||||
if (ress.dctx==NULL)
|
FIO_rust_createDResources_createWritePool,
|
||||||
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
|
FIO_rust_createDResources_createReadPool,
|
||||||
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
|
FIO_rust_createDResources_isError
|
||||||
CHECK( ZSTD_DCtx_setParameter(ress.dctx, ZSTD_d_forceIgnoreChecksum, !prefs->checksumFlag));
|
};
|
||||||
|
CHECK(FIO_rust_createDResources(&state));
|
||||||
/* dictionary */
|
|
||||||
{
|
|
||||||
FIO_dictBufferType_t const dictBufferType = (FIO_dictBufferType_t)FIO_rust_selectDictBufferType(
|
|
||||||
prefs->mmapDict, prefs->patchFromMode, dictSize, prefs->memLimit);
|
|
||||||
FIO_initDict(&ress.dict, dictFileName, prefs, &statbuf, dictBufferType);
|
|
||||||
|
|
||||||
CHECK(ZSTD_DCtx_reset(ress.dctx, ZSTD_reset_session_only) );
|
|
||||||
|
|
||||||
if (prefs->patchFromMode){
|
|
||||||
CHECK(ZSTD_DCtx_refPrefix(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));
|
|
||||||
} else {
|
|
||||||
CHECK(ZSTD_DCtx_loadDictionary_byReference(ress.dctx, ress.dict.dictBuffer, ress.dict.dictBufferSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_DStreamOutSize());
|
|
||||||
ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_DStreamInSize());
|
|
||||||
return ress;
|
return ress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -358,6 +358,99 @@ pub unsafe extern "C" fn FIO_rust_freeDResources(state: *const FIO_rust_freeDRes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type FIO_createDResourcesPrepareDictionaryFn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, *mut FIO_prefs_t, *const c_char);
|
||||||
|
pub type FIO_createDResourcesCreateDctxFn = unsafe extern "C" fn(*mut c_void);
|
||||||
|
pub type FIO_createDResourcesSetMaxWindowSizeFn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, c_uint) -> usize;
|
||||||
|
pub type FIO_createDResourcesSetParameterFn = unsafe extern "C" fn(*mut c_void, c_int) -> usize;
|
||||||
|
pub type FIO_createDResourcesLoadDictionaryFn =
|
||||||
|
unsafe extern "C" fn(*mut c_void, *mut FIO_prefs_t, *const c_char) -> usize;
|
||||||
|
pub type FIO_createDResourcesCreatePoolFn = unsafe extern "C" fn(*mut c_void, *const FIO_prefs_t);
|
||||||
|
pub type FIO_createDResourcesIsErrorFn = unsafe extern "C" fn(usize) -> c_int;
|
||||||
|
|
||||||
|
/// Decompression-resource initialization projection.
|
||||||
|
///
|
||||||
|
/// Rust owns the stable creation order and error short-circuiting. C keeps
|
||||||
|
/// the `dRess_t`, decoder context, dictionary/stat storage, and asynchronous
|
||||||
|
/// pools private behind callbacks which preserve the original diagnostics and
|
||||||
|
/// resource operations.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FIO_rust_createDResourcesState {
|
||||||
|
callback_context: *mut c_void,
|
||||||
|
prefs: *mut FIO_prefs_t,
|
||||||
|
dict_file_name: *const c_char,
|
||||||
|
prepare_dictionary: FIO_createDResourcesPrepareDictionaryFn,
|
||||||
|
create_dctx: FIO_createDResourcesCreateDctxFn,
|
||||||
|
set_max_window_size: FIO_createDResourcesSetMaxWindowSizeFn,
|
||||||
|
set_parameter: FIO_createDResourcesSetParameterFn,
|
||||||
|
load_dictionary: FIO_createDResourcesLoadDictionaryFn,
|
||||||
|
create_write_pool: FIO_createDResourcesCreatePoolFn,
|
||||||
|
create_read_pool: FIO_createDResourcesCreatePoolFn,
|
||||||
|
is_error: FIO_createDResourcesIsErrorFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
let word = size_of::<usize>();
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, callback_context) == 0);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, prefs) == word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, dict_file_name) == 2 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, prepare_dictionary) == 3 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, create_dctx) == 4 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, set_max_window_size) == 5 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, set_parameter) == 6 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, load_dictionary) == 7 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, create_write_pool) == 8 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, create_read_pool) == 9 * word);
|
||||||
|
assert!(offset_of!(FIO_rust_createDResourcesState, is_error) == 10 * word);
|
||||||
|
assert!(size_of::<FIO_rust_createDResourcesState>() == 11 * word);
|
||||||
|
};
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn FIO_rust_createDResources(
|
||||||
|
state: *const FIO_rust_createDResourcesState,
|
||||||
|
) -> usize {
|
||||||
|
let Some(state) = (unsafe { state.as_ref() }) else {
|
||||||
|
return usize::MAX;
|
||||||
|
};
|
||||||
|
if state.prefs.is_null() {
|
||||||
|
return usize::MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(state.prepare_dictionary)(state.callback_context, state.prefs, state.dict_file_name);
|
||||||
|
(state.create_dctx)(state.callback_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The preparation callback may adjust prefs->memLimit for patch mode, so
|
||||||
|
// read the scalar inputs only after that callback has completed.
|
||||||
|
let prefs = unsafe { &*state.prefs };
|
||||||
|
let result = unsafe { (state.set_max_window_size)(state.callback_context, prefs.memLimit) };
|
||||||
|
if unsafe { (state.is_error)(result) } != 0 {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
(state.set_parameter)(state.callback_context, c_int::from(prefs.checksumFlag == 0))
|
||||||
|
};
|
||||||
|
if unsafe { (state.is_error)(result) } != 0 {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
(state.load_dictionary)(state.callback_context, state.prefs, state.dict_file_name)
|
||||||
|
};
|
||||||
|
if unsafe { (state.is_error)(result) } != 0 {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(state.create_write_pool)(state.callback_context, state.prefs);
|
||||||
|
(state.create_read_pool)(state.callback_context, state.prefs);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "decompression")]
|
#[cfg(feature = "decompression")]
|
||||||
// `ZSTD_error_frameParameter_windowTooLarge` from zstd_errors.h.
|
// `ZSTD_error_frameParameter_windowTooLarge` from zstd_errors.h.
|
||||||
const ZSTD_ERROR_FRAME_PARAMETER_WINDOW_TOO_LARGE: c_int = 16;
|
const ZSTD_ERROR_FRAME_PARAMETER_WINDOW_TOO_LARGE: c_int = 16;
|
||||||
@@ -3189,6 +3282,164 @@ mod tests {
|
|||||||
assert!(context.events.is_empty());
|
assert!(context.events.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct CreateDResourcesTestState {
|
||||||
|
lifecycle: Vec<&'static str>,
|
||||||
|
max_window_size: Option<c_uint>,
|
||||||
|
ignore_checksum: Option<c_int>,
|
||||||
|
fail_at: Option<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_prepare_dictionary_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_prefs: *mut FIO_prefs_t,
|
||||||
|
_dict_file_name: *const c_char,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
(*context.cast::<CreateDResourcesTestState>())
|
||||||
|
.lifecycle
|
||||||
|
.push("prepare-dictionary");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_create_dctx_test(context: *mut c_void) {
|
||||||
|
unsafe {
|
||||||
|
(*context.cast::<CreateDResourcesTestState>())
|
||||||
|
.lifecycle
|
||||||
|
.push("create-dctx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_set_max_window_size_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
value: c_uint,
|
||||||
|
) -> usize {
|
||||||
|
let state = unsafe { &mut *context.cast::<CreateDResourcesTestState>() };
|
||||||
|
state.lifecycle.push("set-max-window");
|
||||||
|
state.max_window_size = Some(value);
|
||||||
|
usize::from(state.fail_at == Some("set-max-window")) * usize::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_set_parameter_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
value: c_int,
|
||||||
|
) -> usize {
|
||||||
|
let state = unsafe { &mut *context.cast::<CreateDResourcesTestState>() };
|
||||||
|
state.lifecycle.push("set-parameter");
|
||||||
|
state.ignore_checksum = Some(value);
|
||||||
|
usize::from(state.fail_at == Some("set-parameter")) * usize::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_load_dictionary_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_prefs: *mut FIO_prefs_t,
|
||||||
|
_dict_file_name: *const c_char,
|
||||||
|
) -> usize {
|
||||||
|
let state = unsafe { &mut *context.cast::<CreateDResourcesTestState>() };
|
||||||
|
state.lifecycle.push("load-dictionary");
|
||||||
|
usize::from(state.fail_at == Some("load-dictionary")) * usize::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_create_write_pool_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_prefs: *const FIO_prefs_t,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
(*context.cast::<CreateDResourcesTestState>())
|
||||||
|
.lifecycle
|
||||||
|
.push("create-write-pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_create_read_pool_test(
|
||||||
|
context: *mut c_void,
|
||||||
|
_prefs: *const FIO_prefs_t,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
(*context.cast::<CreateDResourcesTestState>())
|
||||||
|
.lifecycle
|
||||||
|
.push("create-read-pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn create_d_resources_is_error_test(result: usize) -> c_int {
|
||||||
|
c_int::from(result == usize::MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_d_resources_test_prefs() -> FIO_prefs_t {
|
||||||
|
let mut prefs: FIO_prefs_t = unsafe { std::mem::zeroed() };
|
||||||
|
prefs.memLimit = 64;
|
||||||
|
prefs.checksumFlag = 1;
|
||||||
|
prefs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_d_resources_test_state(
|
||||||
|
prefs: &FIO_prefs_t,
|
||||||
|
context: &mut CreateDResourcesTestState,
|
||||||
|
) -> FIO_rust_createDResourcesState {
|
||||||
|
FIO_rust_createDResourcesState {
|
||||||
|
callback_context: context as *mut CreateDResourcesTestState as *mut c_void,
|
||||||
|
prefs: prefs as *const FIO_prefs_t as *mut FIO_prefs_t,
|
||||||
|
dict_file_name: ptr::null(),
|
||||||
|
prepare_dictionary: create_d_resources_prepare_dictionary_test,
|
||||||
|
create_dctx: create_d_resources_create_dctx_test,
|
||||||
|
set_max_window_size: create_d_resources_set_max_window_size_test,
|
||||||
|
set_parameter: create_d_resources_set_parameter_test,
|
||||||
|
load_dictionary: create_d_resources_load_dictionary_test,
|
||||||
|
create_write_pool: create_d_resources_create_write_pool_test,
|
||||||
|
create_read_pool: create_d_resources_create_read_pool_test,
|
||||||
|
is_error: create_d_resources_is_error_test,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_d_resources_preserves_creation_order_and_scalar_policy() {
|
||||||
|
let prefs = create_d_resources_test_prefs();
|
||||||
|
let mut context = CreateDResourcesTestState::default();
|
||||||
|
let state = create_d_resources_test_state(&prefs, &mut context);
|
||||||
|
|
||||||
|
let result = unsafe { FIO_rust_createDResources(&state) };
|
||||||
|
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
assert_eq!(context.max_window_size, Some(64));
|
||||||
|
assert_eq!(context.ignore_checksum, Some(0));
|
||||||
|
assert_eq!(
|
||||||
|
context.lifecycle,
|
||||||
|
vec![
|
||||||
|
"prepare-dictionary",
|
||||||
|
"create-dctx",
|
||||||
|
"set-max-window",
|
||||||
|
"set-parameter",
|
||||||
|
"load-dictionary",
|
||||||
|
"create-write-pool",
|
||||||
|
"create-read-pool",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_d_resources_short_circuits_on_decoder_parameter_error() {
|
||||||
|
let prefs = create_d_resources_test_prefs();
|
||||||
|
let mut context = CreateDResourcesTestState {
|
||||||
|
fail_at: Some("set-parameter"),
|
||||||
|
..CreateDResourcesTestState::default()
|
||||||
|
};
|
||||||
|
let state = create_d_resources_test_state(&prefs, &mut context);
|
||||||
|
|
||||||
|
let result = unsafe { FIO_rust_createDResources(&state) };
|
||||||
|
|
||||||
|
assert_eq!(result, usize::MAX);
|
||||||
|
assert_eq!(
|
||||||
|
context.lifecycle,
|
||||||
|
vec![
|
||||||
|
"prepare-dictionary",
|
||||||
|
"create-dctx",
|
||||||
|
"set-max-window",
|
||||||
|
"set-parameter",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "decompression")]
|
#[cfg(feature = "decompression")]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ZstdErrorHelpTestState {
|
struct ZstdErrorHelpTestState {
|
||||||
|
|||||||
Reference in New Issue
Block a user