#![no_std]
#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
#[cfg(feature = "std")]
extern crate std;
#[cfg(test)]
mod tests;
#[cfg(feature = "seekable")]
pub mod seekable;
pub use zstd_sys;
pub use zstd_sys::ZSTD_strategy as Strategy;
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub use zstd_sys::ZSTD_frameProgression as FrameProgression;
use core::ffi::{c_char, c_int, c_ulonglong, c_void};
use core::marker::PhantomData;
use core::num::{NonZeroU32, NonZeroU64};
use core::ops::{Deref, DerefMut};
use core::ptr::NonNull;
use core::str;
include!("constants.rs");
#[cfg(feature = "experimental")]
include!("constants_experimental.rs");
#[cfg(feature = "seekable")]
include!("constants_seekable.rs");
pub type CompressionLevel = i32;
pub type ErrorCode = usize;
pub type SafeResult = Result<usize, ErrorCode>;
#[derive(Debug)]
pub struct ContentSizeError;
impl core::fmt::Display for ContentSizeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("Could not get content size")
}
}
fn is_error(code: usize) -> bool {
unsafe { zstd_sys::ZSTD_isError(code) != 0 }
}
fn parse_code(code: usize) -> SafeResult {
if !is_error(code) {
Ok(code)
} else {
Err(code)
}
}
fn parse_content_size(
content_size: u64,
) -> Result<Option<u64>, ContentSizeError> {
match content_size {
CONTENTSIZE_ERROR => Err(ContentSizeError),
CONTENTSIZE_UNKNOWN => Ok(None),
other => Ok(Some(other)),
}
}
fn ptr_void(src: &[u8]) -> *const c_void {
src.as_ptr() as *const c_void
}
fn ptr_mut_void(dst: &mut (impl WriteBuf + ?Sized)) -> *mut c_void {
dst.as_mut_ptr() as *mut c_void
}
pub fn version_number() -> u32 {
unsafe { zstd_sys::ZSTD_versionNumber() as u32 }
}
pub fn version_string() -> &'static str {
unsafe { c_char_to_str(zstd_sys::ZSTD_versionString()) }
}
pub fn min_c_level() -> CompressionLevel {
unsafe { zstd_sys::ZSTD_minCLevel() as CompressionLevel }
}
pub fn max_c_level() -> CompressionLevel {
unsafe { zstd_sys::ZSTD_maxCLevel() as CompressionLevel }
}
pub fn compress<C: WriteBuf + ?Sized>(
dst: &mut C,
src: &[u8],
compression_level: CompressionLevel,
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compress(
buffer,
capacity,
ptr_void(src),
src.len(),
compression_level,
))
})
}
}
pub fn decompress<C: WriteBuf + ?Sized>(
dst: &mut C,
src: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_decompress(
buffer,
capacity,
ptr_void(src),
src.len(),
))
})
}
}
#[deprecated(note = "Use ZSTD_getFrameContentSize instead")]
pub fn get_decompressed_size(src: &[u8]) -> Option<NonZeroU64> {
NonZeroU64::new(unsafe {
zstd_sys::ZSTD_getDecompressedSize(ptr_void(src), src.len()) as u64
})
}
pub fn compress_bound(src_size: usize) -> usize {
unsafe { zstd_sys::ZSTD_compressBound(src_size) }
}
pub struct CCtx<'a>(NonNull<zstd_sys::ZSTD_CCtx>, PhantomData<&'a ()>);
impl Default for CCtx<'_> {
fn default() -> Self {
CCtx::create()
}
}
impl<'a> CCtx<'a> {
pub fn try_create() -> Option<Self> {
Some(CCtx(
NonNull::new(unsafe { zstd_sys::ZSTD_createCCtx() })?,
PhantomData,
))
}
pub fn create() -> Self {
Self::try_create()
.expect("zstd returned null pointer when creating new context")
}
pub fn compress<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
compression_level: CompressionLevel,
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compressCCtx(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
compression_level,
))
})
}
}
pub fn compress2<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compress2(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
))
})
}
}
pub fn compress_using_dict<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
dict: &[u8],
compression_level: CompressionLevel,
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compress_usingDict(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
ptr_void(dict),
dict.len(),
compression_level,
))
})
}
}
pub fn compress_using_cdict<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
cdict: &CDict<'_>,
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compress_usingCDict(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
cdict.0.as_ptr(),
))
})
}
}
pub fn init(&mut self, compression_level: CompressionLevel) -> SafeResult {
let code = unsafe {
zstd_sys::ZSTD_initCStream(self.0.as_ptr(), compression_level)
};
parse_code(code)
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[deprecated]
pub fn init_src_size(
&mut self,
compression_level: CompressionLevel,
pledged_src_size: u64,
) -> SafeResult {
let code = unsafe {
zstd_sys::ZSTD_initCStream_srcSize(
self.0.as_ptr(),
compression_level as c_int,
pledged_src_size as c_ulonglong,
)
};
parse_code(code)
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[deprecated]
pub fn init_using_dict(
&mut self,
dict: &[u8],
compression_level: CompressionLevel,
) -> SafeResult {
let code = unsafe {
zstd_sys::ZSTD_initCStream_usingDict(
self.0.as_ptr(),
ptr_void(dict),
dict.len(),
compression_level,
)
};
parse_code(code)
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[deprecated]
pub fn init_using_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
where
'b: 'a, {
let code = unsafe {
zstd_sys::ZSTD_initCStream_usingCDict(
self.0.as_ptr(),
cdict.0.as_ptr(),
)
};
parse_code(code)
}
pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_loadDictionary(
self.0.as_ptr(),
ptr_void(dict),
dict.len(),
)
})
}
pub fn ref_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
where
'b: 'a,
{
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_refCDict(self.0.as_ptr(), cdict.0.as_ptr())
})
}
pub fn disable_dictionary(&mut self) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_loadDictionary(
self.0.as_ptr(),
core::ptr::null(),
0,
)
})
}
pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
where
'b: 'a,
{
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_refPrefix(
self.0.as_ptr(),
ptr_void(prefix),
prefix.len(),
)
})
}
pub fn compress_stream<C: WriteBuf + ?Sized>(
&mut self,
output: &mut OutBuffer<'_, C>,
input: &mut InBuffer<'_>,
) -> SafeResult {
let mut output = output.wrap();
let mut input = input.wrap();
let code = unsafe {
zstd_sys::ZSTD_compressStream(
self.0.as_ptr(),
ptr_mut(&mut output),
ptr_mut(&mut input),
)
};
parse_code(code)
}
pub fn compress_stream2<C: WriteBuf + ?Sized>(
&mut self,
output: &mut OutBuffer<'_, C>,
input: &mut InBuffer<'_>,
end_op: zstd_sys::ZSTD_EndDirective,
) -> SafeResult {
let mut output = output.wrap();
let mut input = input.wrap();
parse_code(unsafe {
zstd_sys::ZSTD_compressStream2(
self.0.as_ptr(),
ptr_mut(&mut output),
ptr_mut(&mut input),
end_op,
)
})
}
pub fn flush_stream<C: WriteBuf + ?Sized>(
&mut self,
output: &mut OutBuffer<'_, C>,
) -> SafeResult {
let mut output = output.wrap();
let code = unsafe {
zstd_sys::ZSTD_flushStream(self.0.as_ptr(), ptr_mut(&mut output))
};
parse_code(code)
}
pub fn end_stream<C: WriteBuf + ?Sized>(
&mut self,
output: &mut OutBuffer<'_, C>,
) -> SafeResult {
let mut output = output.wrap();
let code = unsafe {
zstd_sys::ZSTD_endStream(self.0.as_ptr(), ptr_mut(&mut output))
};
parse_code(code)
}
pub fn sizeof(&self) -> usize {
unsafe { zstd_sys::ZSTD_sizeof_CCtx(self.0.as_ptr()) }
}
pub fn reset(&mut self, reset: ResetDirective) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_reset(self.0.as_ptr(), reset.as_sys())
})
}
pub fn set_parameter(&mut self, param: CParameter) -> SafeResult {
#[cfg(feature = "experimental")]
use zstd_sys::ZSTD_cParameter::{
ZSTD_c_experimentalParam1 as ZSTD_c_rsyncable,
ZSTD_c_experimentalParam10 as ZSTD_c_stableOutBuffer,
ZSTD_c_experimentalParam11 as ZSTD_c_blockDelimiters,
ZSTD_c_experimentalParam12 as ZSTD_c_validateSequences,
ZSTD_c_experimentalParam13 as ZSTD_c_useBlockSplitter,
ZSTD_c_experimentalParam14 as ZSTD_c_useRowMatchFinder,
ZSTD_c_experimentalParam15 as ZSTD_c_deterministicRefPrefix,
ZSTD_c_experimentalParam16 as ZSTD_c_prefetchCDictTables,
ZSTD_c_experimentalParam17 as ZSTD_c_enableSeqProducerFallback,
ZSTD_c_experimentalParam18 as ZSTD_c_maxBlockSize,
ZSTD_c_experimentalParam19 as ZSTD_c_searchForExternalRepcodes,
ZSTD_c_experimentalParam2 as ZSTD_c_format,
ZSTD_c_experimentalParam3 as ZSTD_c_forceMaxWindow,
ZSTD_c_experimentalParam4 as ZSTD_c_forceAttachDict,
ZSTD_c_experimentalParam5 as ZSTD_c_literalCompressionMode,
ZSTD_c_experimentalParam7 as ZSTD_c_srcSizeHint,
ZSTD_c_experimentalParam8 as ZSTD_c_enableDedicatedDictSearch,
ZSTD_c_experimentalParam9 as ZSTD_c_stableInBuffer,
};
use zstd_sys::ZSTD_cParameter::*;
use CParameter::*;
let (param, value) = match param {
#[cfg(feature = "experimental")]
RSyncable(rsyncable) => (ZSTD_c_rsyncable, rsyncable as c_int),
#[cfg(feature = "experimental")]
Format(format) => (ZSTD_c_format, format as c_int),
#[cfg(feature = "experimental")]
ForceMaxWindow(force) => (ZSTD_c_forceMaxWindow, force as c_int),
#[cfg(feature = "experimental")]
ForceAttachDict(force) => (ZSTD_c_forceAttachDict, force as c_int),
#[cfg(feature = "experimental")]
LiteralCompressionMode(mode) => {
(ZSTD_c_literalCompressionMode, mode as c_int)
}
#[cfg(feature = "experimental")]
SrcSizeHint(value) => (ZSTD_c_srcSizeHint, value as c_int),
#[cfg(feature = "experimental")]
EnableDedicatedDictSearch(enable) => {
(ZSTD_c_enableDedicatedDictSearch, enable as c_int)
}
#[cfg(feature = "experimental")]
StableInBuffer(stable) => (ZSTD_c_stableInBuffer, stable as c_int),
#[cfg(feature = "experimental")]
StableOutBuffer(stable) => {
(ZSTD_c_stableOutBuffer, stable as c_int)
}
#[cfg(feature = "experimental")]
BlockDelimiters(value) => (ZSTD_c_blockDelimiters, value as c_int),
#[cfg(feature = "experimental")]
ValidateSequences(validate) => {
(ZSTD_c_validateSequences, validate as c_int)
}
#[cfg(feature = "experimental")]
UseBlockSplitter(split) => {
(ZSTD_c_useBlockSplitter, split as c_int)
}
#[cfg(feature = "experimental")]
UseRowMatchFinder(mode) => {
(ZSTD_c_useRowMatchFinder, mode as c_int)
}
#[cfg(feature = "experimental")]
DeterministicRefPrefix(deterministic) => {
(ZSTD_c_deterministicRefPrefix, deterministic as c_int)
}
#[cfg(feature = "experimental")]
PrefetchCDictTables(prefetch) => {
(ZSTD_c_prefetchCDictTables, prefetch as c_int)
}
#[cfg(feature = "experimental")]
EnableSeqProducerFallback(enable) => {
(ZSTD_c_enableSeqProducerFallback, enable as c_int)
}
#[cfg(feature = "experimental")]
MaxBlockSize(value) => (ZSTD_c_maxBlockSize, value as c_int),
#[cfg(feature = "experimental")]
SearchForExternalRepcodes(value) => {
(ZSTD_c_searchForExternalRepcodes, value as c_int)
}
TargetCBlockSize(value) => {
(ZSTD_c_targetCBlockSize, value as c_int)
}
CompressionLevel(level) => (ZSTD_c_compressionLevel, level),
WindowLog(value) => (ZSTD_c_windowLog, value as c_int),
HashLog(value) => (ZSTD_c_hashLog, value as c_int),
ChainLog(value) => (ZSTD_c_chainLog, value as c_int),
SearchLog(value) => (ZSTD_c_searchLog, value as c_int),
MinMatch(value) => (ZSTD_c_minMatch, value as c_int),
TargetLength(value) => (ZSTD_c_targetLength, value as c_int),
Strategy(strategy) => (ZSTD_c_strategy, strategy as c_int),
EnableLongDistanceMatching(flag) => {
(ZSTD_c_enableLongDistanceMatching, flag as c_int)
}
LdmHashLog(value) => (ZSTD_c_ldmHashLog, value as c_int),
LdmMinMatch(value) => (ZSTD_c_ldmMinMatch, value as c_int),
LdmBucketSizeLog(value) => {
(ZSTD_c_ldmBucketSizeLog, value as c_int)
}
LdmHashRateLog(value) => (ZSTD_c_ldmHashRateLog, value as c_int),
ContentSizeFlag(flag) => (ZSTD_c_contentSizeFlag, flag as c_int),
ChecksumFlag(flag) => (ZSTD_c_checksumFlag, flag as c_int),
DictIdFlag(flag) => (ZSTD_c_dictIDFlag, flag as c_int),
NbWorkers(value) => (ZSTD_c_nbWorkers, value as c_int),
JobSize(value) => (ZSTD_c_jobSize, value as c_int),
OverlapSizeLog(value) => (ZSTD_c_overlapLog, value as c_int),
};
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_setParameter(self.0.as_ptr(), param, value)
})
}
pub fn set_pledged_src_size(
&mut self,
pledged_src_size: Option<u64>,
) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_setPledgedSrcSize(
self.0.as_ptr(),
pledged_src_size.unwrap_or(CONTENTSIZE_UNKNOWN) as c_ulonglong,
)
})
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn try_clone(
&self,
pledged_src_size: Option<u64>,
) -> Result<Self, ErrorCode> {
let context = NonNull::new(unsafe { zstd_sys::ZSTD_createCCtx() })
.ok_or(0usize)?;
parse_code(unsafe {
zstd_sys::ZSTD_copyCCtx(
context.as_ptr(),
self.0.as_ptr(),
pledged_src_size.unwrap_or(CONTENTSIZE_UNKNOWN),
)
})?;
Ok(CCtx(context, self.1))
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn get_block_size(&self) -> usize {
unsafe { zstd_sys::ZSTD_getBlockSize(self.0.as_ptr()) }
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn compress_block<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_compressBlock(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
))
})
}
}
pub fn in_size() -> usize {
unsafe { zstd_sys::ZSTD_CStreamInSize() }
}
pub fn out_size() -> usize {
unsafe { zstd_sys::ZSTD_CStreamOutSize() }
}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
pub fn ref_thread_pool<'b>(&mut self, pool: &'b ThreadPool) -> SafeResult
where
'b: 'a,
{
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_refThreadPool(self.0.as_ptr(), pool.0.as_ptr())
})
}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
pub fn disable_thread_pool(&mut self) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_CCtx_refThreadPool(
self.0.as_ptr(),
core::ptr::null_mut(),
)
})
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn get_frame_progression(&self) -> FrameProgression {
unsafe { zstd_sys::ZSTD_getFrameProgression(self.0.as_ptr()) }
}
}
impl<'a> Drop for CCtx<'a> {
fn drop(&mut self) {
unsafe {
zstd_sys::ZSTD_freeCCtx(self.0.as_ptr());
}
}
}
unsafe impl Send for CCtx<'_> {}
unsafe impl Sync for CCtx<'_> {}
unsafe fn c_char_to_str(text: *const c_char) -> &'static str {
core::ffi::CStr::from_ptr(text)
.to_str()
.expect("bad error message from zstd")
}
pub fn get_error_name(code: usize) -> &'static str {
unsafe {
let name = zstd_sys::ZSTD_getErrorName(code);
c_char_to_str(name)
}
}
pub struct DCtx<'a>(NonNull<zstd_sys::ZSTD_DCtx>, PhantomData<&'a ()>);
impl Default for DCtx<'_> {
fn default() -> Self {
DCtx::create()
}
}
impl<'a> DCtx<'a> {
pub fn try_create() -> Option<Self> {
Some(DCtx(
NonNull::new(unsafe { zstd_sys::ZSTD_createDCtx() })?,
PhantomData,
))
}
pub fn create() -> Self {
Self::try_create()
.expect("zstd returned null pointer when creating new context")
}
pub fn decompress<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_decompressDCtx(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
))
})
}
}
pub fn decompress_using_dict<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
dict: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_decompress_usingDict(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
ptr_void(dict),
dict.len(),
))
})
}
}
pub fn decompress_using_ddict<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
ddict: &DDict<'_>,
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_decompress_usingDDict(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
ddict.0.as_ptr(),
))
})
}
}
pub fn init(&mut self) -> SafeResult {
let code = unsafe { zstd_sys::ZSTD_initDStream(self.0.as_ptr()) };
parse_code(code)
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[deprecated]
pub fn init_using_dict(&mut self, dict: &[u8]) -> SafeResult {
let code = unsafe {
zstd_sys::ZSTD_initDStream_usingDict(
self.0.as_ptr(),
ptr_void(dict),
dict.len(),
)
};
parse_code(code)
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[deprecated]
pub fn init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
where
'b: 'a,
{
let code = unsafe {
zstd_sys::ZSTD_initDStream_usingDDict(
self.0.as_ptr(),
ddict.0.as_ptr(),
)
};
parse_code(code)
}
pub fn reset(&mut self, reset: ResetDirective) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_reset(self.0.as_ptr(), reset.as_sys())
})
}
pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_loadDictionary(
self.0.as_ptr(),
ptr_void(dict),
dict.len(),
)
})
}
pub fn disable_dictionary(&mut self) -> SafeResult {
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_loadDictionary(
self.0.as_ptr(),
core::ptr::null(),
0,
)
})
}
pub fn ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
where
'b: 'a,
{
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_refDDict(self.0.as_ptr(), ddict.0.as_ptr())
})
}
pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
where
'b: 'a,
{
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_refPrefix(
self.0.as_ptr(),
ptr_void(prefix),
prefix.len(),
)
})
}
pub fn set_parameter(&mut self, param: DParameter) -> SafeResult {
#[cfg(feature = "experimental")]
use zstd_sys::ZSTD_dParameter::{
ZSTD_d_experimentalParam1 as ZSTD_d_format,
ZSTD_d_experimentalParam2 as ZSTD_d_stableOutBuffer,
ZSTD_d_experimentalParam3 as ZSTD_d_forceIgnoreChecksum,
ZSTD_d_experimentalParam4 as ZSTD_d_refMultipleDDicts,
};
use zstd_sys::ZSTD_dParameter::*;
use DParameter::*;
let (param, value) = match param {
#[cfg(feature = "experimental")]
Format(format) => (ZSTD_d_format, format as c_int),
#[cfg(feature = "experimental")]
StableOutBuffer(stable) => {
(ZSTD_d_stableOutBuffer, stable as c_int)
}
#[cfg(feature = "experimental")]
ForceIgnoreChecksum(force) => {
(ZSTD_d_forceIgnoreChecksum, force as c_int)
}
#[cfg(feature = "experimental")]
RefMultipleDDicts(value) => {
(ZSTD_d_refMultipleDDicts, value as c_int)
}
WindowLogMax(value) => (ZSTD_d_windowLogMax, value as c_int),
};
parse_code(unsafe {
zstd_sys::ZSTD_DCtx_setParameter(self.0.as_ptr(), param, value)
})
}
pub fn decompress_stream<C: WriteBuf + ?Sized>(
&mut self,
output: &mut OutBuffer<'_, C>,
input: &mut InBuffer<'_>,
) -> SafeResult {
let mut output = output.wrap();
let mut input = input.wrap();
let code = unsafe {
zstd_sys::ZSTD_decompressStream(
self.0.as_ptr(),
ptr_mut(&mut output),
ptr_mut(&mut input),
)
};
parse_code(code)
}
pub fn in_size() -> usize {
unsafe { zstd_sys::ZSTD_DStreamInSize() }
}
pub fn out_size() -> usize {
unsafe { zstd_sys::ZSTD_DStreamOutSize() }
}
pub fn sizeof(&self) -> usize {
unsafe { zstd_sys::ZSTD_sizeof_DCtx(self.0.as_ptr()) }
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn decompress_block<C: WriteBuf + ?Sized>(
&mut self,
dst: &mut C,
src: &[u8],
) -> SafeResult {
unsafe {
dst.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZSTD_decompressBlock(
self.0.as_ptr(),
buffer,
capacity,
ptr_void(src),
src.len(),
))
})
}
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn insert_block(&mut self, block: &[u8]) -> usize {
unsafe {
zstd_sys::ZSTD_insertBlock(
self.0.as_ptr(),
ptr_void(block),
block.len(),
)
}
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn try_clone(&self) -> Result<Self, ErrorCode> {
let context = NonNull::new(unsafe { zstd_sys::ZSTD_createDCtx() })
.ok_or(0usize)?;
unsafe { zstd_sys::ZSTD_copyDCtx(context.as_ptr(), self.0.as_ptr()) };
Ok(DCtx(context, self.1))
}
}
impl Drop for DCtx<'_> {
fn drop(&mut self) {
unsafe {
zstd_sys::ZSTD_freeDCtx(self.0.as_ptr());
}
}
}
unsafe impl Send for DCtx<'_> {}
unsafe impl Sync for DCtx<'_> {}
pub struct CDict<'a>(NonNull<zstd_sys::ZSTD_CDict>, PhantomData<&'a ()>);
impl CDict<'static> {
pub fn create(
dict_buffer: &[u8],
compression_level: CompressionLevel,
) -> Self {
Self::try_create(dict_buffer, compression_level)
.expect("zstd returned null pointer when creating dict")
}
pub fn try_create(
dict_buffer: &[u8],
compression_level: CompressionLevel,
) -> Option<Self> {
Some(CDict(
NonNull::new(unsafe {
zstd_sys::ZSTD_createCDict(
ptr_void(dict_buffer),
dict_buffer.len(),
compression_level,
)
})?,
PhantomData,
))
}
}
impl<'a> CDict<'a> {
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn create_by_reference(
dict_buffer: &'a [u8],
compression_level: CompressionLevel,
) -> Self {
CDict(
NonNull::new(unsafe {
zstd_sys::ZSTD_createCDict_byReference(
ptr_void(dict_buffer),
dict_buffer.len(),
compression_level,
)
})
.expect("zstd returned null pointer"),
PhantomData,
)
}
pub fn sizeof(&self) -> usize {
unsafe { zstd_sys::ZSTD_sizeof_CDict(self.0.as_ptr()) }
}
pub fn get_dict_id(&self) -> Option<NonZeroU32> {
NonZeroU32::new(unsafe {
zstd_sys::ZSTD_getDictID_fromCDict(self.0.as_ptr()) as u32
})
}
}
pub fn create_cdict(
dict_buffer: &[u8],
compression_level: CompressionLevel,
) -> CDict<'static> {
CDict::create(dict_buffer, compression_level)
}
impl<'a> Drop for CDict<'a> {
fn drop(&mut self) {
unsafe {
zstd_sys::ZSTD_freeCDict(self.0.as_ptr());
}
}
}
unsafe impl<'a> Send for CDict<'a> {}
unsafe impl<'a> Sync for CDict<'a> {}
pub fn compress_using_cdict(
cctx: &mut CCtx<'_>,
dst: &mut [u8],
src: &[u8],
cdict: &CDict<'_>,
) -> SafeResult {
cctx.compress_using_cdict(dst, src, cdict)
}
pub struct DDict<'a>(NonNull<zstd_sys::ZSTD_DDict>, PhantomData<&'a ()>);
impl DDict<'static> {
pub fn create(dict_buffer: &[u8]) -> Self {
Self::try_create(dict_buffer)
.expect("zstd returned null pointer when creating dict")
}
pub fn try_create(dict_buffer: &[u8]) -> Option<Self> {
Some(DDict(
NonNull::new(unsafe {
zstd_sys::ZSTD_createDDict(
ptr_void(dict_buffer),
dict_buffer.len(),
)
})?,
PhantomData,
))
}
}
impl<'a> DDict<'a> {
pub fn sizeof(&self) -> usize {
unsafe { zstd_sys::ZSTD_sizeof_DDict(self.0.as_ptr()) }
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn create_by_reference(dict_buffer: &'a [u8]) -> Self {
DDict(
NonNull::new(unsafe {
zstd_sys::ZSTD_createDDict_byReference(
ptr_void(dict_buffer),
dict_buffer.len(),
)
})
.expect("zstd returned null pointer"),
PhantomData,
)
}
pub fn get_dict_id(&self) -> Option<NonZeroU32> {
NonZeroU32::new(unsafe {
zstd_sys::ZSTD_getDictID_fromDDict(self.0.as_ptr()) as u32
})
}
}
pub fn create_ddict(dict_buffer: &[u8]) -> DDict<'static> {
DDict::create(dict_buffer)
}
impl<'a> Drop for DDict<'a> {
fn drop(&mut self) {
unsafe {
zstd_sys::ZSTD_freeDDict(self.0.as_ptr());
}
}
}
unsafe impl<'a> Send for DDict<'a> {}
unsafe impl<'a> Sync for DDict<'a> {}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
pub struct ThreadPool(NonNull<zstd_sys::ZSTD_threadPool>);
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
impl ThreadPool {
pub fn new(num_threads: usize) -> Self {
Self::try_new(num_threads)
.expect("zstd returned null pointer when creating thread pool")
}
pub fn try_new(num_threads: usize) -> Option<Self> {
Some(Self(NonNull::new(unsafe {
zstd_sys::ZSTD_createThreadPool(num_threads)
})?))
}
}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
impl Drop for ThreadPool {
fn drop(&mut self) {
unsafe {
zstd_sys::ZSTD_freeThreadPool(self.0.as_ptr());
}
}
}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
unsafe impl Send for ThreadPool {}
#[cfg(all(feature = "experimental", feature = "zstdmt"))]
#[cfg_attr(
feature = "doc-cfg",
doc(cfg(all(feature = "experimental", feature = "zstdmt")))
)]
unsafe impl Sync for ThreadPool {}
pub fn decompress_using_ddict(
dctx: &mut DCtx<'_>,
dst: &mut [u8],
src: &[u8],
ddict: &DDict<'_>,
) -> SafeResult {
dctx.decompress_using_ddict(dst, src, ddict)
}
pub type CStream<'a> = CCtx<'a>;
pub fn create_cstream<'a>() -> CStream<'a> {
CCtx::create()
}
pub fn init_cstream(
zcs: &mut CStream<'_>,
compression_level: CompressionLevel,
) -> SafeResult {
zcs.init(compression_level)
}
#[derive(Debug)]
pub struct InBuffer<'a> {
pub src: &'a [u8],
pub pos: usize,
}
pub unsafe trait WriteBuf {
fn as_slice(&self) -> &[u8];
fn capacity(&self) -> usize;
fn as_mut_ptr(&mut self) -> *mut u8;
unsafe fn filled_until(&mut self, n: usize);
unsafe fn write_from<F>(&mut self, f: F) -> SafeResult
where
F: FnOnce(*mut c_void, usize) -> SafeResult,
{
let res = f(ptr_mut_void(self), self.capacity());
if let Ok(n) = res {
self.filled_until(n);
}
res
}
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "std")))]
unsafe impl<T> WriteBuf for std::io::Cursor<T>
where
T: WriteBuf,
{
fn as_slice(&self) -> &[u8] {
&self.get_ref().as_slice()[self.position() as usize..]
}
fn capacity(&self) -> usize {
self.get_ref()
.capacity()
.saturating_sub(self.position() as usize)
}
fn as_mut_ptr(&mut self) -> *mut u8 {
let start = self.position() as usize;
assert!(start <= self.get_ref().capacity());
unsafe { self.get_mut().as_mut_ptr().add(start) }
}
unsafe fn filled_until(&mut self, n: usize) {
if n == 0 {
return;
}
let position = self.position() as usize;
let initialized = self.get_ref().as_slice().len();
if let Some(uninitialized) = position.checked_sub(initialized) {
unsafe {
self.get_mut()
.as_mut_ptr()
.add(initialized)
.write_bytes(0u8, uninitialized)
};
}
let start = self.position() as usize;
assert!(start + n <= self.get_ref().capacity());
self.get_mut().filled_until(start + n);
}
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "std")))]
unsafe impl<'a> WriteBuf for &'a mut std::vec::Vec<u8> {
fn as_slice(&self) -> &[u8] {
std::vec::Vec::as_slice(self)
}
fn capacity(&self) -> usize {
std::vec::Vec::capacity(self)
}
fn as_mut_ptr(&mut self) -> *mut u8 {
std::vec::Vec::as_mut_ptr(self)
}
unsafe fn filled_until(&mut self, n: usize) {
std::vec::Vec::set_len(self, n)
}
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "std")))]
unsafe impl WriteBuf for std::vec::Vec<u8> {
fn as_slice(&self) -> &[u8] {
&self[..]
}
fn capacity(&self) -> usize {
self.capacity()
}
fn as_mut_ptr(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
unsafe fn filled_until(&mut self, n: usize) {
self.set_len(n);
}
}
#[cfg(feature = "arrays")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "arrays")))]
unsafe impl<const N: usize> WriteBuf for [u8; N] {
fn as_slice(&self) -> &[u8] {
self
}
fn capacity(&self) -> usize {
self.len()
}
fn as_mut_ptr(&mut self) -> *mut u8 {
(&mut self[..]).as_mut_ptr()
}
unsafe fn filled_until(&mut self, _n: usize) {
}
}
unsafe impl WriteBuf for [u8] {
fn as_slice(&self) -> &[u8] {
self
}
fn capacity(&self) -> usize {
self.len()
}
fn as_mut_ptr(&mut self) -> *mut u8 {
self.as_mut_ptr()
}
unsafe fn filled_until(&mut self, _n: usize) {
}
}
#[derive(Debug)]
pub struct OutBuffer<'a, C: WriteBuf + ?Sized> {
dst: &'a mut C,
pos: usize,
}
fn ptr_mut<B>(ptr_void: &mut B) -> *mut B {
ptr_void as *mut B
}
struct OutBufferWrapper<'a, 'b, C: WriteBuf + ?Sized> {
buf: zstd_sys::ZSTD_outBuffer,
parent: &'a mut OutBuffer<'b, C>,
}
impl<'a, 'b: 'a, C: WriteBuf + ?Sized> Deref for OutBufferWrapper<'a, 'b, C> {
type Target = zstd_sys::ZSTD_outBuffer;
fn deref(&self) -> &Self::Target {
&self.buf
}
}
impl<'a, 'b: 'a, C: WriteBuf + ?Sized> DerefMut
for OutBufferWrapper<'a, 'b, C>
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buf
}
}
impl<'a, C: WriteBuf + ?Sized> OutBuffer<'a, C> {
pub fn around(dst: &'a mut C) -> Self {
OutBuffer { dst, pos: 0 }
}
pub fn around_pos(dst: &'a mut C, pos: usize) -> Self {
if pos > dst.capacity() {
panic!("Given position outside of the buffer bounds.");
}
OutBuffer { dst, pos }
}
pub fn pos(&self) -> usize {
assert!(self.pos <= self.dst.capacity());
self.pos
}
pub fn capacity(&self) -> usize {
self.dst.capacity()
}
pub unsafe fn set_pos(&mut self, pos: usize) {
if pos > self.dst.capacity() {
panic!("Given position outside of the buffer bounds.");
}
self.dst.filled_until(pos);
self.pos = pos;
}
fn wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a, C> {
OutBufferWrapper {
buf: zstd_sys::ZSTD_outBuffer {
dst: ptr_mut_void(self.dst),
size: self.dst.capacity(),
pos: self.pos,
},
parent: self,
}
}
pub fn as_slice<'b>(&'b self) -> &'a [u8]
where
'b: 'a,
{
let pos = self.pos;
&self.dst.as_slice()[..pos]
}
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.dst.as_mut_ptr()
}
}
impl<'a, 'b, C: WriteBuf + ?Sized> Drop for OutBufferWrapper<'a, 'b, C> {
fn drop(&mut self) {
unsafe { self.parent.set_pos(self.buf.pos) };
}
}
struct InBufferWrapper<'a, 'b> {
buf: zstd_sys::ZSTD_inBuffer,
parent: &'a mut InBuffer<'b>,
}
impl<'a, 'b: 'a> Deref for InBufferWrapper<'a, 'b> {
type Target = zstd_sys::ZSTD_inBuffer;
fn deref(&self) -> &Self::Target {
&self.buf
}
}
impl<'a, 'b: 'a> DerefMut for InBufferWrapper<'a, 'b> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buf
}
}
impl<'a> InBuffer<'a> {
pub fn around(src: &'a [u8]) -> Self {
InBuffer { src, pos: 0 }
}
pub fn pos(&self) -> usize {
self.pos
}
pub fn set_pos(&mut self, pos: usize) {
if pos > self.src.len() {
panic!("Given position outside of the buffer bounds.");
}
self.pos = pos;
}
fn wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a> {
InBufferWrapper {
buf: zstd_sys::ZSTD_inBuffer {
src: ptr_void(self.src),
size: self.src.len(),
pos: self.pos,
},
parent: self,
}
}
}
impl<'a, 'b> Drop for InBufferWrapper<'a, 'b> {
fn drop(&mut self) {
self.parent.set_pos(self.buf.pos);
}
}
pub type DStream<'a> = DCtx<'a>;
pub fn find_frame_compressed_size(src: &[u8]) -> SafeResult {
let code = unsafe {
zstd_sys::ZSTD_findFrameCompressedSize(ptr_void(src), src.len())
};
parse_code(code)
}
pub fn get_frame_content_size(
src: &[u8],
) -> Result<Option<u64>, ContentSizeError> {
parse_content_size(unsafe {
zstd_sys::ZSTD_getFrameContentSize(ptr_void(src), src.len())
})
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn find_decompressed_size(
src: &[u8],
) -> Result<Option<u64>, ContentSizeError> {
parse_content_size(unsafe {
zstd_sys::ZSTD_findDecompressedSize(ptr_void(src), src.len())
})
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn is_frame(buffer: &[u8]) -> bool {
unsafe { zstd_sys::ZSTD_isFrame(ptr_void(buffer), buffer.len()) > 0 }
}
pub fn get_dict_id_from_dict(dict: &[u8]) -> Option<NonZeroU32> {
NonZeroU32::new(unsafe {
zstd_sys::ZSTD_getDictID_fromDict(ptr_void(dict), dict.len()) as u32
})
}
pub fn get_dict_id_from_frame(src: &[u8]) -> Option<NonZeroU32> {
NonZeroU32::new(unsafe {
zstd_sys::ZSTD_getDictID_fromFrame(ptr_void(src), src.len()) as u32
})
}
pub enum ResetDirective {
SessionOnly,
Parameters,
SessionAndParameters,
}
impl ResetDirective {
fn as_sys(self) -> zstd_sys::ZSTD_ResetDirective {
match self {
ResetDirective::SessionOnly => zstd_sys::ZSTD_ResetDirective::ZSTD_reset_session_only,
ResetDirective::Parameters => zstd_sys::ZSTD_ResetDirective::ZSTD_reset_parameters,
ResetDirective::SessionAndParameters => zstd_sys::ZSTD_ResetDirective::ZSTD_reset_session_and_parameters,
}
}
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum FrameFormat {
One = zstd_sys::ZSTD_format_e::ZSTD_f_zstd1 as u32,
Magicless = zstd_sys::ZSTD_format_e::ZSTD_f_zstd1_magicless as u32,
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum DictAttachPref {
DefaultAttach =
zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictDefaultAttach as u32,
ForceAttach = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceAttach as u32,
ForceCopy = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceCopy as u32,
ForceLoad = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceLoad as u32,
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum ParamSwitch {
Auto = zstd_sys::ZSTD_ParamSwitch_e::ZSTD_ps_auto as u32,
Enable = zstd_sys::ZSTD_ParamSwitch_e::ZSTD_ps_enable as u32,
Disable = zstd_sys::ZSTD_ParamSwitch_e::ZSTD_ps_disable as u32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CParameter {
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
RSyncable(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
Format(FrameFormat),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
ForceMaxWindow(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
ForceAttachDict(DictAttachPref),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
LiteralCompressionMode(ParamSwitch),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
SrcSizeHint(u32),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
EnableDedicatedDictSearch(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
StableInBuffer(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
StableOutBuffer(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
BlockDelimiters(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
ValidateSequences(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
UseBlockSplitter(ParamSwitch),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
UseRowMatchFinder(ParamSwitch),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
DeterministicRefPrefix(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
PrefetchCDictTables(ParamSwitch),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
EnableSeqProducerFallback(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
MaxBlockSize(u32),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
SearchForExternalRepcodes(ParamSwitch),
TargetCBlockSize(u32),
CompressionLevel(CompressionLevel),
WindowLog(u32),
HashLog(u32),
ChainLog(u32),
SearchLog(u32),
MinMatch(u32),
TargetLength(u32),
Strategy(Strategy),
EnableLongDistanceMatching(bool),
LdmHashLog(u32),
LdmMinMatch(u32),
LdmBucketSizeLog(u32),
LdmHashRateLog(u32),
ContentSizeFlag(bool),
ChecksumFlag(bool),
DictIdFlag(bool),
NbWorkers(u32),
JobSize(u32),
OverlapSizeLog(u32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum DParameter {
WindowLogMax(u32),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
Format(FrameFormat),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
StableOutBuffer(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
ForceIgnoreChecksum(bool),
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
RefMultipleDDicts(bool),
}
#[cfg(feature = "zdict_builder")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "zdict_builder")))]
pub fn train_from_buffer<C: WriteBuf + ?Sized>(
dict_buffer: &mut C,
samples_buffer: &[u8],
samples_sizes: &[usize],
) -> SafeResult {
assert_eq!(samples_buffer.len(), samples_sizes.iter().sum());
unsafe {
dict_buffer.write_from(|buffer, capacity| {
parse_code(zstd_sys::ZDICT_trainFromBuffer(
buffer,
capacity,
ptr_void(samples_buffer),
samples_sizes.as_ptr(),
samples_sizes.len() as u32,
))
})
}
}
#[cfg(feature = "zdict_builder")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "zdict_builder")))]
pub fn get_dict_id(dict_buffer: &[u8]) -> Option<NonZeroU32> {
NonZeroU32::new(unsafe {
zstd_sys::ZDICT_getDictID(ptr_void(dict_buffer), dict_buffer.len())
})
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn get_block_size(cctx: &CCtx) -> usize {
unsafe { zstd_sys::ZSTD_getBlockSize(cctx.0.as_ptr()) }
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn decompress_bound(data: &[u8]) -> Result<u64, ErrorCode> {
let bound =
unsafe { zstd_sys::ZSTD_decompressBound(ptr_void(data), data.len()) };
if is_error(bound as usize) {
Err(bound as usize)
} else {
Ok(bound)
}
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn sequence_bound(src_size: usize) -> usize {
unsafe { zstd_sys::ZSTD_sequenceBound(src_size) }
}
#[cfg(feature = "experimental")]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
pub fn decompression_margin(
compressed_data: &[u8],
) -> Result<usize, ErrorCode> {
parse_code(unsafe {
zstd_sys::ZSTD_decompressionMargin(
ptr_void(compressed_data),
compressed_data.len(),
)
})
}