refactor(decompress): move heap mode policy to Rust
`ZSTD_HEAPMODE` was still returned directly from C, and the stack entry projection also copied the raw macro. That left the one-shot stack-versus-heap classification in the C configuration shim even though Rust owns the public decompression branch and stack action. Keep the build-time override in C, but pass it through a one-field repr(C) projection to Rust. Rust normalizes values below one to the stack mode and values at or above one to the heap mode, preserving the existing behavior while making the branch policy explicit. The C stack object, private DCtx layout, platform initialization, and trace boundary remain C-owned; moving those would either duplicate build configuration or cross the requested ABI boundary. The stack projection now uses the same normalized result as the one-shot branch. ABI layout assertions cover the scalar projection, and focused Rust tests cover negative, zero, positive, maximum, and missing-configuration inputs. Test Plan: - `git diff --cached --check` -- passed - `rustfmt --edition 2021 --check rust/src/zstd_decompress.rs` -- passed - Cargo, Make, native tests, and heavy commands intentionally not run per the task restriction; integration verification remains pending.
This commit is contained in:
@@ -321,6 +321,17 @@ const _: () = {
|
||||
assert!(size_of::<ZSTD_rustNoForwardProgressProjection>() == size_of::<c_int>());
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ZSTD_rustHeapModeProjection {
|
||||
pub configured_mode: c_int,
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
assert!(offset_of!(ZSTD_rustHeapModeProjection, configured_mode) == 0);
|
||||
assert!(size_of::<ZSTD_rustHeapModeProjection>() == size_of::<c_int>());
|
||||
};
|
||||
|
||||
const _: () = {
|
||||
assert!(offset_of!(ZSTD_rustDctxView, dctx) == 0);
|
||||
assert!(offset_of!(ZSTD_rustDctxView, static_size) == 29 * size_of::<usize>());
|
||||
@@ -682,6 +693,21 @@ pub unsafe extern "C" fn ZSTD_rust_no_forward_progress_policy(
|
||||
projection.configured_max
|
||||
}
|
||||
|
||||
/// Normalize the C build's heap-mode setting to the one-shot branch policy.
|
||||
///
|
||||
/// C supplies the compile-time value because it may be overridden by the
|
||||
/// build. Rust owns the decision that values below one use the stack entry
|
||||
/// path and values at or above one use an allocated DCtx.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_heapmode_policy(
|
||||
projection: *const ZSTD_rustHeapModeProjection,
|
||||
) -> c_int {
|
||||
let Some(projection) = (unsafe { projection.as_ref() }) else {
|
||||
return 0;
|
||||
};
|
||||
c_int::from(projection.configured_mode >= 1)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod no_forward_progress_policy_tests {
|
||||
use super::*;
|
||||
@@ -706,6 +732,28 @@ mod no_forward_progress_policy_tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod heapmode_policy_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn normalizes_stack_and_heap_modes() {
|
||||
for configured_mode in [c_int::MIN, -1, 0] {
|
||||
let projection = ZSTD_rustHeapModeProjection { configured_mode };
|
||||
assert_eq!(unsafe { ZSTD_rust_heapmode_policy(&projection) }, 0);
|
||||
}
|
||||
for configured_mode in [1, c_int::MAX] {
|
||||
let projection = ZSTD_rustHeapModeProjection { configured_mode };
|
||||
assert_eq!(unsafe { ZSTD_rust_heapmode_policy(&projection) }, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_missing_heapmode_configuration() {
|
||||
assert_eq!(unsafe { ZSTD_rust_heapmode_policy(ptr::null()) }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalize the C build's legacy-support threshold before dispatch.
|
||||
///
|
||||
/// C supplies the active compile-time value because test builds intentionally
|
||||
|
||||
Reference in New Issue
Block a user