Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
46ff040
`fn HIST_count_simple`: pointer argument to reference
folkertdev Aug 10, 2026
30c52a7
`fn HIST_count_parallel_wksp`: pointer argument to reference
folkertdev Aug 10, 2026
3cb1988
`fn HIST_countFast_wksp`: pointer argument to reference
folkertdev Aug 10, 2026
5e0540b
`fn HIST_count_wksp`: pointer argument to reference
folkertdev Aug 10, 2026
78cacf9
`fn HIST_countFast`: pointer argument to reference
folkertdev Aug 10, 2026
71fd7ef
`fn HIST_count`: pointer argument to reference
folkertdev Aug 10, 2026
ebb41c9
`fn FSE_initCState`: pointer argument to reference
folkertdev Aug 10, 2026
42a2b2e
`fn FSE_initCState2`: pointer argument to reference
folkertdev Aug 10, 2026
95e587c
`fn FSE_encodeSymbol`: pointer argument to reference
folkertdev Aug 10, 2026
9295db7
`fn FSE_flushCState`: pointer argument to reference
folkertdev Aug 10, 2026
3a42cb4
lib/compress/fse_compress: use the shared `FSE_initCState2` and `FSE_…
folkertdev Aug 10, 2026
436c644
`fn ZSTD_estimateBlockSize_symbolType`: pass `fseCTable` as a slice
folkertdev Aug 10, 2026
d2375f4
`fn ZSTD_estimateSubBlockSize_symbolType`: pass `fseCTable` as a slice
folkertdev Aug 10, 2026
3319fe9
`fn ZSTD_selectEncodingType`: pass `prevCTable` as a slice
folkertdev Aug 10, 2026
191f2fc
`fn ZSTD_fseBitCost`: pass `ctable` as a slice
folkertdev Aug 10, 2026
f8aef70
`fn ZSTD_getFSEMaxSymbolValue`: pass `ctable` as a slice
folkertdev Aug 10, 2026
8b0e974
`fn ZSTD_encodeSequences`: pass the CTables as slices
folkertdev Aug 10, 2026
b12a3e1
`fn ZSTD_encodeSequences_default` and `_bmi2`: pass the CTables as sl…
folkertdev Aug 10, 2026
505ee97
`fn ZSTD_encodeSequences_body`: pass the CTables as slices
folkertdev Aug 10, 2026
08e54fa
`fn FSE_compress_usingCTable`: pass `ct` as a slice
folkertdev Aug 10, 2026
2c063ad
`fn FSE_compress_usingCTable_generic`: pass `ct` as a slice
folkertdev Aug 10, 2026
7213b2e
`fn FSE_initCState2`: pass `ct` as a slice
folkertdev Aug 10, 2026
55c778a
`fn FSE_initCState`: pass `ct` as a slice
folkertdev Aug 10, 2026
853fa82
`fn FSE_initCState` is now safe
folkertdev Aug 10, 2026
893aa8a
`fn ZSTD_buildCTable`: pass `prevCTable` as a slice
folkertdev Aug 10, 2026
fd5fd79
`fn ZSTD_buildCTable`: drop the redundant `prevCTableSize` argument
folkertdev Aug 10, 2026
9a99521
lib/common/fse: add a `FSE_readU16` helper
folkertdev Aug 10, 2026
a873f00
`fn FSE_initCState2` is now safe
folkertdev Aug 10, 2026
06c6137
`fn ZSTD_buildCTable`: pass `nextCTable` as a mutable slice
folkertdev Aug 10, 2026
d719066
`fn FSE_buildCTable_rle`: pass `ct` as a mutable slice
folkertdev Aug 10, 2026
fc5d00b
`fn FSE_buildCTable_rle` is now safe
folkertdev Aug 10, 2026
f347a1d
`fn ZSTD_getFSEMaxSymbolValue`: make safe
folkertdev Aug 10, 2026
dfd32d7
clippy
folkertdev Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 73 additions & 40 deletions lib/common/fse.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use libc::ptrdiff_t;

use crate::lib::common::bitstream::{BIT_CStream_t, BIT_addBits, BIT_flushBits, BitContainerType};
use crate::lib::common::mem::MEM_read16;

pub(crate) type FSE_CTable = core::ffi::c_uint;

Expand Down Expand Up @@ -69,63 +68,97 @@ pub(crate) struct FSE_symbolCompressionTransform {
pub(crate) deltaNbBits: u32,
}

/// Pack two consecutive `u16` values into one `u32`.
#[inline]
pub(crate) unsafe fn FSE_initCState(statePtr: *mut FSE_CState_t, ct: *const FSE_CTable) {
let ptr = ct as *const core::ffi::c_void;
let u16ptr = ptr as *const u16;
let tableLog = MEM_read16(ptr) as u32;
(*statePtr).value = (1) << tableLog;
(*statePtr).stateTable = u16ptr.add(2) as *const core::ffi::c_void;
(*statePtr).symbolTT = ct.add(1).offset(
(if tableLog != 0 {
(1) << tableLog.wrapping_sub(1)
} else {
1
}) as isize,
) as *const core::ffi::c_void;
(*statePtr).stateLog = tableLog;
pub(crate) fn FSE_writeU16Pair(first: u16, second: u16) -> FSE_CTable {
let [a, b] = first.to_ne_bytes();
let [c, d] = second.to_ne_bytes();

u32::from_ne_bytes([a, b, c, d])
}

/// Read the `index`th `u16` of a `&[u32]`.
#[inline]
fn FSE_readU16(ct: &[FSE_CTable], index: usize) -> u16 {
let bytes = ct[index / 2].to_ne_bytes();
if index.is_multiple_of(2) {
u16::from_ne_bytes([bytes[0], bytes[1]])
} else {
u16::from_ne_bytes([bytes[2], bytes[3]])
}
}

#[inline]
pub(crate) fn FSE_initCState(statePtr: &mut FSE_CState_t, ct: &[FSE_CTable]) {
// the table header occupies the first two bytes of `ct`
let tableLog = FSE_readU16(ct, 0) as u32;

// the state table follows the header
let stateTable = &ct[1..];
let symbolTT = &ct[FSE_symbolTTIndex(tableLog)..];

statePtr.value = 1 << tableLog;
statePtr.stateTable = stateTable.as_ptr().cast::<core::ffi::c_void>();
statePtr.symbolTT = symbolTT.as_ptr().cast::<core::ffi::c_void>();
statePtr.stateLog = tableLog;
}

#[inline]
pub(crate) unsafe fn FSE_initCState2(
statePtr: *mut FSE_CState_t,
ct: *const FSE_CTable,
pub(crate) const fn FSE_symbolTTIndex(tableLog: u32) -> usize {
let skip_header = 1;

match tableLog {
0 => skip_header + 1,
_ => skip_header + (1 << (tableLog - 1)),
}
}

/// Read the transform of `symbol` out of the symbol transformation table of `ct`.
#[inline]
fn FSE_readSymbolTT(
ct: &[FSE_CTable],
tableLog: u32,
symbol: u32,
) {
) -> FSE_symbolCompressionTransform {
let index = FSE_symbolTTIndex(tableLog) + 2 * symbol as usize;

FSE_symbolCompressionTransform {
deltaFindState: ct[index] as core::ffi::c_int,
deltaNbBits: ct[index + 1],
}
}

#[inline]
pub(crate) fn FSE_initCState2(statePtr: &mut FSE_CState_t, ct: &[FSE_CTable], symbol: u32) {
FSE_initCState(statePtr, ct);
let symbolTT =
*((*statePtr).symbolTT as *const FSE_symbolCompressionTransform).offset(symbol as isize);
let stateTable = (*statePtr).stateTable as *const u16;
let nbBitsOut = (symbolTT.deltaNbBits).wrapping_add(((1) << 15) as u32) >> 16;
(*statePtr).value = (nbBitsOut << 16).wrapping_sub(symbolTT.deltaNbBits) as ptrdiff_t;
(*statePtr).value = *stateTable
.offset(((*statePtr).value >> nbBitsOut) + symbolTT.deltaFindState as ptrdiff_t)
as ptrdiff_t;
let symbolTT = FSE_readSymbolTT(ct, statePtr.stateLog, symbol);
let nbBitsOut = (symbolTT.deltaNbBits).wrapping_add((1) << 15) >> 16;
let value = (nbBitsOut << 16).wrapping_sub(symbolTT.deltaNbBits) as ptrdiff_t;

// the state table starts at the third `u16` of `ct`
let index = 2 + (value >> nbBitsOut) + symbolTT.deltaFindState as ptrdiff_t;
statePtr.value = FSE_readU16(ct, index as usize) as ptrdiff_t;
}

#[inline]
pub(crate) unsafe fn FSE_encodeSymbol(
bitC: &mut BIT_CStream_t,
statePtr: *mut FSE_CState_t,
statePtr: &mut FSE_CState_t,
symbol: core::ffi::c_uint,
) {
let symbolTT =
*((*statePtr).symbolTT as *const FSE_symbolCompressionTransform).offset(symbol as isize);
let stateTable = (*statePtr).stateTable as *const u16;
let nbBitsOut = (((*statePtr).value + symbolTT.deltaNbBits as ptrdiff_t) >> 16) as u32;
BIT_addBits(bitC, (*statePtr).value as BitContainerType, nbBitsOut);
(*statePtr).value = *stateTable
.offset(((*statePtr).value >> nbBitsOut) + symbolTT.deltaFindState as ptrdiff_t)
*(statePtr.symbolTT as *const FSE_symbolCompressionTransform).offset(symbol as isize);
let stateTable = statePtr.stateTable as *const u16;
let nbBitsOut = ((statePtr.value + symbolTT.deltaNbBits as ptrdiff_t) >> 16) as u32;
BIT_addBits(bitC, statePtr.value as BitContainerType, nbBitsOut);
statePtr.value = *stateTable
.offset((statePtr.value >> nbBitsOut) + symbolTT.deltaFindState as ptrdiff_t)
as ptrdiff_t;
}

#[inline]
pub(crate) unsafe fn FSE_flushCState(bitC: &mut BIT_CStream_t, statePtr: *const FSE_CState_t) {
BIT_addBits(
bitC,
(*statePtr).value as BitContainerType,
(*statePtr).stateLog,
);
pub(crate) unsafe fn FSE_flushCState(bitC: &mut BIT_CStream_t, statePtr: &FSE_CState_t) {
BIT_addBits(bitC, statePtr.value as BitContainerType, statePtr.stateLog);
BIT_flushBits(bitC);
}

Expand Down
75 changes: 17 additions & 58 deletions lib/compress/fse_compress.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,17 @@
use libc::{ptrdiff_t, size_t};
use libc::size_t;

use crate::lib::common::bits::ZSTD_highbit32;
use crate::lib::common::bitstream::{
BIT_CStream_t, BIT_addBits, BIT_closeCStream, BIT_flushBits, BIT_flushBitsFast,
BIT_initCStream, BitContainerType,
BIT_CStream_t, BIT_closeCStream, BIT_flushBits, BIT_flushBitsFast, BIT_initCStream,
BitContainerType,
};
use crate::lib::common::error_private::{ERR_isError, Error};
use crate::lib::common::fse::{
FSE_CState_t, FSE_CTable, FSE_encodeSymbol, FSE_symbolCompressionTransform,
FSE_DEFAULT_TABLELOG, FSE_MAX_TABLELOG, FSE_MIN_TABLELOG, FSE_NCOUNTBOUND,
FSE_CState_t, FSE_CTable, FSE_encodeSymbol, FSE_flushCState, FSE_initCState2,
FSE_symbolCompressionTransform, FSE_symbolTTIndex, FSE_writeU16Pair, FSE_DEFAULT_TABLELOG,
FSE_MAX_TABLELOG, FSE_MIN_TABLELOG, FSE_NCOUNTBOUND,
};
use crate::lib::common::mem::{MEM_read16, MEM_write64};

#[inline]
unsafe fn FSE_initCState(statePtr: &mut FSE_CState_t, ct: *const FSE_CTable) {
let ptr = ct as *const core::ffi::c_void;
let u16ptr = ptr as *const u16;
let tableLog = MEM_read16(ptr) as u32;
statePtr.value = 1 << tableLog;
statePtr.stateTable = u16ptr.add(2) as *const core::ffi::c_void;
statePtr.symbolTT = ct.add(1).offset(
(if tableLog != 0 {
1 << tableLog.wrapping_sub(1)
} else {
1
}) as isize,
) as *const core::ffi::c_void;
statePtr.stateLog = tableLog;
}

#[inline]
unsafe fn FSE_initCState2(statePtr: &mut FSE_CState_t, ct: *const FSE_CTable, symbol: u32) {
FSE_initCState(statePtr, ct);
let symbolTT =
*(statePtr.symbolTT as *const FSE_symbolCompressionTransform).offset(symbol as isize);
let stateTable = statePtr.stateTable as *const u16;
let nbBitsOut = (symbolTT.deltaNbBits).wrapping_add((1 << 15) as u32) >> 16;
statePtr.value = (nbBitsOut << 16).wrapping_sub(symbolTT.deltaNbBits) as ptrdiff_t;
statePtr.value = *stateTable
.offset((statePtr.value >> nbBitsOut) + symbolTT.deltaFindState as ptrdiff_t)
as ptrdiff_t;
}

#[inline]
unsafe fn FSE_flushCState(bitC: &mut BIT_CStream_t, statePtr: &FSE_CState_t) {
BIT_addBits(bitC, statePtr.value as BitContainerType, statePtr.stateLog);
BIT_flushBits(bitC);
}
use crate::lib::common::mem::MEM_write64;

/// Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
/// wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`
Expand Down Expand Up @@ -629,23 +594,17 @@ pub(crate) unsafe fn FSE_normalizeCount(
}

