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