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