feat(compress): move CDict query leaves into Rust
Move CDict compression-parameter and dictionary-ID snapshot reads behind a Rust-owned projection while retaining the private C field access and the existing non-null assertion for ZSTD_getCParamsFromCDict. Preserve the public NULL dictionary-ID result and ABI-compatible compression-parameter return. Test Plan: - cargo test --manifest-path rust/Cargo.toml --lib - cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings - make -B -C programs -j1 zstd - make -C tests -j1 test-zstream ZSTREAM_TESTTIME=-T1s - focused cdict_query_projection unit tests
This commit is contained in:
@@ -1277,6 +1277,19 @@ typedef char ZSTD_rust_compress_begin_using_cdict_state_layout[
|
||||
&& sizeof(ZSTD_rust_compressBeginUsingCDictState)
|
||||
== 12 * sizeof(void*))
|
||||
? 1 : -1];
|
||||
typedef struct {
|
||||
const ZSTD_compressionParameters* cParams;
|
||||
const unsigned* dictID;
|
||||
} ZSTD_rust_cdictQueryState;
|
||||
ZSTD_compressionParameters ZSTD_rust_getCParamsFromCDict(
|
||||
const ZSTD_rust_cdictQueryState* state);
|
||||
unsigned ZSTD_rust_getDictIDFromCDict(
|
||||
const ZSTD_rust_cdictQueryState* state);
|
||||
typedef char ZSTD_rust_cdict_query_state_layout[
|
||||
(offsetof(ZSTD_rust_cdictQueryState, cParams) == 0
|
||||
&& offsetof(ZSTD_rust_cdictQueryState, dictID) == sizeof(void*)
|
||||
&& sizeof(ZSTD_rust_cdictQueryState) == 2 * sizeof(void*))
|
||||
? 1 : -1];
|
||||
size_t ZSTD_rust_transferSequencesWBlockDelim(
|
||||
SeqStore_t* seqStore, ZSTD_SequencePosition* seqPos,
|
||||
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
||||
@@ -4939,8 +4952,11 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
|
||||
|
||||
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_rust_cdictQueryState state;
|
||||
assert(cdict != NULL);
|
||||
return cdict->matchState.cParams;
|
||||
state.cParams = &cdict->matchState.cParams;
|
||||
state.dictID = NULL;
|
||||
return ZSTD_rust_getCParamsFromCDict(&state);
|
||||
}
|
||||
|
||||
/*! ZSTD_getDictID_fromCDict() :
|
||||
@@ -4949,8 +4965,10 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
|
||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||
unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)
|
||||
{
|
||||
if (cdict==NULL) return 0;
|
||||
return cdict->dictID;
|
||||
ZSTD_rust_cdictQueryState state;
|
||||
state.cParams = NULL;
|
||||
state.dictID = cdict == NULL ? NULL : &cdict->dictID;
|
||||
return ZSTD_rust_getDictIDFromCDict(&state);
|
||||
}
|
||||
|
||||
static void ZSTD_rust_compressBeginUsingCDict_initParams(
|
||||
|
||||
@@ -232,6 +232,49 @@ pub unsafe extern "C" fn ZSTD_rust_compressBeginUsingCDict(
|
||||
}
|
||||
}
|
||||
|
||||
/// Scalar projections for the public CDict query helpers.
|
||||
#[repr(C)]
|
||||
pub struct ZSTD_rust_cdictQueryState {
|
||||
c_params: *const ZSTD_compressionParameters,
|
||||
dict_id: *const c_uint,
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
assert!(offset_of!(ZSTD_rust_cdictQueryState, c_params) == 0);
|
||||
assert!(offset_of!(ZSTD_rust_cdictQueryState, dict_id) == size_of::<usize>());
|
||||
assert!(size_of::<ZSTD_rust_cdictQueryState>() == 2 * size_of::<usize>());
|
||||
};
|
||||
|
||||
/// Return a copied compression-parameter snapshot from a CDict projection.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_getCParamsFromCDict(
|
||||
state: *const ZSTD_rust_cdictQueryState,
|
||||
) -> ZSTD_compressionParameters {
|
||||
if state.is_null() {
|
||||
return ZSTD_compressionParameters::default();
|
||||
}
|
||||
let state = unsafe { &*state };
|
||||
if state.c_params.is_null() {
|
||||
return ZSTD_compressionParameters::default();
|
||||
}
|
||||
unsafe { *state.c_params }
|
||||
}
|
||||
|
||||
/// Return the dictionary ID from a CDict projection, preserving NULL -> 0.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_getDictIDFromCDict(
|
||||
state: *const ZSTD_rust_cdictQueryState,
|
||||
) -> c_uint {
|
||||
if state.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let state = unsafe { &*state };
|
||||
if state.dict_id.is_null() {
|
||||
return 0;
|
||||
}
|
||||
unsafe { *state.dict_id }
|
||||
}
|
||||
|
||||
/// Rust-owned policy for `ZSTD_CCtx_loadDictionary_advanced()`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_CCtx_loadDictionaryAdvanced(
|
||||
@@ -891,6 +934,46 @@ mod tests {
|
||||
assert_eq!(probe.events, [3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cdict_query_projection_returns_private_snapshots() {
|
||||
let cparams = ZSTD_compressionParameters {
|
||||
windowLog: 17,
|
||||
chainLog: 12,
|
||||
hashLog: 13,
|
||||
searchLog: 1,
|
||||
minMatch: 4,
|
||||
targetLength: 16,
|
||||
strategy: 3,
|
||||
};
|
||||
let dict_id = 0x1234_5678;
|
||||
let state = ZSTD_rust_cdictQueryState {
|
||||
c_params: &cparams,
|
||||
dict_id: &dict_id,
|
||||
};
|
||||
|
||||
assert_eq!(unsafe { ZSTD_rust_getCParamsFromCDict(&state) }, cparams);
|
||||
assert_eq!(unsafe { ZSTD_rust_getDictIDFromCDict(&state) }, dict_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cdict_query_projection_handles_missing_snapshots() {
|
||||
let state = ZSTD_rust_cdictQueryState {
|
||||
c_params: ptr::null(),
|
||||
dict_id: ptr::null(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
unsafe { ZSTD_rust_getCParamsFromCDict(&state) },
|
||||
ZSTD_compressionParameters::default()
|
||||
);
|
||||
assert_eq!(unsafe { ZSTD_rust_getDictIDFromCDict(&state) }, 0);
|
||||
assert_eq!(
|
||||
unsafe { ZSTD_rust_getCParamsFromCDict(ptr::null()) },
|
||||
ZSTD_compressionParameters::default()
|
||||
);
|
||||
assert_eq!(unsafe { ZSTD_rust_getDictIDFromCDict(ptr::null()) }, 0);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CdictBeginProbe {
|
||||
events: Vec<&'static str>,
|
||||
|
||||
Reference in New Issue
Block a user