Files
zstd-rs/lib/compress/zstd_double_fast.c
T
ddidderr f9adcf6aef feat(rust): port double-fast block matching
Move the two-table fast match finder into Rust while retaining a small C
projection of the private match-state. The Rust implementation handles normal,
attached-dictionary, and external-dictionary matching without exposing the
full C context ABI. The C entry points and build-time exclusion guards remain
unchanged for configured consumers.

Document the migrated matcher in the Rust component map and narrow the
remaining-C boundary accordingly.

Test Plan:
- cargo test --all-targets
- cargo test --target i686-unknown-linux-gnu --all-targets
- cargo clippy && cargo clippy --benches && cargo clippy --tests
- cargo +nightly fmt
- make -B -C tests -j2 fuzzer zstreamtest invalidDictionaries poolTests
- ./tests/fuzzer -s5346 -i1 --no-big-tests
- ./tests/zstreamtest -i3000 -s334462
- ./tests/invalidDictionaries
- timeout 20s stdbuf -oL ./tests/poolTests

Refs: rust/README.md
2026-07-11 08:05:25 +02:00

101 lines
4.5 KiB
C

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
/* The double-fast algorithms live in rust/src/zstd_double_fast.rs. Keep the
* private match-state layout in C and pass only the matching leaf fields. */
#include "zstd_compress_internal.h"
#include "zstd_double_fast.h"
#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR
typedef char ZSTD_rust_double_fast_seqdef_layout[(sizeof(SeqDef) == 8) ? 1 : -1];
typedef char ZSTD_rust_double_fast_seqstore_long_length_pos[
(offsetof(SeqStore_t, longLengthPos) == 9 * sizeof(size_t) + 4) ? 1 : -1];
typedef char ZSTD_rust_double_fast_seqstore_layout[
(sizeof(SeqStore_t) == 9 * sizeof(size_t) + 8) ? 1 : -1];
typedef char ZSTD_rust_double_fast_rep_count[(ZSTD_REP_NUM == 3) ? 1 : -1];
void ZSTD_rust_fillDoubleHashTable(
U32* hashLong, U32* hashSmall, const BYTE* base, U32 nextToUpdate,
const void* end, U32 hashLog, U32 chainLog, U32 minMatch,
int fullTableLoad, int forCDict);
size_t ZSTD_rust_compressBlock_doubleFast(
U32* hashLong, U32* hashSmall, const BYTE* base,
U32 dictLimit, U32 loadedDictEnd,
U32 hashLog, U32 chainLog, U32 minMatch, U32 windowLog,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize);
size_t ZSTD_rust_compressBlock_doubleFast_dictMatchState(
U32* hashLong, U32* hashSmall, const BYTE* base, U32 prefixLowestIndex,
U32 hashLog, U32 chainLog, U32 minMatch,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize,
const U32* dictHashLong, const U32* dictHashSmall, const BYTE* dictBase,
U32 dictStartIndex, const BYTE* dictEnd,
U32 dictHashLog, U32 dictChainLog, int prefetchCDictTables);
size_t ZSTD_rust_compressBlock_doubleFast_extDict(
U32* hashLong, U32* hashSmall, const BYTE* base, const BYTE* dictBase,
U32 dictLimit, U32 lowLimit, U32 loadedDictEnd,
U32 hashLog, U32 chainLog, U32 minMatch, U32 windowLog,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize);
void ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms,
const void* end,
ZSTD_dictTableLoadMethod_e dtlm,
ZSTD_tableFillPurpose_e tfp)
{
ZSTD_rust_fillDoubleHashTable(
ms->hashTable, ms->chainTable, ms->window.base, ms->nextToUpdate,
end, ms->cParams.hashLog, ms->cParams.chainLog, ms->cParams.minMatch,
dtlm == ZSTD_dtlm_full, tfp == ZSTD_tfp_forCDict);
}
size_t ZSTD_compressBlock_doubleFast(
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
return ZSTD_rust_compressBlock_doubleFast(
ms->hashTable, ms->chainTable, ms->window.base,
ms->window.dictLimit, ms->loadedDictEnd,
ms->cParams.hashLog, ms->cParams.chainLog, ms->cParams.minMatch,
ms->cParams.windowLog,
seqStore, rep, src, srcSize);
}
size_t ZSTD_compressBlock_doubleFast_dictMatchState(
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
const ZSTD_MatchState_t* const dms = ms->dictMatchState;
assert(dms != NULL);
return ZSTD_rust_compressBlock_doubleFast_dictMatchState(
ms->hashTable, ms->chainTable, ms->window.base, ms->window.dictLimit,
ms->cParams.hashLog, ms->cParams.chainLog, ms->cParams.minMatch,
seqStore, rep, src, srcSize,
dms->hashTable, dms->chainTable, dms->window.base,
dms->window.dictLimit, dms->window.nextSrc,
dms->cParams.hashLog, dms->cParams.chainLog, ms->prefetchCDictTables);
}
size_t ZSTD_compressBlock_doubleFast_extDict(
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
return ZSTD_rust_compressBlock_doubleFast_extDict(
ms->hashTable, ms->chainTable, ms->window.base, ms->window.dictBase,
ms->window.dictLimit, ms->window.lowLimit, ms->loadedDictEnd,
ms->cParams.hashLog, ms->cParams.chainLog, ms->cParams.minMatch,
ms->cParams.windowLog,
seqStore, rep, src, srcSize);
}
#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */