refactor(decompress): move sequence mode policy to Rust
Keep the C build-time mutual-exclusion check and private decoder-context assembly in the C shim, but pass the selected force-short/force-long policy through Rust. Rust now owns normalization to the runtime, short, or long sequence decoder mode, with ABI assertions and focused null/build-policy tests. 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:
@@ -25,13 +25,19 @@
|
|||||||
#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!"
|
#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT)
|
typedef struct {
|
||||||
#define ZSTD_RUST_SEQUENCE_DECODER_MODE 1
|
int forceShort;
|
||||||
#elif defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
int forceLong;
|
||||||
#define ZSTD_RUST_SEQUENCE_DECODER_MODE 2
|
} ZSTD_rustSequenceDecoderPolicy;
|
||||||
#else
|
|
||||||
#define ZSTD_RUST_SEQUENCE_DECODER_MODE 0
|
typedef char ZSTD_rust_sequence_decoder_policy_layout[
|
||||||
#endif
|
(offsetof(ZSTD_rustSequenceDecoderPolicy, forceShort) == 0
|
||||||
|
&& offsetof(ZSTD_rustSequenceDecoderPolicy, forceLong) == sizeof(int)
|
||||||
|
&& sizeof(ZSTD_rustSequenceDecoderPolicy) == 2 * sizeof(int))
|
||||||
|
? 1 : -1];
|
||||||
|
|
||||||
|
int ZSTD_rust_sequence_decoder_mode(
|
||||||
|
const ZSTD_rustSequenceDecoderPolicy* policy);
|
||||||
|
|
||||||
typedef char ZSTD_rust_block_seq_symbol_layout[(sizeof(ZSTD_seqSymbol) == 8) ? 1 : -1];
|
typedef char ZSTD_rust_block_seq_symbol_layout[(sizeof(ZSTD_seqSymbol) == 8) ? 1 : -1];
|
||||||
typedef char ZSTD_rust_block_entropy_rep_offset[
|
typedef char ZSTD_rust_block_entropy_rep_offset[
|
||||||
@@ -72,6 +78,15 @@ typedef struct {
|
|||||||
static ZSTD_rustBlockCtx ZSTD_rust_block_context(ZSTD_DCtx* dctx)
|
static ZSTD_rustBlockCtx ZSTD_rust_block_context(ZSTD_DCtx* dctx)
|
||||||
{
|
{
|
||||||
ZSTD_rustBlockCtx ctx;
|
ZSTD_rustBlockCtx ctx;
|
||||||
|
ZSTD_rustSequenceDecoderPolicy const sequencePolicy = {
|
||||||
|
#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT)
|
||||||
|
1, 0
|
||||||
|
#elif defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
||||||
|
0, 1
|
||||||
|
#else
|
||||||
|
0, 0
|
||||||
|
#endif
|
||||||
|
};
|
||||||
ctx.lltPtr = &dctx->LLTptr;
|
ctx.lltPtr = &dctx->LLTptr;
|
||||||
ctx.mltPtr = &dctx->MLTptr;
|
ctx.mltPtr = &dctx->MLTptr;
|
||||||
ctx.oftPtr = &dctx->OFTptr;
|
ctx.oftPtr = &dctx->OFTptr;
|
||||||
@@ -98,7 +113,7 @@ static ZSTD_rustBlockCtx ZSTD_rust_block_context(ZSTD_DCtx* dctx)
|
|||||||
ctx.litBufferLocation = &dctx->litBufferLocation;
|
ctx.litBufferLocation = &dctx->litBufferLocation;
|
||||||
ctx.litExtraBuffer = dctx->litExtraBuffer;
|
ctx.litExtraBuffer = dctx->litExtraBuffer;
|
||||||
ctx.litExtraBufferSize = ZSTD_LITBUFFEREXTRASIZE;
|
ctx.litExtraBufferSize = ZSTD_LITBUFFEREXTRASIZE;
|
||||||
ctx.sequenceDecoderMode = ZSTD_RUST_SEQUENCE_DECODER_MODE;
|
ctx.sequenceDecoderMode = ZSTD_rust_sequence_decoder_mode(&sequencePolicy);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ use crate::mem::{MEM_32bits, MEM_64bits, MEM_readLE16, MEM_readLE24, U32};
|
|||||||
use crate::zstd_decompress::ZSTD_DCtx;
|
use crate::zstd_decompress::ZSTD_DCtx;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::{offset_of, size_of, MaybeUninit};
|
||||||
use std::os::raw::{c_int, c_short, c_uint};
|
use std::os::raw::{c_int, c_short, c_uint};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
@@ -68,6 +68,47 @@ const LONG_OFFSET_HISTORY_THRESHOLD: usize = 1 << 24;
|
|||||||
const LONG_OFFSET_MIN_SHARE_32: u32 = 20;
|
const LONG_OFFSET_MIN_SHARE_32: u32 = 20;
|
||||||
const LONG_OFFSET_MIN_SHARE_64: u32 = 7;
|
const LONG_OFFSET_MIN_SHARE_64: u32 = 7;
|
||||||
|
|
||||||
|
/// Build-system sequence-decoder choices passed without exposing `ZSTD_DCtx`.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
|
pub struct ZSTD_rustSequenceDecoderPolicy {
|
||||||
|
force_short: c_int,
|
||||||
|
force_long: c_int,
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(offset_of!(ZSTD_rustSequenceDecoderPolicy, force_short) == 0);
|
||||||
|
assert!(
|
||||||
|
offset_of!(ZSTD_rustSequenceDecoderPolicy, force_long) == size_of::<c_int>()
|
||||||
|
);
|
||||||
|
assert!(size_of::<ZSTD_rustSequenceDecoderPolicy>() == 2 * size_of::<c_int>());
|
||||||
|
};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sequence_decoder_mode(policy: &ZSTD_rustSequenceDecoderPolicy) -> c_int {
|
||||||
|
if policy.force_short != 0 {
|
||||||
|
SEQUENCE_DECODER_FORCE_SHORT
|
||||||
|
} else if policy.force_long != 0 {
|
||||||
|
SEQUENCE_DECODER_FORCE_LONG
|
||||||
|
} else {
|
||||||
|
SEQUENCE_DECODER_RUNTIME
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Normalize the build's sequence-decoder choice before block dispatch.
|
||||||
|
///
|
||||||
|
/// C retains the compile-time mutual-exclusion check and private context
|
||||||
|
/// projection; Rust owns the scalar mode selected by that public build policy.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn ZSTD_rust_sequence_decoder_mode(
|
||||||
|
policy: *const ZSTD_rustSequenceDecoderPolicy,
|
||||||
|
) -> c_int {
|
||||||
|
let Some(policy) = (unsafe { policy.as_ref() }) else {
|
||||||
|
return SEQUENCE_DECODER_RUNTIME;
|
||||||
|
};
|
||||||
|
sequence_decoder_mode(policy)
|
||||||
|
}
|
||||||
|
|
||||||
const LL_BASE: [u32; MAX_LL + 1] = [
|
const LL_BASE: [u32; MAX_LL + 1] = [
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 28, 32, 40, 48, 64,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 28, 32, 40, 48, 64,
|
||||||
0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000,
|
0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000,
|
||||||
@@ -1892,6 +1933,34 @@ pub unsafe extern "C" fn ZSTD_decompressBlock(
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sequence_decoder_mode_preserves_build_forcing_policy() {
|
||||||
|
let runtime = ZSTD_rustSequenceDecoderPolicy {
|
||||||
|
force_short: 0,
|
||||||
|
force_long: 0,
|
||||||
|
};
|
||||||
|
let short = ZSTD_rustSequenceDecoderPolicy {
|
||||||
|
force_short: 1,
|
||||||
|
force_long: 0,
|
||||||
|
};
|
||||||
|
let long = ZSTD_rustSequenceDecoderPolicy {
|
||||||
|
force_short: 0,
|
||||||
|
force_long: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(sequence_decoder_mode(&runtime), SEQUENCE_DECODER_RUNTIME);
|
||||||
|
assert_eq!(sequence_decoder_mode(&short), SEQUENCE_DECODER_FORCE_SHORT);
|
||||||
|
assert_eq!(sequence_decoder_mode(&long), SEQUENCE_DECODER_FORCE_LONG);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sequence_decoder_mode_null_policy_defaults_to_runtime() {
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { ZSTD_rust_sequence_decoder_mode(ptr::null()) },
|
||||||
|
SEQUENCE_DECODER_RUNTIME
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn offset_code_22_and_23_keep_their_22_and_23_bit_bases() {
|
fn offset_code_22_and_23_keep_their_22_and_23_bit_bases() {
|
||||||
assert_eq!(OF_BASE[22], 0x3F_FFFD);
|
assert_eq!(OF_BASE[22], 0x3F_FFFD);
|
||||||
|
|||||||
Reference in New Issue
Block a user