/// Fake FSE_CTable, for rle input (always same symbol).
pub(crate) unsafe fn FSE_buildCTable_rle(ct: *mut FSE_CTable, symbolValue: u8) -> size_t {
let ptr = ct as *mut core::ffi::c_void;
let tableU16 = (ptr as *mut u16).add(2);
let FSCTptr = (ptr as *mut u32).add(2) as *mut core::ffi::c_void;
let symbolTT = FSCTptr as *mut FSE_symbolCompressionTransform;
pub(crate) fn FSE_buildCTable_rle(ct: &mut [FSE_CTable], symbolValue: u8) -> size_t {
// header: a tableLog of zero, and `symbolValue` as the maximum symbol value
ct[0] = FSE_writeU16Pair(0, symbolValue as u16);

// header
*tableU16.sub(2) = 0;
*tableU16.sub(1) = symbolValue as u16;

// Build table
*tableU16 = 0;
*tableU16.add(1) = 0; // just in case
// the (two-entry) state table, zeroed just in case
ct[1] = FSE_writeU16Pair(0, 0);

// Build Symbol Transformation Table
(*symbolTT.offset(symbolValue as isize)).deltaNbBits = 0;
(*symbolTT.offset(symbolValue as isize)).deltaFindState = 0;
let index = FSE_symbolTTIndex(0) + 2 * symbolValue as usize;
ct[index] = 0; // deltaFindState
ct[index + 1] = 0; // deltaNbBits

0
}
Expand All @@ -655,7 +614,7 @@ unsafe fn FSE_compress_usingCTable_generic(
dstSize: size_t,
src: *const core::ffi::c_void,
mut srcSize: size_t,
ct: *const FSE_CTable,
ct: &[FSE_CTable],
fast: bool,
) -> size_t {
let istart = src as *const u8;
Expand Down Expand Up @@ -773,7 +732,7 @@ pub(crate) unsafe fn FSE_compress_usingCTable(
dstSize: size_t,
src: *const core::ffi::c_void,
srcSize: size_t,
ct: *const FSE_CTable,
ct: &[FSE_CTable],
) -> size_t {
let fast = dstSize
>= srcSize
Expand Down
12 changes: 6 additions & 6 deletions lib/compress/hist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub unsafe fn HIST_add(

pub unsafe fn HIST_count_simple(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
src: *const core::ffi::c_void,
srcSize: size_t,
) -> core::ffi::c_uint {
Expand Down Expand Up @@ -83,7 +83,7 @@ pub unsafe fn HIST_count_simple(
/// histogram's alphabet is larger than *maxSymbolValuePtr)
unsafe fn HIST_count_parallel_wksp(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
source: *const core::ffi::c_void,
sourceSize: size_t,
check: HIST_checkInput_e,
Expand Down Expand Up @@ -181,7 +181,7 @@ unsafe fn HIST_count_parallel_wksp(
/// `workSpaceSize` must be >= HIST_WKSP_SIZE
pub unsafe fn HIST_countFast_wksp(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
source: *const core::ffi::c_void,
sourceSize: size_t,
workSpace: *mut core::ffi::c_void,
Expand Down Expand Up @@ -211,7 +211,7 @@ pub unsafe fn HIST_countFast_wksp(
/// `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned
pub unsafe fn HIST_count_wksp(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
source: *const core::ffi::c_void,
sourceSize: size_t,
workSpace: *mut core::ffi::c_void,
Expand Down Expand Up @@ -248,7 +248,7 @@ pub unsafe fn HIST_count_wksp(
/// fast variant (unsafe : won't check if src contains values beyond count[] limit)
pub unsafe fn HIST_countFast(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
source: *const core::ffi::c_void,
sourceSize: size_t,
) -> size_t {
Expand All @@ -265,7 +265,7 @@ pub unsafe fn HIST_countFast(

pub unsafe fn HIST_count(
count: *mut core::ffi::c_uint,
maxSymbolValuePtr: *mut core::ffi::c_uint,
maxSymbolValuePtr: &mut core::ffi::c_uint,
src: *const core::ffi::c_void,
srcSize: size_t,
) -> size_t {
Expand Down
2 changes: 1 addition & 1 deletion lib/compress/huf_compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ unsafe fn HUF_compressWeights(
oend.offset_from_unsigned(op),
weightTable.as_ptr().cast::<c_void>(),
wtSize,
((*wksp).CTable).as_mut_ptr(),
&(*wksp).CTable,
);
if ERR_isError(cSize) {
return cSize;
Expand Down
Loading
Loading