Files
zstd-rs/lib/compress/zstd_lazy.c
T
ddidderr 7f16a07375 feat(rust): port lazy block matching
Move greedy, lazy, lazy2, and binary-tree block matchers into Rust. A narrow
C state projection preserves configuration-specific context layout while Rust
owns hash-chain, row-based, attached-dictionary, and external-dictionary
searches and sequence-store updates.

The component map now records the lazy family as migrated; the optimized
matcher and high-level contexts remain outside this commit.

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:06:30 +02:00

254 lines
11 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 lazy matchers are implemented in rust/src/zstd_lazy.rs. Keep only the
* private match-state projection and the established C entry points here. */
#include "zstd_compress_internal.h"
#include "zstd_lazy.h"
#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \
|| !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \
|| !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \
|| !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)
typedef char ZSTD_rust_lazy_seqdef_layout[(sizeof(SeqDef) == 8) ? 1 : -1];
typedef char ZSTD_rust_lazy_seqstore_long_length_pos[
(offsetof(SeqStore_t, longLengthPos) == 9 * sizeof(size_t) + 4) ? 1 : -1];
typedef char ZSTD_rust_lazy_seqstore_layout[
(sizeof(SeqStore_t) == 9 * sizeof(size_t) + 8) ? 1 : -1];
typedef char ZSTD_rust_lazy_rep_count[(ZSTD_REP_NUM == 3) ? 1 : -1];
/* This must remain in lock-step with `ZSTD_RustLazyState` in Rust. The large
* and private `ZSTD_MatchState_t` itself deliberately never crosses FFI. */
typedef struct ZSTD_RustLazyState_s {
U32* hashTable;
U32* chainTable;
BYTE* tagTable;
U32* hashCache;
const BYTE* base;
const BYTE* dictBase;
const BYTE* nextSrc;
U32 dictLimit;
U32 lowLimit;
U32 loadedDictEnd;
U32* nextToUpdate;
int* lazySkipping;
U32 hashLog;
U32 chainLog;
U32 minMatch;
U32 searchLog;
U32 windowLog;
U32 rowHashLog;
U64 hashSalt;
U32* hashSaltEntropy;
const struct ZSTD_RustLazyState_s* dictMatchState;
} ZSTD_RustLazyState;
U32 ZSTD_rust_lazy_insertAndFindFirstIndex(ZSTD_RustLazyState* state,
const void* ip);
void ZSTD_rust_lazy_row_update(ZSTD_RustLazyState* state, const void* ip);
void ZSTD_rust_lazy_loadDedicatedDict(ZSTD_RustLazyState* state,
const void* ip);
size_t ZSTD_rust_compressBlock_lazy(
ZSTD_RustLazyState* state, void* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize, int searchMethod, U32 depth,
int dictMode);
enum {
ZSTD_rust_search_hashChain = 0,
ZSTD_rust_search_binaryTree = 1,
ZSTD_rust_search_rowHash = 2,
};
enum {
ZSTD_rust_dict_noDict = 0,
ZSTD_rust_dict_extDict = 1,
ZSTD_rust_dict_dictMatchState = 2,
ZSTD_rust_dict_dedicatedDictSearch = 3,
};
static void ZSTD_rustLazyState_init(
ZSTD_RustLazyState* const out,
ZSTD_MatchState_t* const ms,
const ZSTD_RustLazyState* const dms)
{
out->hashTable = ms->hashTable;
out->chainTable = ms->chainTable;
out->tagTable = ms->tagTable;
out->hashCache = ms->hashCache;
out->base = ms->window.base;
out->dictBase = ms->window.dictBase;
out->nextSrc = ms->window.nextSrc;
out->dictLimit = ms->window.dictLimit;
out->lowLimit = ms->window.lowLimit;
out->loadedDictEnd = ms->loadedDictEnd;
out->nextToUpdate = &ms->nextToUpdate;
out->lazySkipping = &ms->lazySkipping;
out->hashLog = ms->cParams.hashLog;
out->chainLog = ms->cParams.chainLog;
out->minMatch = ms->cParams.minMatch;
out->searchLog = ms->cParams.searchLog;
out->windowLog = ms->cParams.windowLog;
out->rowHashLog = ms->rowHashLog;
out->hashSalt = ms->hashSalt;
out->hashSaltEntropy = &ms->hashSaltEntropy;
out->dictMatchState = dms;
}
/* Dictionary match states are searched but never updated by this module. */
static void ZSTD_rustLazyState_initDict(
ZSTD_RustLazyState* const out,
const ZSTD_MatchState_t* const ms)
{
out->hashTable = ms->hashTable;
out->chainTable = ms->chainTable;
out->tagTable = ms->tagTable;
out->hashCache = NULL;
out->base = ms->window.base;
out->dictBase = ms->window.dictBase;
out->nextSrc = ms->window.nextSrc;
out->dictLimit = ms->window.dictLimit;
out->lowLimit = ms->window.lowLimit;
out->loadedDictEnd = ms->loadedDictEnd;
out->nextToUpdate = NULL;
out->lazySkipping = NULL;
out->hashLog = ms->cParams.hashLog;
out->chainLog = ms->cParams.chainLog;
out->minMatch = ms->cParams.minMatch;
out->searchLog = ms->cParams.searchLog;
out->windowLog = ms->cParams.windowLog;
out->rowHashLog = ms->rowHashLog;
out->hashSalt = ms->hashSalt;
out->hashSaltEntropy = NULL;
out->dictMatchState = NULL;
}
static size_t ZSTD_rust_compressBlock_lazy_call(
ZSTD_MatchState_t* const ms, SeqStore_t* const seqStore,
U32 rep[ZSTD_REP_NUM], const void* const src, size_t const srcSize,
int const searchMethod, U32 const depth, int const dictMode)
{
ZSTD_RustLazyState state;
ZSTD_RustLazyState dictState;
const ZSTD_RustLazyState* dms = NULL;
if (dictMode == ZSTD_rust_dict_dictMatchState
|| dictMode == ZSTD_rust_dict_dedicatedDictSearch) {
const ZSTD_MatchState_t* const rawDms = ms->dictMatchState;
assert(rawDms != NULL);
ZSTD_rustLazyState_initDict(&dictState, rawDms);
dms = &dictState;
}
ZSTD_rustLazyState_init(&state, ms, dms);
return ZSTD_rust_compressBlock_lazy(
&state, seqStore, rep, src, srcSize, searchMethod, depth, dictMode);
}
U32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip)
{
ZSTD_RustLazyState state;
ZSTD_rustLazyState_init(&state, ms, NULL);
return ZSTD_rust_lazy_insertAndFindFirstIndex(&state, ip);
}
void ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* const ip)
{
ZSTD_RustLazyState state;
ZSTD_rustLazyState_init(&state, ms, NULL);
ZSTD_rust_lazy_row_update(&state, ip);
}
void ZSTD_dedicatedDictSearch_lazy_loadDictionary(
ZSTD_MatchState_t* ms, const BYTE* const ip)
{
ZSTD_RustLazyState state;
ZSTD_rustLazyState_init(&state, ms, NULL);
ZSTD_rust_lazy_loadDedicatedDict(&state, ip);
}
#define ZSTD_RUST_LAZY_WRAPPER(name, method, parserDepth, mode) \
size_t name( \
ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
const void* src, size_t srcSize) \
{ \
return ZSTD_rust_compressBlock_lazy_call( \
ms, seqStore, rep, src, srcSize, method, parserDepth, mode); \
}
#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy,
ZSTD_rust_search_hashChain, 0, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_dictMatchState,
ZSTD_rust_search_hashChain, 0, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_dedicatedDictSearch,
ZSTD_rust_search_hashChain, 0, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_row,
ZSTD_rust_search_rowHash, 0, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_dictMatchState_row,
ZSTD_rust_search_rowHash, 0, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_dedicatedDictSearch_row,
ZSTD_rust_search_rowHash, 0, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_extDict,
ZSTD_rust_search_hashChain, 0, ZSTD_rust_dict_extDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_greedy_extDict_row,
ZSTD_rust_search_rowHash, 0, ZSTD_rust_dict_extDict)
#endif
#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy,
ZSTD_rust_search_hashChain, 1, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_dictMatchState,
ZSTD_rust_search_hashChain, 1, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_dedicatedDictSearch,
ZSTD_rust_search_hashChain, 1, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_row,
ZSTD_rust_search_rowHash, 1, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_dictMatchState_row,
ZSTD_rust_search_rowHash, 1, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_dedicatedDictSearch_row,
ZSTD_rust_search_rowHash, 1, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_extDict,
ZSTD_rust_search_hashChain, 1, ZSTD_rust_dict_extDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy_extDict_row,
ZSTD_rust_search_rowHash, 1, ZSTD_rust_dict_extDict)
#endif
#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2,
ZSTD_rust_search_hashChain, 2, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_dictMatchState,
ZSTD_rust_search_hashChain, 2, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_dedicatedDictSearch,
ZSTD_rust_search_hashChain, 2, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_row,
ZSTD_rust_search_rowHash, 2, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_dictMatchState_row,
ZSTD_rust_search_rowHash, 2, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_dedicatedDictSearch_row,
ZSTD_rust_search_rowHash, 2, ZSTD_rust_dict_dedicatedDictSearch)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_extDict,
ZSTD_rust_search_hashChain, 2, ZSTD_rust_dict_extDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_lazy2_extDict_row,
ZSTD_rust_search_rowHash, 2, ZSTD_rust_dict_extDict)
#endif
#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_btlazy2,
ZSTD_rust_search_binaryTree, 2, ZSTD_rust_dict_noDict)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_btlazy2_dictMatchState,
ZSTD_rust_search_binaryTree, 2, ZSTD_rust_dict_dictMatchState)
ZSTD_RUST_LAZY_WRAPPER(ZSTD_compressBlock_btlazy2_extDict,
ZSTD_rust_search_binaryTree, 2, ZSTD_rust_dict_extDict)
#endif
#undef ZSTD_RUST_LAZY_WRAPPER
#endif /* lazy matcher build exclusions */