Coverage Report

Created: 2026-01-09 07:11

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