feat(compress): move sequence-store policy into Rust

Move sequence-store construction, small-block handling, repcode setup,
last-literal storage, block-body no-compress transitions, target/split
post-build policy, and public sequence conversion into Rust projections.
Keep matchfinders, LDM, external sequence producers, workspaces, and private
compression context state behind narrow C callbacks and preserve the existing
C-facing sequence API.

Test Plan:
- ulimit -v 41943040; make -B -C lib -j1 lib (passed)
- ulimit -v 41943040; make -B -C tests -j1 test-zstd (passed)
- ulimit -v 41943040; FUZZERTEST=-T5s make -B -C tests -j1 test-fuzzer (284 passed)
- ulimit -v 41943040; ZSTREAM_TESTTIME=-T2s make -B -C tests -j1 test-zstream (210 passed)
- ulimit -v 41943040; DECODECORPUS_TESTTIME=-T10 make -B -C tests -j1 test-decodecorpus (1608 passed)
- ulimit -v 41943040; CARGO_BUILD_JOBS=1 cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression,decompression,dict-builder,legacy-v01,legacy-v02,legacy-v03,legacy-v04,legacy-v05,legacy-v06,legacy-v07 --all-targets -- --test-threads=1 (562 passed)
This commit is contained in:
2026-07-19 08:21:07 +02:00
parent 7282ec4046
commit 62389c002f
2 changed files with 794 additions and 287 deletions
+554 -4
View File
@@ -13,6 +13,7 @@
//! `ZSTD_compressStream2(..., ZSTD_e_end)` path dispatch through Rust while
//! retaining the C implementation for advanced and partial-stream cases.
use crate::common::MINMATCH;
use crate::errors::{ERR_isError, ZstdErrorCode, ERROR};
#[cfg(not(test))]
use crate::zstd_compress_api::ZSTD_compressBound;
@@ -27,13 +28,16 @@ use crate::zstd_compress_params::{
};
use crate::zstd_compress_sequences::SeqDef;
use crate::zstd_compress_stats::{
SeqCollector, SeqStore_t, ZSTD_Sequence, ZSTD_SequencePosition, ZSTD_compressedBlockState_t,
ZSTD_entropyCTables_t, ZSTD_rust_confirmRepcodesAndEntropyTables, ZSTD_rust_copyBlockSequences,
update_rep, SeqCollector, SeqStore_t, ZSTD_Sequence, ZSTD_SequencePosition,
ZSTD_compressedBlockState_t, ZSTD_entropyCTables_t, ZSTD_rust_confirmRepcodesAndEntropyTables,
ZSTD_rust_convertSequencesNoRepcodes, ZSTD_rust_copyBlockSequences,
ZSTD_rust_countSeqStoreLiteralsBytes, ZSTD_rust_countSeqStoreMatchBytes,
ZSTD_rust_deriveSeqStoreChunk, ZSTD_rust_determineBlockSize, ZSTD_rust_entropyCompressSeqStore,
ZSTD_rust_entropyCompressSeqStore_internal, ZSTD_rust_get1BlockSummary, ZSTD_rust_isRLE,
ZSTD_rust_maybeRLE, ZSTD_rust_resetSeqStore, ZSTD_rust_seqStore_resolveOffCodes,
ZSTD_rust_entropyCompressSeqStore_internal, ZSTD_rust_finalizeOffBase,
ZSTD_rust_get1BlockSummary, ZSTD_rust_isRLE, ZSTD_rust_maybeRLE, ZSTD_rust_resetSeqStore,
ZSTD_rust_seqStore_resolveOffCodes, ZSTD_rust_storeLastLiterals,
ZSTD_rust_transferSequencesNoDelim, ZSTD_rust_transferSequencesWBlockDelim,
ZSTD_rust_validateSeqStore, ZSTD_LLT_LITERAL_LENGTH, ZSTD_LLT_MATCH_LENGTH,
};
use crate::zstd_compress_superblock::ZSTD_rust_compressSuperBlock;
use std::ffi::c_void;
@@ -110,12 +114,73 @@ const ZSTD_E_CONTINUE: c_int = 0;
const ZSTD_E_FLUSH: c_int = 1;
const ZSTD_CSTREAM_STAGE_LOAD: c_int = 1;
const ZSTD_CSTREAM_STAGE_FLUSH: c_int = 2;
const ZSTD_BSS_COMPRESS: c_int = 0;
const ZSTD_BSS_NO_COMPRESS: c_int = 1;
const FSE_REPEAT_CHECK: c_int = 1;
const FSE_REPEAT_VALID: c_int = 2;
type FrameChunkPrepareFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
type FrameChunkCompressFn =
unsafe extern "C" fn(*mut c_void, *mut c_void, usize, *const c_void, usize, c_uint) -> usize;
type FrameChunkChecksumFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
type BuildSeqStoreSkipFn = unsafe extern "C" fn(*mut c_void, usize);
type BuildSeqStorePrepareFn = unsafe extern "C" fn(*mut c_void, *const c_void, usize);
type BuildSeqStoreSelectFn = unsafe extern "C" fn(
*mut c_void,
*mut SeqStore_t,
*mut u32,
*const c_void,
usize,
*mut c_int,
) -> usize;
/// Explicit projection for the sequence-store builder.
///
/// Rust owns the threshold/reset/repcode/literal-store orchestration. The
/// callbacks retain the private matchfinder, LDM, and external sequence
/// producer operations in C without passing `ZSTD_CCtx` across the ABI.
#[repr(C)]
pub struct ZSTD_rust_buildSeqStoreState {
seq_store: *mut SeqStore_t,
prev_c_block: *mut *mut ZSTD_compressedBlockState_t,
next_c_block: *mut *mut ZSTD_compressedBlockState_t,
callback_context: *mut c_void,
min_match: c_uint,
validate_seq_store: c_int,
skip_small_block: BuildSeqStoreSkipFn,
prepare_match_state: BuildSeqStorePrepareFn,
select_sequences: BuildSeqStoreSelectFn,
}
const _: () = {
assert!(offset_of!(ZSTD_rust_buildSeqStoreState, seq_store) == 0);
assert!(offset_of!(ZSTD_rust_buildSeqStoreState, prev_c_block) == size_of::<usize>());
assert!(offset_of!(ZSTD_rust_buildSeqStoreState, next_c_block) == 2 * size_of::<usize>());
assert!(offset_of!(ZSTD_rust_buildSeqStoreState, callback_context) == 3 * size_of::<usize>());
assert!(offset_of!(ZSTD_rust_buildSeqStoreState, min_match) == 4 * size_of::<usize>());
assert!(
offset_of!(ZSTD_rust_buildSeqStoreState, validate_seq_store)
== 4 * size_of::<usize>() + size_of::<c_uint>()
);
assert!(
offset_of!(ZSTD_rust_buildSeqStoreState, skip_small_block)
== 4 * size_of::<usize>() + size_of::<c_uint>() + size_of::<c_int>()
);
assert!(
offset_of!(ZSTD_rust_buildSeqStoreState, prepare_match_state)
== 5 * size_of::<usize>() + size_of::<c_uint>() + size_of::<c_int>()
);
assert!(
offset_of!(ZSTD_rust_buildSeqStoreState, select_sequences)
== 6 * size_of::<usize>() + size_of::<c_uint>() + size_of::<c_int>()
);
assert!(
size_of::<ZSTD_rust_buildSeqStoreState>()
== 7 * size_of::<usize>() + size_of::<c_uint>() + size_of::<c_int>()
);
};
/// Explicit projection of the state used by `ZSTD_compress_frameChunk`.
///
/// The Rust side owns the per-frame block loop and its savings/dispatch
@@ -1036,6 +1101,25 @@ pub struct ZSTD_rust_sequenceLiteralsState {
convert_block_sequences: SequenceLiteralsConvertFn,
}
/// Explicit projection for the public block-sequence conversion entry point.
/// The surrounding `ZSTD_CCtx` remains opaque; only the sequence store and
/// compressed-block repcode slots are needed by the converter.
#[repr(C)]
pub struct ZSTD_rust_convertBlockSequencesState {
seq_store: *mut SeqStore_t,
prev_c_block: *mut *mut ZSTD_compressedBlockState_t,
next_c_block: *mut *mut ZSTD_compressedBlockState_t,
}
const _: () = {
assert!(offset_of!(ZSTD_rust_convertBlockSequencesState, seq_store) == 0);
assert!(offset_of!(ZSTD_rust_convertBlockSequencesState, prev_c_block) == size_of::<usize>());
assert!(
offset_of!(ZSTD_rust_convertBlockSequencesState, next_c_block) == 2 * size_of::<usize>()
);
assert!(size_of::<ZSTD_rust_convertBlockSequencesState>() == 3 * size_of::<usize>());
};
const _: () = {
assert!(offset_of!(ZSTD_rust_sequenceLiteralsState, seq_store) == 0);
assert!(offset_of!(ZSTD_rust_sequenceLiteralsState, prev_c_block) == size_of::<usize>());
@@ -1352,6 +1436,100 @@ impl SingleBlockSeams {
}
}
/// Rust-owned sequence-store boundary. C callbacks perform the operations
/// which need the private matchfinder or CCtx parameter/function-pointer state.
#[allow(clippy::too_many_arguments)]
unsafe fn build_seq_store_body_with(
state: &ZSTD_rust_buildSeqStoreState,
src: *const c_void,
src_size: usize,
) -> usize {
if state.seq_store.is_null()
|| state.skip_small_block as usize == 0
|| state.prepare_match_state as usize == 0
|| state.select_sequences as usize == 0
{
return ERROR(ZstdErrorCode::Generic);
}
if src_size > ZSTD_BLOCKSIZE_MAX {
return ERROR(ZstdErrorCode::SrcSizeWrong);
}
if src_size < MIN_COMPRESSIBLE_BLOCK_SIZE {
unsafe { (state.skip_small_block)(state.callback_context, src_size) };
return ZSTD_BSS_NO_COMPRESS as usize;
}
if src.is_null() || state.prev_c_block.is_null() || state.next_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
let prev_c_block = unsafe { *state.prev_c_block };
let next_c_block = unsafe { *state.next_c_block };
if prev_c_block.is_null() || next_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
unsafe { ZSTD_rust_resetSeqStore(state.seq_store) };
unsafe {
(state.prepare_match_state)(state.callback_context, src, src_size);
}
unsafe {
ptr::copy_nonoverlapping(
(*prev_c_block).rep.as_ptr(),
(*next_c_block).rep.as_mut_ptr(),
ZSTD_REP_NUM,
);
}
let mut seq_store_complete = 0;
let last_literals_size = unsafe {
(state.select_sequences)(
state.callback_context,
state.seq_store,
(*next_c_block).rep.as_mut_ptr(),
src,
src_size,
&mut seq_store_complete,
)
};
if ERR_isError(last_literals_size) {
return last_literals_size;
}
if seq_store_complete != 0 {
return ZSTD_BSS_COMPRESS as usize;
}
if last_literals_size > src_size {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
ZSTD_rust_storeLastLiterals(
state.seq_store,
src.cast::<u8>().add(src_size - last_literals_size),
last_literals_size,
);
}
if state.validate_seq_store != 0 {
unsafe { ZSTD_rust_validateSeqStore(state.seq_store, state.min_match) };
}
ZSTD_BSS_COMPRESS as usize
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_buildSeqStore(
state: *const ZSTD_rust_buildSeqStoreState,
src: *const c_void,
src_size: usize,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
unsafe { build_seq_store_body_with(&*state, src, src_size) }
}
/// Rust implementation of `ZSTD_compressBlock_internal` after the C caller
/// has built the sequence store.
#[allow(clippy::too_many_arguments)]
@@ -1441,6 +1619,40 @@ unsafe fn compress_block_internal_body_with(
c_size
}
unsafe fn compress_block_internal_after_build_body_with(
state: &ZSTD_rust_blockInternalState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
src_size: usize,
frame: c_uint,
bss: c_int,
seams: SingleBlockSeams,
) -> usize {
if bss == ZSTD_BSS_NO_COMPRESS {
if state.seq_collector.is_null() || state.prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
if unsafe { (*state.seq_collector).collectSequences } != 0 {
return ERROR(ZstdErrorCode::SequenceProducerFailed);
}
let prev_c_block = unsafe { *state.prev_c_block };
if prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
if unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode } == FSE_REPEAT_VALID {
unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode = FSE_REPEAT_CHECK };
}
return 0;
}
if bss != ZSTD_BSS_COMPRESS {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
compress_block_internal_body_with(state, dst, dst_capacity, src, src_size, frame, seams)
}
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_compressBlockInternal(
state: *const ZSTD_rust_blockInternalState,
@@ -1466,6 +1678,33 @@ pub unsafe extern "C" fn ZSTD_rust_compressBlockInternal(
}
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_compressBlockInternalAfterBuild(
state: *const ZSTD_rust_blockInternalState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
src_size: usize,
frame: c_uint,
bss: c_int,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
compress_block_internal_after_build_body_with(
&*state,
dst,
dst_capacity,
src,
src_size,
frame,
bss,
SingleBlockSeams::production(),
)
}
}
#[inline]
fn sequence_block_action(
is_first_block: c_int,
@@ -1628,6 +1867,47 @@ unsafe fn compress_block_target_c_block_size_body_with(
unsafe { ZSTD_rust_noCompressBlock(dst, dst_capacity, src, src_size, last_block) }
}
unsafe fn compress_block_target_c_block_size_after_build_body_with(
state: &ZSTD_rust_targetCBlockSizeState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
src_size: usize,
bss: c_int,
last_block: c_uint,
compress_super_block: TargetCBlockSuperBlockFn,
) -> usize {
if bss != ZSTD_BSS_COMPRESS && bss != ZSTD_BSS_NO_COMPRESS {
return ERROR(ZstdErrorCode::Generic);
}
let c_size = unsafe {
compress_block_target_c_block_size_body_with(
state,
dst,
dst_capacity,
src,
src_size,
bss,
last_block,
compress_super_block,
)
};
if ERR_isError(c_size) {
return c_size;
}
if state.prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
let prev_c_block = unsafe { *state.prev_c_block };
if prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
if unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode } == FSE_REPEAT_VALID {
unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode = FSE_REPEAT_CHECK };
}
c_size
}
/// C ABI entry point for the target-sized block body. The public and outer
/// block APIs remain C-owned; this is only the body after `ZSTD_buildSeqStore`.
#[no_mangle]
@@ -1657,6 +1937,33 @@ pub unsafe extern "C" fn ZSTD_rust_compressBlockTargetCBlockSize(
}
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_compressBlockTargetCBlockSizeAfterBuild(
state: *const ZSTD_rust_targetCBlockSizeState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
src_size: usize,
bss: c_int,
last_block: c_uint,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
compress_block_target_c_block_size_after_build_body_with(
&*state,
dst,
dst_capacity,
src,
src_size,
bss,
last_block,
ZSTD_rust_compressSuperBlock,
)
}
}
/// Rust implementation of `ZSTD_compressSeqStore_singleBlock`.
///
/// The C caller still owns sequence-store construction, split-block control,
@@ -1999,6 +2306,52 @@ unsafe fn compress_block_split_body_with(
c_size
}
unsafe fn compress_block_split_after_build_body_with(
state: &ZSTD_rust_splitBlockState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
block_size: usize,
last_block: c_uint,
num_splits: usize,
bss: c_int,
seams: SingleBlockSeams,
) -> usize {
if bss == ZSTD_BSS_NO_COMPRESS {
if state.seq_collector.is_null() || state.prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
if unsafe { (*state.seq_collector).collectSequences } != 0 {
return ERROR(ZstdErrorCode::SequenceProducerFailed);
}
let prev_c_block = unsafe { *state.prev_c_block };
if prev_c_block.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
if unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode } == FSE_REPEAT_VALID {
unsafe { (*prev_c_block).entropy.fse.offcode_repeatMode = FSE_REPEAT_CHECK };
}
return unsafe {
ZSTD_rust_noCompressBlock(dst, dst_capacity, src, block_size, last_block)
};
}
if bss != ZSTD_BSS_COMPRESS {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
compress_block_split_body_with(
state,
dst,
dst_capacity,
src,
block_size,
last_block,
num_splits,
seams,
)
}
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_compressBlockSplit(
state: *const ZSTD_rust_splitBlockState,
@@ -2026,6 +2379,203 @@ pub unsafe extern "C" fn ZSTD_rust_compressBlockSplit(
}
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_compressBlockSplitAfterBuild(
state: *const ZSTD_rust_splitBlockState,
dst: *mut c_void,
dst_capacity: usize,
src: *const c_void,
block_size: usize,
last_block: c_uint,
num_splits: usize,
bss: c_int,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::Generic);
}
unsafe {
compress_block_split_after_build_body_with(
&*state,
dst,
dst_capacity,
src,
block_size,
last_block,
num_splits,
bss,
SingleBlockSeams::production(),
)
}
}
unsafe fn store_converted_sequence(
seq_store: &mut SeqStore_t,
lit_length: u32,
off_base: u32,
match_length: u32,
) -> bool {
let sequence_index = unsafe { seq_store.sequences.offset_from(seq_store.sequencesStart) };
if sequence_index < 0 || sequence_index as usize >= seq_store.maxNbSeq {
return false;
}
let ml_base = match (match_length as usize).checked_sub(MINMATCH) {
Some(value) => value,
None => return false,
};
if lit_length as usize > u16::MAX as usize {
if seq_store.longLengthType != 0 {
return false;
}
seq_store.longLengthType = ZSTD_LLT_LITERAL_LENGTH;
seq_store.longLengthPos = sequence_index as u32;
}
if ml_base > u16::MAX as usize {
if seq_store.longLengthType != 0 {
return false;
}
seq_store.longLengthType = ZSTD_LLT_MATCH_LENGTH;
seq_store.longLengthPos = sequence_index as u32;
}
unsafe {
(*seq_store.sequences).litLength = lit_length as u16;
(*seq_store.sequences).offBase = off_base;
(*seq_store.sequences).mlBase = ml_base as u16;
seq_store.sequences = seq_store.sequences.add(1);
}
true
}
unsafe fn convert_block_sequences_body_with(
state: &ZSTD_rust_convertBlockSequencesState,
in_seqs: *const ZSTD_Sequence,
nb_sequences: usize,
repcode_resolution: c_int,
) -> usize {
if state.seq_store.is_null()
|| state.prev_c_block.is_null()
|| state.next_c_block.is_null()
|| in_seqs.is_null()
|| nb_sequences == 0
{
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
let seq_store = unsafe { &mut *state.seq_store };
if nb_sequences >= seq_store.maxNbSeq {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
let delimiter = unsafe { *in_seqs.add(nb_sequences - 1) };
if delimiter.matchLength != 0 || delimiter.offset != 0 {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
let prev_c_block = unsafe { *state.prev_c_block };
let next_c_block = unsafe { *state.next_c_block };
if prev_c_block.is_null() || next_c_block.is_null() {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
let mut updated_repcodes = [0u32; ZSTD_REP_NUM];
unsafe {
ptr::copy_nonoverlapping(
(*prev_c_block).rep.as_ptr(),
updated_repcodes.as_mut_ptr(),
ZSTD_REP_NUM,
);
}
if repcode_resolution == 0 {
let full_sequence_count = nb_sequences - 1;
let long_length = unsafe {
ZSTD_rust_convertSequencesNoRepcodes(
seq_store.sequencesStart,
in_seqs,
full_sequence_count,
)
};
if long_length != 0 {
if seq_store.longLengthType != 0 {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
if long_length <= full_sequence_count {
seq_store.longLengthType = ZSTD_LLT_MATCH_LENGTH;
seq_store.longLengthPos = (long_length - 1) as u32;
} else if long_length <= full_sequence_count.saturating_mul(2) {
seq_store.longLengthType = ZSTD_LLT_LITERAL_LENGTH;
seq_store.longLengthPos = (long_length - nb_sequences) as u32;
} else {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
}
seq_store.sequences = unsafe { seq_store.sequencesStart.add(full_sequence_count) };
if nb_sequences > 1 {
let rep = &mut updated_repcodes;
if nb_sequences >= 4 {
let last_seq_idx = nb_sequences - 2;
rep[2] = unsafe { (*in_seqs.add(last_seq_idx - 2)).offset };
rep[1] = unsafe { (*in_seqs.add(last_seq_idx - 1)).offset };
rep[0] = unsafe { (*in_seqs.add(last_seq_idx)).offset };
} else if nb_sequences == 3 {
rep[2] = rep[0];
rep[1] = unsafe { (*in_seqs).offset };
rep[0] = unsafe { (*in_seqs.add(1)).offset };
} else {
rep[2] = rep[1];
rep[1] = rep[0];
rep[0] = unsafe { (*in_seqs).offset };
}
}
} else {
for index in 0..(nb_sequences - 1) {
let sequence = unsafe { *in_seqs.add(index) };
let ll0 = sequence.litLength == 0;
let off_base = unsafe {
ZSTD_rust_finalizeOffBase(
sequence.offset,
updated_repcodes.as_ptr(),
u32::from(ll0),
)
};
if !unsafe {
store_converted_sequence(
seq_store,
sequence.litLength,
off_base,
sequence.matchLength,
)
} {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
update_rep(&mut updated_repcodes, off_base, ll0);
}
}
unsafe {
ptr::copy_nonoverlapping(
updated_repcodes.as_ptr(),
(*next_c_block).rep.as_mut_ptr(),
ZSTD_REP_NUM,
);
}
0
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_convertBlockSequences(
state: *const ZSTD_rust_convertBlockSequencesState,
in_seqs: *const ZSTD_Sequence,
nb_sequences: usize,
repcode_resolution: c_int,
) -> usize {
if state.is_null() {
return ERROR(ZstdErrorCode::ExternalSequencesInvalid);
}
unsafe { convert_block_sequences_body_with(&*state, in_seqs, nb_sequences, repcode_resolution) }
}
/// Select the strategy used by the simple compression entry points.
///
/// This is the Rust equivalent of the strategy portion of