diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b05f02dc5..541f508d3 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3077,12 +3077,15 @@ typedef size_t (*ZSTD_rust_compressBeginResetUsingCDict_f)( void* context, const void* cdict, const void* params, U64 pledgedSrcSize, int zbuff); typedef size_t (*ZSTD_rust_compressBeginInsertDictionary_f)( - void* context, const void* cdict, const void* dict, - size_t dictSize, int dictContentType, int dtlm); + void* context, const void* dict, size_t dictSize, + int dictContentType, int dtlm); typedef struct { void* callbackContext; const void* params; const void* cdict; + const void* cdictDictContent; + size_t cdictDictContentSize; + int cdictDictContentType; const size_t* cdictContentSize; const int* cdictCompressionLevel; const ZSTD_dictAttachPref_e* attachDictPref; @@ -3104,37 +3107,43 @@ typedef char ZSTD_rust_compress_begin_state_layout[ (offsetof(ZSTD_rust_compressBeginState, callbackContext) == 0 && offsetof(ZSTD_rust_compressBeginState, params) == sizeof(void*) && offsetof(ZSTD_rust_compressBeginState, cdict) == 2 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, cdictContentSize) + && offsetof(ZSTD_rust_compressBeginState, cdictDictContent) == 3 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, cdictCompressionLevel) + && offsetof(ZSTD_rust_compressBeginState, cdictDictContentSize) == 4 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, attachDictPref) - == 5 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dict) + && offsetof(ZSTD_rust_compressBeginState, cdictDictContentType) + == 4 * sizeof(void*) + sizeof(size_t) + && offsetof(ZSTD_rust_compressBeginState, cdictContentSize) == 6 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dictSize) + && offsetof(ZSTD_rust_compressBeginState, cdictCompressionLevel) == 7 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dictContentType) + && offsetof(ZSTD_rust_compressBeginState, attachDictPref) == 8 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dtlm) + && offsetof(ZSTD_rust_compressBeginState, dict) == 9 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, pledgedSrcSize) + && offsetof(ZSTD_rust_compressBeginState, dictSize) == 10 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, zbuff) + && offsetof(ZSTD_rust_compressBeginState, dictContentType) == 11 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, forceLoad) + && offsetof(ZSTD_rust_compressBeginState, dtlm) == 12 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dictID) + && offsetof(ZSTD_rust_compressBeginState, pledgedSrcSize) == 13 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, dictContentSize) + && offsetof(ZSTD_rust_compressBeginState, zbuff) == 14 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, resetInternal) + && offsetof(ZSTD_rust_compressBeginState, forceLoad) == 15 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, resetUsingCDict) + && offsetof(ZSTD_rust_compressBeginState, dictID) == 16 * sizeof(void*) - && offsetof(ZSTD_rust_compressBeginState, insertDictionary) + && offsetof(ZSTD_rust_compressBeginState, dictContentSize) == 17 * sizeof(void*) - && sizeof(ZSTD_rust_compressBeginState) == 18 * sizeof(void*)) + && offsetof(ZSTD_rust_compressBeginState, resetInternal) + == 18 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, resetUsingCDict) + == 19 * sizeof(void*) + && offsetof(ZSTD_rust_compressBeginState, insertDictionary) + == 20 * sizeof(void*) + && sizeof(ZSTD_rust_compressBeginState) == 21 * sizeof(void*)) ? 1 : -1]; typedef size_t (*ZSTD_rust_resetCCtxUsingCDictAttach_f)( @@ -6743,16 +6752,10 @@ static size_t ZSTD_rust_compressBegin_resetUsingCDict( } static size_t ZSTD_rust_compressBegin_insertDictionary( - void* context, const void* cdict, const void* dict, - size_t dictSize, int dictContentType, int dtlm) + void* context, const void* dict, size_t dictSize, + int dictContentType, int dtlm) { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - if (cdict != NULL) { - ZSTD_CDict const* const dictionary = (const ZSTD_CDict*)cdict; - dict = dictionary->dictContent; - dictSize = dictionary->dictContentSize; - dictContentType = (int)dictionary->dictContentType; - } return ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, @@ -6790,6 +6793,9 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, state.callbackContext = cctx; state.params = params; state.cdict = cdict; + state.cdictDictContent = cdict == NULL ? NULL : cdict->dictContent; + state.cdictDictContentSize = cdict == NULL ? 0 : cdict->dictContentSize; + state.cdictDictContentType = cdict == NULL ? 0 : (int)cdict->dictContentType; state.cdictContentSize = cdict == NULL ? NULL : &cdict->dictContentSize; state.cdictCompressionLevel = cdict == NULL ? NULL : &cdict->compressionLevel; state.attachDictPref = ¶ms->attachDictPref; diff --git a/rust/src/zstd_compress_dictionary.rs b/rust/src/zstd_compress_dictionary.rs index fcbf41c24..0fe06bc8d 100644 --- a/rust/src/zstd_compress_dictionary.rs +++ b/rust/src/zstd_compress_dictionary.rs @@ -1537,18 +1537,22 @@ type CompressBeginResetInternalFn = type CompressBeginResetUsingCDictFn = unsafe extern "C" fn(*mut c_void, *const c_void, *const c_void, u64, c_int) -> usize; type CompressBeginInsertDictionaryFn = - unsafe extern "C" fn(*mut c_void, *const c_void, *const c_void, usize, c_int, c_int) -> usize; + unsafe extern "C" fn(*mut c_void, *const c_void, usize, c_int, c_int) -> usize; /// Projection for the dictionary-selection portion of /// `ZSTD_compressBegin_internal`. /// -/// Rust owns the CDict attach decision and dictionary-result publication. C -/// retains the context reset, CDict attach, and private insertion callbacks. +/// Rust owns the CDict attach decision, dictionary-source selection, and +/// dictionary-result publication. C retains the context reset, CDict attach, +/// and private insertion callbacks. #[repr(C)] pub struct ZSTD_rust_compressBeginState { callback_context: *mut c_void, params: *const c_void, cdict: *const c_void, + cdict_dict_content: *const c_void, + cdict_dict_content_size: usize, + cdict_dict_content_type: c_int, cdict_content_size: *const usize, cdict_compression_level: *const c_int, attach_dict_pref: *const c_int, @@ -1573,26 +1577,32 @@ const _: () = { assert!(offset_of!(ZSTD_rust_compressBeginState, callback_context) == 0); assert!(offset_of!(ZSTD_rust_compressBeginState, params) == size_of::()); assert!(offset_of!(ZSTD_rust_compressBeginState, cdict) == 2 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, cdict_content_size) == 3 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, cdict_dict_content) == 3 * size_of::()); assert!( - offset_of!(ZSTD_rust_compressBeginState, cdict_compression_level) == 4 * size_of::() + offset_of!(ZSTD_rust_compressBeginState, cdict_dict_content_size) == 4 * size_of::() ); - assert!(offset_of!(ZSTD_rust_compressBeginState, attach_dict_pref) == 5 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, dict) == 6 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, dict_size) == 7 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, dict_content_type) == size_of::<[usize; 8]>()); - assert!(offset_of!(ZSTD_rust_compressBeginState, dtlm) == 9 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, pledged_src_size) == 10 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, zbuff) == 11 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, force_load) == size_of::<[usize; 12]>()); - assert!(offset_of!(ZSTD_rust_compressBeginState, dict_id) == 13 * size_of::()); assert!( - offset_of!(ZSTD_rust_compressBeginState, dict_content_size) == size_of::<[usize; 14]>() + offset_of!(ZSTD_rust_compressBeginState, cdict_dict_content_type) + == 4 * size_of::() + size_of::() ); - assert!(offset_of!(ZSTD_rust_compressBeginState, reset_internal) == 15 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, reset_using_cdict) == 16 * size_of::()); - assert!(offset_of!(ZSTD_rust_compressBeginState, insert_dictionary) == 17 * size_of::()); - assert!(size_of::() == size_of::<[usize; 18]>()); + assert!(offset_of!(ZSTD_rust_compressBeginState, cdict_content_size) == 6 * size_of::()); + assert!( + offset_of!(ZSTD_rust_compressBeginState, cdict_compression_level) == 7 * size_of::() + ); + assert!(offset_of!(ZSTD_rust_compressBeginState, attach_dict_pref) == size_of::<[usize; 8]>()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict) == 9 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_size) == 10 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_content_type) == 11 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dtlm) == 12 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, pledged_src_size) == 13 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, zbuff) == 14 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, force_load) == 15 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_id) == 16 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, dict_content_size) == 17 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, reset_internal) == 18 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, reset_using_cdict) == 19 * size_of::()); + assert!(offset_of!(ZSTD_rust_compressBeginState, insert_dictionary) == 20 * size_of::()); + assert!(size_of::() == size_of::<[usize; 21]>()); }; /// Select and begin a dictionary-backed compression context. @@ -1676,13 +1686,23 @@ pub unsafe extern "C" fn ZSTD_rust_compressBegin( return reset_result; } + let (dict, dict_content_size, dict_content_type) = if cdict_present { + ( + state.cdict_dict_content, + state.cdict_dict_content_size, + state.cdict_dict_content_type, + ) + } else { + (state.dict, unsafe { *state.dict_size }, unsafe { + *state.dict_content_type + }) + }; let dict_id = unsafe { insert_dictionary( state.callback_context, - state.cdict, - state.dict, - *state.dict_size, - *state.dict_content_type, + dict, + dict_content_size, + dict_content_type, *state.dtlm, ) }; @@ -3104,7 +3124,6 @@ mod tests { attach_pledged_src_size: u64, attach_zbuff: c_int, attach_result: usize, - insert_cdict: *const c_void, insert_dict: *const c_void, insert_size: usize, insert_content_type: c_int, @@ -3126,7 +3145,6 @@ mod tests { attach_pledged_src_size: 0, attach_zbuff: 0, attach_result: 0, - insert_cdict: ptr::null(), insert_dict: ptr::null(), insert_size: 0, insert_content_type: 0, @@ -3174,7 +3192,6 @@ mod tests { unsafe extern "C" fn compress_begin_insert_dictionary( context: *mut c_void, - cdict: *const c_void, dict: *const c_void, dict_size: usize, dict_content_type: c_int, @@ -3182,7 +3199,6 @@ mod tests { ) -> usize { let probe = unsafe { compress_begin_probe(context) }; probe.events.push("insert"); - probe.insert_cdict = cdict; probe.insert_dict = dict; probe.insert_size = dict_size; probe.insert_content_type = dict_content_type; @@ -3195,6 +3211,9 @@ mod tests { probe: &mut CompressBeginProbe, params: *const c_void, cdict: *const c_void, + cdict_dict_content: *const c_void, + cdict_dict_content_size: usize, + cdict_dict_content_type: c_int, cdict_content_size: *const usize, cdict_compression_level: *const c_int, attach_dict_pref: &c_int, @@ -3212,6 +3231,9 @@ mod tests { callback_context: (probe as *mut CompressBeginProbe).cast(), params, cdict, + cdict_dict_content, + cdict_dict_content_size, + cdict_dict_content_type, cdict_content_size, cdict_compression_level, attach_dict_pref, @@ -3231,7 +3253,7 @@ mod tests { } #[test] - fn compress_begin_resets_then_inserts_for_loaded_dictionary() { + fn compress_begin_resets_then_inserts_by_reference_dictionary() { let dictionary = [1u8, 2, 3, 4]; let mut probe = CompressBeginProbe { insert_result: 17, @@ -3241,7 +3263,7 @@ mod tests { let attach_dict_pref = 0; let dict_size = dictionary.len(); let dict_content_type = ZSTD_DCT_RAW_CONTENT; - let dtlm = 7; + let dtlm = ZSTD_DLM_BY_REF; let pledged_src_size = 1u64 << 20; let zbuff = 9; let force_load = 1; @@ -3252,6 +3274,9 @@ mod tests { params, ptr::null(), ptr::null(), + 0, + 0, + ptr::null(), ptr::null(), &attach_dict_pref, dictionary.as_ptr().cast(), @@ -3273,7 +3298,6 @@ mod tests { assert_eq!(probe.reset_loaded_dict_size, dictionary.len()); assert_eq!(probe.reset_pledged_src_size, pledged_src_size); assert_eq!(probe.reset_zbuff, zbuff); - assert!(probe.insert_cdict.is_null()); assert_eq!(probe.insert_dict, dictionary.as_ptr().cast()); assert_eq!(probe.insert_size, dictionary.len()); assert_eq!(probe.insert_content_type, dict_content_type); @@ -3302,6 +3326,9 @@ mod tests { &mut probe, params, cdict, + ptr::null(), + 0, + 0, &cdict_content_size, &cdict_compression_level, &attach_dict_pref, @@ -3326,6 +3353,63 @@ mod tests { assert_eq!(probe.attach_zbuff, zbuff); } + #[test] + fn compress_begin_inserts_projected_cdict_content_when_forced() { + let dictionary = [5u8, 6, 7, 8]; + let mut probe = CompressBeginProbe { + insert_result: 23, + ..Default::default() + }; + let params = 0x3000usize as *const c_void; + let cdict = 0x4000usize as *const c_void; + let cdict_dict_content = dictionary.as_ptr().cast(); + let cdict_dict_content_size = dictionary.len(); + let cdict_dict_content_type = ZSTD_DCT_RAW_CONTENT; + let cdict_content_size = dictionary.len(); + let cdict_compression_level = 3; + let attach_dict_pref = 0; + let dict_size = 0; + let dict_content_type = ZSTD_DCT_AUTO; + let dtlm = ZSTD_DLM_BY_REF; + let pledged_src_size = 1u64 << 20; + let zbuff = 9; + let force_load = 1; + let mut dict_id = 0; + let mut dict_content_size = 0; + let state = compress_begin_test_state( + &mut probe, + params, + cdict, + cdict_dict_content, + cdict_dict_content_size, + cdict_dict_content_type, + &cdict_content_size, + &cdict_compression_level, + &attach_dict_pref, + ptr::null(), + &dict_size, + &dict_content_type, + &dtlm, + &pledged_src_size, + &zbuff, + &force_load, + &mut dict_id, + &mut dict_content_size, + ); + + let result = unsafe { ZSTD_rust_compressBegin(&state) }; + + assert_eq!(result, 0); + assert_eq!(probe.events, ["reset", "insert"]); + assert_eq!(probe.reset_loaded_dict_size, dictionary.len()); + assert_eq!(probe.insert_dict, cdict_dict_content); + assert_eq!(probe.insert_size, cdict_dict_content_size); + assert_eq!(probe.insert_content_type, cdict_dict_content_type); + assert_eq!(probe.insert_dtlm, dtlm); + assert_eq!(dict_id, probe.insert_result as c_uint); + assert_eq!(dict_content_size, cdict_dict_content_size); + } + struct ResetUsingCDictProbe { events: Vec<&'static str>, attach_cdict: *const c_void,