refactor(decompress): move legacy threshold policy to Rust
Keep the target-specific ZSTD_LEGACY_SUPPORT macro in the C translation unit, but pass its scalar value through a Rust policy bridge before legacy dispatch. Rust now accepts only the historical supported range 1 through 7 and normalizes all other values, including a missing projection, to disabled. ABI assertions and focused tests preserve the compile-time configuration contract. Test Plan: Not run in this atomic commit; the capped serial Rust, native, smoke, and original test-suite verification follows.
This commit is contained in:
@@ -187,6 +187,15 @@ typedef char ZSTD_rust_decompress_stack_callbacks_layout[
|
|||||||
size_t ZSTD_rust_decompress_stack_action(
|
size_t ZSTD_rust_decompress_stack_action(
|
||||||
const ZSTD_rustDecompressStackProjection* projection,
|
const ZSTD_rustDecompressStackProjection* projection,
|
||||||
const ZSTD_rustDecompressStackCallbacks* callbacks);
|
const ZSTD_rustDecompressStackCallbacks* callbacks);
|
||||||
|
typedef struct {
|
||||||
|
unsigned configured_level;
|
||||||
|
} ZSTD_rustLegacySupportProjection;
|
||||||
|
typedef char ZSTD_rust_legacy_support_projection_layout[
|
||||||
|
(offsetof(ZSTD_rustLegacySupportProjection, configured_level) == 0
|
||||||
|
&& sizeof(ZSTD_rustLegacySupportProjection) == sizeof(unsigned))
|
||||||
|
? 1 : -1];
|
||||||
|
unsigned ZSTD_rust_legacy_support_policy(
|
||||||
|
const ZSTD_rustLegacySupportProjection* projection);
|
||||||
unsigned ZSTD_rust_legacy_support(void);
|
unsigned ZSTD_rust_legacy_support(void);
|
||||||
|
|
||||||
#if ZSTD_TRACE
|
#if ZSTD_TRACE
|
||||||
@@ -352,15 +361,17 @@ void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The Rust dispatcher has all version-specific legacy implementations. Keep
|
/* The Rust dispatcher has all version-specific legacy implementations. Keep
|
||||||
* the active C configuration as a leaf so test builds, which compile every
|
* the active C configuration as a scalar leaf so test builds, which compile
|
||||||
* Rust legacy module but vary this C macro per target, retain the historical
|
* every Rust legacy module but vary this C macro per target, retain the
|
||||||
* support boundary. */
|
* historical support boundary. Rust owns normalization of that scalar. */
|
||||||
unsigned ZSTD_rust_legacy_support(void)
|
unsigned ZSTD_rust_legacy_support(void)
|
||||||
{
|
{
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) \
|
ZSTD_rustLegacySupportProjection const projection = {
|
||||||
&& (ZSTD_LEGACY_SUPPORT <= 7)
|
#if defined(ZSTD_LEGACY_SUPPORT)
|
||||||
return ZSTD_LEGACY_SUPPORT;
|
ZSTD_LEGACY_SUPPORT
|
||||||
#else
|
#else
|
||||||
return 0;
|
0
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
|
return ZSTD_rust_legacy_support_policy(&projection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,6 +299,17 @@ struct ZSTD_rustDctxView {
|
|||||||
dctx_size: usize,
|
dctx_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
|
pub struct ZSTD_rustLegacySupportProjection {
|
||||||
|
pub configured_level: c_uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(offset_of!(ZSTD_rustLegacySupportProjection, configured_level) == 0);
|
||||||
|
assert!(size_of::<ZSTD_rustLegacySupportProjection>() == size_of::<c_uint>());
|
||||||
|
};
|
||||||
|
|
||||||
const _: () = {
|
const _: () = {
|
||||||
assert!(offset_of!(ZSTD_rustDctxView, dctx) == 0);
|
assert!(offset_of!(ZSTD_rustDctxView, dctx) == 0);
|
||||||
assert!(offset_of!(ZSTD_rustDctxView, static_size) == 29 * size_of::<usize>());
|
assert!(offset_of!(ZSTD_rustDctxView, static_size) == 29 * size_of::<usize>());
|
||||||
@@ -645,6 +656,50 @@ unsafe fn configured_legacy_support() -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Normalize the C build's legacy-support threshold before dispatch.
|
||||||
|
///
|
||||||
|
/// C supplies the active compile-time value because test builds intentionally
|
||||||
|
/// compile every legacy module while varying `ZSTD_LEGACY_SUPPORT`. Rust owns
|
||||||
|
/// the public policy that accepts levels 1 through 7 and treats every other
|
||||||
|
/// value as legacy-disabled.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_legacy_support_policy(
|
||||||
|
projection: *const ZSTD_rustLegacySupportProjection,
|
||||||
|
) -> c_uint {
|
||||||
|
let Some(projection) = (unsafe { projection.as_ref() }) else {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
let configured = projection.configured_level;
|
||||||
|
if (1..=7).contains(&configured) {
|
||||||
|
configured
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod legacy_support_policy_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn preserves_supported_thresholds_and_disables_other_values() {
|
||||||
|
for (configured, expected) in [(0, 0), (1, 1), (4, 4), (7, 7), (8, 0), (c_uint::MAX, 0)] {
|
||||||
|
let projection = ZSTD_rustLegacySupportProjection {
|
||||||
|
configured_level: configured,
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { ZSTD_rust_legacy_support_policy(&projection) },
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rejects_missing_configuration_projection() {
|
||||||
|
assert_eq!(unsafe { ZSTD_rust_legacy_support_policy(ptr::null()) }, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This is the Rust equivalent of ZSTD_isLegacy(). The v0.1 magic is the one
|
/* This is the Rust equivalent of ZSTD_isLegacy(). The v0.1 magic is the one
|
||||||
* historical exception: its bytes are checked as the little-endian constant
|
* historical exception: its bytes are checked as the little-endian constant
|
||||||
* 0x1EB52FFD, while v0.2 through v0.7 use the usual 0xFD2FB52N values. */
|
* 0x1EB52FFD, while v0.2 through v0.7 use the usual 0xFD2FB52N values. */
|
||||||
|
|||||||
Reference in New Issue
Block a user