diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a14c929ba..b56ce07d5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -88,6 +88,7 @@ size_t ZSTD_rust_nextInputSizeHint(int inBufferMode, size_t inBuffPos); size_t ZSTD_rust_CStreamInSize(void); size_t ZSTD_rust_CStreamOutSize(void); +size_t ZSTD_rust_sizeofCDict(size_t objectSize, size_t workspaceSize); size_t ZSTD_rust_sizeofLocalDict(int dictBufferPresent, size_t dictSize, size_t cdictSize); size_t ZSTD_rust_sizeofCCtx(size_t objectSize, size_t workspaceSize, @@ -4000,11 +4001,13 @@ size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) { + size_t objectSize, workspaceSize; if (cdict==NULL) return 0; /* support sizeof on NULL */ DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict)); /* cdict may be in the workspace */ - return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict)) - + ZSTD_cwksp_sizeof(&cdict->workspace); + objectSize = cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict); + workspaceSize = ZSTD_cwksp_sizeof(&cdict->workspace); + return ZSTD_rust_sizeofCDict(objectSize, workspaceSize); } static size_t ZSTD_initCDict_internal( diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index b25c631ed..47a840ca2 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -485,6 +485,18 @@ pub extern "C" fn ZSTD_rust_sizeofLocalDict( sizeof_local_dict(dict_buffer_present, dict_size, cdict_size) } +#[inline] +fn sizeof_cdict(object_size: usize, workspace_size: usize) -> usize { + object_size.wrapping_add(workspace_size) +} + +/// Aggregate C-owned dictionary size components with C `size_t` wrapping +/// semantics. +#[no_mangle] +pub extern "C" fn ZSTD_rust_sizeofCDict(objectSize: usize, workspaceSize: usize) -> usize { + sizeof_cdict(objectSize, workspaceSize) +} + #[inline] fn sizeof_cctx( object_size: usize, @@ -1678,6 +1690,24 @@ mod tests { assert_eq!(sizeof_local_dict(0, usize::MAX, usize::MAX), usize::MAX); } + #[test] + fn sizeof_cdict_handles_zero_components() { + assert_eq!(sizeof_cdict(0, 0), 0); + assert_eq!(ZSTD_rust_sizeofCDict(0, 0), 0); + } + + #[test] + fn sizeof_cdict_adds_components_in_order() { + assert_eq!(sizeof_cdict(17, 25), 42); + assert_eq!(ZSTD_rust_sizeofCDict(17, 25), 42); + } + + #[test] + fn sizeof_cdict_wraps_like_c_size_t_addition() { + assert_eq!(sizeof_cdict(usize::MAX, 1), 0); + assert_eq!(ZSTD_rust_sizeofCDict(usize::MAX, 1), 0); + } + #[test] fn sizeof_cctx_handles_zero_components() { assert_eq!(sizeof_cctx(0, 0, 0, 0), 0);