feat(compress): route simple context frames through Rust
Dispatch ordinary dictionary-free ZSTD_compress2 calls through the Rust frame compressor while retaining the original C implementation for advanced contexts. Prepare the C workspace first so allocation downsizing and static-context limits remain observable. Mark successful Rust frames so a following one-shot ZSTD_compressStream2(..., ZSTD_e_end) call uses the same output path. Other streaming directives and advanced parameters remain on the C implementation. Test Plan: - RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression zstd_compress::tests - RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression -- -D warnings - cargo +nightly fmt --manifest-path rust/Cargo.toml -- --check - make -B -C tests fuzzer - ./tests/fuzzer -t114 -i1000 --no-big-tests -s1 The basic fuzzer run now reaches the existing Rust one-shot compression-ratio limit at test 113; the new stateful reuse tests pass before that point.
This commit is contained in:
@@ -9,7 +9,10 @@
|
||||
//! already migrated compression leaves. `ZSTD_compressCCtx` uses the same
|
||||
//! path after a narrow C-owned context reset; the public context lifecycle
|
||||
//! and streaming APIs remain C-owned because they share the
|
||||
//! configuration-dependent private `ZSTD_CCtx_s` layout.
|
||||
//! configuration-dependent private `ZSTD_CCtx_s` layout. `ZSTD_compress2`
|
||||
//! dispatches simple, dictionary-free contexts through the same Rust frame
|
||||
//! path and retains the C implementation for advanced contexts. A following
|
||||
//! one-shot `ZSTD_compressStream2(..., ZSTD_e_end)` call can reuse that path.
|
||||
|
||||
use crate::errors::{ERR_isError, ZstdErrorCode, ERROR};
|
||||
use crate::mem::MEM_writeLE24;
|
||||
@@ -29,6 +32,21 @@ use std::ptr;
|
||||
#[cfg(not(test))]
|
||||
unsafe extern "C" {
|
||||
fn ZSTD_rust_resetCCtxForSimpleCompression(cctx: *mut c_void) -> usize;
|
||||
fn ZSTD_rust_prepareCCtxForSimpleCompression(
|
||||
cctx: *mut c_void,
|
||||
src_size: usize,
|
||||
compression_level: c_int,
|
||||
) -> usize;
|
||||
fn ZSTD_rust_resetCCtxForSimpleCompressionSession(cctx: *mut c_void) -> usize;
|
||||
fn ZSTD_rust_markSimpleCompression2Complete(cctx: *mut c_void);
|
||||
fn ZSTD_rust_simpleCompress2Level(cctx: *const c_void) -> c_int;
|
||||
fn ZSTD_compress2_c(
|
||||
cctx: *mut c_void,
|
||||
dst: *mut c_void,
|
||||
dst_capacity: usize,
|
||||
src: *const c_void,
|
||||
src_size: usize,
|
||||
) -> usize;
|
||||
}
|
||||
|
||||
const ZSTD_FAST: c_int = 1;
|
||||
@@ -360,10 +378,61 @@ pub unsafe extern "C" fn ZSTD_compressCCtx(
|
||||
if ERR_isError(reset) {
|
||||
return reset;
|
||||
}
|
||||
let prepare =
|
||||
unsafe { ZSTD_rust_prepareCCtxForSimpleCompression(cctx, src_size, compression_level) };
|
||||
if ERR_isError(prepare) {
|
||||
return prepare;
|
||||
}
|
||||
}
|
||||
unsafe { compress_frame(dst, dst_capacity, src, src_size, compression_level) }
|
||||
}
|
||||
|
||||
/// Stateful compression entry point during the context migration.
|
||||
///
|
||||
/// A context with only the ordinary frame settings is reset by the C shim and
|
||||
/// compressed through the Rust frame path. Contexts using dictionaries,
|
||||
/// checksums, target-sized blocks, sequence collection, or other advanced
|
||||
/// state still use the renamed C implementation until their state is moved.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_compress2(
|
||||
cctx: *mut c_void,
|
||||
dst: *mut c_void,
|
||||
dst_capacity: usize,
|
||||
src: *const c_void,
|
||||
src_size: usize,
|
||||
) -> usize {
|
||||
if cctx.is_null() {
|
||||
return ERROR(ZstdErrorCode::Generic);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
{
|
||||
unsafe { compress_frame(dst, dst_capacity, src, src_size, 3) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let level = unsafe { ZSTD_rust_simpleCompress2Level(cctx.cast_const()) };
|
||||
if level != c_int::MIN {
|
||||
let reset = unsafe { ZSTD_rust_resetCCtxForSimpleCompressionSession(cctx) };
|
||||
if ERR_isError(reset) {
|
||||
return reset;
|
||||
}
|
||||
let prepare =
|
||||
unsafe { ZSTD_rust_prepareCCtxForSimpleCompression(cctx, src_size, level) };
|
||||
if ERR_isError(prepare) {
|
||||
return prepare;
|
||||
}
|
||||
let result = unsafe { compress_frame(dst, dst_capacity, src, src_size, level) };
|
||||
if !ERR_isError(result) {
|
||||
unsafe { ZSTD_rust_markSimpleCompression2Complete(cctx) };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
unsafe { ZSTD_compress2_c(cctx, dst, dst_capacity, src, src_size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user