1#![no_std]
2#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
21
22#[cfg(feature = "std")]
23extern crate std;
24
25#[cfg(test)]
26mod tests;
27
28pub use zstd_sys;
30
31pub use zstd_sys::ZSTD_strategy as Strategy;
33
34pub use zstd_sys::ZSTD_ResetDirective as ResetDirective;
36
37#[cfg(feature = "std")]
38use std::os::raw::{c_char, c_int, c_ulonglong, c_void};
39
40#[cfg(not(feature = "std"))]
41use libc::{c_char, c_int, c_ulonglong, c_void};
42
43use core::marker::PhantomData;
44use core::ops::{Deref, DerefMut};
45use core::ptr::NonNull;
46use core::str;
47
48include!("constants.rs");
49
50#[cfg(feature = "experimental")]
51include!("constants_experimental.rs");
52
53pub type CompressionLevel = i32;
55
56pub type ErrorCode = usize;
58
59pub type SafeResult = Result<usize, ErrorCode>;
63
64fn is_error(code: usize) -> bool {
66 unsafe { zstd_sys::ZSTD_isError(code) != 0 }
67}
68
69fn parse_code(code: usize) -> SafeResult {
74 if !is_error(code) {
75 Ok(code)
76 } else {
77 Err(code)
78 }
79}
80
81fn ptr_void(src: &[u8]) -> *const c_void {
82 src.as_ptr() as *const c_void
83}
84
85fn ptr_mut_void(dst: &mut (impl WriteBuf + ?Sized)) -> *mut c_void {
86 dst.as_mut_ptr() as *mut c_void
87}
88
89pub fn version_number() -> u32 {
90 unsafe { zstd_sys::ZSTD_versionNumber() as u32 }
91}
92
93pub fn version_string() -> &'static str {
94 unsafe { c_char_to_str(zstd_sys::ZSTD_versionString()) }
95}
96
97pub fn min_c_level() -> CompressionLevel {
99 unsafe { zstd_sys::ZSTD_minCLevel() as CompressionLevel }
100}
101
102pub fn max_c_level() -> CompressionLevel {
104 unsafe { zstd_sys::ZSTD_maxCLevel() as CompressionLevel }
105}
106
107pub fn compress<C: WriteBuf + ?Sized>(
109 dst: &mut C,
110 src: &[u8],
111 compression_level: CompressionLevel,
112) -> SafeResult {
113 unsafe {
114 dst.write_from(|buffer, capacity| {
115 parse_code(zstd_sys::ZSTD_compress(
116 buffer,
117 capacity,
118 ptr_void(src),
119 src.len(),
120 compression_level,
121 ))
122 })
123 }
124}
125
126pub fn decompress<C: WriteBuf + ?Sized>(
128 dst: &mut C,
129 src: &[u8],
130) -> SafeResult {
131 unsafe {
132 dst.write_from(|buffer, capacity| {
133 parse_code(zstd_sys::ZSTD_decompress(
134 buffer,
135 capacity,
136 ptr_void(src),
137 src.len(),
138 ))
139 })
140 }
141}
142
143#[deprecated(note = "Use ZSTD_getFrameContentSize instead")]
145pub fn get_decompressed_size(src: &[u8]) -> u64 {
146 unsafe {
147 zstd_sys::ZSTD_getDecompressedSize(ptr_void(src), src.len()) as u64
148 }
149}
150
151pub fn compress_bound(src_size: usize) -> usize {
153 unsafe { zstd_sys::ZSTD_compressBound(src_size) }
154}
155
156pub struct CCtx<'a>(NonNull<zstd_sys::ZSTD_CCtx>, PhantomData<&'a ()>);
157
158impl Default for CCtx<'_> {
159 fn default() -> Self {
160 CCtx::create()
161 }
162}
163
164impl CCtx<'static> {
165 pub fn try_create() -> Option<Self> {
169 Some(CCtx(
170 NonNull::new(unsafe { zstd_sys::ZSTD_createCCtx() })?,
171 PhantomData,
172 ))
173 }
174
175 pub fn create() -> Self {
181 Self::try_create()
182 .expect("zstd returned null pointer when creating new context")
183 }
184}
185
186impl<'a> CCtx<'a> {
187 pub fn compress<C: WriteBuf + ?Sized>(
189 &mut self,
190 dst: &mut C,
191 src: &[u8],
192 compression_level: CompressionLevel,
193 ) -> SafeResult {
194 unsafe {
195 dst.write_from(|buffer, capacity| {
196 parse_code(zstd_sys::ZSTD_compressCCtx(
197 self.0.as_ptr(),
198 buffer,
199 capacity,
200 ptr_void(src),
201 src.len(),
202 compression_level,
203 ))
204 })
205 }
206 }
207
208 pub fn compress2<C: WriteBuf + ?Sized>(
210 &mut self,
211 dst: &mut C,
212 src: &[u8],
213 ) -> SafeResult {
214 unsafe {
215 dst.write_from(|buffer, capacity| {
216 parse_code(zstd_sys::ZSTD_compress2(
217 self.0.as_ptr(),
218 buffer,
219 capacity,
220 ptr_void(src),
221 src.len(),
222 ))
223 })
224 }
225 }
226
227 pub fn compress_using_dict<C: WriteBuf + ?Sized>(
229 &mut self,
230 dst: &mut C,
231 src: &[u8],
232 dict: &[u8],
233 compression_level: CompressionLevel,
234 ) -> SafeResult {
235 unsafe {
236 dst.write_from(|buffer, capacity| {
237 parse_code(zstd_sys::ZSTD_compress_usingDict(
238 self.0.as_ptr(),
239 buffer,
240 capacity,
241 ptr_void(src),
242 src.len(),
243 ptr_void(dict),
244 dict.len(),
245 compression_level,
246 ))
247 })
248 }
249 }
250
251 pub fn compress_using_cdict<C: WriteBuf + ?Sized>(
253 &mut self,
254 dst: &mut C,
255 src: &[u8],
256 cdict: &CDict<'_>,
257 ) -> SafeResult {
258 unsafe {
259 dst.write_from(|buffer, capacity| {
260 parse_code(zstd_sys::ZSTD_compress_usingCDict(
261 self.0.as_ptr(),
262 buffer,
263 capacity,
264 ptr_void(src),
265 src.len(),
266 cdict.0.as_ptr(),
267 ))
268 })
269 }
270 }
271
272 pub fn init(&mut self, compression_level: CompressionLevel) -> usize {
273 unsafe {
274 zstd_sys::ZSTD_initCStream(self.0.as_ptr(), compression_level)
275 }
276 }
277
278 #[cfg(feature = "experimental")]
280 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
281 #[deprecated]
282 pub fn init_src_size(
283 &mut self,
284 compression_level: CompressionLevel,
285 pledged_src_size: u64,
286 ) -> usize {
287 unsafe {
288 zstd_sys::ZSTD_initCStream_srcSize(
289 self.0.as_ptr(),
290 compression_level as c_int,
291 pledged_src_size as c_ulonglong,
292 )
293 }
294 }
295
296 #[cfg(feature = "experimental")]
298 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
299 #[deprecated]
300 pub fn init_using_dict(
301 &mut self,
302 dict: &[u8],
303 compression_level: CompressionLevel,
304 ) -> SafeResult {
305 let code = unsafe {
306 zstd_sys::ZSTD_initCStream_usingDict(
307 self.0.as_ptr(),
308 ptr_void(dict),
309 dict.len(),
310 compression_level,
311 )
312 };
313 parse_code(code)
314 }
315
316 #[cfg(feature = "experimental")]
318 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
319 #[deprecated]
320 pub fn init_using_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
321 where
322 'b: 'a, {
324 let code = unsafe {
325 zstd_sys::ZSTD_initCStream_usingCDict(
326 self.0.as_ptr(),
327 cdict.0.as_ptr(),
328 )
329 };
330 parse_code(code)
331 }
332
333 pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
334 parse_code(unsafe {
335 zstd_sys::ZSTD_CCtx_loadDictionary(
336 self.0.as_ptr(),
337 ptr_void(dict),
338 dict.len(),
339 )
340 })
341 }
342
343 pub fn ref_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
347 where
348 'b: 'a,
349 {
350 parse_code(unsafe {
351 zstd_sys::ZSTD_CCtx_refCDict(self.0.as_ptr(), cdict.0.as_ptr())
352 })
353 }
354
355 pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
356 where
357 'b: 'a,
358 {
359 parse_code(unsafe {
360 zstd_sys::ZSTD_CCtx_refPrefix(
361 self.0.as_ptr(),
362 ptr_void(prefix),
363 prefix.len(),
364 )
365 })
366 }
367
368 pub fn compress_stream<C: WriteBuf + ?Sized>(
369 &mut self,
370 output: &mut OutBuffer<'_, C>,
371 input: &mut InBuffer<'_>,
372 ) -> SafeResult {
373 let mut output = output.wrap();
374 let mut input = input.wrap();
375 let code = unsafe {
376 zstd_sys::ZSTD_compressStream(
377 self.0.as_ptr(),
378 ptr_mut(&mut output),
379 ptr_mut(&mut input),
380 )
381 };
382 parse_code(code)
383 }
384
385 pub fn compress_stream2<C: WriteBuf + ?Sized>(
387 &mut self,
388 output: &mut OutBuffer<'_, C>,
389 input: &mut InBuffer<'_>,
390 end_op: zstd_sys::ZSTD_EndDirective,
391 ) -> SafeResult {
392 let mut output = output.wrap();
393 let mut input = input.wrap();
394 parse_code(unsafe {
395 zstd_sys::ZSTD_compressStream2(
396 self.0.as_ptr(),
397 ptr_mut(&mut output),
398 ptr_mut(&mut input),
399 end_op,
400 )
401 })
402 }
403
404 pub fn flush_stream<C: WriteBuf + ?Sized>(
406 &mut self,
407 output: &mut OutBuffer<'_, C>,
408 ) -> SafeResult {
409 let mut output = output.wrap();
410 let code = unsafe {
411 zstd_sys::ZSTD_flushStream(self.0.as_ptr(), ptr_mut(&mut output))
412 };
413 parse_code(code)
414 }
415
416 pub fn end_stream<C: WriteBuf + ?Sized>(
418 &mut self,
419 output: &mut OutBuffer<'_, C>,
420 ) -> SafeResult {
421 let mut output = output.wrap();
422 let code = unsafe {
423 zstd_sys::ZSTD_endStream(self.0.as_ptr(), ptr_mut(&mut output))
424 };
425 parse_code(code)
426 }
427
428 pub fn sizeof(&self) -> usize {
429 unsafe { zstd_sys::ZSTD_sizeof_CCtx(self.0.as_ptr()) }
430 }
431
432 pub fn reset(&mut self, reset: ResetDirective) -> SafeResult {
433 parse_code(unsafe {
434 zstd_sys::ZSTD_CCtx_reset(self.0.as_ptr(), reset)
435 })
436 }
437
438 #[cfg(feature = "experimental")]
439 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
440 #[deprecated]
441 pub fn reset_cstream(&mut self, pledged_src_size: u64) -> SafeResult {
442 let code = unsafe {
443 zstd_sys::ZSTD_resetCStream(
444 self.0.as_ptr(),
445 pledged_src_size as c_ulonglong,
446 )
447 };
448 parse_code(code)
449 }
450
451 pub fn set_parameter(&mut self, param: CParameter) -> SafeResult {
452 #[cfg(feature = "experimental")]
455 use zstd_sys::ZSTD_cParameter::{
456 ZSTD_c_experimentalParam1 as ZSTD_c_rsyncable,
457 ZSTD_c_experimentalParam10 as ZSTD_c_stableOutBuffer,
458 ZSTD_c_experimentalParam11 as ZSTD_c_blockDelimiters,
459 ZSTD_c_experimentalParam12 as ZSTD_c_validateSequences,
460 ZSTD_c_experimentalParam13 as ZSTD_c_useBlockSplitter,
461 ZSTD_c_experimentalParam14 as ZSTD_c_useRowMatchFinder,
462 ZSTD_c_experimentalParam15 as ZSTD_c_deterministicRefPrefix,
463 ZSTD_c_experimentalParam2 as ZSTD_c_format,
464 ZSTD_c_experimentalParam3 as ZSTD_c_forceMaxWindow,
465 ZSTD_c_experimentalParam4 as ZSTD_c_forceAttachDict,
466 ZSTD_c_experimentalParam5 as ZSTD_c_literalCompressionMode,
467 ZSTD_c_experimentalParam6 as ZSTD_c_targetCBlockSize,
468 ZSTD_c_experimentalParam7 as ZSTD_c_srcSizeHint,
469 ZSTD_c_experimentalParam8 as ZSTD_c_enableDedicatedDictSearch,
470 ZSTD_c_experimentalParam9 as ZSTD_c_stableInBuffer,
471 };
472
473 use zstd_sys::ZSTD_cParameter::*;
474 use CParameter::*;
475
476 let (param, value) = match param {
477 #[cfg(feature = "experimental")]
478 RSyncable(rsyncable) => (ZSTD_c_rsyncable, rsyncable as c_int),
479 #[cfg(feature = "experimental")]
480 Format(format) => (ZSTD_c_format, format as c_int),
481 #[cfg(feature = "experimental")]
482 ForceMaxWindow(force) => (ZSTD_c_forceMaxWindow, force as c_int),
483 #[cfg(feature = "experimental")]
484 ForceAttachDict(force) => (ZSTD_c_forceAttachDict, force as c_int),
485 #[cfg(feature = "experimental")]
486 TargetCBlockSize(value) => {
487 (ZSTD_c_targetCBlockSize, value as c_int)
488 }
489 #[cfg(feature = "experimental")]
490 SrcSizeHint(value) => (ZSTD_c_srcSizeHint, value as c_int),
491 #[cfg(feature = "experimental")]
492 EnableDedicatedDictSearch(enable) => {
493 (ZSTD_c_enableDedicatedDictSearch, enable as c_int)
494 }
495 #[cfg(feature = "experimental")]
496 StableInBuffer(stable) => (ZSTD_c_stableInBuffer, stable as c_int),
497 #[cfg(feature = "experimental")]
498 StableOutBuffer(stable) => {
499 (ZSTD_c_stableOutBuffer, stable as c_int)
500 }
501 #[cfg(feature = "experimental")]
502 BlockDelimiters(value) => (ZSTD_c_blockDelimiters, value as c_int),
503 #[cfg(feature = "experimental")]
504 ValidateSequences(validate) => {
505 (ZSTD_c_validateSequences, validate as c_int)
506 }
507 #[cfg(feature = "experimental")]
508 UseBlockSplitter(split) => {
509 (ZSTD_c_useBlockSplitter, split as c_int)
510 }
511 #[cfg(feature = "experimental")]
512 UseRowMatchFinder(mode) => {
513 (ZSTD_c_useRowMatchFinder, mode as c_int)
514 }
515 #[cfg(feature = "experimental")]
516 DeterministicRefPrefix(deterministic) => {
517 (ZSTD_c_deterministicRefPrefix, deterministic as c_int)
518 }
519 CompressionLevel(level) => (ZSTD_c_compressionLevel, level),
520 WindowLog(value) => (ZSTD_c_windowLog, value as c_int),
521 HashLog(value) => (ZSTD_c_hashLog, value as c_int),
522 ChainLog(value) => (ZSTD_c_chainLog, value as c_int),
523 SearchLog(value) => (ZSTD_c_searchLog, value as c_int),
524 MinMatch(value) => (ZSTD_c_minMatch, value as c_int),
525 TargetLength(value) => (ZSTD_c_targetLength, value as c_int),
526 Strategy(strategy) => (ZSTD_c_strategy, strategy as c_int),
527 #[cfg(feature = "experimental")]
528 LiteralCompressionMode(mode) => {
529 (ZSTD_c_literalCompressionMode, mode as c_int)
530 }
531 EnableLongDistanceMatching(flag) => {
532 (ZSTD_c_enableLongDistanceMatching, flag as c_int)
533 }
534 LdmHashLog(value) => (ZSTD_c_ldmHashLog, value as c_int),
535 LdmMinMatch(value) => (ZSTD_c_ldmMinMatch, value as c_int),
536 LdmBucketSizeLog(value) => {
537 (ZSTD_c_ldmBucketSizeLog, value as c_int)
538 }
539 LdmHashRateLog(value) => (ZSTD_c_ldmHashRateLog, value as c_int),
540 ContentSizeFlag(flag) => (ZSTD_c_contentSizeFlag, flag as c_int),
541 ChecksumFlag(flag) => (ZSTD_c_checksumFlag, flag as c_int),
542 DictIdFlag(flag) => (ZSTD_c_dictIDFlag, flag as c_int),
543
544 NbWorkers(value) => (ZSTD_c_nbWorkers, value as c_int),
545
546 JobSize(value) => (ZSTD_c_jobSize, value as c_int),
547
548 OverlapSizeLog(value) => (ZSTD_c_overlapLog, value as c_int),
549 };
550
551 parse_code(unsafe {
552 zstd_sys::ZSTD_CCtx_setParameter(self.0.as_ptr(), param, value)
553 })
554 }
555
556 pub fn set_pledged_src_size(
557 &mut self,
558 pledged_src_size: u64,
559 ) -> SafeResult {
560 parse_code(unsafe {
561 zstd_sys::ZSTD_CCtx_setPledgedSrcSize(
562 self.0.as_ptr(),
563 pledged_src_size as c_ulonglong,
564 )
565 })
566 }
567
568 #[cfg(feature = "experimental")]
573 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
574 pub fn try_clone(
575 &self,
576 pledged_src_size: Option<u64>,
577 ) -> Result<Self, ErrorCode> {
578 let context = NonNull::new(unsafe { zstd_sys::ZSTD_createCCtx() })
579 .ok_or(0usize)?;
580
581 parse_code(unsafe {
582 zstd_sys::ZSTD_copyCCtx(
583 context.as_ptr(),
584 self.0.as_ptr(),
585 pledged_src_size.unwrap_or(CONTENTSIZE_UNKNOWN),
586 )
587 })?;
588
589 Ok(CCtx(context, self.1))
590 }
591
592 #[cfg(feature = "experimental")]
594 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
595 pub fn get_block_size(&self) -> usize {
596 unsafe { zstd_sys::ZSTD_getBlockSize(self.0.as_ptr()) }
597 }
598
599 #[cfg(feature = "experimental")]
601 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
602 pub fn compress_block<C: WriteBuf + ?Sized>(
603 &mut self,
604 dst: &mut C,
605 src: &[u8],
606 ) -> SafeResult {
607 unsafe {
608 dst.write_from(|buffer, capacity| {
609 parse_code(zstd_sys::ZSTD_compressBlock(
610 self.0.as_ptr(),
611 buffer,
612 capacity,
613 ptr_void(src),
614 src.len(),
615 ))
616 })
617 }
618 }
619 pub fn in_size() -> usize {
620 unsafe { zstd_sys::ZSTD_CStreamInSize() }
621 }
622
623 pub fn out_size() -> usize {
624 unsafe { zstd_sys::ZSTD_CStreamOutSize() }
625 }
626}
627
628pub fn create_cctx<'a>() -> CCtx<'a> {
629 CCtx::create()
630}
631
632impl<'a> Drop for CCtx<'a> {
633 fn drop(&mut self) {
634 unsafe {
635 zstd_sys::ZSTD_freeCCtx(self.0.as_ptr());
636 }
637 }
638}
639
640unsafe impl<'a> Send for CCtx<'a> {}
641unsafe fn c_char_to_str(text: *const c_char) -> &'static str {
644 #[cfg(not(feature = "std"))]
645 {
646 let len = libc::strlen(text);
648
649 let slice = core::slice::from_raw_parts(text as *mut u8, len);
651 str::from_utf8(slice).expect("bad error message from zstd")
653 }
654
655 #[cfg(feature = "std")]
656 {
657 std::ffi::CStr::from_ptr(text)
658 .to_str()
659 .expect("bad error message from zstd")
660 }
661}
662
663pub fn get_error_name(code: usize) -> &'static str {
664 unsafe {
665 let name = zstd_sys::ZSTD_getErrorName(code);
666 c_char_to_str(name)
667 }
668}
669
670pub fn compress_cctx(
672 ctx: &mut CCtx<'_>,
673 dst: &mut [u8],
674 src: &[u8],
675 compression_level: CompressionLevel,
676) -> SafeResult {
677 ctx.compress(dst, src, compression_level)
678}
679
680pub fn compress2(
682 ctx: &mut CCtx<'_>,
683 dst: &mut [u8],
684 src: &[u8],
685) -> SafeResult {
686 ctx.compress2(dst, src)
687}
688
689pub struct DCtx<'a>(NonNull<zstd_sys::ZSTD_DCtx>, PhantomData<&'a ()>);
697
698impl Default for DCtx<'_> {
699 fn default() -> Self {
700 DCtx::create()
701 }
702}
703
704impl DCtx<'static> {
705 pub fn try_create() -> Option<Self> {
706 Some(DCtx(
707 NonNull::new(unsafe { zstd_sys::ZSTD_createDCtx() })?,
708 PhantomData,
709 ))
710 }
711 pub fn create() -> Self {
712 Self::try_create()
713 .expect("zstd returned null pointer when creating new context")
714 }
715}
716
717impl<'a> DCtx<'a> {
718 pub fn decompress<C: WriteBuf + ?Sized>(
720 &mut self,
721 dst: &mut C,
722 src: &[u8],
723 ) -> SafeResult {
724 unsafe {
725 dst.write_from(|buffer, capacity| {
726 parse_code(zstd_sys::ZSTD_decompressDCtx(
727 self.0.as_ptr(),
728 buffer,
729 capacity,
730 ptr_void(src),
731 src.len(),
732 ))
733 })
734 }
735 }
736
737 pub fn decompress_using_dict<C: WriteBuf + ?Sized>(
739 &mut self,
740 dst: &mut C,
741 src: &[u8],
742 dict: &[u8],
743 ) -> SafeResult {
744 unsafe {
745 dst.write_from(|buffer, capacity| {
746 parse_code(zstd_sys::ZSTD_decompress_usingDict(
747 self.0.as_ptr(),
748 buffer,
749 capacity,
750 ptr_void(src),
751 src.len(),
752 ptr_void(dict),
753 dict.len(),
754 ))
755 })
756 }
757 }
758
759 pub fn decompress_using_ddict<C: WriteBuf + ?Sized>(
761 &mut self,
762 dst: &mut C,
763 src: &[u8],
764 ddict: &DDict<'_>,
765 ) -> SafeResult {
766 unsafe {
767 dst.write_from(|buffer, capacity| {
768 parse_code(zstd_sys::ZSTD_decompress_usingDDict(
769 self.0.as_ptr(),
770 buffer,
771 capacity,
772 ptr_void(src),
773 src.len(),
774 ddict.0.as_ptr(),
775 ))
776 })
777 }
778 }
779
780 pub fn init(&mut self) -> usize {
784 unsafe { zstd_sys::ZSTD_initDStream(self.0.as_ptr()) }
785 }
786
787 #[cfg(feature = "experimental")]
789 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
790 #[deprecated]
791 pub fn init_using_dict(&mut self, dict: &[u8]) -> SafeResult {
792 let code = unsafe {
793 zstd_sys::ZSTD_initDStream_usingDict(
794 self.0.as_ptr(),
795 ptr_void(dict),
796 dict.len(),
797 )
798 };
799 parse_code(code)
800 }
801
802 #[cfg(feature = "experimental")]
804 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
805 #[deprecated]
806 pub fn init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
807 where
808 'b: 'a,
809 {
810 let code = unsafe {
811 zstd_sys::ZSTD_initDStream_usingDDict(
812 self.0.as_ptr(),
813 ddict.0.as_ptr(),
814 )
815 };
816 parse_code(code)
817 }
818
819 pub fn reset(&mut self) -> SafeResult {
821 let code = unsafe {
822 zstd_sys::ZSTD_DCtx_reset(
823 self.0.as_ptr(),
824 ResetDirective::ZSTD_reset_session_only,
825 )
826 };
827 parse_code(code)
828 }
829
830 pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
831 parse_code(unsafe {
832 zstd_sys::ZSTD_DCtx_loadDictionary(
833 self.0.as_ptr(),
834 ptr_void(dict),
835 dict.len(),
836 )
837 })
838 }
839
840 pub fn ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
841 where
842 'b: 'a,
843 {
844 parse_code(unsafe {
845 zstd_sys::ZSTD_DCtx_refDDict(self.0.as_ptr(), ddict.0.as_ptr())
846 })
847 }
848
849 pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
850 where
851 'b: 'a,
852 {
853 parse_code(unsafe {
854 zstd_sys::ZSTD_DCtx_refPrefix(
855 self.0.as_ptr(),
856 ptr_void(prefix),
857 prefix.len(),
858 )
859 })
860 }
861
862 pub fn set_parameter(&mut self, param: DParameter) -> SafeResult {
863 #[cfg(feature = "experimental")]
864 use zstd_sys::ZSTD_dParameter::{
865 ZSTD_d_experimentalParam1 as ZSTD_d_format,
866 ZSTD_d_experimentalParam2 as ZSTD_d_stableOutBuffer,
867 ZSTD_d_experimentalParam3 as ZSTD_d_forceIgnoreChecksum,
868 ZSTD_d_experimentalParam4 as ZSTD_d_refMultipleDDicts,
869 };
870
871 use zstd_sys::ZSTD_dParameter::*;
872 use DParameter::*;
873
874 let (param, value) = match param {
875 #[cfg(feature = "experimental")]
876 Format(format) => (ZSTD_d_format, format as c_int),
877 #[cfg(feature = "experimental")]
878 StableOutBuffer(stable) => {
879 (ZSTD_d_stableOutBuffer, stable as c_int)
880 }
881 #[cfg(feature = "experimental")]
882 ForceIgnoreChecksum(force) => {
883 (ZSTD_d_forceIgnoreChecksum, force as c_int)
884 }
885 #[cfg(feature = "experimental")]
886 RefMultipleDDicts(value) => {
887 (ZSTD_d_refMultipleDDicts, value as c_int)
888 }
889
890 WindowLogMax(value) => (ZSTD_d_windowLogMax, value as c_int),
891 };
892
893 parse_code(unsafe {
894 zstd_sys::ZSTD_DCtx_setParameter(self.0.as_ptr(), param, value)
895 })
896 }
897
898 pub fn decompress_stream<C: WriteBuf + ?Sized>(
900 &mut self,
901 output: &mut OutBuffer<'_, C>,
902 input: &mut InBuffer<'_>,
903 ) -> SafeResult {
904 let mut output = output.wrap();
905 let mut input = input.wrap();
906 let code = unsafe {
907 zstd_sys::ZSTD_decompressStream(
908 self.0.as_ptr(),
909 ptr_mut(&mut output),
910 ptr_mut(&mut input),
911 )
912 };
913 parse_code(code)
914 }
915
916 pub fn in_size() -> usize {
920 unsafe { zstd_sys::ZSTD_DStreamInSize() }
921 }
922
923 pub fn out_size() -> usize {
927 unsafe { zstd_sys::ZSTD_DStreamOutSize() }
928 }
929
930 pub fn sizeof(&self) -> usize {
932 unsafe { zstd_sys::ZSTD_sizeof_DCtx(self.0.as_ptr()) }
933 }
934
935 #[cfg(feature = "experimental")]
937 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
938 pub fn decompress_block<C: WriteBuf + ?Sized>(
939 &mut self,
940 dst: &mut C,
941 src: &[u8],
942 ) -> SafeResult {
943 unsafe {
944 dst.write_from(|buffer, capacity| {
945 parse_code(zstd_sys::ZSTD_decompressBlock(
946 self.0.as_ptr(),
947 buffer,
948 capacity,
949 ptr_void(src),
950 src.len(),
951 ))
952 })
953 }
954 }
955
956 #[cfg(feature = "experimental")]
958 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
959 pub fn insert_block(&mut self, block: &[u8]) -> usize {
960 unsafe {
961 zstd_sys::ZSTD_insertBlock(
962 self.0.as_ptr(),
963 ptr_void(block),
964 block.len(),
965 )
966 }
967 }
968
969 #[cfg(feature = "experimental")]
974 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
975 pub fn try_clone(&self) -> Result<Self, ErrorCode> {
976 let context = NonNull::new(unsafe { zstd_sys::ZSTD_createDCtx() })
977 .ok_or(0usize)?;
978
979 unsafe { zstd_sys::ZSTD_copyDCtx(context.as_ptr(), self.0.as_ptr()) };
980
981 Ok(DCtx(context, self.1))
982 }
983}
984
985pub fn create_dctx() -> DCtx<'static> {
987 DCtx::create()
988}
989
990impl Drop for DCtx<'_> {
991 fn drop(&mut self) {
992 unsafe {
993 zstd_sys::ZSTD_freeDCtx(self.0.as_ptr());
994 }
995 }
996}
997
998unsafe impl Send for DCtx<'_> {}
999pub fn decompress_dctx(
1003 ctx: &mut DCtx<'_>,
1004 dst: &mut [u8],
1005 src: &[u8],
1006) -> SafeResult {
1007 ctx.decompress(dst, src)
1008}
1009
1010pub fn compress_using_dict(
1012 ctx: &mut CCtx<'_>,
1013 dst: &mut [u8],
1014 src: &[u8],
1015 dict: &[u8],
1016 compression_level: CompressionLevel,
1017) -> SafeResult {
1018 ctx.compress_using_dict(dst, src, dict, compression_level)
1019}
1020
1021pub fn decompress_using_dict(
1023 dctx: &mut DCtx<'_>,
1024 dst: &mut [u8],
1025 src: &[u8],
1026 dict: &[u8],
1027) -> SafeResult {
1028 dctx.decompress_using_dict(dst, src, dict)
1029}
1030
1031pub struct CDict<'a>(NonNull<zstd_sys::ZSTD_CDict>, PhantomData<&'a ()>);
1033
1034impl CDict<'static> {
1035 pub fn create(
1036 dict_buffer: &[u8],
1037 compression_level: CompressionLevel,
1038 ) -> Self {
1039 Self::try_create(dict_buffer, compression_level)
1040 .expect("zstd returned null pointer when creating dict")
1041 }
1042
1043 pub fn try_create(
1044 dict_buffer: &[u8],
1045 compression_level: CompressionLevel,
1046 ) -> Option<Self> {
1047 Some(CDict(
1048 NonNull::new(unsafe {
1049 zstd_sys::ZSTD_createCDict(
1050 ptr_void(dict_buffer),
1051 dict_buffer.len(),
1052 compression_level,
1053 )
1054 })?,
1055 PhantomData,
1056 ))
1057 }
1058}
1059
1060impl<'a> CDict<'a> {
1061 #[cfg(feature = "experimental")]
1062 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1063 pub fn create_by_reference(
1064 dict_buffer: &'a [u8],
1065 compression_level: CompressionLevel,
1066 ) -> Self {
1067 CDict(
1068 NonNull::new(unsafe {
1069 zstd_sys::ZSTD_createCDict_byReference(
1070 ptr_void(dict_buffer),
1071 dict_buffer.len(),
1072 compression_level,
1073 )
1074 })
1075 .expect("zstd returned null pointer"),
1076 PhantomData,
1077 )
1078 }
1079
1080 pub fn sizeof(&self) -> usize {
1081 unsafe { zstd_sys::ZSTD_sizeof_CDict(self.0.as_ptr()) }
1082 }
1083
1084 pub fn get_dict_id(&self) -> u32 {
1085 unsafe { zstd_sys::ZSTD_getDictID_fromCDict(self.0.as_ptr()) as u32 }
1086 }
1087}
1088
1089pub fn create_cdict(
1091 dict_buffer: &[u8],
1092 compression_level: CompressionLevel,
1093) -> CDict<'static> {
1094 CDict::create(dict_buffer, compression_level)
1095}
1096
1097impl<'a> Drop for CDict<'a> {
1098 fn drop(&mut self) {
1099 unsafe {
1100 zstd_sys::ZSTD_freeCDict(self.0.as_ptr());
1101 }
1102 }
1103}
1104
1105unsafe impl<'a> Send for CDict<'a> {}
1106unsafe impl<'a> Sync for CDict<'a> {}
1107
1108pub fn compress_using_cdict(
1110 cctx: &mut CCtx<'_>,
1111 dst: &mut [u8],
1112 src: &[u8],
1113 cdict: &CDict<'_>,
1114) -> SafeResult {
1115 cctx.compress_using_cdict(dst, src, cdict)
1116}
1117
1118pub struct DDict<'a>(NonNull<zstd_sys::ZSTD_DDict>, PhantomData<&'a ()>);
1120
1121impl DDict<'static> {
1122 pub fn create(dict_buffer: &[u8]) -> Self {
1123 Self::try_create(dict_buffer)
1124 .expect("zstd returned null pointer when creating dict")
1125 }
1126
1127 pub fn try_create(dict_buffer: &[u8]) -> Option<Self> {
1128 Some(DDict(
1129 NonNull::new(unsafe {
1130 zstd_sys::ZSTD_createDDict(
1131 ptr_void(dict_buffer),
1132 dict_buffer.len(),
1133 )
1134 })?,
1135 PhantomData,
1136 ))
1137 }
1138}
1139
1140impl<'a> DDict<'a> {
1141 pub fn sizeof(&self) -> usize {
1142 unsafe { zstd_sys::ZSTD_sizeof_DDict(self.0.as_ptr()) }
1143 }
1144
1145 #[cfg(feature = "experimental")]
1149 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1150 pub fn create_by_reference(dict_buffer: &'a [u8]) -> Self {
1151 DDict(
1152 NonNull::new(unsafe {
1153 zstd_sys::ZSTD_createDDict_byReference(
1154 ptr_void(dict_buffer),
1155 dict_buffer.len(),
1156 )
1157 })
1158 .expect("zstd returned null pointer"),
1159 PhantomData,
1160 )
1161 }
1162
1163 pub fn get_dict_id(&self) -> u32 {
1164 unsafe { zstd_sys::ZSTD_getDictID_fromDDict(self.0.as_ptr()) as u32 }
1165 }
1166}
1167
1168pub fn create_ddict(dict_buffer: &[u8]) -> DDict<'static> {
1172 DDict::create(dict_buffer)
1173}
1174
1175impl<'a> Drop for DDict<'a> {
1176 fn drop(&mut self) {
1177 unsafe {
1178 zstd_sys::ZSTD_freeDDict(self.0.as_ptr());
1179 }
1180 }
1181}
1182
1183unsafe impl<'a> Send for DDict<'a> {}
1184unsafe impl<'a> Sync for DDict<'a> {}
1185
1186pub fn decompress_using_ddict(
1188 dctx: &mut DCtx<'_>,
1189 dst: &mut [u8],
1190 src: &[u8],
1191 ddict: &DDict<'_>,
1192) -> SafeResult {
1193 dctx.decompress_using_ddict(dst, src, ddict)
1194}
1195
1196pub type CStream<'a> = CCtx<'a>;
1200
1201pub fn create_cstream<'a>() -> CStream<'a> {
1205 CCtx::create()
1206}
1207
1208pub fn init_cstream(
1210 zcs: &mut CStream<'_>,
1211 compression_level: CompressionLevel,
1212) -> usize {
1213 zcs.init(compression_level)
1214}
1215
1216#[derive(Debug)]
1217pub struct InBuffer<'a> {
1223 pub src: &'a [u8],
1224 pub pos: usize,
1225}
1226
1227pub unsafe trait WriteBuf {
1239 fn as_slice(&self) -> &[u8];
1241
1242 fn capacity(&self) -> usize;
1244
1245 fn as_mut_ptr(&mut self) -> *mut u8;
1247
1248 unsafe fn filled_until(&mut self, n: usize);
1250
1251 unsafe fn write_from<F>(&mut self, f: F) -> SafeResult
1262 where
1263 F: FnOnce(*mut c_void, usize) -> SafeResult,
1264 {
1265 let res = f(ptr_mut_void(self), self.capacity());
1266 if let Ok(n) = res {
1267 self.filled_until(n);
1268 }
1269 res
1270 }
1271}
1272
1273#[cfg(feature = "std")]
1274#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "std")))]
1275unsafe impl WriteBuf for std::vec::Vec<u8> {
1276 fn as_slice(&self) -> &[u8] {
1277 &self[..]
1278 }
1279 fn capacity(&self) -> usize {
1280 self.capacity()
1281 }
1282 fn as_mut_ptr(&mut self) -> *mut u8 {
1283 self.as_mut_ptr()
1284 }
1285 unsafe fn filled_until(&mut self, n: usize) {
1286 self.set_len(n);
1287 }
1288}
1289
1290#[cfg(feature = "arrays")]
1291#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "arrays")))]
1292unsafe impl<const N: usize> WriteBuf for [u8; N] {
1293 fn as_slice(&self) -> &[u8] {
1294 self
1295 }
1296 fn capacity(&self) -> usize {
1297 self.len()
1298 }
1299
1300 fn as_mut_ptr(&mut self) -> *mut u8 {
1301 (&mut self[..]).as_mut_ptr()
1302 }
1303
1304 unsafe fn filled_until(&mut self, _n: usize) {
1305 }
1307}
1308
1309unsafe impl WriteBuf for [u8] {
1310 fn as_slice(&self) -> &[u8] {
1311 self
1312 }
1313 fn capacity(&self) -> usize {
1314 self.len()
1315 }
1316
1317 fn as_mut_ptr(&mut self) -> *mut u8 {
1318 self.as_mut_ptr()
1319 }
1320
1321 unsafe fn filled_until(&mut self, _n: usize) {
1322 }
1324}
1325
1326#[derive(Debug)]
1345pub struct OutBuffer<'a, C: WriteBuf + ?Sized> {
1357 pub dst: &'a mut C,
1358 pos: usize,
1359}
1360
1361fn ptr_mut<B>(ptr_void: &mut B) -> *mut B {
1363 ptr_void as *mut B
1364}
1365
1366struct OutBufferWrapper<'a, 'b, C: WriteBuf + ?Sized> {
1370 buf: zstd_sys::ZSTD_outBuffer,
1371 parent: &'a mut OutBuffer<'b, C>,
1372}
1373
1374impl<'a, 'b: 'a, C: WriteBuf + ?Sized> Deref for OutBufferWrapper<'a, 'b, C> {
1375 type Target = zstd_sys::ZSTD_outBuffer;
1376
1377 fn deref(&self) -> &Self::Target {
1378 &self.buf
1379 }
1380}
1381
1382impl<'a, 'b: 'a, C: WriteBuf + ?Sized> DerefMut
1383 for OutBufferWrapper<'a, 'b, C>
1384{
1385 fn deref_mut(&mut self) -> &mut Self::Target {
1386 &mut self.buf
1387 }
1388}
1389
1390impl<'a, C: WriteBuf + ?Sized> OutBuffer<'a, C> {
1391 pub fn around(dst: &'a mut C) -> Self {
1395 OutBuffer { dst, pos: 0 }
1396 }
1397
1398 pub fn around_pos(dst: &'a mut C, pos: usize) -> Self {
1404 if pos >= dst.capacity() {
1405 panic!("Given position outside of the buffer bounds.");
1406 }
1407
1408 OutBuffer { dst, pos }
1409 }
1410
1411 pub fn pos(&self) -> usize {
1413 self.pos
1414 }
1415
1416 pub unsafe fn set_pos(&mut self, pos: usize) {
1426 if pos > self.dst.capacity() {
1427 panic!("Given position outside of the buffer bounds.");
1428 }
1429
1430 self.dst.filled_until(pos);
1431
1432 self.pos = pos;
1433 }
1434
1435 fn wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a, C> {
1436 OutBufferWrapper {
1437 buf: zstd_sys::ZSTD_outBuffer {
1438 dst: ptr_mut_void(self.dst),
1439 size: self.dst.capacity(),
1440 pos: self.pos,
1441 },
1442 parent: self,
1443 }
1444 }
1445
1446 pub fn as_slice<'b>(&'b self) -> &'a [u8]
1448 where
1449 'b: 'a,
1450 {
1451 let pos = self.pos;
1452 &self.dst.as_slice()[..pos]
1453 }
1454}
1455
1456impl<'a, 'b, C: WriteBuf + ?Sized> Drop for OutBufferWrapper<'a, 'b, C> {
1457 fn drop(&mut self) {
1458 unsafe { self.parent.set_pos(self.buf.pos) };
1460 }
1461}
1462
1463struct InBufferWrapper<'a, 'b> {
1464 buf: zstd_sys::ZSTD_inBuffer,
1465 parent: &'a mut InBuffer<'b>,
1466}
1467
1468impl<'a, 'b: 'a> Deref for InBufferWrapper<'a, 'b> {
1469 type Target = zstd_sys::ZSTD_inBuffer;
1470
1471 fn deref(&self) -> &Self::Target {
1472 &self.buf
1473 }
1474}
1475
1476impl<'a, 'b: 'a> DerefMut for InBufferWrapper<'a, 'b> {
1477 fn deref_mut(&mut self) -> &mut Self::Target {
1478 &mut self.buf
1479 }
1480}
1481
1482impl<'a> InBuffer<'a> {
1483 pub fn around(src: &'a [u8]) -> Self {
1487 InBuffer { src, pos: 0 }
1488 }
1489
1490 pub fn pos(&self) -> usize {
1492 self.pos
1493 }
1494
1495 pub fn set_pos(&mut self, pos: usize) {
1501 if pos > self.src.len() {
1502 panic!("Given position outside of the buffer bounds.");
1503 }
1504 self.pos = pos;
1505 }
1506
1507 fn wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a> {
1508 InBufferWrapper {
1509 buf: zstd_sys::ZSTD_inBuffer {
1510 src: ptr_void(self.src),
1511 size: self.src.len(),
1512 pos: self.pos,
1513 },
1514 parent: self,
1515 }
1516 }
1517}
1518
1519impl<'a, 'b> Drop for InBufferWrapper<'a, 'b> {
1520 fn drop(&mut self) {
1521 self.parent.set_pos(self.buf.pos);
1522 }
1523}
1524
1525pub fn compress_stream<C: WriteBuf + ?Sized>(
1527 zcs: &mut CStream<'_>,
1528 output: &mut OutBuffer<'_, C>,
1529 input: &mut InBuffer<'_>,
1530) -> SafeResult {
1531 zcs.compress_stream(output, input)
1532}
1533
1534pub fn compress_stream2<C: WriteBuf + ?Sized>(
1535 cctx: &mut CCtx<'_>,
1536 output: &mut OutBuffer<'_, C>,
1537 input: &mut InBuffer<'_>,
1538 end_op: zstd_sys::ZSTD_EndDirective,
1539) -> SafeResult {
1540 cctx.compress_stream2(output, input, end_op)
1541}
1542
1543pub fn flush_stream<C: WriteBuf + ?Sized>(
1545 zcs: &mut CStream<'_>,
1546 output: &mut OutBuffer<'_, C>,
1547) -> SafeResult {
1548 zcs.flush_stream(output)
1549}
1550
1551pub fn end_stream<C: WriteBuf + ?Sized>(
1553 zcs: &mut CStream<'_>,
1554 output: &mut OutBuffer<'_, C>,
1555) -> SafeResult {
1556 zcs.end_stream(output)
1557}
1558
1559pub fn cstream_in_size() -> usize {
1561 CCtx::in_size()
1562}
1563
1564pub fn cstream_out_size() -> usize {
1566 CCtx::out_size()
1567}
1568
1569pub type DStream<'a> = DCtx<'a>;
1573
1574pub fn create_dstream() -> DStream<'static> {
1575 DStream::create()
1576}
1577
1578pub fn init_dstream(zds: &mut DStream<'_>) -> usize {
1582 zds.init()
1583}
1584
1585pub fn decompress_stream<C: WriteBuf + ?Sized>(
1587 zds: &mut DStream<'_>,
1588 output: &mut OutBuffer<'_, C>,
1589 input: &mut InBuffer<'_>,
1590) -> SafeResult {
1591 zds.decompress_stream(output, input)
1592}
1593
1594pub fn dstream_in_size() -> usize {
1598 DStream::in_size()
1599}
1600
1601pub fn dstream_out_size() -> usize {
1605 DStream::out_size()
1606}
1607
1608pub fn find_frame_compressed_size(src: &[u8]) -> SafeResult {
1612 let code = unsafe {
1613 zstd_sys::ZSTD_findFrameCompressedSize(ptr_void(src), src.len())
1614 };
1615 parse_code(code)
1616}
1617
1618pub fn get_frame_content_size(src: &[u8]) -> u64 {
1622 unsafe { zstd_sys::ZSTD_getFrameContentSize(ptr_void(src), src.len()) }
1623}
1624
1625#[cfg(feature = "experimental")]
1629#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1630pub fn find_decompressed_size(src: &[u8]) -> u64 {
1631 unsafe { zstd_sys::ZSTD_findDecompressedSize(ptr_void(src), src.len()) }
1632}
1633
1634pub fn sizeof_cctx(cctx: &CCtx<'_>) -> usize {
1636 cctx.sizeof()
1637}
1638
1639pub fn sizeof_dctx(dctx: &DCtx<'_>) -> usize {
1641 dctx.sizeof()
1642}
1643
1644pub fn sizeof_cstream(zcs: &CStream<'_>) -> usize {
1646 zcs.sizeof()
1647}
1648
1649pub fn sizeof_dstream(zds: &DStream<'_>) -> usize {
1651 zds.sizeof()
1652}
1653
1654pub fn sizeof_cdict(cdict: &CDict<'_>) -> usize {
1656 cdict.sizeof()
1657}
1658
1659pub fn sizeof_ddict(ddict: &DDict<'_>) -> usize {
1661 ddict.sizeof()
1662}
1663
1664#[cfg(feature = "experimental")]
1668#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1669pub fn create_cdict_by_reference<'a>(
1670 dict_buffer: &'a [u8],
1671 compression_level: CompressionLevel,
1672) -> CDict<'a> {
1673 CDict::create_by_reference(dict_buffer, compression_level)
1674}
1675
1676#[cfg(feature = "experimental")]
1678#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1679pub fn is_frame(buffer: &[u8]) -> u32 {
1680 unsafe { zstd_sys::ZSTD_isFrame(ptr_void(buffer), buffer.len()) as u32 }
1681}
1682
1683#[cfg(feature = "experimental")]
1687#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1688pub fn create_ddict_by_reference(dict_buffer: &[u8]) -> DDict {
1689 DDict::create_by_reference(dict_buffer)
1690}
1691
1692pub fn get_dict_id_from_dict(dict: &[u8]) -> u32 {
1694 unsafe {
1695 zstd_sys::ZSTD_getDictID_fromDict(ptr_void(dict), dict.len()) as u32
1696 }
1697}
1698
1699pub fn get_dict_id_from_ddict(ddict: &DDict<'_>) -> u32 {
1701 ddict.get_dict_id()
1702}
1703
1704pub fn get_dict_id_from_frame(src: &[u8]) -> u32 {
1706 unsafe {
1707 zstd_sys::ZSTD_getDictID_fromFrame(ptr_void(src), src.len()) as u32
1708 }
1709}
1710
1711#[cfg(feature = "experimental")]
1713#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1714#[deprecated]
1715#[allow(deprecated)]
1716pub fn init_cstream_src_size(
1717 zcs: &mut CStream,
1718 compression_level: CompressionLevel,
1719 pledged_src_size: u64,
1720) -> usize {
1721 zcs.init_src_size(compression_level, pledged_src_size)
1722}
1723
1724#[cfg(feature = "experimental")]
1726#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1727#[deprecated]
1728#[allow(deprecated)]
1729pub fn init_cstream_using_dict(
1730 zcs: &mut CStream,
1731 dict: &[u8],
1732 compression_level: CompressionLevel,
1733) -> SafeResult {
1734 zcs.init_using_dict(dict, compression_level)
1735}
1736
1737#[cfg(feature = "experimental")]
1739#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1740#[deprecated]
1741#[allow(deprecated)]
1742pub fn init_cstream_using_cdict<'a, 'b>(
1743 zcs: &mut CStream<'a>,
1744 cdict: &CDict<'b>,
1745) -> SafeResult
1746where
1747 'b: 'a, {
1749 zcs.init_using_cdict(cdict)
1750}
1751
1752pub fn cctx_load_dictionary(cctx: &mut CCtx<'_>, dict: &[u8]) -> SafeResult {
1754 cctx.load_dictionary(dict)
1755}
1756
1757pub fn cctx_ref_cdict<'a, 'b>(
1761 cctx: &mut CCtx<'a>,
1762 cdict: &CDict<'b>,
1763) -> SafeResult
1764where
1765 'b: 'a,
1766{
1767 cctx.ref_cdict(cdict)
1768}
1769
1770pub fn cctx_ref_prefix<'a, 'b>(
1774 cctx: &mut CCtx<'a>,
1775 prefix: &'b [u8],
1776) -> SafeResult
1777where
1778 'b: 'a,
1779{
1780 cctx.ref_prefix(prefix)
1781}
1782
1783pub fn dctx_load_dictionary(dctx: &mut DCtx<'_>, dict: &[u8]) -> SafeResult {
1785 dctx.load_dictionary(dict)
1786}
1787
1788pub fn dctx_ref_ddict<'a, 'b>(
1790 dctx: &mut DCtx<'a>,
1791 ddict: &'b DDict<'b>,
1792) -> SafeResult
1793where
1794 'b: 'a,
1795{
1796 dctx.ref_ddict(ddict)
1797}
1798
1799pub fn dctx_ref_prefix<'a, 'b>(
1801 dctx: &mut DCtx<'a>,
1802 prefix: &'b [u8],
1803) -> SafeResult
1804where
1805 'b: 'a,
1806{
1807 dctx.ref_prefix(prefix)
1808}
1809
1810pub fn cctx_reset(cctx: &mut CCtx<'_>, reset: ResetDirective) -> SafeResult {
1812 cctx.reset(reset)
1813}
1814
1815pub fn dctx_reset(dctx: &mut DCtx<'_>, reset: ResetDirective) -> SafeResult {
1817 parse_code(unsafe { zstd_sys::ZSTD_DCtx_reset(dctx.0.as_ptr(), reset) })
1818}
1819
1820#[cfg(feature = "experimental")]
1822#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1823#[deprecated]
1824#[allow(deprecated)]
1825pub fn reset_cstream(zcs: &mut CStream, pledged_src_size: u64) -> SafeResult {
1826 zcs.reset_cstream(pledged_src_size)
1827}
1828
1829#[cfg(feature = "experimental")]
1831#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1832#[deprecated]
1833#[allow(deprecated)]
1834pub fn init_dstream_using_dict(zds: &mut DStream, dict: &[u8]) -> SafeResult {
1835 zds.init_using_dict(dict)
1836}
1837
1838#[cfg(feature = "experimental")]
1840#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1841#[deprecated]
1842#[allow(deprecated)]
1843pub fn init_dstream_using_ddict<'a, 'b>(
1844 zds: &mut DStream<'a>,
1845 ddict: &DDict<'b>,
1846) -> SafeResult
1847where
1848 'b: 'a,
1849{
1850 zds.init_using_ddict(ddict)
1851}
1852
1853#[cfg(feature = "experimental")]
1855#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1856pub fn reset_dstream(zds: &mut DStream) -> SafeResult {
1857 zds.reset()
1858}
1859
1860#[cfg(feature = "experimental")]
1861#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1862#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1863#[repr(u32)]
1864pub enum FrameFormat {
1865 One = zstd_sys::ZSTD_format_e::ZSTD_f_zstd1 as u32,
1867
1868 Magicless = zstd_sys::ZSTD_format_e::ZSTD_f_zstd1_magicless as u32,
1870}
1871
1872#[cfg(feature = "experimental")]
1873#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1874#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1875#[repr(u32)]
1876pub enum DictAttachPref {
1877 DefaultAttach =
1878 zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictDefaultAttach as u32,
1879 ForceAttach = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceAttach as u32,
1880 ForceCopy = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceCopy as u32,
1881 ForceLoad = zstd_sys::ZSTD_dictAttachPref_e::ZSTD_dictForceLoad as u32,
1882}
1883
1884#[cfg(feature = "experimental")]
1885#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1886#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1887#[repr(u32)]
1888pub enum ParamSwitch {
1889 Auto = zstd_sys::ZSTD_paramSwitch_e::ZSTD_ps_auto as u32,
1890 Enable = zstd_sys::ZSTD_paramSwitch_e::ZSTD_ps_enable as u32,
1891 Disable = zstd_sys::ZSTD_paramSwitch_e::ZSTD_ps_disable as u32,
1892}
1893
1894#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1896pub enum CParameter {
1897 #[cfg(feature = "experimental")]
1898 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1899 RSyncable(bool),
1900
1901 #[cfg(feature = "experimental")]
1902 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1903 Format(FrameFormat),
1904
1905 #[cfg(feature = "experimental")]
1906 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1907 ForceMaxWindow(bool),
1908
1909 #[cfg(feature = "experimental")]
1910 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1911 ForceAttachDict(DictAttachPref),
1912
1913 #[cfg(feature = "experimental")]
1914 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1915 LiteralCompressionMode(ParamSwitch),
1916
1917 #[cfg(feature = "experimental")]
1918 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1919 TargetCBlockSize(u32),
1920
1921 #[cfg(feature = "experimental")]
1922 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1923 SrcSizeHint(u32),
1924
1925 #[cfg(feature = "experimental")]
1926 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1927 EnableDedicatedDictSearch(bool),
1928
1929 #[cfg(feature = "experimental")]
1930 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1931 StableInBuffer(bool),
1932
1933 #[cfg(feature = "experimental")]
1934 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1935 StableOutBuffer(bool),
1936
1937 #[cfg(feature = "experimental")]
1938 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1939 BlockDelimiters(bool),
1940
1941 #[cfg(feature = "experimental")]
1942 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1943 ValidateSequences(bool),
1944
1945 #[cfg(feature = "experimental")]
1946 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1947 UseBlockSplitter(ParamSwitch),
1948
1949 #[cfg(feature = "experimental")]
1950 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1951 UseRowMatchFinder(ParamSwitch),
1952
1953 #[cfg(feature = "experimental")]
1954 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
1955 DeterministicRefPrefix(bool),
1956
1957 CompressionLevel(CompressionLevel),
1958
1959 WindowLog(u32),
1960
1961 HashLog(u32),
1962
1963 ChainLog(u32),
1964
1965 SearchLog(u32),
1966
1967 MinMatch(u32),
1968
1969 TargetLength(u32),
1970
1971 Strategy(Strategy),
1972
1973 EnableLongDistanceMatching(bool),
1974
1975 LdmHashLog(u32),
1976
1977 LdmMinMatch(u32),
1978
1979 LdmBucketSizeLog(u32),
1980
1981 LdmHashRateLog(u32),
1982
1983 ContentSizeFlag(bool),
1984
1985 ChecksumFlag(bool),
1986
1987 DictIdFlag(bool),
1988
1989 NbWorkers(u32),
1991
1992 JobSize(u32),
1993
1994 OverlapSizeLog(u32),
1995}
1996
1997pub enum DParameter {
1999 WindowLogMax(u32),
2000
2001 #[cfg(feature = "experimental")]
2003 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2004 Format(FrameFormat),
2005
2006 #[cfg(feature = "experimental")]
2007 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2008 StableOutBuffer(bool),
2009
2010 #[cfg(feature = "experimental")]
2011 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2012 ForceIgnoreChecksum(bool),
2013
2014 #[cfg(feature = "experimental")]
2015 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2016 RefMultipleDDicts(bool),
2017}
2018
2019pub fn dctx_set_parameter(
2021 dctx: &mut DCtx<'_>,
2022 param: DParameter,
2023) -> SafeResult {
2024 dctx.set_parameter(param)
2025}
2026
2027pub fn cctx_set_parameter(
2029 cctx: &mut CCtx<'_>,
2030 param: CParameter,
2031) -> SafeResult {
2032 cctx.set_parameter(param)
2033}
2034
2035pub fn cctx_set_pledged_src_size(
2037 cctx: &mut CCtx<'_>,
2038 pledged_src_size: u64,
2039) -> SafeResult {
2040 cctx.set_pledged_src_size(pledged_src_size)
2041}
2042
2043#[cfg(feature = "zdict_builder")]
2045#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "zdict_builder")))]
2046pub fn train_from_buffer<C: WriteBuf + ?Sized>(
2047 dict_buffer: &mut C,
2048 samples_buffer: &[u8],
2049 samples_sizes: &[usize],
2050) -> SafeResult {
2051 assert_eq!(samples_buffer.len(), samples_sizes.iter().sum());
2052
2053 unsafe {
2054 dict_buffer.write_from(|buffer, capacity| {
2055 parse_code(zstd_sys::ZDICT_trainFromBuffer(
2056 buffer,
2057 capacity,
2058 ptr_void(samples_buffer),
2059 samples_sizes.as_ptr(),
2060 samples_sizes.len() as u32,
2061 ))
2062 })
2063 }
2064}
2065
2066#[cfg(feature = "zdict_builder")]
2068#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "zdict_builder")))]
2069pub fn get_dict_id(dict_buffer: &[u8]) -> Option<u32> {
2070 let id = unsafe {
2071 zstd_sys::ZDICT_getDictID(ptr_void(dict_buffer), dict_buffer.len())
2072 };
2073 if id > 0 {
2074 Some(id)
2075 } else {
2076 None
2077 }
2078}
2079
2080#[cfg(feature = "experimental")]
2082#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2083pub fn get_block_size(cctx: &CCtx) -> usize {
2084 unsafe { zstd_sys::ZSTD_getBlockSize(cctx.0.as_ptr()) }
2085}
2086
2087#[cfg(feature = "experimental")]
2089#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2090pub fn compress_block(
2091 cctx: &mut CCtx,
2092 dst: &mut [u8],
2093 src: &[u8],
2094) -> SafeResult {
2095 cctx.compress_block(dst, src)
2096}
2097
2098#[cfg(feature = "experimental")]
2100#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2101pub fn decompress_block(
2102 dctx: &mut DCtx,
2103 dst: &mut [u8],
2104 src: &[u8],
2105) -> SafeResult {
2106 dctx.decompress_block(dst, src)
2107}
2108
2109#[cfg(feature = "experimental")]
2111#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2112pub fn insert_block(dctx: &mut DCtx, block: &[u8]) -> usize {
2113 dctx.insert_block(block)
2114}
2115
2116#[cfg(feature = "experimental")]
2118#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "experimental")))]
2119pub fn decompress_bound(data: &[u8]) -> Result<u64, ErrorCode> {
2120 let bound =
2121 unsafe { zstd_sys::ZSTD_decompressBound(ptr_void(data), data.len()) };
2122 if is_error(bound as usize) {
2123 Err(bound as usize)
2124 } else {
2125 Ok(bound)
2126 }
2127}