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     }
529 }
530 
create_cctx<'a>() -> CCtx<'a>531 pub fn create_cctx<'a>() -> CCtx<'a> {
532     CCtx::create()
533 }
534 
535 impl<'a> Drop for CCtx<'a> {
drop(&mut self)536     fn drop(&mut self) {
537         unsafe {
538             zstd_sys::ZSTD_freeCCtx(self.0);
539         }
540     }
541 }
542 
543 unsafe impl<'a> Send for CCtx<'a> {}
544 // CCtx can't be shared across threads, so it does not implement Sync.
545 
c_char_to_str(text: *const c_char) -> &'static str546 unsafe fn c_char_to_str(text: *const c_char) -> &'static str {
547     #[cfg(not(feature = "std"))]
548     {
549         // To be safe, we need to compute right now its length
550         let len = libc::strlen(text);
551 
552         // Cast it to a slice
553         let slice = core::slice::from_raw_parts(text as *mut u8, len);
554         // And hope it's still text.
555         str::from_utf8(slice).expect("bad error message from zstd")
556     }
557 
558     #[cfg(feature = "std")]
559     {
560         std::ffi::CStr::from_ptr(text)
561             .to_str()
562             .expect("bad error message from zstd")
563     }
564 }
565 
get_error_name(code: usize) -> &'static str566 pub fn get_error_name(code: usize) -> &'static str {
567     unsafe {
568         let name = zstd_sys::ZSTD_getErrorName(code);
569         c_char_to_str(name)
570     }
571 }
572 
573 /// Wraps the `ZSTD_compressCCtx()` function
compress_cctx( ctx: &mut CCtx, dst: &mut [u8], src: &[u8], compression_level: CompressionLevel, ) -> SafeResult574 pub fn compress_cctx(
575     ctx: &mut CCtx,
576     dst: &mut [u8],
577     src: &[u8],
578     compression_level: CompressionLevel,
579 ) -> SafeResult {
580     ctx.compress(dst, src, compression_level)
581 }
582 
583 /// Wraps the `ZSTD_compress2()` function.
compress2(ctx: &mut CCtx, dst: &mut [u8], src: &[u8]) -> SafeResult584 pub fn compress2(ctx: &mut CCtx, dst: &mut [u8], src: &[u8]) -> SafeResult {
585     ctx.compress2(dst, src)
586 }
587 
588 /// A Decompression Context.
589 ///
590 /// The lifetime references the potential dictionary used for this context.
591 ///
592 /// If no dictionary was used, it will most likely be `'static`.
593 ///
594 /// Same as `DStream`.
595 pub struct DCtx<'a>(*mut zstd_sys::ZSTD_DCtx, PhantomData<&'a ()>);
596 
597 impl Default for DCtx<'_> {
default() -> Self598     fn default() -> Self {
599         create_dctx()
600     }
601 }
602 
603 impl DCtx<'static> {
create() -> Self604     pub fn create() -> Self {
605         DCtx(unsafe { zstd_sys::ZSTD_createDCtx() }, PhantomData)
606     }
607 }
608 
609 impl<'a> DCtx<'a> {
610     /// Wraps the `ZSTD_decompressDCtx()` function.
decompress(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult611     pub fn decompress(&mut self, dst: &mut [u8], src: &[u8]) -> SafeResult {
612         parse_code(unsafe {
613             zstd_sys::ZSTD_decompressDCtx(
614                 self.0,
615                 ptr_mut_void(dst),
616                 dst.len(),
617                 ptr_void(src),
618                 src.len(),
619             )
620         })
621     }
622 
decompress_using_dict( &mut self, dst: &mut [u8], src: &[u8], dict: &[u8], ) -> SafeResult623     pub fn decompress_using_dict(
624         &mut self,
625         dst: &mut [u8],
626         src: &[u8],
627         dict: &[u8],
628     ) -> SafeResult {
629         let code = unsafe {
630             zstd_sys::ZSTD_decompress_usingDict(
631                 self.0,
632                 ptr_mut_void(dst),
633                 dst.len(),
634                 ptr_void(src),
635                 src.len(),
636                 ptr_void(dict),
637                 dict.len(),
638             )
639         };
640         parse_code(code)
641     }
642 
643     /// Wraps the `ZSTD_decompress_usingDDict()` function.
decompress_using_ddict( &mut self, dst: &mut [u8], src: &[u8], ddict: &DDict, ) -> SafeResult644     pub fn decompress_using_ddict(
645         &mut self,
646         dst: &mut [u8],
647         src: &[u8],
648         ddict: &DDict,
649     ) -> SafeResult {
650         let code = unsafe {
651             zstd_sys::ZSTD_decompress_usingDDict(
652                 self.0,
653                 ptr_mut_void(dst),
654                 dst.len(),
655                 ptr_void(src),
656                 src.len(),
657                 ddict.0,
658             )
659         };
660         parse_code(code)
661     }
662 
663     /// Wraps the `ZSTD_initCStream()` function.
664     ///
665     /// Initializes an existing `DStream` for decompression.
init(&mut self) -> usize666     pub fn init(&mut self) -> usize {
667         unsafe { zstd_sys::ZSTD_initDStream(self.0) }
668     }
669 
670     /// Wraps the `ZSTD_initDStream_usingDict()` function.
671     #[cfg(feature = "experimental")]
672     #[deprecated]
init_using_dict(&mut self, dict: &[u8]) -> SafeResult673     pub fn init_using_dict(&mut self, dict: &[u8]) -> SafeResult {
674         let code = unsafe {
675             zstd_sys::ZSTD_initDStream_usingDict(
676                 self.0,
677                 ptr_void(dict),
678                 dict.len(),
679             )
680         };
681         parse_code(code)
682     }
683 
684     /// Wraps the `ZSTD_initDStream_usingDDict()` function.
685     #[cfg(feature = "experimental")]
686     #[deprecated]
init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult where 'b: 'a,687     pub fn init_using_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
688     where
689         'b: 'a,
690     {
691         let code =
692             unsafe { zstd_sys::ZSTD_initDStream_usingDDict(self.0, ddict.0) };
693         parse_code(code)
694     }
695 
696     /// Wraps the `ZSTD_resetDStream()` function.
697     #[cfg(feature = "experimental")]
reset(&mut self) -> SafeResult698     pub fn reset(&mut self) -> SafeResult {
699         let code = unsafe { zstd_sys::ZSTD_resetDStream(self.0) };
700         parse_code(code)
701     }
702 
load_dictionary(&mut self, dict: &[u8]) -> SafeResult703     pub fn load_dictionary(&mut self, dict: &[u8]) -> SafeResult {
704         parse_code(unsafe {
705             zstd_sys::ZSTD_DCtx_loadDictionary(
706                 self.0,
707                 ptr_void(dict),
708                 dict.len(),
709             )
710         })
711     }
712 
ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult where 'b: 'a,713     pub fn ref_ddict<'b>(&mut self, ddict: &DDict<'b>) -> SafeResult
714     where
715         'b: 'a,
716     {
717         parse_code(unsafe { zstd_sys::ZSTD_DCtx_refDDict(self.0, ddict.0) })
718     }
719 
ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult where 'b: 'a,720     pub fn ref_prefix<'b>(&mut self, prefix: &'b [u8]) -> SafeResult
721     where
722         'b: 'a,
723     {
724         parse_code(unsafe {
725             zstd_sys::ZSTD_DCtx_refPrefix(
726                 self.0,
727                 ptr_void(prefix),
728                 prefix.len(),
729             )
730         })
731     }
732 
set_parameter(&mut self, param: DParameter) -> SafeResult733     pub fn set_parameter(&mut self, param: DParameter) -> SafeResult {
734         #[cfg(feature = "experimental")]
735         use zstd_sys::ZSTD_dParameter::ZSTD_d_experimentalParam1 as ZSTD_d_format;
736         #[cfg(feature = "experimental")]
737         use zstd_sys::ZSTD_format_e;
738 
739         use zstd_sys::ZSTD_dParameter::*;
740         use DParameter::*;
741 
742         let (param, value) = match param {
743             #[cfg(feature = "experimental")]
744             Format(FrameFormat::One) => {
745                 (ZSTD_d_format, ZSTD_format_e::ZSTD_f_zstd1 as c_int)
746             }
747             #[cfg(feature = "experimental")]
748             Format(FrameFormat::Magicless) => (
749                 ZSTD_d_format,
750                 ZSTD_format_e::ZSTD_f_zstd1_magicless as c_int,
751             ),
752 
753             WindowLogMax(value) => (ZSTD_d_windowLogMax, value as c_int),
754         };
755 
756         parse_code(unsafe {
757             zstd_sys::ZSTD_DCtx_setParameter(self.0, param, value)
758         })
759     }
760 
761     /// Wraps the `ZSTD_decompressStream()` function.
decompress_stream( &mut self, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult762     pub fn decompress_stream(
763         &mut self,
764         output: &mut OutBuffer,
765         input: &mut InBuffer,
766     ) -> SafeResult {
767         let mut output = output.wrap();
768         let mut input = input.wrap();
769         let code = unsafe {
770             zstd_sys::ZSTD_decompressStream(
771                 self.0,
772                 ptr_mut(&mut output),
773                 ptr_mut(&mut input),
774             )
775         };
776         parse_code(code)
777     }
778 
779     /// Wraps the `ZSTD_DStreamInSize()` function.
780     ///
781     /// Returns a hint for the recommended size of the input buffer for decompression.
in_size() -> usize782     pub fn in_size() -> usize {
783         unsafe { zstd_sys::ZSTD_DStreamInSize() }
784     }
785 
786     /// Wraps the `ZSTD_DStreamOutSize()` function.
787     ///
788     /// Returns a hint for the recommended size of the output buffer for decompression.
out_size() -> usize789     pub fn out_size() -> usize {
790         unsafe { zstd_sys::ZSTD_DStreamOutSize() }
791     }
792 
793     /// Wraps the `ZSTD_sizeof_DCtx()` function.
sizeof(&self) -> usize794     pub fn sizeof(&self) -> usize {
795         unsafe { zstd_sys::ZSTD_sizeof_DCtx(self.0) }
796     }
797 
798     /// Wraps the `ZSTD_decompressBlock()` function.
799     #[cfg(feature = "experimental")]
decompress_block(&mut self, dst: &mut [u8], src: &[u8]) -> usize800     pub fn decompress_block(&mut self, dst: &mut [u8], src: &[u8]) -> usize {
801         unsafe {
802             zstd_sys::ZSTD_decompressBlock(
803                 self.0,
804                 ptr_mut_void(dst),
805                 dst.len(),
806                 ptr_void(src),
807                 src.len(),
808             )
809         }
810     }
811 
812     /// Wraps the `ZSTD_insertBlock()` function.
813     #[cfg(feature = "experimental")]
insert_block(&mut self, block: &[u8]) -> usize814     pub fn insert_block(&mut self, block: &[u8]) -> usize {
815         unsafe {
816             zstd_sys::ZSTD_insertBlock(self.0, ptr_void(block), block.len())
817         }
818     }
819 }
820 
821 /// Prepares a new decompression context without dictionary.
create_dctx() -> DCtx<'static>822 pub fn create_dctx() -> DCtx<'static> {
823     DCtx::create()
824 }
825 
826 impl Drop for DCtx<'_> {
drop(&mut self)827     fn drop(&mut self) {
828         unsafe {
829             zstd_sys::ZSTD_freeDCtx(self.0);
830         }
831     }
832 }
833 
834 unsafe impl Send for DCtx<'_> {}
835 // DCtx can't be shared across threads, so it does not implement Sync.
836 
837 /// Wraps the `ZSTD_decompressDCtx()` function.
decompress_dctx( ctx: &mut DCtx, dst: &mut [u8], src: &[u8], ) -> SafeResult838 pub fn decompress_dctx(
839     ctx: &mut DCtx,
840     dst: &mut [u8],
841     src: &[u8],
842 ) -> SafeResult {
843     ctx.decompress(dst, src)
844 }
845 
846 /// Wraps the `ZSTD_compress_usingDict()` function.
compress_using_dict( ctx: &mut CCtx, dst: &mut [u8], src: &[u8], dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult847 pub fn compress_using_dict(
848     ctx: &mut CCtx,
849     dst: &mut [u8],
850     src: &[u8],
851     dict: &[u8],
852     compression_level: CompressionLevel,
853 ) -> SafeResult {
854     ctx.compress_using_dict(dst, src, dict, compression_level)
855 }
856 
857 /// Wraps the `ZSTD_decompress_usingDict()` function.
decompress_using_dict( dctx: &mut DCtx, dst: &mut [u8], src: &[u8], dict: &[u8], ) -> SafeResult858 pub fn decompress_using_dict(
859     dctx: &mut DCtx,
860     dst: &mut [u8],
861     src: &[u8],
862     dict: &[u8],
863 ) -> SafeResult {
864     dctx.decompress_using_dict(dst, src, dict)
865 }
866 
867 /// Compression dictionary.
868 pub struct CDict<'a>(*mut zstd_sys::ZSTD_CDict, PhantomData<&'a ()>);
869 
870 impl CDict<'static> {
create( dict_buffer: &[u8], compression_level: CompressionLevel, ) -> Self871     pub fn create(
872         dict_buffer: &[u8],
873         compression_level: CompressionLevel,
874     ) -> Self {
875         CDict(
876             unsafe {
877                 zstd_sys::ZSTD_createCDict(
878                     ptr_void(dict_buffer),
879                     dict_buffer.len(),
880                     compression_level,
881                 )
882             },
883             PhantomData,
884         )
885     }
886 }
887 
888 impl<'a> CDict<'a> {
889     #[cfg(feature = "experimental")]
create_by_reference( dict_buffer: &'a [u8], compression_level: CompressionLevel, ) -> Self890     pub fn create_by_reference(
891         dict_buffer: &'a [u8],
892         compression_level: CompressionLevel,
893     ) -> Self {
894         CDict(
895             unsafe {
896                 zstd_sys::ZSTD_createCDict_byReference(
897                     ptr_void(dict_buffer),
898                     dict_buffer.len(),
899                     compression_level,
900                 )
901             },
902             PhantomData,
903         )
904     }
sizeof(&self) -> usize905     pub fn sizeof(&self) -> usize {
906         unsafe { zstd_sys::ZSTD_sizeof_CDict(self.0) }
907     }
908 }
909 
910 /// Wraps the `ZSTD_createCDict()` function.
create_cdict( dict_buffer: &[u8], compression_level: CompressionLevel, ) -> CDict<'static>911 pub fn create_cdict(
912     dict_buffer: &[u8],
913     compression_level: CompressionLevel,
914 ) -> CDict<'static> {
915     CDict::create(dict_buffer, compression_level)
916 }
917 
918 impl<'a> Drop for CDict<'a> {
drop(&mut self)919     fn drop(&mut self) {
920         unsafe {
921             zstd_sys::ZSTD_freeCDict(self.0);
922         }
923     }
924 }
925 
926 unsafe impl<'a> Send for CDict<'a> {}
927 unsafe impl<'a> Sync for CDict<'a> {}
928 
929 /// Wraps the `ZSTD_compress_usingCDict()` function.
compress_using_cdict( cctx: &mut CCtx, dst: &mut [u8], src: &[u8], cdict: &CDict, ) -> SafeResult930 pub fn compress_using_cdict(
931     cctx: &mut CCtx,
932     dst: &mut [u8],
933     src: &[u8],
934     cdict: &CDict,
935 ) -> SafeResult {
936     cctx.compress_using_cdict(dst, src, cdict)
937 }
938 
939 pub struct DDict<'a>(*mut zstd_sys::ZSTD_DDict, PhantomData<&'a ()>);
940 
941 impl DDict<'static> {
create(dict_buffer: &[u8]) -> Self942     pub fn create(dict_buffer: &[u8]) -> Self {
943         DDict(
944             unsafe {
945                 zstd_sys::ZSTD_createDDict(
946                     ptr_void(dict_buffer),
947                     dict_buffer.len(),
948                 )
949             },
950             PhantomData,
951         )
952     }
953 }
954 
955 impl<'a> DDict<'a> {
sizeof(&self) -> usize956     pub fn sizeof(&self) -> usize {
957         unsafe { zstd_sys::ZSTD_sizeof_DDict(self.0) }
958     }
959 
960     /// Wraps the `ZSTD_createDDict_byReference()` function.
961     ///
962     /// The dictionary will keep referencing `dict_buffer`.
963     #[cfg(feature = "experimental")]
create_by_reference(dict_buffer: &'a [u8]) -> Self964     pub fn create_by_reference(dict_buffer: &'a [u8]) -> Self {
965         DDict(
966             unsafe {
967                 zstd_sys::ZSTD_createDDict_byReference(
968                     ptr_void(dict_buffer),
969                     dict_buffer.len(),
970                 )
971             },
972             PhantomData,
973         )
974     }
975 
get_dict_id(&self) -> u32976     pub fn get_dict_id(&self) -> u32 {
977         unsafe { zstd_sys::ZSTD_getDictID_fromDDict(self.0) as u32 }
978     }
979 }
980 
981 /// Wraps the `ZSTD_createDDict()` function.
982 ///
983 /// It copies the dictionary internally, so the resulting `DDict` is `'static`.
create_ddict(dict_buffer: &[u8]) -> DDict<'static>984 pub fn create_ddict(dict_buffer: &[u8]) -> DDict<'static> {
985     DDict::create(dict_buffer)
986 }
987 
988 impl<'a> Drop for DDict<'a> {
drop(&mut self)989     fn drop(&mut self) {
990         unsafe {
991             zstd_sys::ZSTD_freeDDict(self.0);
992         }
993     }
994 }
995 
996 unsafe impl<'a> Send for DDict<'a> {}
997 unsafe impl<'a> Sync for DDict<'a> {}
998 
999 /// Wraps the `ZSTD_decompress_usingDDict()` function.
decompress_using_ddict( dctx: &mut DCtx, dst: &mut [u8], src: &[u8], ddict: &DDict, ) -> SafeResult1000 pub fn decompress_using_ddict(
1001     dctx: &mut DCtx,
1002     dst: &mut [u8],
1003     src: &[u8],
1004     ddict: &DDict,
1005 ) -> SafeResult {
1006     dctx.decompress_using_ddict(dst, src, ddict)
1007 }
1008 
1009 /// Compression stream.
1010 ///
1011 /// Same as `CCtx`.
1012 pub type CStream<'a> = CCtx<'a>;
1013 
1014 // CStream can't be shared across threads, so it does not implement Sync.
1015 
1016 /// Allocates a new `CStream`.
create_cstream<'a>() -> CStream<'a>1017 pub fn create_cstream<'a>() -> CStream<'a> {
1018     CCtx(unsafe { zstd_sys::ZSTD_createCStream() }, PhantomData)
1019 }
1020 
1021 /// Prepares an existing `CStream` for compression at the given level.
init_cstream( zcs: &mut CStream, compression_level: CompressionLevel, ) -> usize1022 pub fn init_cstream(
1023     zcs: &mut CStream,
1024     compression_level: CompressionLevel,
1025 ) -> usize {
1026     zcs.init(compression_level)
1027 }
1028 
1029 #[derive(Debug)]
1030 /// Wrapper around an input buffer.
1031 ///
1032 /// Bytes will be read starting at `src[pos]`.
1033 ///
1034 /// `pos` will be updated after reading.
1035 pub struct InBuffer<'a> {
1036     pub src: &'a [u8],
1037     pub pos: usize,
1038 }
1039 
1040 #[derive(Debug)]
1041 /// Wrapper around an output buffer.
1042 ///
1043 /// Bytes will be written starting at `dst[pos]`.
1044 ///
1045 /// `pos` will be updated after writing.
1046 pub struct OutBuffer<'a> {
1047     pub dst: &'a mut [u8],
1048     pub pos: usize,
1049 }
1050 
1051 /// Convenience method to get a mut pointer from a mut ref.
ptr_mut<B>(ptr_void: &mut B) -> *mut B1052 fn ptr_mut<B>(ptr_void: &mut B) -> *mut B {
1053     ptr_void as *mut B
1054 }
1055 
1056 /// Interface between a C-level ZSTD_outBuffer and a rust-level `OutBuffer`.
1057 ///
1058 /// Will update the parent buffer from the C buffer on drop.
1059 struct OutBufferWrapper<'a, 'b: 'a> {
1060     buf: zstd_sys::ZSTD_outBuffer,
1061     parent: &'a mut OutBuffer<'b>,
1062 }
1063 
1064 impl<'a, 'b: 'a> Deref for OutBufferWrapper<'a, 'b> {
1065     type Target = zstd_sys::ZSTD_outBuffer;
1066 
deref(&self) -> &Self::Target1067     fn deref(&self) -> &Self::Target {
1068         &self.buf
1069     }
1070 }
1071 
1072 impl<'a, 'b: 'a> DerefMut for OutBufferWrapper<'a, 'b> {
deref_mut(&mut self) -> &mut Self::Target1073     fn deref_mut(&mut self) -> &mut Self::Target {
1074         &mut self.buf
1075     }
1076 }
1077 
1078 impl<'a> OutBuffer<'a> {
1079     /// Returns a new `OutBuffer` around the given slice.
1080     ///
1081     /// Starts with `pos = 0`.
around(dst: &'a mut [u8]) -> Self1082     pub fn around(dst: &'a mut [u8]) -> Self {
1083         OutBuffer { dst, pos: 0 }
1084     }
1085 
wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a>1086     fn wrap<'b>(&'b mut self) -> OutBufferWrapper<'b, 'a> {
1087         OutBufferWrapper {
1088             buf: zstd_sys::ZSTD_outBuffer {
1089                 dst: ptr_mut_void(self.dst),
1090                 size: self.dst.len(),
1091                 pos: self.pos,
1092             },
1093             parent: self,
1094         }
1095     }
1096 
1097     /// Returns the part of this buffer that was written to.
as_slice<'b>(&'b self) -> &'a [u8] where 'b: 'a,1098     pub fn as_slice<'b>(&'b self) -> &'a [u8]
1099     where
1100         'b: 'a,
1101     {
1102         let pos = self.pos;
1103         &self.dst[..pos]
1104     }
1105 }
1106 
1107 impl<'a, 'b> Drop for OutBufferWrapper<'a, 'b> {
drop(&mut self)1108     fn drop(&mut self) {
1109         self.parent.pos = self.buf.pos;
1110     }
1111 }
1112 
1113 struct InBufferWrapper<'a, 'b: 'a> {
1114     buf: zstd_sys::ZSTD_inBuffer,
1115     parent: &'a mut InBuffer<'b>,
1116 }
1117 
1118 impl<'a, 'b: 'a> Deref for InBufferWrapper<'a, 'b> {
1119     type Target = zstd_sys::ZSTD_inBuffer;
1120 
deref(&self) -> &Self::Target1121     fn deref(&self) -> &Self::Target {
1122         &self.buf
1123     }
1124 }
1125 
1126 impl<'a, 'b: 'a> DerefMut for InBufferWrapper<'a, 'b> {
deref_mut(&mut self) -> &mut Self::Target1127     fn deref_mut(&mut self) -> &mut Self::Target {
1128         &mut self.buf
1129     }
1130 }
1131 
1132 impl<'a> InBuffer<'a> {
1133     /// Returns a new `InBuffer` around the given slice.
1134     ///
1135     /// Starts with `pos = 0`.
around(src: &'a [u8]) -> Self1136     pub fn around(src: &'a [u8]) -> Self {
1137         InBuffer { src, pos: 0 }
1138     }
1139 
wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a>1140     fn wrap<'b>(&'b mut self) -> InBufferWrapper<'b, 'a> {
1141         InBufferWrapper {
1142             buf: zstd_sys::ZSTD_inBuffer {
1143                 src: ptr_void(self.src),
1144                 size: self.src.len(),
1145                 pos: self.pos,
1146             },
1147             parent: self,
1148         }
1149     }
1150 }
1151 
1152 impl<'a, 'b> Drop for InBufferWrapper<'a, 'b> {
drop(&mut self)1153     fn drop(&mut self) {
1154         self.parent.pos = self.buf.pos;
1155     }
1156 }
1157 
1158 /// Wraps the `ZSTD_compressStream()` function.
compress_stream( zcs: &mut CStream, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult1159 pub fn compress_stream(
1160     zcs: &mut CStream,
1161     output: &mut OutBuffer,
1162     input: &mut InBuffer,
1163 ) -> SafeResult {
1164     zcs.compress_stream(output, input)
1165 }
1166 
compress_stream2( cctx: &mut CCtx, output: &mut OutBuffer, input: &mut InBuffer, end_op: zstd_sys::ZSTD_EndDirective, ) -> SafeResult1167 pub fn compress_stream2(
1168     cctx: &mut CCtx,
1169     output: &mut OutBuffer,
1170     input: &mut InBuffer,
1171     end_op: zstd_sys::ZSTD_EndDirective,
1172 ) -> SafeResult {
1173     cctx.compress_stream2(output, input, end_op)
1174 }
1175 
1176 /// Wraps the `ZSTD_flushStream()` function.
flush_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult1177 pub fn flush_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult {
1178     zcs.flush_stream(output)
1179 }
1180 
1181 /// Wraps the `ZSTD_endStream()` function.
end_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult1182 pub fn end_stream(zcs: &mut CStream, output: &mut OutBuffer) -> SafeResult {
1183     zcs.end_stream(output)
1184 }
1185 
1186 /// Wraps `ZSTD_CStreamInSize()`
cstream_in_size() -> usize1187 pub fn cstream_in_size() -> usize {
1188     unsafe { zstd_sys::ZSTD_CStreamInSize() }
1189 }
1190 
1191 /// Wraps `ZSTD_CStreamOutSize()`
cstream_out_size() -> usize1192 pub fn cstream_out_size() -> usize {
1193     unsafe { zstd_sys::ZSTD_CStreamOutSize() }
1194 }
1195 
1196 /// A Decompression stream.
1197 ///
1198 /// Same as `DCtx`.
1199 pub type DStream<'a> = DCtx<'a>;
1200 
create_dstream() -> DStream<'static>1201 pub fn create_dstream() -> DStream<'static> {
1202     DStream::create()
1203 }
1204 
1205 /// Wraps the `ZSTD_initCStream()` function.
1206 ///
1207 /// Initializes an existing `DStream` for decompression.
init_dstream(zds: &mut DStream) -> usize1208 pub fn init_dstream(zds: &mut DStream) -> usize {
1209     zds.init()
1210 }
1211 
1212 /// Wraps the `ZSTD_decompressStream()` function.
decompress_stream( zds: &mut DStream, output: &mut OutBuffer, input: &mut InBuffer, ) -> SafeResult1213 pub fn decompress_stream(
1214     zds: &mut DStream,
1215     output: &mut OutBuffer,
1216     input: &mut InBuffer,
1217 ) -> SafeResult {
1218     zds.decompress_stream(output, input)
1219 }
1220 
1221 /// Wraps the `ZSTD_DStreamInSize()` function.
1222 ///
1223 /// Returns a hint for the recommended size of the input buffer for decompression.
dstream_in_size() -> usize1224 pub fn dstream_in_size() -> usize {
1225     DStream::in_size()
1226 }
1227 
1228 /// Wraps the `ZSTD_DStreamOutSize()` function.
1229 ///
1230 /// Returns a hint for the recommended size of the output buffer for decompression.
dstream_out_size() -> usize1231 pub fn dstream_out_size() -> usize {
1232     DStream::out_size()
1233 }
1234 
1235 /// Wraps the `ZSTD_findFrameCompressedSize()` function.
1236 ///
1237 /// `src` should contain at least an entire frame.
find_frame_compressed_size(src: &[u8]) -> SafeResult1238 pub fn find_frame_compressed_size(src: &[u8]) -> SafeResult {
1239     let code = unsafe {
1240         zstd_sys::ZSTD_findFrameCompressedSize(ptr_void(src), src.len())
1241     };
1242     parse_code(code)
1243 }
1244 
1245 /// Wraps the `ZSTD_getFrameContentSize()` function.
1246 ///
1247 /// `src` should contain at least a frame header.
get_frame_content_size(src: &[u8]) -> u641248 pub fn get_frame_content_size(src: &[u8]) -> u64 {
1249     unsafe { zstd_sys::ZSTD_getFrameContentSize(ptr_void(src), src.len()) }
1250 }
1251 
1252 /// Wraps the `ZSTD_findDecompressedSize()` function.
1253 ///
1254 /// `src` should be exactly a sequence of ZSTD frames.
1255 #[cfg(feature = "experimental")]
find_decompressed_size(src: &[u8]) -> u641256 pub fn find_decompressed_size(src: &[u8]) -> u64 {
1257     unsafe { zstd_sys::ZSTD_findDecompressedSize(ptr_void(src), src.len()) }
1258 }
1259 
1260 /// Wraps the `ZSTD_sizeofCCtx()` function.
sizeof_cctx(cctx: &CCtx) -> usize1261 pub fn sizeof_cctx(cctx: &CCtx) -> usize {
1262     cctx.sizeof()
1263 }
1264 
1265 /// Wraps the `ZSTD_sizeof_DCtx()` function.
sizeof_dctx(dctx: &DCtx) -> usize1266 pub fn sizeof_dctx(dctx: &DCtx) -> usize {
1267     dctx.sizeof()
1268 }
1269 
1270 /// Wraps the `ZSTD_sizeof_CStream()` function.
sizeof_cstream(zcs: &CStream) -> usize1271 pub fn sizeof_cstream(zcs: &CStream) -> usize {
1272     zcs.sizeof()
1273 }
1274 
1275 /// Wraps the `ZSTD_sizeof_DStream()` function.
sizeof_dstream(zds: &DStream) -> usize1276 pub fn sizeof_dstream(zds: &DStream) -> usize {
1277     zds.sizeof()
1278 }
1279 
1280 /// Wraps the `ZSTD_sizeof_CDict()` function.
sizeof_cdict(cdict: &CDict) -> usize1281 pub fn sizeof_cdict(cdict: &CDict) -> usize {
1282     cdict.sizeof()
1283 }
1284 
1285 /// Wraps the `ZSTD_sizeof_DDict()` function.
sizeof_ddict(ddict: &DDict) -> usize1286 pub fn sizeof_ddict(ddict: &DDict) -> usize {
1287     ddict.sizeof()
1288 }
1289 
1290 /// Wraps the `ZSTD_createCDict_byReference()` function.
1291 ///
1292 /// The dictionary will keep referencing `dict_buffer`.
1293 #[cfg(feature = "experimental")]
create_cdict_by_reference<'a>( dict_buffer: &'a [u8], compression_level: CompressionLevel, ) -> CDict<'a>1294 pub fn create_cdict_by_reference<'a>(
1295     dict_buffer: &'a [u8],
1296     compression_level: CompressionLevel,
1297 ) -> CDict<'a> {
1298     CDict::create_by_reference(dict_buffer, compression_level)
1299 }
1300 
1301 /// Wraps the `ZSTD_isFrame()` function.
1302 #[cfg(feature = "experimental")]
is_frame(buffer: &[u8]) -> u321303 pub fn is_frame(buffer: &[u8]) -> u32 {
1304     unsafe { zstd_sys::ZSTD_isFrame(ptr_void(buffer), buffer.len()) as u32 }
1305 }
1306 
1307 /// Wraps the `ZSTD_createDDict_byReference()` function.
1308 ///
1309 /// The dictionary will keep referencing `dict_buffer`.
1310 #[cfg(feature = "experimental")]
create_ddict_by_reference(dict_buffer: &[u8]) -> DDict1311 pub fn create_ddict_by_reference(dict_buffer: &[u8]) -> DDict {
1312     DDict::create_by_reference(dict_buffer)
1313 }
1314 
1315 /// Wraps the `ZSTD_getDictID_fromDict()` function.
get_dict_id_from_dict(dict: &[u8]) -> u321316 pub fn get_dict_id_from_dict(dict: &[u8]) -> u32 {
1317     unsafe {
1318         zstd_sys::ZSTD_getDictID_fromDict(ptr_void(dict), dict.len()) as u32
1319     }
1320 }
1321 
1322 /// Wraps the `ZSTD_getDictID_fromDDict()` function.
get_dict_id_from_ddict(ddict: &DDict) -> u321323 pub fn get_dict_id_from_ddict(ddict: &DDict) -> u32 {
1324     ddict.get_dict_id()
1325 }
1326 
1327 /// Wraps the `ZSTD_getDictID_fromFrame()` function.
get_dict_id_from_frame(src: &[u8]) -> u321328 pub fn get_dict_id_from_frame(src: &[u8]) -> u32 {
1329     unsafe {
1330         zstd_sys::ZSTD_getDictID_fromFrame(ptr_void(src), src.len()) as u32
1331     }
1332 }
1333 
1334 /// Wraps the `ZSTD_initCStream_srcSize()` function.
1335 #[cfg(feacctxture = "experimental")]
1336 #[deprecated]
1337 #[allow(deprecated)]
init_cstream_src_size( zcs: &mut CStream, compression_level: CompressionLevel, pledged_src_size: u64, ) -> usize1338 pub fn init_cstream_src_size(
1339     zcs: &mut CStream,
1340     compression_level: CompressionLevel,
1341     pledged_src_size: u64,
1342 ) -> usize {
1343     zcs.init_src_size(compression_level, pledged_src_size)
1344 }
1345 
1346 /// Wraps the `ZSTD_initCStream_usingDict()` function.
1347 #[cfg(feature = "experimental")]
1348 #[deprecated]
1349 #[allow(deprecated)]
init_cstream_using_dict( zcs: &mut CStream, dict: &[u8], compression_level: CompressionLevel, ) -> SafeResult1350 pub fn init_cstream_using_dict(
1351     zcs: &mut CStream,
1352     dict: &[u8],
1353     compression_level: CompressionLevel,
1354 ) -> SafeResult {
1355     zcs.init_using_dict(dict, compression_level)
1356 }
1357 
1358 /// Wraps the `ZSTD_initCStream_usingCDict()` function.
1359 #[cfg(feature = "experimental")]
1360 #[deprecated]
1361 #[allow(deprecated)]
init_cstream_using_cdict<'a, 'b>( zcs: &mut CStream<'a>, cdict: &CDict<'b>, ) -> SafeResult where 'b: 'a,1362 pub fn init_cstream_using_cdict<'a, 'b>(
1363     zcs: &mut CStream<'a>,
1364     cdict: &CDict<'b>,
1365 ) -> SafeResult
1366 where
1367     'b: 'a, // Dictionary outlives the stream.
1368 {
1369     zcs.init_using_cdict(cdict)
1370 }
1371 
1372 /// Wraps the `ZSTD_CCtx_loadDictionary()` function.
cctx_load_dictionary(cctx: &mut CCtx, dict: &[u8]) -> SafeResult1373 pub fn cctx_load_dictionary(cctx: &mut CCtx, dict: &[u8]) -> SafeResult {
1374     cctx.load_dictionary(dict)
1375 }
1376 
1377 /// Wraps the `ZSTD_CCtx_refCDict()` function.
1378 ///
1379 /// Dictionary must outlive the context.
cctx_ref_cdict<'a, 'b>( cctx: &mut CCtx<'a>, cdict: &CDict<'b>, ) -> SafeResult where 'b: 'a,1380 pub fn cctx_ref_cdict<'a, 'b>(
1381     cctx: &mut CCtx<'a>,
1382     cdict: &CDict<'b>,
1383 ) -> SafeResult
1384 where
1385     'b: 'a,
1386 {
1387     cctx.ref_cdict(cdict)
1388 }
1389 
1390 /// Wraps the `ZSTD_CCtx_refPrefix()` function.
1391 ///
1392 /// Dictionary must outlive the prefix.
cctx_ref_prefix<'a, 'b>( cctx: &mut CCtx<'a>, prefix: &'b [u8], ) -> SafeResult where 'b: 'a,1393 pub fn cctx_ref_prefix<'a, 'b>(
1394     cctx: &mut CCtx<'a>,
1395     prefix: &'b [u8],
1396 ) -> SafeResult
1397 where
1398     'b: 'a,
1399 {
1400     cctx.ref_prefix(prefix)
1401 }
1402 
1403 /// Wraps the `ZSTD_DCtx_loadDictionary()` function.
dctx_load_dictionary(dctx: &mut DCtx<'_>, dict: &[u8]) -> SafeResult1404 pub fn dctx_load_dictionary(dctx: &mut DCtx<'_>, dict: &[u8]) -> SafeResult {
1405     dctx.load_dictionary(dict)
1406 }
1407 
1408 /// Wraps the `ZSTD_DCtx_refDDict()` function.
dctx_ref_ddict<'a, 'b>( dctx: &mut DCtx<'a>, ddict: &'b DDict<'b>, ) -> SafeResult where 'b: 'a,1409 pub fn dctx_ref_ddict<'a, 'b>(
1410     dctx: &mut DCtx<'a>,
1411     ddict: &'b DDict<'b>,
1412 ) -> SafeResult
1413 where
1414     'b: 'a,
1415 {
1416     dctx.ref_ddict(ddict)
1417 }
1418 
1419 /// Wraps the `ZSTD_DCtx_refPrefix()` function.
dctx_ref_prefix<'a, 'b>( dctx: &mut DCtx<'a>, prefix: &'b [u8], ) -> SafeResult where 'b: 'a,1420 pub fn dctx_ref_prefix<'a, 'b>(
1421     dctx: &mut DCtx<'a>,
1422     prefix: &'b [u8],
1423 ) -> SafeResult
1424 where
1425     'b: 'a,
1426 {
1427     dctx.ref_prefix(prefix)
1428 }
1429 
1430 /// Wraps the `ZSTD_CCtx_reset()` function.
cctx_reset(cctx: &mut CCtx, reset: ResetDirective) -> SafeResult1431 pub fn cctx_reset(cctx: &mut CCtx, reset: ResetDirective) -> SafeResult {
1432     cctx.reset(reset)
1433 }
1434 
1435 /// Wraps the `ZSTD_DCtx_reset()` function.
dctx_reset(dctx: &mut DCtx, reset: ResetDirective) -> SafeResult1436 pub fn dctx_reset(dctx: &mut DCtx, reset: ResetDirective) -> SafeResult {
1437     parse_code(unsafe { zstd_sys::ZSTD_DCtx_reset(dctx.0, reset) })
1438 }
1439 
1440 /// Wraps the `ZSTD_resetCStream()` function.
1441 #[cfg(feature = "experimental")]
1442 #[deprecated]
1443 #[allow(deprecated)]
reset_cstream(zcs: &mut CStream, pledged_src_size: u64) -> SafeResult1444 pub fn reset_cstream(zcs: &mut CStream, pledged_src_size: u64) -> SafeResult {
1445     zcs.reset_cstream(pledged_src_size)
1446 }
1447 
1448 /// Wraps the `ZSTD_initDStream_usingDict()` function.
1449 #[cfg(feature = "experimental")]
1450 #[deprecated]
1451 #[allow(deprecated)]
init_dstream_using_dict(zds: &mut DStream, dict: &[u8]) -> SafeResult1452 pub fn init_dstream_using_dict(zds: &mut DStream, dict: &[u8]) -> SafeResult {
1453     zds.init_using_dict(dict)
1454 }
1455 
1456 /// Wraps the `ZSTD_initDStream_usingDDict()` function.
1457 #[cfg(feature = "experimental")]
1458 #[deprecated]
1459 #[allow(deprecated)]
init_dstream_using_ddict<'a, 'b>( zds: &mut DStream<'a>, ddict: &DDict<'b>, ) -> SafeResult where 'b: 'a,1460 pub fn init_dstream_using_ddict<'a, 'b>(
1461     zds: &mut DStream<'a>,
1462     ddict: &DDict<'b>,
1463 ) -> SafeResult
1464 where
1465     'b: 'a,
1466 {
1467     zds.init_using_ddict(ddict)
1468 }
1469 
1470 /// Wraps the `ZSTD_resetDStream()` function.
1471 #[cfg(feature = "experimental")]
reset_dstream(zds: &mut DStream) -> SafeResult1472 pub fn reset_dstream(zds: &mut DStream) -> SafeResult {
1473     zds.reset()
1474 }
1475 
1476 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1477 pub enum FrameFormat {
1478     /// Regular zstd format.
1479     One,
1480 
1481     /// Skip the 4 bytes identifying the content as zstd-compressed data.
1482     Magicless,
1483 }
1484 
1485 /// A compression parameter.
1486 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1487 pub enum CParameter {
1488     #[cfg(feature = "experimental")]
1489     Format(FrameFormat),
1490 
1491     CompressionLevel(CompressionLevel),
1492 
1493     WindowLog(u32),
1494 
1495     HashLog(u32),
1496 
1497     ChainLog(u32),
1498 
1499     SearchLog(u32),
1500 
1501     MinMatch(u32),
1502 
1503     TargetLength(u32),
1504 
1505     Strategy(Strategy),
1506 
1507     EnableLongDistanceMatching(bool),
1508 
1509     LdmHashLog(u32),
1510 
1511     LdmMinMatch(u32),
1512 
1513     LdmBucketSizeLog(u32),
1514 
1515     LdmHashRateLog(u32),
1516 
1517     ContentSizeFlag(bool),
1518 
1519     ChecksumFlag(bool),
1520 
1521     DictIdFlag(bool),
1522 
1523     NbWorkers(u32),
1524 
1525     JobSize(u32),
1526 
1527     OverlapSizeLog(u32),
1528 }
1529 
1530 /// A decompression parameter.
1531 pub enum DParameter {
1532     WindowLogMax(u32),
1533 
1534     /// See `FrameFormat`.
1535     #[cfg(feature = "experimental")]
1536     Format(FrameFormat),
1537 }
1538 
1539 /// Wraps the `ZSTD_DCtx_setParameter()` function.
dctx_set_parameter(dctx: &mut DCtx, param: DParameter) -> SafeResult1540 pub fn dctx_set_parameter(dctx: &mut DCtx, param: DParameter) -> SafeResult {
1541     dctx.set_parameter(param)
1542 }
1543 
1544 /// Wraps the `ZSTD_CCtx_setParameter()` function.
cctx_set_parameter(cctx: &mut CCtx, param: CParameter) -> SafeResult1545 pub fn cctx_set_parameter(cctx: &mut CCtx, param: CParameter) -> SafeResult {
1546     cctx.set_parameter(param)
1547 }
1548 
1549 /// Wraps the `ZSTD_CCtx_setPledgedSrcSize()` function.
cctx_set_pledged_src_size( cctx: &mut CCtx, pledged_src_size: u64, ) -> SafeResult1550 pub fn cctx_set_pledged_src_size(
1551     cctx: &mut CCtx,
1552     pledged_src_size: u64,
1553 ) -> SafeResult {
1554     cctx.set_pledged_src_size(pledged_src_size)
1555 }
1556 
1557 /// Wraps thge `ZDICT_trainFromBuffer()` function.
train_from_buffer( dict_buffer: &mut [u8], samples_buffer: &[u8], samples_sizes: &[usize], ) -> SafeResult1558 pub fn train_from_buffer(
1559     dict_buffer: &mut [u8],
1560     samples_buffer: &[u8],
1561     samples_sizes: &[usize],
1562 ) -> SafeResult {
1563     assert_eq!(samples_buffer.len(), samples_sizes.iter().sum());
1564     parse_code(unsafe {
1565         zstd_sys::ZDICT_trainFromBuffer(
1566             ptr_mut_void(dict_buffer),
1567             dict_buffer.len(),
1568             ptr_void(samples_buffer),
1569             samples_sizes.as_ptr(),
1570             samples_sizes.len() as u32,
1571         )
1572     })
1573 }
1574 
1575 /// Wraps the `ZSTD_getDictID_fromDict()` function.
get_dict_id(dict_buffer: &[u8]) -> Option<u32>1576 pub fn get_dict_id(dict_buffer: &[u8]) -> Option<u32> {
1577     let id = unsafe {
1578         zstd_sys::ZDICT_getDictID(ptr_void(dict_buffer), dict_buffer.len())
1579     };
1580     if id > 0 {
1581         Some(id)
1582     } else {
1583         None
1584     }
1585 }
1586 
1587 /// Wraps the `ZSTD_getBlockSize()` function.
1588 #[cfg(feature = "experimental")]
get_block_size(cctx: &CCtx) -> usize1589 pub fn get_block_size(cctx: &CCtx) -> usize {
1590     unsafe { zstd_sys::ZSTD_getBlockSize(cctx.0) }
1591 }
1592 
1593 /// Wraps the `ZSTD_compressBlock()` function.
1594 #[cfg(feature = "experimental")]
compress_block( cctx: &mut CCtx, dst: &mut [u8], src: &[u8], ) -> SafeResult1595 pub fn compress_block(
1596     cctx: &mut CCtx,
1597     dst: &mut [u8],
1598     src: &[u8],
1599 ) -> SafeResult {
1600     cctx.compress_block(dst, src)
1601 }
1602 
1603 /// Wraps the `ZSTD_decompressBlock()` function.
1604 #[cfg(feature = "experimental")]
decompress_block(dctx: &mut DCtx, dst: &mut [u8], src: &[u8]) -> usize1605 pub fn decompress_block(dctx: &mut DCtx, dst: &mut [u8], src: &[u8]) -> usize {
1606     dctx.decompress_block(dst, src)
1607 }
1608 
1609 /// Wraps the `ZSTD_insertBlock()` function.
1610 #[cfg(feature = "experimental")]
insert_block(dctx: &mut DCtx, block: &[u8]) -> usize1611 pub fn insert_block(dctx: &mut DCtx, block: &[u8]) -> usize {
1612     dctx.insert_block(block)
1613 }
1614