Files
zstd-rs/lib/compress/zstd_fast.c
T
ddidderr 74140c318f feat(rust): port fast block matching
Move fast hash-table filling and no-dictionary, external-dictionary, and
attached-CDict match loops into Rust. The C shim keeps `ZSTD_MatchState_t`
opaque, extracts only its needed fields, and asserts the mirrored SeqStore
leaf layout so existing compression dispatch remains ABI-compatible.

Test Plan:
- cargo clippy
- cargo clippy --benches
- cargo clippy --tests
- cargo +nightly fmt
- cargo test zstd_fast::tests -- --nocapture
- cargo test --target i686-unknown-linux-gnu zstd_fast::tests -- --nocapture
- byte-identical C-control frames for dictionary and streaming variants
- fuzzer -s2066 -i5 --no-big-tests
- invalidDictionaries and zstreamtest -i1

Refs: Rust superblock port fde1d70c
2026-07-10 22:46:15 +02:00

96 lines
4.3 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 matching algorithms live in rust/src/zstd_fast.rs. Keep match-state
* extraction here: it is a large private structure whose layout should not be
* duplicated in Rust. */
#include "zstd_compress_internal.h"
#include "zstd_fast.h"
typedef char ZSTD_rust_fast_seqdef_layout[(sizeof(SeqDef) == 8) ? 1 : -1];
typedef char ZSTD_rust_fast_seqstore_long_length_pos[
(offsetof(SeqStore_t, longLengthPos) == 9 * sizeof(size_t) + 4) ? 1 : -1];
typedef char ZSTD_rust_fast_seqstore_layout[
(sizeof(SeqStore_t) == 9 * sizeof(size_t) + 8) ? 1 : -1];
typedef char ZSTD_rust_fast_rep_count[(ZSTD_REP_NUM == 3) ? 1 : -1];
void ZSTD_rust_fillHashTable(U32* hashTable, const BYTE* base, U32 nextToUpdate,
const void* end, U32 hashLog, U32 minMatch,
int fullTableLoad, int forCDict);
size_t ZSTD_rust_compressBlock_fast(
U32* hashTable, const BYTE* base, U32 dictLimit, U32 loadedDictEnd,
U32 hashLog, U32 minMatch, U32 targetLength, U32 windowLog,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize);
size_t ZSTD_rust_compressBlock_fast_dictMatchState(
U32* hashTable, const BYTE* base, U32 prefixStartIndex,
U32 hashLog, U32 minMatch, U32 targetLength,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize,
const U32* dictHashTable, const BYTE* dictBase, U32 dictStartIndex,
const BYTE* dictEnd, U32 dictHashLog, int prefetchCDictTables);
size_t ZSTD_rust_compressBlock_fast_extDict(
U32* hashTable, const BYTE* base, const BYTE* dictBase,
U32 dictLimit, U32 lowLimit, U32 loadedDictEnd,
U32 hashLog, U32 minMatch, U32 targetLength, U32 windowLog,
void* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize);
void ZSTD_fillHashTable(ZSTD_MatchState_t* ms,
const void* end,
ZSTD_dictTableLoadMethod_e dtlm,
ZSTD_tableFillPurpose_e tfp)
{
assert((tfp == ZSTD_tfp_forCDict && dtlm == ZSTD_dtlm_full)
|| (tfp != ZSTD_tfp_forCDict && dtlm == ZSTD_dtlm_fast));
ZSTD_rust_fillHashTable(ms->hashTable, ms->window.base, ms->nextToUpdate,
end, ms->cParams.hashLog, ms->cParams.minMatch,
dtlm == ZSTD_dtlm_full, tfp == ZSTD_tfp_forCDict);
}
size_t ZSTD_compressBlock_fast(
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
assert(ms->dictMatchState == NULL);
return ZSTD_rust_compressBlock_fast(
ms->hashTable, ms->window.base, ms->window.dictLimit, ms->loadedDictEnd,
ms->cParams.hashLog, ms->cParams.minMatch,
ms->cParams.targetLength, ms->cParams.windowLog,
seqStore, rep, src, srcSize);
}
size_t ZSTD_compressBlock_fast_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_fast_dictMatchState(
ms->hashTable, ms->window.base, ms->window.dictLimit,
ms->cParams.hashLog, ms->cParams.minMatch, ms->cParams.targetLength,
seqStore, rep, src, srcSize,
dms->hashTable, dms->window.base, dms->window.dictLimit,
dms->window.nextSrc, dms->cParams.hashLog, ms->prefetchCDictTables);
}
size_t ZSTD_compressBlock_fast_extDict(
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
assert(ms->dictMatchState == NULL);
return ZSTD_rust_compressBlock_fast_extDict(
ms->hashTable, ms->window.base, ms->window.dictBase,
ms->window.dictLimit, ms->window.lowLimit, ms->loadedDictEnd,
ms->cParams.hashLog, ms->cParams.minMatch,
ms->cParams.targetLength, ms->cParams.windowLog,
seqStore, rep, src, srcSize);
}