Skip to main content

zstd_pure_rs/
lib.rs

1//! Pure-Rust port of the Zstandard (zstd) compression library.
2//!
3//! See `README.md` for status and the overall plan.
4//!
5//! # Quickstart
6//!
7//! ```
8//! use zstd_pure_rs::prelude::*;
9//!
10//! let src = b"Pure-Rust zstd can compress this.".to_vec();
11//!
12//! // Compress at level 3 (upstream default).
13//! let mut compressed = vec![0u8; ZSTD_compressBound(src.len())];
14//! let cSize = ZSTD_compress(&mut compressed, &src, 3);
15//! assert!(!ERR_isError(cSize));
16//! compressed.truncate(cSize);
17//!
18//! // Decompress.
19//! let mut decoded = vec![0u8; src.len()];
20//! let dSize = ZSTD_decompress(&mut decoded, &compressed);
21//! assert_eq!(dSize, src.len());
22//! assert_eq!(decoded, src);
23//! ```
24//!
25//! # Skippable frames
26//!
27//! ```
28//! use zstd_pure_rs::prelude::*;
29//!
30//! // Skippable frames embed arbitrary user data that decoders skip.
31//! let payload = b"custom-metadata-goes-here";
32//! let mut frame = vec![0u8; payload.len() + 8];
33//! let wn = ZSTD_writeSkippableFrame(&mut frame, payload, 7);
34//! assert_eq!(wn, payload.len() + 8);
35//!
36//! // Read back the payload + magic variant.
37//! let mut out = vec![0u8; payload.len()];
38//! let mut variant = 0u32;
39//! let rn = ZSTD_readSkippableFrame(&mut out, Some(&mut variant), &frame);
40//! assert_eq!(rn, payload.len());
41//! assert_eq!(variant, 7);
42//! assert_eq!(&out, payload);
43//! ```
44//!
45//! # Dictionary-based compression
46//!
47//! ```
48//! use zstd_pure_rs::prelude::*;
49//!
50//! let dict = b"common prefix shared across messages ".to_vec();
51//! let src = b"common prefix shared across messages \
52//!             plus per-message content".to_vec();
53//!
54//! // One-shot dict compression via raw content.
55//! let mut cctx = ZSTD_createCCtx().expect("alloc");
56//! let mut dst = vec![0u8; ZSTD_compressBound(src.len())];
57//! let n = ZSTD_compress_usingDict(&mut cctx, &mut dst, &src, &dict, 3);
58//! assert!(!ERR_isError(n));
59//! dst.truncate(n);
60//!
61//! // Decompress with the same dict.
62//! let mut dctx = ZSTD_createDCtx();
63//! let mut out = vec![0u8; src.len() + 64];
64//! let d = ZSTD_decompress_usingDict(&mut dctx, &mut out, &dst, &dict);
65//! assert_eq!(&out[..d], &src[..]);
66//! ```
67//!
68//! # Streaming compression
69//!
70//! ```
71//! use zstd_pure_rs::prelude::*;
72//!
73//! let src = b"streaming compression demo ".repeat(30);
74//! let mut cctx = ZSTD_createCCtx().expect("alloc");
75//! ZSTD_initCStream(&mut cctx, 3);
76//!
77//! // Stage input, then drive endStream until fully drained.
78//! let mut dst = vec![0u8; ZSTD_compressBound(src.len())];
79//! let mut dst_pos = 0usize;
80//! let mut src_pos = 0usize;
81//! ZSTD_compressStream(&mut cctx, &mut dst, &mut dst_pos, &src, &mut src_pos);
82//! loop {
83//!     let rc = ZSTD_endStream(&mut cctx, &mut dst, &mut dst_pos);
84//!     if rc == 0 || ERR_isError(rc) { break; }
85//! }
86//!
87//! // Decompress via the public one-shot entry.
88//! let mut out = vec![0u8; src.len() + 64];
89//! let d = ZSTD_decompress(&mut out, &dst[..dst_pos]);
90//! assert_eq!(&out[..d], &src[..]);
91//! ```
92//!
93//! # Parametric API (advanced)
94//!
95//! ```
96//! use zstd_pure_rs::prelude::*;
97//!
98//! let src = b"parametric api demo".repeat(20);
99//! let mut cctx = ZSTD_createCCtx().expect("alloc");
100//! // Opt into XXH64 checksum + exact frame-header FCS.
101//! ZSTD_CCtx_setParameter(&mut cctx, ZSTD_cParameter::ZSTD_c_compressionLevel, 5);
102//! ZSTD_CCtx_setParameter(&mut cctx, ZSTD_cParameter::ZSTD_c_checksumFlag, 1);
103//! ZSTD_CCtx_setParameter(&mut cctx, ZSTD_cParameter::ZSTD_c_contentSizeFlag, 1);
104//!
105//! let mut dst = vec![0u8; ZSTD_compressBound(src.len())];
106//! let n = ZSTD_compress2(&mut cctx, &mut dst, &src);
107//! assert!(!ERR_isError(n));
108//! dst.truncate(n);
109//!
110//! let mut out = vec![0u8; src.len() + 64];
111//! let d = ZSTD_decompress(&mut out, &dst);
112//! assert_eq!(&out[..d], &src[..]);
113//! ```
114//!
115//! See upstream's `zstd.h` for API semantics. The main public `ZSTD_`
116//! entry points are available under the `zstd_pure_rs::prelude`
117//! re-exports. Lower-level `HUF_` and `FSE_` helpers remain in their
118//! module namespaces unless explicitly re-exported there; unsupported
119//! experimental parameters return the corresponding error codes.
120
121#![allow(non_snake_case)]
122#![allow(non_camel_case_types)]
123#![allow(non_upper_case_globals)]
124// Upstream zstd functions often take many arguments; we preserve 1:1
125// signatures so code-complexity-comparator stays meaningful.
126#![allow(clippy::too_many_arguments)]
127// This crate intentionally preserves upstream C control flow and test
128// structure closely, so we suppress style-oriented lints that would
129// otherwise demand less faithful Rust rewrites.
130#![allow(clippy::collapsible_if)]
131#![allow(clippy::default_constructed_unit_structs)]
132#![allow(clippy::derivable_impls)]
133#![allow(clippy::field_reassign_with_default)]
134#![allow(clippy::implicit_saturating_sub)]
135#![allow(clippy::needless_late_init)]
136#![allow(clippy::needless_option_as_deref)]
137#![allow(clippy::needless_return)]
138#![allow(clippy::not_unsafe_ptr_arg_deref)]
139#![allow(clippy::type_complexity)]
140#![allow(clippy::unnecessary_cast)]
141#![allow(clippy::unnecessary_mut_passed)]
142
143// v0.1 is std-only — the port uses `Vec`, `format!`, and `std::thread`
144// throughout. A proper `no_std` variant is a future effort.
145#[cfg(not(feature = "std"))]
146compile_error!(
147    "zstd-pure-rs requires the `std` feature (enabled by default). \
148     no_std support is a future goal."
149);
150
151pub mod common;
152pub mod compress;
153pub mod decompress;
154pub mod dict_builder;
155
156pub use common::error::{ErrorCode, ZstdError};
157pub use common::mem::is_little_endian;
158pub use common::zstd_common::{
159    ZSTD_getErrorCode, ZSTD_getErrorName, ZSTD_getErrorString, ZSTD_isDeterministicBuild,
160    ZSTD_isError, ZSTD_versionNumber, ZSTD_versionString, ZSTD_VERSION_MAJOR, ZSTD_VERSION_MINOR,
161    ZSTD_VERSION_NUMBER, ZSTD_VERSION_RELEASE, ZSTD_VERSION_STRING,
162};
163
164/// Upstream-compatible alias for `ZSTD_frameParameters`.
165pub type ZSTD_frameParameters = compress::zstd_compress::ZSTD_FrameParameters;
166/// Upstream-compatible legacy alias for `ZSTD_FrameHeader`.
167pub type ZSTD_frameHeader = decompress::zstd_decompress::ZSTD_FrameHeader;
168/// Upstream-compatible legacy alias for `ZSTD_FrameType_e`.
169pub type ZSTD_frameType_e = decompress::zstd_decompress::ZSTD_FrameType_e;
170/// Upstream-compatible legacy alias for `ZSTD_ParamSwitch_e`.
171pub type ZSTD_paramSwitch_e = compress::zstd_ldm::ZSTD_ParamSwitch_e;
172/// Upstream-compatible legacy alias for `ZSTD_SequenceFormat_e`.
173pub type ZSTD_sequenceFormat_e = compress::zstd_compress::ZSTD_SequenceFormat_e;
174/// Upstream-compatible alias for `ZSTD_threadPool`.
175#[cfg(feature = "std")]
176pub type ZSTD_threadPool = common::pool::POOL_ctx;
177
178/// Upstream `ZSTD_BLOCKSPLITTER_LEVEL_MAX`.
179pub const ZSTD_BLOCKSPLITTER_LEVEL_MAX: i32 = 6;
180/// Upstream `ZSTD_SEQUENCE_PRODUCER_ERROR`.
181pub const ZSTD_SEQUENCE_PRODUCER_ERROR: usize = usize::MAX;
182
183/// Upstream macro aliases for implemented experimental parameter names.
184pub const ZSTD_c_format: compress::zstd_compress::ZSTD_cParameter =
185    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_format;
186pub const ZSTD_c_rsyncable: compress::zstd_compress::ZSTD_cParameter =
187    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_rsyncable;
188pub const ZSTD_c_forceMaxWindow: compress::zstd_compress::ZSTD_cParameter =
189    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_forceMaxWindow;
190pub const ZSTD_c_forceAttachDict: compress::zstd_compress::ZSTD_cParameter =
191    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_forceAttachDict;
192pub const ZSTD_c_literalCompressionMode: compress::zstd_compress::ZSTD_cParameter =
193    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_literalCompressionMode;
194pub const ZSTD_c_srcSizeHint: compress::zstd_compress::ZSTD_cParameter =
195    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_srcSizeHint;
196pub const ZSTD_c_enableDedicatedDictSearch: compress::zstd_compress::ZSTD_cParameter =
197    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_enableDedicatedDictSearch;
198pub const ZSTD_c_stableInBuffer: compress::zstd_compress::ZSTD_cParameter =
199    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_stableInBuffer;
200pub const ZSTD_c_stableOutBuffer: compress::zstd_compress::ZSTD_cParameter =
201    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_stableOutBuffer;
202pub const ZSTD_c_blockDelimiters: compress::zstd_compress::ZSTD_cParameter =
203    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_blockDelimiters;
204pub const ZSTD_c_validateSequences: compress::zstd_compress::ZSTD_cParameter =
205    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_validateSequences;
206pub const ZSTD_c_splitAfterSequences: compress::zstd_compress::ZSTD_cParameter =
207    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_splitAfterSequences;
208pub const ZSTD_c_useRowMatchFinder: compress::zstd_compress::ZSTD_cParameter =
209    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_useRowMatchFinder;
210pub const ZSTD_c_deterministicRefPrefix: compress::zstd_compress::ZSTD_cParameter =
211    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_deterministicRefPrefix;
212pub const ZSTD_c_prefetchCDictTables: compress::zstd_compress::ZSTD_cParameter =
213    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_prefetchCDictTables;
214pub const ZSTD_c_blockSplitterLevel: compress::zstd_compress::ZSTD_cParameter =
215    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_blockSplitterLevel;
216pub const ZSTD_c_enableSeqProducerFallback: compress::zstd_compress::ZSTD_cParameter =
217    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_enableSeqProducerFallback;
218pub const ZSTD_c_maxBlockSize: compress::zstd_compress::ZSTD_cParameter =
219    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_maxBlockSize;
220pub const ZSTD_c_repcodeResolution: compress::zstd_compress::ZSTD_cParameter =
221    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_repcodeResolution;
222pub const ZSTD_c_searchForExternalRepcodes: compress::zstd_compress::ZSTD_cParameter =
223    compress::zstd_compress::ZSTD_cParameter::ZSTD_c_repcodeResolution;
224pub const ZSTD_d_format: decompress::zstd_decompress::ZSTD_dParameter =
225    decompress::zstd_decompress::ZSTD_dParameter::ZSTD_d_format;
226pub const ZSTD_d_forceIgnoreChecksum: decompress::zstd_decompress::ZSTD_dParameter =
227    decompress::zstd_decompress::ZSTD_dParameter::ZSTD_d_forceIgnoreChecksum;
228
229/// Re-exports of the most commonly-used public API, so callers can
230/// write `use zstd_pure_rs::prelude::*;` instead of drilling into
231/// `compress::zstd_compress` / `decompress::zstd_decompress`.
232pub mod prelude {
233    // One-shot compression.
234    #[cfg(feature = "mt")]
235    pub use crate::compress::zstd_compress::ZSTD_CCtx_refRayonThreadPool;
236    #[cfg(feature = "std")]
237    pub use crate::compress::zstd_compress::ZSTD_CCtx_refThreadPool;
238    pub use crate::compress::zstd_compress::{
239        ZSTD_CCtx, ZSTD_CCtx_loadDictionary, ZSTD_CCtx_loadDictionary_advanced,
240        ZSTD_CCtx_loadDictionary_byReference, ZSTD_CCtx_refCDict, ZSTD_CCtx_refPrefix,
241        ZSTD_CCtx_refPrefix_advanced, ZSTD_CDict, ZSTD_Sequence, ZSTD_SequenceFormat_e,
242        ZSTD_SequencePosition, ZSTD_compress, ZSTD_compress2, ZSTD_compressBegin,
243        ZSTD_compressBegin_usingCDict, ZSTD_compressBegin_usingDict, ZSTD_compressBound,
244        ZSTD_compressCCtx, ZSTD_compressSequences, ZSTD_compressSequencesAndLiterals,
245        ZSTD_compress_usingCDict, ZSTD_compress_usingCDict_advanced, ZSTD_compress_usingDict,
246        ZSTD_createCCtx, ZSTD_createCCtx_advanced, ZSTD_createCDict, ZSTD_createCDict_advanced,
247        ZSTD_createCDict_advanced2, ZSTD_createCDict_byReference, ZSTD_customMem,
248        ZSTD_frameProgression, ZSTD_freeCCtx, ZSTD_freeCDict, ZSTD_generateSequences,
249        ZSTD_getDictID_fromCDict, ZSTD_getFrameProgression, ZSTD_mergeBlockDelimiters,
250        ZSTD_sequenceBound, ZSTD_toFlushNow, ZSTD_writeSkippableFrame,
251    };
252    // Streaming compression.
253    pub use crate::compress::zstd_compress::{
254        ZSTD_CCtx_setPledgedSrcSize, ZSTD_CStream, ZSTD_CStreamInSize, ZSTD_CStreamOutSize,
255        ZSTD_EndDirective, ZSTD_compressBegin_advanced, ZSTD_compressBegin_usingCDict_advanced,
256        ZSTD_compressStream, ZSTD_compressStream2, ZSTD_compressStream2_simpleArgs,
257        ZSTD_createCStream, ZSTD_createCStream_advanced, ZSTD_endStream,
258        ZSTD_estimateCCtxSize_usingCCtxParams, ZSTD_estimateCCtxSize_usingCParams,
259        ZSTD_estimateCStreamSize_usingCCtxParams, ZSTD_estimateCStreamSize_usingCParams,
260        ZSTD_flushStream, ZSTD_freeCStream, ZSTD_inBuffer, ZSTD_initCStream,
261        ZSTD_initCStream_advanced, ZSTD_initCStream_srcSize, ZSTD_initCStream_usingCDict,
262        ZSTD_initCStream_usingCDict_advanced, ZSTD_initCStream_usingDict, ZSTD_outBuffer,
263        ZSTD_resetCStream,
264    };
265    // Parametric + level info.
266    pub use crate::compress::match_state::ZSTD_compressionParameters;
267    pub use crate::compress::zstd_compress::ZSTD_dictAttachPref_e;
268    pub use crate::compress::zstd_compress::{
269        ZSTD_CCtxParams_getParameter, ZSTD_CCtxParams_init, ZSTD_CCtxParams_init_advanced,
270        ZSTD_CCtxParams_registerSequenceProducer, ZSTD_CCtxParams_reset,
271        ZSTD_CCtxParams_setParameter, ZSTD_CCtxParams_setZstdParams, ZSTD_CCtx_getParameter,
272        ZSTD_CCtx_params, ZSTD_CCtx_reset, ZSTD_CCtx_setCParams, ZSTD_CCtx_setFParams,
273        ZSTD_CCtx_setFormat, ZSTD_CCtx_setParameter, ZSTD_CCtx_setParametersUsingCCtxParams,
274        ZSTD_CCtx_setParams, ZSTD_FrameParameters, ZSTD_ResetDirective, ZSTD_adjustCParams,
275        ZSTD_allocFunction, ZSTD_bounds, ZSTD_cParam_clampBounds, ZSTD_cParam_getBounds,
276        ZSTD_cParam_withinBounds, ZSTD_cParameter, ZSTD_checkCParams,
277        ZSTD_compressFrame_fast_advanced, ZSTD_compressFrame_fast_with_prefix_advanced,
278        ZSTD_createCCtxParams, ZSTD_defaultCLevel, ZSTD_forceIgnoreChecksum_e, ZSTD_freeCCtxParams,
279        ZSTD_freeFunction, ZSTD_getCParams, ZSTD_getParams, ZSTD_literalCompressionMode_e,
280        ZSTD_maxCLevel, ZSTD_minCLevel, ZSTD_parameters, ZSTD_refMultipleDDicts_e,
281        ZSTD_registerSequenceProducer, ZSTD_sequenceProducer_F, ZSTD_writeFrameHeader_advanced,
282        ZSTD_BLOCKSIZE_MAX_MIN, ZSTD_CHAINLOG_MAX, ZSTD_CHAINLOG_MAX_32, ZSTD_CHAINLOG_MAX_64,
283        ZSTD_CHAINLOG_MIN, ZSTD_CLEVEL_DEFAULT, ZSTD_COMPRESSBOUND, ZSTD_FRAMEHEADERSIZE_MAX,
284        ZSTD_MAX_CLEVEL, ZSTD_MAX_INPUT_SIZE, ZSTD_MINMATCH_MAX, ZSTD_MINMATCH_MIN, ZSTD_NO_CLEVEL,
285        ZSTD_OVERLAPLOG_MAX, ZSTD_OVERLAPLOG_MIN, ZSTD_SEARCHLOG_MAX, ZSTD_SEARCHLOG_MIN,
286        ZSTD_SRCSIZEHINT_MAX, ZSTD_SRCSIZEHINT_MIN, ZSTD_STRATEGY_MAX, ZSTD_STRATEGY_MIN,
287        ZSTD_TARGETCBLOCKSIZE_MAX, ZSTD_TARGETCBLOCKSIZE_MIN, ZSTD_TARGETLENGTH_MAX,
288        ZSTD_TARGETLENGTH_MIN, ZSTD_WINDOWLOG_MAX, ZSTD_WINDOWLOG_MIN,
289    };
290    pub use crate::compress::zstd_compress::{
291        ZSTD_LDM_BUCKETSIZELOG_MIN, ZSTD_LDM_HASHLOG_MAX, ZSTD_LDM_HASHLOG_MIN,
292        ZSTD_LDM_HASHRATELOG_MAX, ZSTD_LDM_HASHRATELOG_MIN, ZSTD_LDM_MINMATCH_MAX,
293        ZSTD_LDM_MINMATCH_MIN,
294    };
295    pub use crate::compress::zstd_compress_literals::ZSTD_strategy;
296    pub use crate::compress::zstd_compress_sequences::{
297        ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra, ZSTD_btultra2, ZSTD_dfast, ZSTD_fast, ZSTD_greedy,
298        ZSTD_lazy, ZSTD_lazy2,
299    };
300    pub use crate::compress::zstd_ldm::{
301        ZSTD_ParamSwitch_e, ZSTD_HASHLOG_MAX, ZSTD_HASHLOG_MIN, ZSTD_LDM_BUCKETSIZELOG_MAX,
302        ZSTD_LDM_DEFAULT_WINDOW_LOG,
303    };
304    // Memory estimation.
305    pub use crate::compress::zstd_compress::{
306        ZSTD_estimateCCtxSize, ZSTD_estimateCDictSize, ZSTD_estimateCDictSize_advanced,
307        ZSTD_estimateCStreamSize, ZSTD_initStaticCCtx, ZSTD_initStaticCDict,
308        ZSTD_initStaticCStream, ZSTD_sizeof_CCtx, ZSTD_sizeof_CDict, ZSTD_sizeof_CStream,
309        ZSTD_sizeof_mtctx,
310    };
311    // Legacy block-level API stubs.
312    pub use crate::compress::zstd_compress::{
313        ZSTD_compressBegin_usingCDict_deprecated, ZSTD_compressBegin_usingDict_deprecated,
314        ZSTD_compressBlock, ZSTD_compressBlock_deprecated, ZSTD_compressContinue,
315        ZSTD_compressContinue_public, ZSTD_compressEnd, ZSTD_compressEnd_public, ZSTD_getBlockSize,
316    };
317    // Advanced + ctx-copy helpers.
318    pub use crate::compress::zstd_compress::{
319        ZSTD_compress_advanced, ZSTD_copyCCtx, ZSTD_cycleLog, ZSTD_dedicatedDictSearch_getCParams,
320        ZSTD_dedicatedDictSearch_isSupported, ZSTD_dedicatedDictSearch_revertCParams,
321        ZSTD_dictAndWindowLog,
322    };
323    // Dictionary trainer (ZDICT: cover / fastCover / legacy).
324    pub use crate::dict_builder::{
325        ZDICT_addEntropyTablesFromBuffer, ZDICT_cover_params_t, ZDICT_fastCover_params_t,
326        ZDICT_finalizeDictionary, ZDICT_getDictHeaderSize, ZDICT_getDictID, ZDICT_getErrorName,
327        ZDICT_isError, ZDICT_legacy_params_t, ZDICT_optimizeTrainFromBuffer_cover,
328        ZDICT_optimizeTrainFromBuffer_fastCover, ZDICT_params_t, ZDICT_trainFromBuffer,
329        ZDICT_trainFromBuffer_cover, ZDICT_trainFromBuffer_fastCover, ZDICT_trainFromBuffer_legacy,
330    };
331    // One-shot + streaming decompression.
332    pub use crate::decompress::zstd_decompress::{
333        ZSTD_DCtx, ZSTD_DCtx_getParameter, ZSTD_DCtx_loadDictionary,
334        ZSTD_DCtx_loadDictionary_advanced, ZSTD_DCtx_loadDictionary_byReference,
335        ZSTD_DCtx_refDDict, ZSTD_DCtx_refPrefix, ZSTD_DCtx_refPrefix_advanced, ZSTD_DCtx_reset,
336        ZSTD_DCtx_setFormat, ZSTD_DCtx_setMaxWindowSize, ZSTD_DCtx_setParameter,
337        ZSTD_DResetDirective, ZSTD_DStream, ZSTD_DStreamInSize, ZSTD_DStreamOutSize,
338        ZSTD_FrameHeader, ZSTD_FrameType_e, ZSTD_copyDCtx, ZSTD_createDCtx, ZSTD_createDStream,
339        ZSTD_dParam_getBounds, ZSTD_dParam_withinBounds, ZSTD_dParameter,
340        ZSTD_decodingBufferSize_min, ZSTD_decompress, ZSTD_decompressBound, ZSTD_decompressDCtx,
341        ZSTD_decompressStream, ZSTD_decompressStream_simpleArgs, ZSTD_decompress_usingDDict,
342        ZSTD_decompress_usingDict, ZSTD_decompressionMargin, ZSTD_dictUses_e,
343        ZSTD_estimateDCtxSize, ZSTD_estimateDStreamSize, ZSTD_estimateDStreamSize_fromFrame,
344        ZSTD_findDecompressedSize, ZSTD_findFrameCompressedSize,
345        ZSTD_findFrameCompressedSize_advanced, ZSTD_findFrameSizeInfo, ZSTD_format_e,
346        ZSTD_frameHeaderSize, ZSTD_frameSizeInfo, ZSTD_freeDCtx, ZSTD_freeDStream,
347        ZSTD_getDecompressedSize, ZSTD_getDictID_fromFrame, ZSTD_getFrameContentSize,
348        ZSTD_getFrameHeader, ZSTD_getFrameHeader_advanced, ZSTD_initDStream,
349        ZSTD_initDStream_usingDDict, ZSTD_initDStream_usingDict, ZSTD_isFrame,
350        ZSTD_isSkippableFrame, ZSTD_nextSrcSizeToDecompress, ZSTD_readSkippableFrame,
351        ZSTD_resetDStream, ZSTD_sizeof_DCtx, ZSTD_sizeof_DStream, ZSTD_CONTENTSIZE_ERROR,
352        ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_DECOMPRESSION_MARGIN, ZSTD_FRAMEHEADERSIZE_MIN,
353        ZSTD_FRAMEHEADERSIZE_PREFIX, ZSTD_FRAMEIDSIZE, ZSTD_MAGICNUMBER, ZSTD_MAGIC_DICTIONARY,
354        ZSTD_MAGIC_SKIPPABLE_MASK, ZSTD_MAGIC_SKIPPABLE_START, ZSTD_SKIPPABLEHEADERSIZE,
355        ZSTD_WINDOWLOG_ABSOLUTEMIN, ZSTD_WINDOWLOG_LIMIT_DEFAULT, ZSTD_WINDOWLOG_MAX_32,
356        ZSTD_WINDOWLOG_MAX_64,
357    };
358    pub use crate::decompress::zstd_decompress_block::{
359        ZSTD_BLOCKHEADERSIZE, ZSTD_BLOCKSIZELOG_MAX, ZSTD_BLOCKSIZE_MAX,
360    };
361    // Decompress-side legacy block-level + static-init API stubs.
362    pub use crate::decompress::zstd_ddict::{
363        ZSTD_DDict, ZSTD_DDict_dictContent, ZSTD_DDict_dictSize, ZSTD_copyDDictParameters,
364        ZSTD_createDDict, ZSTD_createDDict_advanced, ZSTD_createDDict_byReference,
365        ZSTD_dictContentType_e, ZSTD_dictLoadMethod_e, ZSTD_estimateDDictSize, ZSTD_freeDDict,
366        ZSTD_getDictID_fromDDict, ZSTD_getDictID_fromDict, ZSTD_sizeof_DDict,
367    };
368    pub use crate::decompress::zstd_decompress::{
369        ZSTD_createDCtx_advanced, ZSTD_createDStream_advanced, ZSTD_decompressBegin,
370        ZSTD_decompressBegin_usingDDict, ZSTD_decompressBegin_usingDict, ZSTD_decompressBlock,
371        ZSTD_decompressBlock_deprecated, ZSTD_decompressContinue, ZSTD_initStaticDCtx,
372        ZSTD_initStaticDDict, ZSTD_initStaticDStream, ZSTD_insertBlock, ZSTD_nextInputType,
373        ZSTD_nextInputType_e,
374    };
375    // Error handling.
376    pub use crate::common::error::{ERR_getErrorName, ERR_isError, ErrorCode, ZstdError};
377    // Thread pool API.
378    #[cfg(feature = "std")]
379    pub use crate::common::pool::{POOL_ctx, ZSTD_createThreadPool, ZSTD_freeThreadPool};
380    #[cfg(feature = "std")]
381    pub use crate::ZSTD_threadPool;
382    pub use crate::{
383        ZSTD_c_blockDelimiters, ZSTD_c_blockSplitterLevel, ZSTD_c_deterministicRefPrefix,
384        ZSTD_c_enableDedicatedDictSearch, ZSTD_c_enableSeqProducerFallback, ZSTD_c_forceAttachDict,
385        ZSTD_c_forceMaxWindow, ZSTD_c_format, ZSTD_c_literalCompressionMode, ZSTD_c_maxBlockSize,
386        ZSTD_c_prefetchCDictTables, ZSTD_c_repcodeResolution, ZSTD_c_rsyncable,
387        ZSTD_c_searchForExternalRepcodes, ZSTD_c_splitAfterSequences, ZSTD_c_srcSizeHint,
388        ZSTD_c_stableInBuffer, ZSTD_c_stableOutBuffer, ZSTD_c_useRowMatchFinder,
389        ZSTD_c_validateSequences, ZSTD_d_forceIgnoreChecksum, ZSTD_d_format, ZSTD_frameHeader,
390        ZSTD_frameParameters, ZSTD_frameType_e, ZSTD_paramSwitch_e, ZSTD_sequenceFormat_e,
391        ZSTD_BLOCKSPLITTER_LEVEL_MAX, ZSTD_SEQUENCE_PRODUCER_ERROR,
392    };
393    // Version + determinism helpers.
394    pub use crate::common::zstd_common::{
395        ZSTD_getErrorCode, ZSTD_getErrorName, ZSTD_getErrorString, ZSTD_isDeterministicBuild,
396        ZSTD_isError, ZSTD_versionNumber, ZSTD_versionString, ZSTD_VERSION_MAJOR,
397        ZSTD_VERSION_MINOR, ZSTD_VERSION_NUMBER, ZSTD_VERSION_RELEASE, ZSTD_VERSION_STRING,
398    };
399}
400
401#[cfg(test)]
402mod prelude_tests {
403    use crate::prelude::*;
404
405    #[test]
406    fn prelude_exposes_common_compress_decompress_flow() {
407        let src = b"prelude smoke test. ".repeat(50);
408        let mut dst = vec![0u8; ZSTD_compressBound(src.len())];
409        let n = ZSTD_compress(&mut dst, &src, 1);
410        assert!(!ERR_isError(n));
411        dst.truncate(n);
412        let mut out = vec![0u8; src.len() + 64];
413        let d = ZSTD_decompress(&mut out, &dst);
414        assert_eq!(&out[..d], &src[..]);
415    }
416
417    #[test]
418    fn prelude_exposes_api_types_and_version_helpers() {
419        // Version + error helpers reachable through prelude.
420        // The concrete string literal is pinned in `ZSTD_VERSION_STRING`;
421        // see the unit test in `zstd_common` for that gate.
422        assert_eq!(ZSTD_versionString(), ZSTD_VERSION_STRING);
423        assert_eq!(ZSTD_versionNumber(), ZSTD_VERSION_NUMBER);
424        assert_eq!(ZSTD_isDeterministicBuild(), 1);
425        assert!(!ZSTD_isError(0));
426
427        // Error-code round-trip.
428        use crate::common::error::ERROR;
429        let e = ERROR(ErrorCode::DstSizeTooSmall);
430        assert_eq!(ZSTD_getErrorCode(e), ErrorCode::DstSizeTooSmall);
431        let s1 = ZSTD_getErrorString(ErrorCode::DstSizeTooSmall);
432        let s2 = ZSTD_getErrorName(e);
433        assert_eq!(s1, s2);
434
435        // Type names reachable.
436        let _: Option<ZSTD_nextInputType_e> = None;
437        let _: Option<ZSTD_dictUses_e> = None;
438        let _: Option<ZSTD_dictContentType_e> = None;
439        let _: Option<ZSTD_dictLoadMethod_e> = None;
440        let _: Option<ZSTD_format_e> = None;
441        let _: Option<ZSTD_EndDirective> = None;
442        let _: Option<ZSTD_ResetDirective> = None;
443        let _: Option<ZSTD_DResetDirective> = None;
444        let _: Option<ZSTD_FrameParameters> = None;
445        let _: Option<ZSTD_parameters> = None;
446        let _: Option<ZSTD_FrameHeader> = None;
447        let _: Option<ZSTD_frameHeader> = None;
448        let _: Option<ZSTD_frameProgression> = None;
449        let _: Option<ZSTD_Sequence> = None;
450        let _: Option<ZSTD_sequenceFormat_e> = None;
451        let _: Option<ZSTD_DCtx> = None;
452        let _: Option<ZSTD_inBuffer<'static>> = None;
453        let _: Option<ZSTD_outBuffer<'static>> = None;
454        let _: Option<ZSTD_customMem> = None;
455        let _: Option<ZSTD_allocFunction> = None;
456        let _: Option<ZSTD_freeFunction> = None;
457        let _: Option<ZSTD_sequenceProducer_F> = None;
458        let _: Option<ZSTD_forceIgnoreChecksum_e> = None;
459        let _: Option<ZSTD_refMultipleDDicts_e> = None;
460        let _: Option<ZSTD_dictAttachPref_e> = None;
461        let _: Option<ZSTD_literalCompressionMode_e> = None;
462        let _: Option<ZSTD_paramSwitch_e> = None;
463        let _: Option<ZSTD_strategy> = None;
464        let _: Option<ErrorCode> = None;
465
466        // Upstream's public block-level helper takes a compression context.
467        let _: fn(&ZSTD_CCtx) -> usize = ZSTD_getBlockSize;
468    }
469
470    #[test]
471    fn crate_root_exposes_common_public_helpers() {
472        use crate::common::error::ERROR;
473
474        assert_eq!(crate::ZSTD_versionString(), crate::ZSTD_VERSION_STRING);
475        assert_eq!(crate::ZSTD_versionNumber(), crate::ZSTD_VERSION_NUMBER);
476        assert_eq!(crate::ZSTD_VERSION_MAJOR, 1);
477        assert_eq!(crate::ZSTD_VERSION_MINOR, 6);
478        assert_eq!(crate::ZSTD_VERSION_RELEASE, 0);
479        assert_eq!(crate::ZSTD_isDeterministicBuild(), 1);
480        assert!(!crate::ZSTD_isError(0));
481
482        let e = ERROR(crate::ErrorCode::DstSizeTooSmall);
483        assert_eq!(
484            crate::ZSTD_getErrorCode(e),
485            crate::ErrorCode::DstSizeTooSmall
486        );
487        assert_eq!(
488            crate::ZSTD_getErrorName(e),
489            crate::ZSTD_getErrorString(crate::ErrorCode::DstSizeTooSmall)
490        );
491    }
492
493    #[test]
494    fn prelude_exposes_new_helpers() {
495        // Touch the recently-added entry points to make sure they're
496        // reachable from the public prelude.
497        let src = b"prelude extended touch".to_vec();
498        let mut dst = vec![0u8; 256];
499        let mut cctx = ZSTD_createCCtx().unwrap();
500        // No level set — ZSTD_compress2 must default to CLEVEL_DEFAULT.
501        let n = ZSTD_compress2(&mut cctx, &mut dst, &src);
502        assert!(!ERR_isError(n), "compress2 err={n:#x}");
503        dst.truncate(n);
504
505        // Frame-level queries
506        let b = ZSTD_decompressBound(&dst);
507        assert!(b >= src.len() as u64);
508        let _ = ZSTD_decompressionMargin(&dst);
509        let _ = ZSTD_getDecompressedSize(&dst);
510        let _ = ZSTD_sequenceBound(1024);
511        let _compress_sequences_and_literals: fn(
512            &mut ZSTD_CCtx,
513            &mut [u8],
514            &[ZSTD_Sequence],
515            &[u8],
516            usize,
517            usize,
518        ) -> usize = ZSTD_compressSequencesAndLiterals;
519
520        // Skippable frames
521        let mut skip = vec![0u8; 16];
522        ZSTD_writeSkippableFrame(&mut skip, b"meta", 3);
523        let mut out = vec![0u8; 16];
524        let mut v = 0u32;
525        ZSTD_readSkippableFrame(&mut out, Some(&mut v), &skip);
526        assert_eq!(v, 3);
527    }
528
529    #[test]
530    fn prelude_exposes_upstream_static_aliases_and_constants() {
531        assert_eq!(ZSTD_frameType_e::ZSTD_frame as u32, 0);
532        assert_eq!(ZSTD_FrameType_e::ZSTD_skippableFrame as u32, 1);
533        assert_eq!(ZSTD_fast, 1);
534        assert_eq!(ZSTD_dfast, 2);
535        assert_eq!(ZSTD_greedy, 3);
536        assert_eq!(ZSTD_lazy, 4);
537        assert_eq!(ZSTD_lazy2, 5);
538        assert_eq!(ZSTD_btlazy2, 6);
539        assert_eq!(ZSTD_btopt, 7);
540        assert_eq!(ZSTD_btultra, 8);
541        assert_eq!(ZSTD_btultra2, 9);
542        assert_eq!(ZSTD_STRATEGY_MIN, ZSTD_fast);
543        assert_eq!(ZSTD_STRATEGY_MAX, ZSTD_btultra2);
544        assert_eq!(ZSTD_BLOCKSPLITTER_LEVEL_MAX, 6);
545        assert_eq!(ZSTD_SEQUENCE_PRODUCER_ERROR, usize::MAX);
546        assert_eq!(ZSTD_MAGIC_DICTIONARY, 0xEC30A437);
547        assert_eq!(ZSTD_MAGIC_SKIPPABLE_MASK, 0xFFFFFFF0);
548        assert_eq!(ZSTD_COMPRESSBOUND(1024), ZSTD_compressBound(1024));
549        assert_eq!(ZSTD_BLOCKSIZE_MAX_MIN, 1 << 10);
550        assert_eq!(ZSTD_DECOMPRESSION_MARGIN(0, 1024), 1046);
551        assert_eq!(ZSTD_FRAMEHEADERSIZE_PREFIX(ZSTD_format_e::ZSTD_f_zstd1), 5);
552        assert_eq!(ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_format_e::ZSTD_f_zstd1), 6);
553        assert_eq!(ZSTD_c_format, ZSTD_cParameter::ZSTD_c_format);
554        assert_eq!(ZSTD_c_rsyncable, ZSTD_cParameter::ZSTD_c_rsyncable);
555        assert_eq!(
556            ZSTD_c_forceMaxWindow,
557            ZSTD_cParameter::ZSTD_c_forceMaxWindow
558        );
559        assert_eq!(
560            ZSTD_c_forceAttachDict,
561            ZSTD_cParameter::ZSTD_c_forceAttachDict
562        );
563        assert_eq!(
564            ZSTD_c_literalCompressionMode,
565            ZSTD_cParameter::ZSTD_c_literalCompressionMode
566        );
567        assert_eq!(ZSTD_c_srcSizeHint, ZSTD_cParameter::ZSTD_c_srcSizeHint);
568        assert_eq!(
569            ZSTD_c_enableDedicatedDictSearch,
570            ZSTD_cParameter::ZSTD_c_enableDedicatedDictSearch
571        );
572        assert_eq!(
573            ZSTD_c_stableInBuffer,
574            ZSTD_cParameter::ZSTD_c_stableInBuffer
575        );
576        assert_eq!(
577            ZSTD_c_stableOutBuffer,
578            ZSTD_cParameter::ZSTD_c_stableOutBuffer
579        );
580        assert_eq!(
581            ZSTD_c_blockDelimiters,
582            ZSTD_cParameter::ZSTD_c_blockDelimiters
583        );
584        assert_eq!(
585            ZSTD_c_validateSequences,
586            ZSTD_cParameter::ZSTD_c_validateSequences
587        );
588        assert_eq!(
589            ZSTD_c_splitAfterSequences,
590            ZSTD_cParameter::ZSTD_c_splitAfterSequences
591        );
592        assert_eq!(
593            ZSTD_c_useRowMatchFinder,
594            ZSTD_cParameter::ZSTD_c_useRowMatchFinder
595        );
596        assert_eq!(
597            ZSTD_c_deterministicRefPrefix,
598            ZSTD_cParameter::ZSTD_c_deterministicRefPrefix
599        );
600        assert_eq!(
601            ZSTD_c_prefetchCDictTables,
602            ZSTD_cParameter::ZSTD_c_prefetchCDictTables
603        );
604        assert_eq!(
605            ZSTD_c_blockSplitterLevel,
606            ZSTD_cParameter::ZSTD_c_blockSplitterLevel
607        );
608        assert_eq!(
609            ZSTD_c_enableSeqProducerFallback,
610            ZSTD_cParameter::ZSTD_c_enableSeqProducerFallback
611        );
612        assert_eq!(ZSTD_c_maxBlockSize, ZSTD_cParameter::ZSTD_c_maxBlockSize);
613        assert_eq!(
614            ZSTD_c_repcodeResolution,
615            ZSTD_cParameter::ZSTD_c_repcodeResolution
616        );
617        assert_eq!(
618            ZSTD_c_searchForExternalRepcodes,
619            ZSTD_cParameter::ZSTD_c_repcodeResolution
620        );
621        assert_eq!(ZSTD_d_format, ZSTD_dParameter::ZSTD_d_format);
622        assert_eq!(
623            ZSTD_d_forceIgnoreChecksum,
624            ZSTD_dParameter::ZSTD_d_forceIgnoreChecksum
625        );
626    }
627
628    #[test]
629    fn prelude_exposes_format_helpers() {
630        // The format-aware surface lives behind `*_advanced` + the new
631        // `ZSTD_{C,D}Ctx_setFormat` helpers; verify the prelude
632        // re-exports them so downstream crates don't have to reach
633        // into module paths.
634        let mut cctx = ZSTD_createCCtx().unwrap();
635        let mut dctx = ZSTD_createDCtx();
636        assert_eq!(
637            ZSTD_CCtx_setFormat(&mut cctx, ZSTD_format_e::ZSTD_f_zstd1_magicless),
638            ZSTD_format_e::ZSTD_f_zstd1_magicless as usize,
639        );
640        assert_eq!(
641            ZSTD_DCtx_setFormat(&mut dctx, ZSTD_format_e::ZSTD_f_zstd1_magicless),
642            0,
643        );
644        // Parametric bounds getter reachable.
645        let cb = ZSTD_cParam_getBounds(ZSTD_cParameter::ZSTD_c_format);
646        assert_eq!(cb.upperBound, ZSTD_format_e::ZSTD_f_zstd1_magicless as i32);
647        let db = ZSTD_dParam_getBounds(ZSTD_dParameter::ZSTD_d_format);
648        assert_eq!(db.upperBound, ZSTD_format_e::ZSTD_f_zstd1_magicless as i32);
649        // `_advanced` variants for measurement + header parsing.
650        let mut frame = vec![0u8; 64];
651        let hdrSize = ZSTD_writeFrameHeader_advanced(
652            &mut frame,
653            &ZSTD_FrameParameters {
654                contentSizeFlag: 0,
655                checksumFlag: 0,
656                noDictIDFlag: 1,
657            },
658            15,
659            0,
660            0,
661            ZSTD_format_e::ZSTD_f_zstd1_magicless,
662        );
663        assert!(!ERR_isError(hdrSize));
664    }
665}