diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 946e55e52..3b63f1cdb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2742,28 +2742,21 @@ typedef char ZSTD_rust_sequence_literals_state_layout[ == 6 * sizeof(void*) + 4 * sizeof(int) + 3 * sizeof(void*)) ? 1 : -1]; -/* The public sequence APIs keep their CCtx initialization and checksum state - * in C, while Rust owns frame-header serialization, ordering, and output - * accounting. The two block-loop projections above are populated by the +/* The public sequence APIs keep their CCtx initialization in C, while Rust + * owns frame-header/checksum serialization, ordering, and output accounting. + * The checksum state and two block-loop projections are populated by the * initialization callback after the private CCtx has been initialized. */ typedef struct ZSTD_rust_sequenceApiState_s ZSTD_rust_sequenceApiState; typedef size_t (*ZSTD_rust_sequenceApiInit_f)( void* context, size_t pledgedSrcSize, ZSTD_rust_sequenceApiState* state); -typedef void (*ZSTD_rust_sequenceApiUpdateChecksum_f)( - void* context, const void* src, size_t srcSize); -typedef U32 (*ZSTD_rust_sequenceApiDigestChecksum_f)(void* context); -typedef void (*ZSTD_rust_sequenceApiWriteChecksum_f)( - void* context, void* dst, U32 checksum); struct ZSTD_rust_sequenceApiState_s { void* callbackContext; ZSTD_rust_sequenceCompressionState* sequenceState; ZSTD_rust_sequenceLiteralsState* sequenceLiteralsState; ZSTD_rust_sequenceApiInit_f init; - ZSTD_rust_sequenceApiUpdateChecksum_f updateChecksum; - ZSTD_rust_sequenceApiDigestChecksum_f digestChecksum; - ZSTD_rust_sequenceApiWriteChecksum_f writeChecksum; + XXH64_state_t* checksumState; int checksumFlag; int blockDelimiters; int validateSequences; @@ -2792,30 +2785,26 @@ typedef char ZSTD_rust_sequence_api_state_layout[ == 2 * sizeof(void*) && offsetof(ZSTD_rust_sequenceApiState, init) == 3 * sizeof(void*) - && offsetof(ZSTD_rust_sequenceApiState, updateChecksum) + && offsetof(ZSTD_rust_sequenceApiState, checksumState) == 4 * sizeof(void*) - && offsetof(ZSTD_rust_sequenceApiState, digestChecksum) - == 5 * sizeof(void*) - && offsetof(ZSTD_rust_sequenceApiState, writeChecksum) - == 6 * sizeof(void*) && offsetof(ZSTD_rust_sequenceApiState, checksumFlag) - == 7 * sizeof(void*) + == 5 * sizeof(void*) && offsetof(ZSTD_rust_sequenceApiState, blockDelimiters) - == 7 * sizeof(void*) + sizeof(int) + == 5 * sizeof(void*) + sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, validateSequences) - == 7 * sizeof(void*) + 2 * sizeof(int) + == 5 * sizeof(void*) + 2 * sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, noDictIDFlag) - == 7 * sizeof(void*) + 3 * sizeof(int) + == 5 * sizeof(void*) + 3 * sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, contentSizeFlag) - == 7 * sizeof(void*) + 4 * sizeof(int) + == 5 * sizeof(void*) + 4 * sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, format) - == 7 * sizeof(void*) + 5 * sizeof(int) + == 5 * sizeof(void*) + 5 * sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, windowLog) - == 7 * sizeof(void*) + 6 * sizeof(int) + == 5 * sizeof(void*) + 6 * sizeof(int) && offsetof(ZSTD_rust_sequenceApiState, dictID) - == 7 * sizeof(void*) + 6 * sizeof(int) + sizeof(U32) + == 5 * sizeof(void*) + 6 * sizeof(int) + sizeof(U32) && sizeof(ZSTD_rust_sequenceApiState) - == (sizeof(void*) == 8 ? 88 : 60)) + == (sizeof(void*) == 8 ? 72 : 52)) ? 1 : -1]; typedef char ZSTD_rust_stats_seqdef_layout[(sizeof(SeqDef) == 8) ? 1 : -1]; @@ -8037,27 +8026,6 @@ static size_t ZSTD_rust_sequenceApi_init( return 0; } -static void ZSTD_rust_sequenceApi_updateChecksum( - void* context, const void* src, size_t srcSize) -{ - ZSTD_CCtx* const cctx = (ZSTD_CCtx*)context; - (void)XXH64_update(&cctx->xxhState, src, srcSize); -} - -static U32 ZSTD_rust_sequenceApi_digestChecksum(void* context) -{ - ZSTD_CCtx const* const cctx = (ZSTD_CCtx const*)context; - return (U32)XXH64_digest(&cctx->xxhState); -} - -static void ZSTD_rust_sequenceApi_writeChecksum( - void* context, void* dst, U32 checksum) -{ - (void)context; - DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum); - MEM_writeLE32((char*)dst, checksum); -} - static void ZSTD_rust_sequenceApi_initState( ZSTD_rust_sequenceApiState* state, ZSTD_CCtx* cctx, @@ -8068,9 +8036,7 @@ static void ZSTD_rust_sequenceApi_initState( state->sequenceState = sequenceState; state->sequenceLiteralsState = sequenceLiteralsState; state->init = ZSTD_rust_sequenceApi_init; - state->updateChecksum = ZSTD_rust_sequenceApi_updateChecksum; - state->digestChecksum = ZSTD_rust_sequenceApi_digestChecksum; - state->writeChecksum = ZSTD_rust_sequenceApi_writeChecksum; + state->checksumState = &cctx->xxhState; state->checksumFlag = 0; state->blockDelimiters = 0; state->validateSequences = 0; diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index 28ce0665c..671ef7a31 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -15,7 +15,8 @@ use crate::common::MINMATCH; use crate::errors::{ERR_isError, ZstdErrorCode, ERROR}; -use crate::xxhash::{XXH64_digest, XXH64_state_t}; +use crate::mem::MEM_writeLE32; +use crate::xxhash::{XXH64_digest, XXH64_state_t, XXH64_update}; #[cfg(not(test))] use crate::zstd_compress_api::ZSTD_compressBound; use crate::zstd_compress_frame::{ @@ -3739,25 +3740,21 @@ const _: () = { type SequenceApiInitFn = unsafe extern "C" fn(*mut c_void, usize, *mut ZSTD_rust_sequenceApiState) -> usize; -type SequenceApiUpdateChecksumFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize); -type SequenceApiDigestChecksumFn = unsafe extern "C" fn(*mut c_void) -> c_uint; -type SequenceApiWriteChecksumFn = unsafe extern "C" fn(*mut c_void, *mut c_void, c_uint); /// Explicit projection for the public sequence-compression API orchestration. /// /// Rust owns validation ordering, frame-header/checksum sequencing, and /// output accounting. Frame-header parameters are projected as scalars; C -/// retains the private CCtx, sequence-store, block, and checksum layouts -/// through the two block-state projections and callbacks. +/// retains the private CCtx and sequence-store/block layouts through the +/// initialization callback and two block-state projections. The XXH64 state +/// is projected directly so checksum updates and serialization stay in Rust. #[repr(C)] pub struct ZSTD_rust_sequenceApiState { callback_context: *mut c_void, sequence_state: *mut ZSTD_rust_sequenceCompressionState, sequence_literals_state: *mut ZSTD_rust_sequenceLiteralsState, init: SequenceApiInitFn, - update_checksum: SequenceApiUpdateChecksumFn, - digest_checksum: SequenceApiDigestChecksumFn, - write_checksum: SequenceApiWriteChecksumFn, + checksum_state: *mut XXH64_state_t, checksum_flag: c_int, block_delimiters: c_int, validate_sequences: c_int, @@ -3775,40 +3772,38 @@ const _: () = { offset_of!(ZSTD_rust_sequenceApiState, sequence_literals_state) == 2 * size_of::() ); assert!(offset_of!(ZSTD_rust_sequenceApiState, init) == 3 * size_of::()); - assert!(offset_of!(ZSTD_rust_sequenceApiState, update_checksum) == 4 * size_of::()); - assert!(offset_of!(ZSTD_rust_sequenceApiState, digest_checksum) == 5 * size_of::()); - assert!(offset_of!(ZSTD_rust_sequenceApiState, write_checksum) == 6 * size_of::()); - assert!(offset_of!(ZSTD_rust_sequenceApiState, checksum_flag) == size_of::<[usize; 7]>()); + assert!(offset_of!(ZSTD_rust_sequenceApiState, checksum_state) == 4 * size_of::()); + assert!(offset_of!(ZSTD_rust_sequenceApiState, checksum_flag) == size_of::<[usize; 5]>()); assert!( offset_of!(ZSTD_rust_sequenceApiState, block_delimiters) - == size_of::<[usize; 7]>() + size_of::() + == size_of::<[usize; 5]>() + size_of::() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, validate_sequences) - == size_of::<[usize; 7]>() + size_of::<[c_int; 2]>() + == size_of::<[usize; 5]>() + size_of::<[c_int; 2]>() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, no_dict_id_flag) - == size_of::<[usize; 7]>() + size_of::<[c_int; 3]>() + == size_of::<[usize; 5]>() + size_of::<[c_int; 3]>() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, content_size_flag) - == size_of::<[usize; 7]>() + size_of::<[c_int; 4]>() + == size_of::<[usize; 5]>() + size_of::<[c_int; 4]>() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, format) - == size_of::<[usize; 7]>() + size_of::<[c_int; 5]>() + == size_of::<[usize; 5]>() + size_of::<[c_int; 5]>() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, window_log) - == size_of::<[usize; 7]>() + size_of::<[c_int; 6]>() + == size_of::<[usize; 5]>() + size_of::<[c_int; 6]>() ); assert!( offset_of!(ZSTD_rust_sequenceApiState, dict_id) - == size_of::<[usize; 7]>() + size_of::<[c_int; 6]>() + size_of::() + == size_of::<[usize; 5]>() + size_of::<[c_int; 6]>() + size_of::() ); assert!( - size_of::() == if size_of::() == 8 { 88 } else { 60 } + size_of::() == if size_of::() == 8 { 72 } else { 52 } ); }; @@ -8263,9 +8258,7 @@ unsafe fn sequence_api_prepare( || state.sequence_state.is_null() || state.sequence_literals_state.is_null() || state.init as usize == 0 - || state.update_checksum as usize == 0 - || state.digest_checksum as usize == 0 - || state.write_checksum as usize == 0 + || state.checksum_state.is_null() { return Err(ERROR(ZstdErrorCode::Generic)); } @@ -8337,13 +8330,11 @@ unsafe fn sequence_api_append_frame_checksum( /* Keep the original ordering: digest the checksum before checking the * remaining destination capacity. */ - let checksum = unsafe { (state.digest_checksum)(state.callback_context) }; + let checksum = unsafe { XXH64_digest(state.checksum_state) as c_uint }; if dst_capacity < 4 { return ERROR(ZstdErrorCode::DstSizeTooSmall); } - unsafe { - (state.write_checksum)(state.callback_context, op.cast(), checksum); - } + unsafe { MEM_writeLE32(op.cast(), checksum) }; *c_size = c_size.wrapping_add(4); 0 } @@ -8351,10 +8342,10 @@ unsafe fn sequence_api_append_frame_checksum( /// Rust-owned orchestration for `ZSTD_compressSequences`. /// /// The C wrapper provides the post-initialization block-state projection and -/// callbacks for the private CCtx/checksum operations; frame-header fields are -/// projected as scalars. Rust preserves the public ordering: initialize, -/// write the frame header, update the input checksum, emit blocks, then append -/// the frame checksum. +/// callback for private CCtx initialization; frame-header fields and the +/// checksum state are projected directly. Rust preserves the public ordering: +/// initialize, write the frame header, update the input checksum, emit blocks, +/// then append the frame checksum. #[no_mangle] pub unsafe extern "C" fn ZSTD_rust_compressSequences( state: *mut ZSTD_rust_sequenceApiState, @@ -8385,7 +8376,9 @@ pub unsafe extern "C" fn ZSTD_rust_compressSequences( } if plan.update_input_checksum && src_size != 0 { - unsafe { (state.update_checksum)(state.callback_context, src, src_size) }; + unsafe { + let _ = XXH64_update(state.checksum_state, src, src_size); + } } let block_size = unsafe {