1 #![no_std]
2 //! Minimal safe wrapper around zstd-sys.
3 //!
4 //! This crates provides a minimal translation of the [zstd-sys] methods.
5 //! For a more comfortable high-level library, see the [zstd] crate.
6 //!
7 //! [zstd-sys]: http://crates.io/crates/zstd-sys
8 //! [zstd]: https://crates.io/crates/zstd
9 //!
10 //! Most of the functions here map 1-for-1 to a function from
11 //! [the C zstd library][zstd-c] mentionned in their descriptions.
12 //! Check the [source documentation][doc] for more information on their
13 //! behaviour.
14 //!
15 //! [doc]: http://facebook.github.io/zstd/zstd_manual.html
16 //! [zstd-c]: https://facebook.github.io/zstd/
17 //!
18 //! Features denoted as experimental in the C library are hidden behind an
19 //! `experimental` feature.
20 
21 extern crate libc;
22 extern crate zstd_sys;
23 
24 #[cfg(feature = "std")]
25 extern crate std;
26 
27 #[cfg(test)]
28 mod tests;
29 
30 /// How to compress data.
31 pub use zstd_sys::ZSTD_strategy as Strategy;
32 
33 /// Reset directive.
34 pub use zstd_sys::ZSTD_ResetDirective as ResetDirective;
35 
36 #[cfg(feature = "std")]
37 use std::os::raw::{c_char, c_int, c_ulonglong, c_void};
38 
39 #[cfg(not(feature = "std"))]
40 use libc::{c_char, c_int, c_ulonglong, c_void};
41 
42 use core::marker::PhantomData;
43 use core::ops::Deref;
44 use core::ops::DerefMut;
45 use core::str;
46 
47 // Re-define constants from zstd_sys
48 pub const VERSION_MAJOR: u32 = zstd_sys::ZSTD_VERSION_MAJOR;
49 pub const VERSION_MINOR: u32 = zstd_sys::ZSTD_VERSION_MINOR;
50 pub const VERSION_RELEASE: u32 = zstd_sys::ZSTD_VERSION_RELEASE;
51 pub const VERSION_NUMBER: u32 = zstd_sys::ZSTD_VERSION_NUMBER;
52 
53 /// Default compression level.
54 pub const CLEVEL_DEFAULT: CompressionLevel =
55     zstd_sys::ZSTD_CLEVEL_DEFAULT as CompressionLevel;
56 pub const CONTENTSIZE_UNKNOWN: u64 = zstd_sys::ZSTD_CONTENTSIZE_UNKNOWN as u64;
57 pub const CONTENTSIZE_ERROR: u64 = zstd_sys::ZSTD_CONTENTSIZE_ERROR as u64;
58 pub const MAGICNUMBER: u32 = zstd_sys::ZSTD_MAGICNUMBER;
59 pub const MAGIC_DICTIONARY: u32 = zstd_sys::ZSTD_MAGIC_DICTIONARY;
60 pub const MAGIC_SKIPPABLE_START: u32 = zstd_sys::ZSTD_MAGIC_SKIPPABLE_START;
61 pub const BLOCKSIZELOG_MAX: u32 = zstd_sys::ZSTD_BLOCKSIZELOG_MAX;
62 pub const BLOCKSIZE_MAX: u32 = zstd_sys::ZSTD_BLOCKSIZE_MAX;
63 #[cfg(feature = "experimental")]
64 pub const WINDOWLOG_MAX_32: u32 = zstd_sys::ZSTD_WINDOWLOG_MAX_32;
65 #[cfg(feature = "experimental")]
66 pub const WINDOWLOG_MAX_64: u32 = zstd_sys::ZSTD_WINDOWLOG_MAX_64;
67 #[cfg(feature = "experimental")]
68 pub const WINDOWLOG_MIN: u32 = zstd_sys::ZSTD_WINDOWLOG_MIN;
69 #[cfg(feature = "experimental")]
70 pub const HASHLOG_MIN: u32 = zstd_sys::ZSTD_HASHLOG_MIN;
71 #[cfg(feature = "experimental")]
72 pub const CHAINLOG_MAX_32: u32 = zstd_sys::ZSTD_CHAINLOG_MAX_32;
73 #[cfg(feature = "experimental")]
74 pub const CHAINLOG_MAX_64: u32 = zstd_sys::ZSTD_CHAINLOG_MAX_64;
75 #[cfg(feature = "experimental")]
76 pub const CHAINLOG_MIN: u32 = zstd_sys::ZSTD_CHAINLOG_MIN;
77 #[cfg(feature = "experimental")]
78 pub const HASHLOG3_MAX: u32 = zstd_sys::ZSTD_HASHLOG3_MAX;
79 #[cfg(feature = "experimental")]
80 pub const SEARCHLOG_MIN: u32 = zstd_sys::ZSTD_SEARCHLOG_MIN;
81 #[cfg(feature = "experimental")]
82 pub const TARGETLENGTH_MAX: u32 = zstd_sys::ZSTD_TARGETLENGTH_MAX;
83 #[cfg(feature = "experimental")]
84 pub const TARGETLENGTH_MIN: u32 = zstd_sys::ZSTD_TARGETLENGTH_MIN;
85 #[cfg(feature = "experimental")]
86 pub const LDM_MINMATCH_MAX: u32 = zstd_sys::ZSTD_LDM_MINMATCH_MAX;
87 #[cfg(feature = "experimental")]
88 pub const LDM_MINMATCH_MIN: u32 = zstd_sys::ZSTD_LDM_MINMATCH_MIN;
89 #[cfg(feature = "experimental")]
90 pub const LDM_BUCKETSIZELOG_MAX: u32 = zstd_sys::ZSTD_LDM_BUCKETSIZELOG_MAX;
91 
92 /// Represents the compression level used by zstd.
93 pub type CompressionLevel = i32;
94 
95 /// Represents a possible error from the zstd library.
96 pub type ErrorCode = usize;
97 
98 /// Wrapper result around most zstd functions.
99 ///
100 /// Either a success code (usually number of bytes written), or an error code.
101 pub type SafeResult = Result<usize, ErrorCode>;
102 
103 /// Returns true if code represents error.
is_error(code: usize) -> bool104 fn is_error(code: usize) -> bool {
105     unsafe { zstd_sys::ZSTD_isError(code) != 0 }
106 }
107 
108 /// Parse the result code
109 ///
110 /// Returns the number of bytes written if the code represents success,
111 /// or the error message code otherwise.
parse_code(code: usize) -> SafeResult112 fn parse_code(code: usize) -> SafeResult {
113     if !is_error(code) {
114         Ok(code)
115     } else {
116         Err(code)
117     }
118 }
119 
ptr_void(src: &[u8]) -> *const c_void120 fn ptr_void(src: &[u8]) -> *const c_void {
121     src.as_ptr() as *const c_void
122 }
123 
ptr_mut_void(dst: &mut [u8]) -> *mut c_void124 fn ptr_mut_void(dst: &mut [u8]) -> *mut c_void {
125     dst.as_mut_ptr() as *mut c_void
126 }
127 
version_number() -> u32128 pub fn version_number() -> u32 {
129     unsafe { zstd_sys::ZSTD_versionNumber() as u32 }
130 }
131 
version_string() -> &'static str132 pub fn version_string() -> &'static str {
133     unsafe { c_char_to_str(zstd_sys::ZSTD_versionString()) }
134 }
135 
136 /// Returns the minimum (fastest) compression level supported.
min_c_level() -> CompressionLevel137 pub fn min_c_level() -> CompressionLevel {
138     unsafe { zstd_sys::ZSTD_minCLevel() as CompressionLevel }
139 }
140 
141 /// Returns the maximum (slowest) compression level supported.
max_c_level() -> CompressionLevel142 pub fn max_c_level() -> CompressionLevel {
143     unsafe { zstd_sys::ZSTD_maxCLevel() as CompressionLevel }
144 }
145 
146 /// Wraps the `ZSTD_compress` function.
compress( dst: &mut [u8], src: &[u8], compression_level: CompressionLevel, ) -> SafeResult147 pub fn compress(
148     dst: &mut [u8],
149     src: &[u8],
150     compression_level: CompressionLevel,
151 ) -> SafeResult {
152     let code = unsafe {
153         zstd_sys::ZSTD_compress(
154             ptr_mut_void(dst),
155             dst.len(),
156             ptr_void(src),
157             src.len(),
158             compression_level,
159         )
160     };
161     parse_code(code)
162 }
163 
164 /// Wraps the `ZSTD_decompress` function.
decompress(dst: &mut [u8], src: &[u8]) -> SafeResult165 pub fn decompress(dst: &mut [u8], src: &[u8]) -> SafeResult {
166     let code = unsafe {
167         zstd_sys::ZSTD_decompress(
168             ptr_mut_void(dst),
169             dst.len(),
170             ptr_void(src),
171             src.len(),
172         )
173     };
174     parse_code(code)
175 }
176 
177 /// Wraps the `ZSTD_getDecompressedSize` function.
178 #[deprecated(note = "Use ZSTD_getFrameContentSize instead")]
get_decompressed_size(src: &[u8]) -> u64179 pub fn get_decompressed_size(src: &[u8]) -> u64 {
180     unsafe {
181         zstd_sys::ZSTD_getDecompressedSize(ptr_void(src), src.len()) as u64
182     }
183 }
184 
185 /// maximum compressed size in worst case single-pass scenario
compress_bound(src_size: usize) -> usize186 pub fn compress_bound(src_size: usize) -> usize {
187     unsafe { zstd_sys::ZSTD_compressBound(src_size) }
188 }
189 
190 pub struct CCtx<'a>(*mut zstd_sys::ZSTD_CCtx, PhantomData<&'a ()>);
191 
192 impl<'a> Default for CCtx<'a> {
default() -> Self193     fn default() -> Self {
194         create_cctx()
195     }
196 }
197 
198 impl CCtx<'static> {
199     /// Wrap `ZSTD_createCCtx`
create() -> Self200     pub fn create() -> Self {
201         CCtx(unsafe { zstd_sys::ZSTD_createCCtx() }, PhantomData)
202     }
203 }
204 
205 impl<'a> CCtx<'a> {
206     /// Wraps the `ZSTD_compressCCtx()` function
compress( &mut self, dst: &mut [u8], src: &[u8], compression_level: CompressionLevel, ) -> SafeResult207     pub fn compress(
208         &mut self,
209         dst: &mut [u8],
210         src: &[u8],
211         compression_level: CompressionLevel,
212     ) -> SafeResult {
213         let code = unsafe {
214             zstd_sys::ZSTD_compressCCtx(
215                 self.0,
216                 ptr_mut_void(dst),
217                 dst.len(),
218                 ptr_void(src),
219                 src.len(),
220                 compression_level,
221             )
222         };
223         parse_code(code)
224     }
225 
226     /// Wraps the `ZSTD_compress2()` function.
compress2(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult227     pub fn compress2(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult {
228         parse_code(unsafe {
229             zstd_sys::ZSTD_compress2(
230                 self.0,
231                 ptr_mut_void(dst),
232                 dst.len(),
233                 ptr_void(src),
234                 src.len(),
235             )
236         })
237     }
238 
239     /// Wraps the `ZSTD_compress_usingDict()` function.
compress_using_dict( &mut self, dst: &mut [u8], src: &[u8], dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult240     pub fn compress_using_dict(
241         &mut self,
242         dst: &mut [u8],
243         src: &[u8],
244         dict: &[u8],
245         compression_level: CompressionLevel,
246     ) -> SafeResult {
247         let code = unsafe {
248             zstd_sys::ZSTD_compress_usingDict(
249                 self.0,
250                 ptr_mut_void(dst),
251                 dst.len(),
252                 ptr_void(src),
253                 src.len(),
254                 ptr_void(dict),
255                 dict.len(),
256                 compression_level,
257             )
258         };
259         parse_code(code)
260     }
261 
262     /// Wraps the `ZSTD_compress_usingCDict()` function.
compress_using_cdict( &mut self, dst: &mut [u8], src: &[u8], cdict: &CDict, ) -> SafeResult263     pub fn compress_using_cdict(
264         &mut self,
265         dst: &mut [u8],
266         src: &[u8],
267         cdict: &CDict,
268     ) -> SafeResult {
269         let code = unsafe {
270             zstd_sys::ZSTD_compress_usingCDict(
271                 self.0,
272                 ptr_mut_void(dst),
273                 dst.len(),
274                 ptr_void(src),
275                 src.len(),
276                 cdict.0,
277             )
278         };
279         parse_code(code)
280     }
281 
init(&mut self, compression_level: CompressionLevel) -> usize282     pub fn init(&mut self, compression_level: CompressionLevel) -> usize {
283         unsafe { zstd_sys::ZSTD_initCStream(self.0, compression_level) }
284     }
285 
286     /// Wraps the `ZSTD_initCStream_srcSize()` function.
287     #[cfg(feature = "experimental")]
288     #[deprecated]
init_src_size( &mut self, compression_level: CompressionLevel, pledged_src_size: u64, ) -> usize289     pub fn init_src_size(
290         &mut self,
291         compression_level: CompressionLevel,
292         pledged_src_size: u64,
293     ) -> usize {
294         unsafe {
295             zstd_sys::ZSTD_initCStream_srcSize(
296                 self.0,
297                 compression_level as c_int,
298                 pledged_src_size as c_ulonglong,
299             )
300         }
301     }
302 
303     /// Wraps the `ZSTD_initCStream_usingDict()` function.
304     #[cfg(feature = "experimental")]
305     #[deprecated]
init_using_dict( &mut self, dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult306     pub fn init_using_dict(
307         &mut self,
308         dict: &[u8],
309         compression_level: CompressionLevel,
310     ) -> SafeResult {
311         let code = unsafe {
312             zstd_sys::ZSTD_initCStream_usingDict(
313                 self.0,
314                 ptr_void(dict),
315                 dict.len(),
316                 compression_level,
317             )
318         };
319         parse_code(code)
320     }
321 
322     /// Wraps the `ZSTD_initCStream_usingCDict()` function.
323     #[cfg(feature = "experimental")]
324     #[deprecated]
init_using_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult where 'b: 'a,325     pub fn init_using_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
326     where
327         'b: 'a, // Dictionary outlives the stream.
328     {
329         let code =
330             unsafe { zstd_sys::ZSTD_initCStream_usingCDict(self.0, cdict.0) };
331         parse_code(code)
332     }
333 
load_dictionary(&mut self, dict: &[u8]) -> SafeResult334     pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
335         parse_code(unsafe {
336             zstd_sys::ZSTD_CCtx_loadDictionary(
337                 self.0,
338                 ptr_void(dict),
339                 dict.len(),
340             )
341         })
342     }
343 
344     /// Wraps the `ZSTD_CCtx_refCDict()` function.
345     ///
346     /// Dictionary must outlive the context.
ref_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult where 'b: 'a,347     pub fn ref_cdict<'b>(&mut self, cdict: &CDict<'b>) -> SafeResult
348     where
349         'b: 'a,
350     {
351         parse_code(unsafe { zstd_sys::ZSTD_CCtx_refCDict(self.0, cdict.0) })
352     }
353 
ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult where 'b: 'a,354     pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
355     where
356         'b: 'a,
357     {
358         parse_code(unsafe {
359             zstd_sys::ZSTD_CCtx_refPrefix(
360                 self.0,
361                 ptr_void(prefix),
362                 prefix.len(),
363             )
364         })
365     }
366 
compress_stream( &mut self, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult367     pub fn compress_stream(
368         &mut self,
369         output: &mut OutBuffer,
370         input: &mut InBuffer,
371     ) -> SafeResult {
372         let mut output = output.wrap();
373         let mut input = input.wrap();
374         let code = unsafe {
375             zstd_sys::ZSTD_compressStream(
376                 self.0,
377                 ptr_mut(&mut output),
378                 ptr_mut(&mut input),
379             )
380         };
381         parse_code(code)
382     }
383 
384     /// Wraps the `ZSTD_compressStream2()` function.
compress_stream2( &mut self, output: &mut OutBuffer, input: &mut InBuffer, end_op: zstd_sys::ZSTD_EndDirective, ) -> SafeResult385     pub fn compress_stream2(
386         &mut self,
387         output: &mut OutBuffer,
388         input: &mut InBuffer,
389         end_op: zstd_sys::ZSTD_EndDirective,
390     ) -> SafeResult {
391         let mut output = output.wrap();
392         let mut input = input.wrap();
393         parse_code(unsafe {
394             zstd_sys::ZSTD_compressStream2(
395                 self.0,
396                 ptr_mut(&mut output),
397                 ptr_mut(&mut input),
398                 end_op,
399             )
400         })
401     }
402 
403     /// Wraps the `ZSTD_flushStream()` function.
flush_stream(&mut self, output: &mut OutBuffer) -> SafeResult404     pub fn flush_stream(&mut self, output: &mut OutBuffer) -> SafeResult {
405         let mut output = output.wrap();
406         let code = unsafe {
407             zstd_sys::ZSTD_flushStream(self.0, ptr_mut(&mut output))
408         };
409         parse_code(code)
410     }
411 
412     /// Wraps the `ZSTD_endStream()` function.
end_stream(&mut self, output: &mut OutBuffer) -> SafeResult413     pub fn end_stream(&mut self, output: &mut OutBuffer) -> SafeResult {
414         let mut output = output.wrap();
415         let code =
416             unsafe { zstd_sys::ZSTD_endStream(self.0, ptr_mut(&mut output)) };
417         parse_code(code)
418     }
419 
sizeof(&self) -> usize420     pub fn sizeof(&self) -> usize {
421         unsafe { zstd_sys::ZSTD_sizeof_CCtx(self.0) }
422     }
423 
reset(&mut self, reset: ResetDirective) -> SafeResult424     pub fn reset(&mut self, reset: ResetDirective) -> SafeResult {
425         parse_code(unsafe { zstd_sys::ZSTD_CCtx_reset(self.0, reset) })
426     }
427 
428     #[cfg(feature = "experimental")]
429     #[deprecated]
reset_cstream(&mut self, pledged_src_size: u64) -> SafeResult430     pub fn reset_cstream(&mut self, pledged_src_size: u64) -> SafeResult {
431         let code = unsafe {
432             zstd_sys::ZSTD_resetCStream(
433                 self.0,
434                 pledged_src_size as c_ulonglong,
435             )
436         };
437         parse_code(code)
438     }
439 
set_parameter(&mut self, param: CParameter) -> SafeResult440     pub fn set_parameter(&mut self, param: CParameter) -> SafeResult {
441         // TODO: Until bindgen properly generates a binding for this, we'll need to do it here.
442         #[cfg(feature = "experimental")]
443         use zstd_sys::ZSTD_cParameter::ZSTD_c_experimentalParam2 as ZSTD_c_format;
444         #[cfg(feature = "experimental")]
445         use zstd_sys::ZSTD_format_e;
446 
447         use zstd_sys::ZSTD_cParameter::*;
448         use CParameter::*;
449 
450         let (param, value) = match param {
451             #[cfg(feature = "experimental")]
452             Format(FrameFormat::One) => {
453                 (ZSTD_c_format, ZSTD_format_e::ZSTD_f_zstd1 as c_int)
454             }
455             #[cfg(feature = "experimental")]
456             Format(FrameFormat::Magicless) => (
457                 ZSTD_c_format,
458                 ZSTD_format_e::ZSTD_f_zstd1_magicless as c_int,
459             ),
460             CompressionLevel(level) => (ZSTD_c_compressionLevel, level),
461             WindowLog(value) => (ZSTD_c_windowLog, value as c_int),
462             HashLog(value) => (ZSTD_c_hashLog, value as c_int),
463             ChainLog(value) => (ZSTD_c_chainLog, value as c_int),
464             SearchLog(value) => (ZSTD_c_searchLog, value as c_int),
465             MinMatch(value) => (ZSTD_c_minMatch, value as c_int),
466             TargetLength(value) => (ZSTD_c_targetLength, value as c_int),
467             Strategy(strategy) => (ZSTD_c_strategy, strategy as c_int),
468             EnableLongDistanceMatching(flag) => {
469                 (ZSTD_c_enableLongDistanceMatching, flag as c_int)
470             }
471             LdmHashLog(value) => (ZSTD_c_ldmHashLog, value as c_int),
472             LdmMinMatch(value) => (ZSTD_c_ldmMinMatch, value as c_int),
473             LdmBucketSizeLog(value) => {
474                 (ZSTD_c_ldmBucketSizeLog, value as c_int)
475             }
476             LdmHashRateLog(value) => (ZSTD_c_ldmHashRateLog, value as c_int),
477             ContentSizeFlag(flag) => (ZSTD_c_contentSizeFlag, flag as c_int),
478             ChecksumFlag(flag) => (ZSTD_c_checksumFlag, flag as c_int),
479             DictIdFlag(flag) => (ZSTD_c_dictIDFlag, flag as c_int),
480 
481             NbWorkers(value) => (ZSTD_c_nbWorkers, value as c_int),
482 
483             JobSize(value) => (ZSTD_c_jobSize, value as c_int),
484 
485             OverlapSizeLog(value) => (ZSTD_c_overlapLog, value as c_int),
486         };
487 
488         parse_code(unsafe {
489             zstd_sys::ZSTD_CCtx_setParameter(self.0, param, value)
490         })
491     }
492 
set_pledged_src_size( &mut self, pledged_src_size: u64, ) -> SafeResult493     pub fn set_pledged_src_size(
494         &mut self,
495         pledged_src_size: u64,
496     ) -> SafeResult {
497         parse_code(unsafe {
498             zstd_sys::ZSTD_CCtx_setPledgedSrcSize(
499                 self.0,
500                 pledged_src_size as c_ulonglong,
501             )
502         })
503     }
504 
505     /// Wraps the `ZSTD_getBlockSize()` function.
506     #[cfg(feature = "experimental")]
get_block_size(&self) -> usize507     pub fn get_block_size(&self) -> usize {
508         unsafe { zstd_sys::ZSTD_getBlockSize(self.0) }
509     }
510 
511     /// Wraps the `ZSTD_compressBlock()` function.
512     #[cfg(feature = "experimental")]
compress_block( &mut self, dst: &mut [u8], src: &[u8], ) -> SafeResult513     pub fn compress_block(
514         &mut self,
515         dst: &mut [u8],
516         src: &[u8],
517     ) -> SafeResult {
518         let code = unsafe {
519             zstd_sys::ZSTD_compressBlock(
520                 self.0,
521                 ptr_mut_void(dst),
522                 dst.len(),
523                 ptr_void(src),
524                 src.len(),
525             )
526         };
527         parse_code(code)
528     }
in_size() -> usize529     pub fn in_size() -> usize {
530         unsafe { zstd_sys::ZSTD_CStreamInSize() }
531     }
532 
out_size() -> usize533     pub fn out_size() -> usize {
534         unsafe { zstd_sys::ZSTD_CStreamOutSize() }
535     }
536 }
537 
create_cctx<'a>() -> CCtx<'a>538 pub fn create_cctx<'a>() -> CCtx<'a> {
539     CCtx::create()
540 }
541 
542 impl<'a> Drop for CCtx<'a> {
drop(&mut self)543     fn drop(&mut self) {
544         unsafe {
545             zstd_sys::ZSTD_freeCCtx(self.0);
546         }
547     }
548 }
549 
550 unsafe impl<'a> Send for CCtx<'a> {}
551 // CCtx can't be shared across threads, so it does not implement Sync.
552 
c_char_to_str(text: *const c_char) -> &'static str553 unsafe fn c_char_to_str(text: *const c_char) -> &'static str {
554     #[cfg(not(feature = "std"))]
555     {
556         // To be safe, we need to compute right now its length
557         let len = libc::strlen(text);
558 
559         // Cast it to a slice
560         let slice = core::slice::from_raw_parts(text as *mut u8, len);
561         // And hope it's still text.
562         str::from_utf8(slice).expect("bad error message from zstd")
563     }
564 
565     #[cfg(feature = "std")]
566     {
567         std::ffi::CStr::from_ptr(text)
568             .to_str()
569             .expect("bad error message from zstd")
570     }
571 }
572 
get_error_name(code: usize) -> &'static str573 pub fn get_error_name(code: usize) -> &'static str {
574     unsafe {
575         let name = zstd_sys::ZSTD_getErrorName(code);
576         c_char_to_str(name)
577     }
578 }
579 
580 /// Wraps the `ZSTD_compressCCtx()` function
compress_cctx( ctx: &mut CCtx, dst: &mut [u8], src: &[u8], compression_level: CompressionLevel, ) -> SafeResult581 pub fn compress_cctx(
582     ctx: &mut CCtx,
583     dst: &mut [u8],
584     src: &[u8],
585     compression_level: CompressionLevel,
586 ) -> SafeResult {
587     ctx.compress(dst, src, compression_level)
588 }
589 
590 /// Wraps the `ZSTD_compress2()` function.
compress2(ctx: &mut CCtx, dst: &mut [u8], src: &[u8]) -> SafeResult591 pub fn compress2(ctx: &mut CCtx, dst: &mut [u8], src: &[u8]) -> SafeResult {
592     ctx.compress2(dst, src)
593 }
594 
595 /// A Decompression Context.
596 ///
597 /// The lifetime references the potential dictionary used for this context.
598 ///
599 /// If no dictionary was used, it will most likely be `'static`.
600 ///
601 /// Same as `DStream`.
602 pub struct DCtx<'a>(*mut zstd_sys::ZSTD_DCtx, PhantomData<&'a ()>);
603 
604 impl Default for DCtx<'_> {
default() -> Self605     fn default() -> Self {
606         create_dctx()
607     }
608 }
609 
610 impl DCtx<'static> {
create() -> Self611     pub fn create() -> Self {
612         DCtx(unsafe { zstd_sys::ZSTD_createDCtx() }, PhantomData)
613     }
614 }
615 
616 impl<'a> DCtx<'a> {
617     /// Wraps the `ZSTD_decompressDCtx()` function.
decompress(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult618     pub fn decompress(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult {
619         parse_code(unsafe {
620             zstd_sys::ZSTD_decompressDCtx(
621                 self.0,
622                 ptr_mut_void(dst),
623                 dst.len(),
624                 ptr_void(src),
625                 src.len(),
626             )
627         })
628     }
629 
decompress_using_dict( &mut self, dst: &mut [u8], src: &[u8], dict: &[u8], ) -> SafeResult630     pub fn decompress_using_dict(
631         &mut self,
632         dst: &mut [u8],
633         src: &[u8],
634         dict: &[u8],
635     ) -> SafeResult {
636         let code = unsafe {
637             zstd_sys::ZSTD_decompress_usingDict(
638                 self.0,
639                 ptr_mut_void(dst),
640                 dst.len(),
641                 ptr_void(src),
642                 src.len(),
643                 ptr_void(dict),
644                 dict.len(),
645             )
646         };
647         parse_code(code)
648     }
649 
650     /// Wraps the `ZSTD_decompress_usingDDict()` function.
decompress_using_ddict( &mut self, dst: &mut [u8], src: &[u8], ddict: &DDict, ) -> SafeResult651     pub fn decompress_using_ddict(
652         &mut self,
653         dst: &mut [u8],
654         src: &[u8],
655         ddict: &DDict,
656     ) -> SafeResult {
657         let code = unsafe {
658             zstd_sys::ZSTD_decompress_usingDDict(
659                 self.0,
660                 ptr_mut_void(dst),
661                 dst.len(),
662                 ptr_void(src),
663                 src.len(),
664                 ddict.0,
665             )
666         };
667         parse_code(code)
668     }
669 
670     /// Wraps the `ZSTD_initCStream()` function.
671     ///
672     /// Initializes an existing `DStream` for decompression.
init(&mut self) -> usize673     pub fn init(&mut self) -> usize {
674         unsafe { zstd_sys::ZSTD_initDStream(self.0) }
675     }
676 
677     /// Wraps the `ZSTD_initDStream_usingDict()` function.
678     #[cfg(feature = "experimental")]
679     #[deprecated]
init_using_dict(&mut self, dict: &[u8]) -> SafeResult680     pub fn init_using_dict(&mut self, dict: &[u8]) -> SafeResult {
681         let code = unsafe {
682             zstd_sys::ZSTD_initDStream_usingDict(
683                 self.0,
684                 ptr_void(dict),
685                 dict.len(),
686             )
687         };
688         parse_code(code)
689     }
690 
691     /// Wraps the `ZSTD_initDStream_usingDDict()` function.
692     #[cfg(feature = "experimental")]
693     #[deprecated]
init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult where 'b: 'a,694     pub fn init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
695     where
696         'b: 'a,
697     {
698         let code =
699             unsafe { zstd_sys::ZSTD_initDStream_usingDDict(self.0, ddict.0) };
700         parse_code(code)
701     }
702 
703     /// Wraps the `ZSTD_resetDStream()` function.
reset(&mut self) -> SafeResult704     pub fn reset(&mut self) -> SafeResult {
705         let code = unsafe {
706             zstd_sys::ZSTD_DCtx_reset(
707                 self.0,
708                 ResetDirective::ZSTD_reset_session_only,
709             )
710         };
711         parse_code(code)
712     }
713 
load_dictionary(&mut self, dict: &[u8]) -> SafeResult714     pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
715         parse_code(unsafe {
716             zstd_sys::ZSTD_DCtx_loadDictionary(
717                 self.0,
718                 ptr_void(dict),
719                 dict.len(),
720             )
721         })
722     }
723 
ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult where 'b: 'a,724     pub fn ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
725     where
726         'b: 'a,
727     {
728         parse_code(unsafe { zstd_sys::ZSTD_DCtx_refDDict(self.0, ddict.0) })
729     }
730 
ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult where 'b: 'a,731     pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
732     where
733         'b: 'a,
734     {
735         parse_code(unsafe {
736             zstd_sys::ZSTD_DCtx_refPrefix(
737                 self.0,
738                 ptr_void(prefix),
739                 prefix.len(),
740             )
741         })
742     }
743 
set_parameter(&mut self, param: DParameter) -> SafeResult744     pub fn set_parameter(&mut self, param: DParameter) -> SafeResult {
745         #[cfg(feature = "experimental")]
746         use zstd_sys::ZSTD_dParameter::ZSTD_d_experimentalParam1 as ZSTD_d_format;
747         #[cfg(feature = "experimental")]
748         use zstd_sys::ZSTD_format_e;
749 
750         use zstd_sys::ZSTD_dParameter::*;
751         use DParameter::*;
752 
753         let (param, value) = match param {
754             #[cfg(feature = "experimental")]
755             Format(FrameFormat::One) => {
756                 (ZSTD_d_format, ZSTD_format_e::ZSTD_f_zstd1 as c_int)
757             }
758             #[cfg(feature = "experimental")]
759             Format(FrameFormat::Magicless) => (
760                 ZSTD_d_format,
761                 ZSTD_format_e::ZSTD_f_zstd1_magicless as c_int,
762             ),
763 
764             WindowLogMax(value) => (ZSTD_d_windowLogMax, value as c_int),
765         };
766 
767         parse_code(unsafe {
768             zstd_sys::ZSTD_DCtx_setParameter(self.0, param, value)
769         })
770     }
771 
772     /// Wraps the `ZSTD_decompressStream()` function.
decompress_stream( &mut self, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult773     pub fn decompress_stream(
774         &mut self,
775         output: &mut OutBuffer,
776         input: &mut InBuffer,
777     ) -> SafeResult {
778         let mut output = output.wrap();
779         let mut input = input.wrap();
780         let code = unsafe {
781             zstd_sys::ZSTD_decompressStream(
782                 self.0,
783                 ptr_mut(&mut output),
784                 ptr_mut(&mut input),
785             )
786         };
787         parse_code(code)
788     }
789 
790     /// Wraps the `ZSTD_DStreamInSize()` function.
791     ///
792     /// Returns a hint for the recommended size of the input buffer for decompression.
in_size() -> usize793     pub fn in_size() -> usize {
794         unsafe { zstd_sys::ZSTD_DStreamInSize() }
795     }
796 
797     /// Wraps the `ZSTD_DStreamOutSize()` function.
798     ///
799     /// Returns a hint for the recommended size of the output buffer for decompression.
out_size() -> usize800     pub fn out_size() -> usize {
801         unsafe { zstd_sys::ZSTD_DStreamOutSize() }
802     }
803 
804     /// Wraps the `ZSTD_sizeof_DCtx()` function.
sizeof(&self) -> usize805     pub fn sizeof(&self) -> usize {
806         unsafe { zstd_sys::ZSTD_sizeof_DCtx(self.0) }
807     }
808 
809     /// Wraps the `ZSTD_decompressBlock()` function.
810     #[cfg(feature = "experimental")]
decompress_block(&mut self, dst: &mut [u8], src: &[u8]) -> usize811     pub fn decompress_block(&mut self, dst: &mut [u8], src: &[u8]) -> usize {
812         unsafe {
813             zstd_sys::ZSTD_decompressBlock(
814                 self.0,
815                 ptr_mut_void(dst),
816                 dst.len(),
817                 ptr_void(src),
818                 src.len(),
819             )
820         }
821     }
822 
823     /// Wraps the `ZSTD_insertBlock()` function.
824     #[cfg(feature = "experimental")]
insert_block(&mut self, block: &[u8]) -> usize825     pub fn insert_block(&mut self, block: &[u8]) -> usize {
826         unsafe {
827             zstd_sys::ZSTD_insertBlock(self.0, ptr_void(block), block.len())
828         }
829     }
830 }
831 
832 /// Prepares a new decompression context without dictionary.
create_dctx() -> DCtx<'static>833 pub fn create_dctx() -> DCtx<'static> {
834     DCtx::create()
835 }
836 
837 impl Drop for DCtx<'_> {
drop(&mut self)838     fn drop(&mut self) {
839         unsafe {
840             zstd_sys::ZSTD_freeDCtx(self.0);
841         }
842     }
843 }
844 
845 unsafe impl Send for DCtx<'_> {}
846 // DCtx can't be shared across threads, so it does not implement Sync.
847 
848 /// Wraps the `ZSTD_decompressDCtx()` function.
decompress_dctx( ctx: &mut DCtx, dst: &mut [u8], src: &[u8], ) -> SafeResult849 pub fn decompress_dctx(
850     ctx: &mut DCtx,
851     dst: &mut [u8],
852     src: &[u8],
853 ) -> SafeResult {
854     ctx.decompress(dst, src)
855 }
856 
857 /// Wraps the `ZSTD_compress_usingDict()` function.
compress_using_dict( ctx: &mut CCtx, dst: &mut [u8], src: &[u8], dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult858 pub fn compress_using_dict(
859     ctx: &mut CCtx,
860     dst: &mut [u8],
861     src: &[u8],
862     dict: &[u8],
863     compression_level: CompressionLevel,
864 ) -> SafeResult {
865     ctx.compress_using_dict(dst, src, dict, compression_level)
866 }
867 
868 /// Wraps the `ZSTD_decompress_usingDict()` function.
decompress_using_dict( dctx: &mut DCtx, dst: &mut [u8], src: &[u8], dict: &[u8], ) -> SafeResult869 pub fn decompress_using_dict(
870     dctx: &mut DCtx,
871     dst: &mut [u8],
872     src: &[u8],
873     dict: &[u8],
874 ) -> SafeResult {
875     dctx.decompress_using_dict(dst, src, dict)
876 }
877 
878 /// Compression dictionary.
879 pub struct CDict<'a>(*mut zstd_sys::ZSTD_CDict, PhantomData<&'a ()>);
880 
881 impl CDict<'static> {
create( dict_buffer: &[u8], compression_level: CompressionLevel, ) -> Self882     pub fn create(
883         dict_buffer: &[u8],
884         compression_level: CompressionLevel,
885     ) -> Self {
886         CDict(
887             unsafe {
888                 zstd_sys::ZSTD_createCDict(
889                     ptr_void(dict_buffer),
890                     dict_buffer.len(),
891                     compression_level,
892                 )
893             },
894             PhantomData,
895         )
896     }
897 }
898 
899 impl<'a> CDict<'a> {
900     #[cfg(feature = "experimental")]
create_by_reference( dict_buffer: &'a [u8], compression_level: CompressionLevel, ) -> Self901     pub fn create_by_reference(
902         dict_buffer: &'a [u8],
903         compression_level: CompressionLevel,
904     ) -> Self {
905         CDict(
906             unsafe {
907                 zstd_sys::ZSTD_createCDict_byReference(
908                     ptr_void(dict_buffer),
909                     dict_buffer.len(),
910                     compression_level,
911                 )
912             },
913             PhantomData,
914         )
915     }
sizeof(&self) -> usize916     pub fn sizeof(&self) -> usize {
917         unsafe { zstd_sys::ZSTD_sizeof_CDict(self.0) }
918     }
919 }
920 
921 /// Wraps the `ZSTD_createCDict()` function.
create_cdict( dict_buffer: &[u8], compression_level: CompressionLevel, ) -> CDict<'static>922 pub fn create_cdict(
923     dict_buffer: &[u8],
924     compression_level: CompressionLevel,
925 ) -> CDict<'static> {
926     CDict::create(dict_buffer, compression_level)
927 }
928 
929 impl<'a> Drop for CDict<'a> {
drop(&mut self)930     fn drop(&mut self) {
931         unsafe {
932             zstd_sys::ZSTD_freeCDict(self.0);
933         }
934     }
935 }
936 
937 unsafe impl<'a> Send for CDict<'a> {}
938 unsafe impl<'a> Sync for CDict<'a> {}
939 
940 /// Wraps the `ZSTD_compress_usingCDict()` function.
compress_using_cdict( cctx: &mut CCtx, dst: &mut [u8], src: &[u8], cdict: &CDict, ) -> SafeResult941 pub fn compress_using_cdict(
942     cctx: &mut CCtx,
943     dst: &mut [u8],
944     src: &[u8],
945     cdict: &CDict,
946 ) -> SafeResult {
947     cctx.compress_using_cdict(dst, src, cdict)
948 }
949 
950 pub struct DDict<'a>(*mut zstd_sys::ZSTD_DDict, PhantomData<&'a ()>);
951 
952 impl DDict<'static> {
create(dict_buffer: &[u8]) -> Self953     pub fn create(dict_buffer: &[u8]) -> Self {
954         DDict(
955             unsafe {
956                 zstd_sys::ZSTD_createDDict(
957                     ptr_void(dict_buffer),
958                     dict_buffer.len(),
959                 )
960             },
961             PhantomData,
962         )
963     }
964 }
965 
966 impl<'a> DDict<'a> {
sizeof(&self) -> usize967     pub fn sizeof(&self) -> usize {
968         unsafe { zstd_sys::ZSTD_sizeof_DDict(self.0) }
969     }
970 
971     /// Wraps the `ZSTD_createDDict_byReference()` function.
972     ///
973     /// The dictionary will keep referencing `dict_buffer`.
974     #[cfg(feature = "experimental")]
create_by_reference(dict_buffer: &'a [u8]) -> Self975     pub fn create_by_reference(dict_buffer: &'a [u8]) -> Self {
976         DDict(
977             unsafe {
978                 zstd_sys::ZSTD_createDDict_byReference(
979                     ptr_void(dict_buffer),
980                     dict_buffer.len(),
981                 )
982             },
983             PhantomData,
984         )
985     }
986 
get_dict_id(&self) -> u32987     pub fn get_dict_id(&self) -> u32 {
988         unsafe { zstd_sys::ZSTD_getDictID_fromDDict(self.0) as u32 }
989     }
990 }
991 
992 /// Wraps the `ZSTD_createDDict()` function.
993 ///
994 /// It copies the dictionary internally, so the resulting `DDict` is `'static`.
create_ddict(dict_buffer: &[u8]) -> DDict<'static>995 pub fn create_ddict(dict_buffer: &[u8]) -> DDict<'static> {
996     DDict::create(dict_buffer)
997 }
998 
999 impl<'a> Drop for DDict<'a> {
drop(&mut self)1000     fn drop(&mut self) {
1001         unsafe {
1002             zstd_sys::ZSTD_freeDDict(self.0);
1003         }
1004     }
1005 }
1006 
1007 unsafe impl<'a> Send for DDict<'a> {}
1008 unsafe impl<'a> Sync for DDict<'a> {}
1009 
1010 /// Wraps the `ZSTD_decompress_usingDDict()` function.
decompress_using_ddict( dctx: &mut DCtx, dst: &mut [u8], src: &[u8], ddict: &DDict, ) -> SafeResult1011 pub fn decompress_using_ddict(
1012     dctx: &mut DCtx,
1013     dst: &mut [u8],
1014     src: &[u8],
1015     ddict: &DDict,
1016 ) -> SafeResult {
1017     dctx.decompress_using_ddict(dst, src, ddict)
1018 }
1019 
1020 /// Compression stream.
1021 ///
1022 /// Same as `CCtx`.
1023 pub type CStream<'a> = CCtx<'a>;
1024 
1025 // CStream can't be shared across threads, so it does not implement Sync.
1026 
1027 /// Allocates a new `CStream`.
create_cstream<'a>() -> CStream<'a>1028 pub fn create_cstream<'a>() -> CStream<'a> {
1029     CCtx(unsafe { zstd_sys::ZSTD_createCStream() }, PhantomData)
1030 }
1031 
1032 /// Prepares an existing `CStream` for compression at the given level.
init_cstream( zcs: &mut CStream, compression_level: CompressionLevel, ) -> usize1033 pub fn init_cstream(
1034     zcs: &mut CStream,
1035     compression_level: CompressionLevel,
1036 ) -> usize {
1037     zcs.init(compression_level)
1038 }
1039 
1040 #[derive(Debug)]
1041 /// Wrapper around an input buffer.
1042 ///
1043 /// Bytes will be read starting at `src[pos]`.
1044 ///
1045 /// `pos` will be updated after reading.
1046 pub struct InBuffer<'a> {
1047     pub src: &'a [u8],
1048     pub pos: usize,
1049 }
1050 
1051 #[derive(Debug)]
1052 /// Wrapper around an output buffer.
1053 ///
1054 /// Bytes will be written starting at `dst[pos]`.
1055 ///
1056 /// `pos` will be updated after writing.
1057 pub struct OutBuffer<'a> {
1058     pub dst: &'a mut [u8],
1059     pub pos: usize,
1060 }
1061 
1062 /// Convenience method to get a mut pointer from a mut ref.
ptr_mut<B>(ptr_void: &mut B) -> *mut B1063 fn ptr_mut<B>(ptr_void: &mut B) -> *mut B {
1064     ptr_void as *mut B
1065 }
1066 
1067 /// Interface between a C-level ZSTD_outBuffer and a rust-level `OutBuffer`.
1068 ///
1069 /// Will update the parent buffer from the C buffer on drop.
1070 struct OutBufferWrapper<'a, 'b: 'a> {
1071     buf: zstd_sys::ZSTD_outBuffer,
1072     parent: &'a mut OutBuffer<'b>,
1073 }
1074 
1075 impl<'a, 'b: 'a> Deref for OutBufferWrapper<'a, 'b> {
1076     type Target = zstd_sys::ZSTD_outBuffer;
1077 
deref(&self) -> &Self::Target1078     fn deref(&self) -> &Self::Target {
1079         &self.buf
1080     }
1081 }
1082 
1083 impl<'a, 'b: 'a> DerefMut for OutBufferWrapper<'a, 'b> {
deref_mut(&mut self) -> &mut Self::Target1084     fn deref_mut(&mut self) -> &mut Self::Target {
1085         &mut self.buf
1086     }
1087 }
1088 
1089 impl<'a> OutBuffer<'a> {
1090     /// Returns a new `OutBuffer` around the given slice.
1091     ///
1092     /// Starts with `pos = 0`.
around(dst: &'a mut [u8]) -> Self1093     pub fn around(dst: &'a mut [u8]) -> Self {
1094         OutBuffer { dst, pos: 0 }
1095     }
1096 
wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a>1097     fn wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a> {
1098         OutBufferWrapper {
1099             buf: zstd_sys::ZSTD_outBuffer {
1100                 dst: ptr_mut_void(self.dst),
1101                 size: self.dst.len(),
1102                 pos: self.pos,
1103             },
1104             parent: self,
1105         }
1106     }
1107 
1108     /// Returns the part of this buffer that was written to.
as_slice<'b>(&'b self) -> &'a [u8] where 'b: 'a,1109     pub fn as_slice<'b>(&'b self) -> &'a [u8]
1110     where
1111         'b: 'a,
1112     {
1113         let pos = self.pos;
1114         &self.dst[..pos]
1115     }
1116 }
1117 
1118 impl<'a, 'b> Drop for OutBufferWrapper<'a, 'b> {
drop(&mut self)1119     fn drop(&mut self) {
1120         self.parent.pos = self.buf.pos;
1121     }
1122 }
1123 
1124 struct InBufferWrapper<'a, 'b: 'a> {
1125     buf: zstd_sys::ZSTD_inBuffer,
1126     parent: &'a mut InBuffer<'b>,
1127 }
1128 
1129 impl<'a, 'b: 'a> Deref for InBufferWrapper<'a, 'b> {
1130     type Target = zstd_sys::ZSTD_inBuffer;
1131 
deref(&self) -> &Self::Target1132     fn deref(&self) -> &Self::Target {
1133         &self.buf
1134     }
1135 }
1136 
1137 impl<'a, 'b: 'a> DerefMut for InBufferWrapper<'a, 'b> {
deref_mut(&mut self) -> &mut Self::Target1138     fn deref_mut(&mut self) -> &mut Self::Target {
1139         &mut self.buf
1140     }
1141 }
1142 
1143 impl<'a> InBuffer<'a> {
1144     /// Returns a new `InBuffer` around the given slice.
1145     ///
1146     /// Starts with `pos = 0`.
around(src: &'a [u8]) -> Self1147     pub fn around(src: &'a [u8]) -> Self {
1148         InBuffer { src, pos: 0 }
1149     }
1150 
wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a>1151     fn wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a> {
1152         InBufferWrapper {
1153             buf: zstd_sys::ZSTD_inBuffer {
1154                 src: ptr_void(self.src),
1155                 size: self.src.len(),
1156                 pos: self.pos,
1157             },
1158             parent: self,
1159         }
1160     }
1161 }
1162 
1163 impl<'a, 'b> Drop for InBufferWrapper<'a, 'b> {
drop(&mut self)1164     fn drop(&mut self) {
1165         self.parent.pos = self.buf.pos;
1166     }
1167 }
1168 
1169 /// Wraps the `ZSTD_compressStream()` function.
compress_stream( zcs: &mut CStream, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult1170 pub fn compress_stream(
1171     zcs: &mut CStream,
1172     output: &mut OutBuffer,
1173     input: &mut InBuffer,
1174 ) -> SafeResult {
1175     zcs.compress_stream(output, input)
1176 }
1177 
compress_stream2( cctx: &mut CCtx, output: &mut OutBuffer, input: &mut InBuffer, end_op: zstd_sys::ZSTD_EndDirective, ) -> SafeResult1178 pub fn compress_stream2(
1179     cctx: &mut CCtx,
1180     output: &mut OutBuffer,
1181     input: &mut InBuffer,
1182     end_op: zstd_sys::ZSTD_EndDirective,
1183 ) -> SafeResult {
1184     cctx.compress_stream2(output, input, end_op)
1185 }
1186 
1187 /// Wraps the `ZSTD_flushStream()` function.
flush_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult1188 pub fn flush_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult {
1189     zcs.flush_stream(output)
1190 }
1191 
1192 /// Wraps the `ZSTD_endStream()` function.
end_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult1193 pub fn end_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult {
1194     zcs.end_stream(output)
1195 }
1196 
1197 /// Wraps `ZSTD_CStreamInSize()`
cstream_in_size() -> usize1198 pub fn cstream_in_size() -> usize {
1199     CCtx::in_size()
1200 }
1201 
1202 /// Wraps `ZSTD_CStreamOutSize()`
cstream_out_size() -> usize1203 pub fn cstream_out_size() -> usize {
1204     CCtx::out_size()
1205 }
1206 
1207 /// A Decompression stream.
1208 ///
1209 /// Same as `DCtx`.
1210 pub type DStream<'a> = DCtx<'a>;
1211 
create_dstream() -> DStream<'static>1212 pub fn create_dstream() -> DStream<'static> {
1213     DStream::create()
1214 }
1215 
1216 /// Wraps the `ZSTD_initCStream()` function.
1217 ///
1218 /// Initializes an existing `DStream` for decompression.
init_dstream(zds: &mut DStream) -> usize1219 pub fn init_dstream(zds: &mut DStream) -> usize {
1220     zds.init()
1221 }
1222 
1223 /// Wraps the `ZSTD_decompressStream()` function.
decompress_stream( zds: &mut DStream, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult1224 pub fn decompress_stream(
1225     zds: &mut DStream,
1226     output: &mut OutBuffer,
1227     input: &mut InBuffer,
1228 ) -> SafeResult {
1229     zds.decompress_stream(output, input)
1230 }
1231 
1232 /// Wraps the `ZSTD_DStreamInSize()` function.
1233 ///
1234 /// Returns a hint for the recommended size of the input buffer for decompression.
dstream_in_size() -> usize1235 pub fn dstream_in_size() -> usize {
1236     DStream::in_size()
1237 }
1238 
1239 /// Wraps the `ZSTD_DStreamOutSize()` function.
1240 ///
1241 /// Returns a hint for the recommended size of the output buffer for decompression.
dstream_out_size() -> usize1242 pub fn dstream_out_size() -> usize {
1243     DStream::out_size()
1244 }
1245 
1246 /// Wraps the `ZSTD_findFrameCompressedSize()` function.
1247 ///
1248 /// `src` should contain at least an entire frame.
find_frame_compressed_size(src: &[u8]) -> SafeResult1249 pub fn find_frame_compressed_size(src: &[u8]) -> SafeResult {
1250     let code = unsafe {
1251         zstd_sys::ZSTD_findFrameCompressedSize(ptr_void(src), src.len())
1252     };
1253     parse_code(code)
1254 }
1255 
1256 /// Wraps the `ZSTD_getFrameContentSize()` function.
1257 ///
1258 /// `src` should contain at least a frame header.
get_frame_content_size(src: &[u8]) -> u641259 pub fn get_frame_content_size(src: &[u8]) -> u64 {
1260     unsafe { zstd_sys::ZSTD_getFrameContentSize(ptr_void(src), src.len()) }
1261 }
1262 
1263 /// Wraps the `ZSTD_findDecompressedSize()` function.
1264 ///
1265 /// `src` should be exactly a sequence of ZSTD frames.
1266 #[cfg(feature = "experimental")]
find_decompressed_size(src: &[u8]) -> u641267 pub fn find_decompressed_size(src: &[u8]) -> u64 {
1268     unsafe { zstd_sys::ZSTD_findDecompressedSize(ptr_void(src), src.len()) }
1269 }
1270 
1271 /// Wraps the `ZSTD_sizeofCCtx()` function.
sizeof_cctx(cctx: &CCtx) -> usize1272 pub fn sizeof_cctx(cctx: &CCtx) -> usize {
1273     cctx.sizeof()
1274 }
1275 
1276 /// Wraps the `ZSTD_sizeof_DCtx()` function.
sizeof_dctx(dctx: &DCtx) -> usize1277 pub fn sizeof_dctx(dctx: &DCtx) -> usize {
1278     dctx.sizeof()
1279 }
1280 
1281 /// Wraps the `ZSTD_sizeof_CStream()` function.
sizeof_cstream(zcs: &CStream) -> usize1282 pub fn sizeof_cstream(zcs: &CStream) -> usize {
1283     zcs.sizeof()
1284 }
1285 
1286 /// Wraps the `ZSTD_sizeof_DStream()` function.
sizeof_dstream(zds: &DStream) -> usize1287 pub fn sizeof_dstream(zds: &DStream) -> usize {
1288     zds.sizeof()
1289 }
1290 
1291 /// Wraps the `ZSTD_sizeof_CDict()` function.
sizeof_cdict(cdict: &CDict) -> usize1292 pub fn sizeof_cdict(cdict: &CDict) -> usize {
1293     cdict.sizeof()
1294 }
1295 
1296 /// Wraps the `ZSTD_sizeof_DDict()` function.
sizeof_ddict(ddict: &DDict) -> usize1297 pub fn sizeof_ddict(ddict: &DDict) -> usize {
1298     ddict.sizeof()
1299 }
1300 
1301 /// Wraps the `ZSTD_createCDict_byReference()` function.
1302 ///
1303 /// The dictionary will keep referencing `dict_buffer`.
1304 #[cfg(feature = "experimental")]
create_cdict_by_reference<'a>( dict_buffer: &'a [u8], compression_level: CompressionLevel, ) -> CDict<'a>1305 pub fn create_cdict_by_reference<'a>(
1306     dict_buffer: &'a [u8],
1307     compression_level: CompressionLevel,
1308 ) -> CDict<'a> {
1309     CDict::create_by_reference(dict_buffer, compression_level)
1310 }
1311 
1312 /// Wraps the `ZSTD_isFrame()` function.
1313 #[cfg(feature = "experimental")]
is_frame(buffer: &[u8]) -> u321314 pub fn is_frame(buffer: &[u8]) -> u32 {
1315     unsafe { zstd_sys::ZSTD_isFrame(ptr_void(buffer), buffer.len()) as u32 }
1316 }
1317 
1318 /// Wraps the `ZSTD_createDDict_byReference()` function.
1319 ///
1320 /// The dictionary will keep referencing `dict_buffer`.
1321 #[cfg(feature = "experimental")]
create_ddict_by_reference(dict_buffer: &[u8]) -> DDict1322 pub fn create_ddict_by_reference(dict_buffer: &[u8]) -> DDict {
1323     DDict::create_by_reference(dict_buffer)
1324 }
1325 
1326 /// Wraps the `ZSTD_getDictID_fromDict()` function.
get_dict_id_from_dict(dict: &[u8]) -> u321327 pub fn get_dict_id_from_dict(dict: &[u8]) -> u32 {
1328     unsafe {
1329         zstd_sys::ZSTD_getDictID_fromDict(ptr_void(dict), dict.len()) as u32
1330     }
1331 }
1332 
1333 /// Wraps the `ZSTD_getDictID_fromDDict()` function.
get_dict_id_from_ddict(ddict: &DDict) -> u321334 pub fn get_dict_id_from_ddict(ddict: &DDict) -> u32 {
1335     ddict.get_dict_id()
1336 }
1337 
1338 /// Wraps the `ZSTD_getDictID_fromFrame()` function.
get_dict_id_from_frame(src: &[u8]) -> u321339 pub fn get_dict_id_from_frame(src: &[u8]) -> u32 {
1340     unsafe {
1341         zstd_sys::ZSTD_getDictID_fromFrame(ptr_void(src), src.len()) as u32
1342     }
1343 }
1344 
1345 /// Wraps the `ZSTD_initCStream_srcSize()` function.
1346 #[cfg(feacctxture = "experimental")]
1347 #[deprecated]
1348 #[allow(deprecated)]
init_cstream_src_size( zcs: &mut CStream, compression_level: CompressionLevel, pledged_src_size: u64, ) -> usize1349 pub fn init_cstream_src_size(
1350     zcs: &mut CStream,
1351     compression_level: CompressionLevel,
1352     pledged_src_size: u64,
1353 ) -> usize {
1354     zcs.init_src_size(compression_level, pledged_src_size)
1355 }
1356 
1357 /// Wraps the `ZSTD_initCStream_usingDict()` function.
1358 #[cfg(feature = "experimental")]
1359 #[deprecated]
1360 #[allow(deprecated)]
init_cstream_using_dict( zcs: &mut CStream, dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult1361 pub fn init_cstream_using_dict(
1362     zcs: &mut CStream,
1363     dict: &[u8],
1364     compression_level: CompressionLevel,
1365 ) -> SafeResult {
1366     zcs.init_using_dict(dict, compression_level)
1367 }
1368 
1369 /// Wraps the `ZSTD_initCStream_usingCDict()` function.
1370 #[cfg(feature = "experimental")]
1371 #[deprecated]
1372 #[allow(deprecated)]
init_cstream_using_cdict<'a, 'b>( zcs: &mut CStream<'a>, cdict: &CDict<'b>, ) -> SafeResult where 'b: 'a,1373 pub fn init_cstream_using_cdict<'a, 'b>(
1374     zcs: &mut CStream<'a>,
1375     cdict: &CDict<'b>,
1376 ) -> SafeResult
1377 where
1378     'b: 'a, // Dictionary outlives the stream.
1379 {
1380     zcs.init_using_cdict(cdict)
1381 }
1382 
1383 /// Wraps the `ZSTD_CCtx_loadDictionary()` function.
cctx_load_dictionary(cctx: &mut CCtx, dict: &[u8]) -> SafeResult1384 pub fn cctx_load_dictionary(cctx: &mut CCtx, dict: &[u8]) -> SafeResult {
1385     cctx.load_dictionary(dict)
1386 }
1387 
1388 /// Wraps the `ZSTD_CCtx_refCDict()` function.
1389 ///
1390 /// Dictionary must outlive the context.
cctx_ref_cdict<'a, 'b>( cctx: &mut CCtx<'a>, cdict: &CDict<'b>, ) -> SafeResult where 'b: 'a,1391 pub fn cctx_ref_cdict<'a, 'b>(
1392     cctx: &mut CCtx<'a>,
1393     cdict: &CDict<'b>,
1394 ) -> SafeResult
1395 where
1396     'b: 'a,
1397 {
1398     cctx.ref_cdict(cdict)
1399 }
1400 
1401 /// Wraps the `ZSTD_CCtx_refPrefix()` function.
1402 ///
1403 /// Dictionary must outlive the prefix.
cctx_ref_prefix<'a, 'b>( cctx: &mut CCtx<'a>, prefix: &'b [u8], ) -> SafeResult where 'b: 'a,1404 pub fn cctx_ref_prefix<'a, 'b>(
1405     cctx: &mut CCtx<'a>,
1406     prefix: &'b [u8],
1407 ) -> SafeResult
1408 where
1409     'b: 'a,
1410 {
1411     cctx.ref_prefix(prefix)
1412 }
1413 
1414 /// Wraps the `ZSTD_DCtx_loadDictionary()` function.
dctx_load_dictionary(dctx: &mut DCtx<'_>, dict: &[u8]) -> SafeResult1415 pub fn dctx_load_dictionary(dctx: &mut DCtx<'_>, dict: &[u8]) -> SafeResult {
1416     dctx.load_dictionary(dict)
1417 }
1418 
1419 /// Wraps the `ZSTD_DCtx_refDDict()` function.
dctx_ref_ddict<'a, 'b>( dctx: &mut DCtx<'a>, ddict: &'b DDict<'b>, ) -> SafeResult where 'b: 'a,1420 pub fn dctx_ref_ddict<'a, 'b>(
1421     dctx: &mut DCtx<'a>,
1422     ddict: &'b DDict<'b>,
1423 ) -> SafeResult
1424 where
1425     'b: 'a,
1426 {
1427     dctx.ref_ddict(ddict)
1428 }
1429 
1430 /// Wraps the `ZSTD_DCtx_refPrefix()` function.
dctx_ref_prefix<'a, 'b>( dctx: &mut DCtx<'a>, prefix: &'b [u8], ) -> SafeResult where 'b: 'a,1431 pub fn dctx_ref_prefix<'a, 'b>(
1432     dctx: &mut DCtx<'a>,
1433     prefix: &'b [u8],
1434 ) -> SafeResult
1435 where
1436     'b: 'a,
1437 {
1438     dctx.ref_prefix(prefix)
1439 }
1440 
1441 /// Wraps the `ZSTD_CCtx_reset()` function.
cctx_reset(cctx: &mut CCtx, reset: ResetDirective) -> SafeResult1442 pub fn cctx_reset(cctx: &mut CCtx, reset: ResetDirective) -> SafeResult {
1443     cctx.reset(reset)
1444 }
1445 
1446 /// Wraps the `ZSTD_DCtx_reset()` function.
dctx_reset(dctx: &mut DCtx, reset: ResetDirective) -> SafeResult1447 pub fn dctx_reset(dctx: &mut DCtx, reset: ResetDirective) -> SafeResult {
1448     parse_code(unsafe { zstd_sys::ZSTD_DCtx_reset(dctx.0, reset) })
1449 }
1450 
1451 /// Wraps the `ZSTD_resetCStream()` function.
1452 #[cfg(feature = "experimental")]
1453 #[deprecated]
1454 #[allow(deprecated)]
reset_cstream(zcs: &mut CStream, pledged_src_size: u64) -> SafeResult1455 pub fn reset_cstream(zcs: &mut CStream, pledged_src_size: u64) -> SafeResult {
1456     zcs.reset_cstream(pledged_src_size)
1457 }
1458 
1459 /// Wraps the `ZSTD_initDStream_usingDict()` function.
1460 #[cfg(feature = "experimental")]
1461 #[deprecated]
1462 #[allow(deprecated)]
init_dstream_using_dict(zds: &mut DStream, dict: &[u8]) -> SafeResult1463 pub fn init_dstream_using_dict(zds: &mut DStream, dict: &[u8]) -> SafeResult {
1464     zds.init_using_dict(dict)
1465 }
1466 
1467 /// Wraps the `ZSTD_initDStream_usingDDict()` function.
1468 #[cfg(feature = "experimental")]
1469 #[deprecated]
1470 #[allow(deprecated)]
init_dstream_using_ddict<'a, 'b>( zds: &mut DStream<'a>, ddict: &DDict<'b>, ) -> SafeResult where 'b: 'a,1471 pub fn init_dstream_using_ddict<'a, 'b>(
1472     zds: &mut DStream<'a>,
1473     ddict: &DDict<'b>,
1474 ) -> SafeResult
1475 where
1476     'b: 'a,
1477 {
1478     zds.init_using_ddict(ddict)
1479 }
1480 
1481 /// Wraps the `ZSTD_resetDStream()` function.
1482 #[cfg(feature = "experimental")]
reset_dstream(zds: &mut DStream) -> SafeResult1483 pub fn reset_dstream(zds: &mut DStream) -> SafeResult {
1484     zds.reset()
1485 }
1486 
1487 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1488 pub enum FrameFormat {
1489     /// Regular zstd format.
1490     One,
1491 
1492     /// Skip the 4 bytes identifying the content as zstd-compressed data.
1493     Magicless,
1494 }
1495 
1496 /// A compression parameter.
1497 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1498 pub enum CParameter {
1499     #[cfg(feature = "experimental")]
1500     Format(FrameFormat),
1501 
1502     CompressionLevel(CompressionLevel),
1503 
1504     WindowLog(u32),
1505 
1506     HashLog(u32),
1507 
1508     ChainLog(u32),
1509 
1510     SearchLog(u32),
1511 
1512     MinMatch(u32),
1513 
1514     TargetLength(u32),
1515 
1516     Strategy(Strategy),
1517 
1518     EnableLongDistanceMatching(bool),
1519 
1520     LdmHashLog(u32),
1521 
1522     LdmMinMatch(u32),
1523 
1524     LdmBucketSizeLog(u32),
1525 
1526     LdmHashRateLog(u32),
1527 
1528     ContentSizeFlag(bool),
1529 
1530     ChecksumFlag(bool),
1531 
1532     DictIdFlag(bool),
1533 
1534     NbWorkers(u32),
1535 
1536     JobSize(u32),
1537 
1538     OverlapSizeLog(u32),
1539 }
1540 
1541 /// A decompression parameter.
1542 pub enum DParameter {
1543     WindowLogMax(u32),
1544 
1545     /// See `FrameFormat`.
1546     #[cfg(feature = "experimental")]
1547     Format(FrameFormat),
1548 }
1549 
1550 /// Wraps the `ZSTD_DCtx_setParameter()` function.
dctx_set_parameter(dctx: &mut DCtx, param: DParameter) -> SafeResult1551 pub fn dctx_set_parameter(dctx: &mut DCtx, param: DParameter) -> SafeResult {
1552     dctx.set_parameter(param)
1553 }
1554 
1555 /// Wraps the `ZSTD_CCtx_setParameter()` function.
cctx_set_parameter(cctx: &mut CCtx, param: CParameter) -> SafeResult1556 pub fn cctx_set_parameter(cctx: &mut CCtx, param: CParameter) -> SafeResult {
1557     cctx.set_parameter(param)
1558 }
1559 
1560 /// Wraps the `ZSTD_CCtx_setPledgedSrcSize()` function.
cctx_set_pledged_src_size( cctx: &mut CCtx, pledged_src_size: u64, ) -> SafeResult1561 pub fn cctx_set_pledged_src_size(
1562     cctx: &mut CCtx,
1563     pledged_src_size: u64,
1564 ) -> SafeResult {
1565     cctx.set_pledged_src_size(pledged_src_size)
1566 }
1567 
1568 /// Wraps thge `ZDICT_trainFromBuffer()` function.
train_from_buffer( dict_buffer: &mut [u8], samples_buffer: &[u8], samples_sizes: &[usize], ) -> SafeResult1569 pub fn train_from_buffer(
1570     dict_buffer: &mut [u8],
1571     samples_buffer: &[u8],
1572     samples_sizes: &[usize],
1573 ) -> SafeResult {
1574     assert_eq!(samples_buffer.len(), samples_sizes.iter().sum());
1575     parse_code(unsafe {
1576         zstd_sys::ZDICT_trainFromBuffer(
1577             ptr_mut_void(dict_buffer),
1578             dict_buffer.len(),
1579             ptr_void(samples_buffer),
1580             samples_sizes.as_ptr(),
1581             samples_sizes.len() as u32,
1582         )
1583     })
1584 }
1585 
1586 /// Wraps the `ZSTD_getDictID_fromDict()` function.
get_dict_id(dict_buffer: &[u8]) -> Option<u32>1587 pub fn get_dict_id(dict_buffer: &[u8]) -> Option<u32> {
1588     let id = unsafe {
1589         zstd_sys::ZDICT_getDictID(ptr_void(dict_buffer), dict_buffer.len())
1590     };
1591     if id > 0 {
1592         Some(id)
1593     } else {
1594         None
1595     }
1596 }
1597 
1598 /// Wraps the `ZSTD_getBlockSize()` function.
1599 #[cfg(feature = "experimental")]
get_block_size(cctx: &CCtx) -> usize1600 pub fn get_block_size(cctx: &CCtx) -> usize {
1601     unsafe { zstd_sys::ZSTD_getBlockSize(cctx.0) }
1602 }
1603 
1604 /// Wraps the `ZSTD_compressBlock()` function.
1605 #[cfg(feature = "experimental")]
compress_block( cctx: &mut CCtx, dst: &mut [u8], src: &[u8], ) -> SafeResult1606 pub fn compress_block(
1607     cctx: &mut CCtx,
1608     dst: &mut [u8],
1609     src: &[u8],
1610 ) -> SafeResult {
1611     cctx.compress_block(dst, src)
1612 }
1613 
1614 /// Wraps the `ZSTD_decompressBlock()` function.
1615 #[cfg(feature = "experimental")]
decompress_block(dctx: &mut DCtx, dst: &mut [u8], src: &[u8]) -> usize1616 pub fn decompress_block(dctx: &mut DCtx, dst: &mut [u8], src: &[u8]) -> usize {
1617     dctx.decompress_block(dst, src)
1618 }
1619 
1620 /// Wraps the `ZSTD_insertBlock()` function.
1621 #[cfg(feature = "experimental")]
insert_block(dctx: &mut DCtx, block: &[u8]) -> usize1622 pub fn insert_block(dctx: &mut DCtx, block: &[u8]) -> usize {
1623     dctx.insert_block(block)
1624 }
1625