1use core::ptr;
2
3use libc::{calloc, free, malloc, size_t};
4
5use crate::lib::common::entropy_common::FSE_readNCount_slice;
6use crate::lib::common::error_private::{ERR_isError, Error};
7use crate::lib::common::mem::MEM_readLE32;
8use crate::lib::common::xxhash::{
9 ZSTD_XXH64_digest, ZSTD_XXH64_reset, ZSTD_XXH64_slice, ZSTD_XXH64_update,
10};
11use crate::lib::common::zstd_common::ZSTD_getErrorCode;
12use crate::lib::common::zstd_internal::{
13 repStartValue, LL_bits, ML_bits, MaxLL, MaxML, MaxOff, ZSTD_blockHeaderSize,
14 ZSTD_cpuSupportsBmi2, ZSTD_limitCopy, WILDCOPY_OVERLENGTH, ZSTD_FRAMEIDSIZE,
15 ZSTD_WORKSPACETOOLARGE_FACTOR, ZSTD_WORKSPACETOOLARGE_MAXDURATION,
16};
17use crate::lib::compress::zstd_compress::{ZSTD_CCtx_params_s, ZSTD_CCtx_s};
18use crate::lib::decompress::huf_decompress::{
19 DTableDesc, HUF_ReadDTableX2_Workspace, HUF_readDTableX2_wksp,
20};
21use crate::lib::decompress::zstd_ddict::{MultipleDDicts, ZSTD_DDict, ZSTD_DDictHashSet};
22use crate::lib::decompress::zstd_decompress_block::{
23 getc_block_size, ZSTD_buildFSETable, ZSTD_checkContinuity, ZSTD_decompressBlock_internal,
24 ZSTD_getcBlockSize,
25};
26use crate::lib::decompress::{
27 blockProperties_t, BlockType, DecompressStage, LL_base, ML_base, NextInputType, OF_base,
28 OF_bits, StreamStage, ZSTD_DCtx, ZSTD_DCtx_s, ZSTD_FrameHeader, ZSTD_d_ignoreChecksum,
29 ZSTD_d_validateChecksum, ZSTD_dont_use, ZSTD_entropyDTables_t, ZSTD_forceIgnoreChecksum_e,
30 ZSTD_frame, ZSTD_skippableFrame, ZSTD_use_indefinitely, ZSTD_use_once,
31};
32use crate::lib::zstd::experimental::ZSTD_FRAMEHEADERSIZE_MIN;
33use crate::lib::zstd::*;
34
35use crate::lib::common::zstd_trace::{
36 ZSTD_Trace, ZSTD_trace_decompress_begin, ZSTD_trace_decompress_end,
37};
38
39use crate::lib::legacy::zstd_v05::{
40 ZBUFFv05_DCtx, ZBUFFv05_createDCtx, ZBUFFv05_decompressContinue,
41 ZBUFFv05_decompressInitDictionary, ZBUFFv05_freeDCtx, ZSTDv05_createDCtx,
42 ZSTDv05_decompress_usingDict, ZSTDv05_fast, ZSTDv05_findFrameSizeInfoLegacy, ZSTDv05_freeDCtx,
43 ZSTDv05_getFrameParams, ZSTDv05_parameters,
44};
45use crate::lib::legacy::zstd_v06::{
46 ZBUFFv06_DCtx_s, ZBUFFv06_createDCtx, ZBUFFv06_decompressContinue,
47 ZBUFFv06_decompressInitDictionary, ZBUFFv06_freeDCtx, ZSTDv06_createDCtx,
48 ZSTDv06_decompress_usingDict, ZSTDv06_findFrameSizeInfoLegacy, ZSTDv06_frameParams_s,
49 ZSTDv06_freeDCtx, ZSTDv06_getFrameParams,
50};
51use crate::lib::legacy::zstd_v07::{
52 ZBUFFv07_DCtx_s, ZBUFFv07_createDCtx, ZBUFFv07_decompressContinue,
53 ZBUFFv07_decompressInitDictionary, ZBUFFv07_freeDCtx, ZSTDv07_createDCtx,
54 ZSTDv07_decompress_usingDict, ZSTDv07_findFrameSizeInfoLegacy, ZSTDv07_frameParams,
55 ZSTDv07_freeDCtx, ZSTDv07_getFrameParams,
56};
57
58use crate::lib::decompress::zstd_ddict::{
59 ZSTD_DDict_dictContent, ZSTD_DDict_dictSize, ZSTD_copyDDictParameters,
60 ZSTD_createDDict_advanced, ZSTD_freeDDict, ZSTD_getDictID_fromDDict, ZSTD_sizeof_DDict,
61};
62
63pub type ZSTD_outBuffer = ZSTD_outBuffer_s;
64#[repr(C)]
65pub struct ZSTD_cpuid_t {
66 pub f1c: u32,
67 pub f1d: u32,
68 pub f7b: u32,
69 pub f7c: u32,
70}
71type ZBUFFv07_DCtx = ZBUFFv07_DCtx_s;
72type ZBUFFv06_DCtx = ZBUFFv06_DCtx_s;
73type XXH_errorcode = core::ffi::c_uint;
74pub const XXH_ERROR: XXH_errorcode = 1;
75pub const XXH_OK: XXH_errorcode = 0;
76pub type streaming_operation = core::ffi::c_uint;
77pub const is_streaming: streaming_operation = 1;
78pub const not_streaming: streaming_operation = 0;
79#[repr(C)]
80pub struct ZSTD_frameSizeInfo {
81 pub nbBlocks: size_t,
82 pub compressedSize: size_t,
83 pub decompressedBound: core::ffi::c_ulonglong,
84}
85#[repr(C)]
86pub struct ZSTD_bounds {
87 pub error: size_t,
88 pub lowerBound: core::ffi::c_int,
89 pub upperBound: core::ffi::c_int,
90}
91pub type ZSTD_ResetDirective = core::ffi::c_uint;
92pub const ZSTD_reset_session_and_parameters: ZSTD_ResetDirective = 3;
93pub const ZSTD_reset_parameters: ZSTD_ResetDirective = 2;
94pub const ZSTD_reset_session_only: ZSTD_ResetDirective = 1;
95pub type ZSTD_dParameter = core::ffi::c_uint;
96pub const ZSTD_d_experimentalParam6: ZSTD_dParameter = 1005;
97pub const ZSTD_d_experimentalParam5: ZSTD_dParameter = 1004;
98pub const ZSTD_d_experimentalParam4: ZSTD_dParameter = 1003;
99pub const ZSTD_d_experimentalParam3: ZSTD_dParameter = 1002;
100pub const ZSTD_d_experimentalParam2: ZSTD_dParameter = 1001;
101pub const ZSTD_d_experimentalParam1: ZSTD_dParameter = 1000;
102pub const ZSTD_d_windowLogMax: ZSTD_dParameter = 100;
103pub type ZSTD_DStream = ZSTD_DCtx;
104pub type ZSTD_nextInputType_e = core::ffi::c_uint;
105pub const ZSTDnit_skippableFrame: ZSTD_nextInputType_e = 5;
106pub const ZSTDnit_checksum: ZSTD_nextInputType_e = 4;
107pub const ZSTDnit_lastBlock: ZSTD_nextInputType_e = 3;
108pub const ZSTDnit_block: ZSTD_nextInputType_e = 2;
109pub const ZSTDnit_blockHeader: ZSTD_nextInputType_e = 1;
110pub const ZSTDnit_frameHeader: ZSTD_nextInputType_e = 0;
111pub type ZSTD_dictContentType_e = core::ffi::c_uint;
112pub const ZSTD_dct_fullDict: ZSTD_dictContentType_e = 2;
113pub const ZSTD_dct_rawContent: ZSTD_dictContentType_e = 1;
114pub const ZSTD_dct_auto: ZSTD_dictContentType_e = 0;
115pub type ZSTD_dictLoadMethod_e = core::ffi::c_uint;
116pub const ZSTD_dlm_byRef: ZSTD_dictLoadMethod_e = 1;
117pub const ZSTD_dlm_byCopy: ZSTD_dictLoadMethod_e = 0;
118pub const ZSTD_MAXWINDOWSIZE_DEFAULT: u32 = (1u32 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).wrapping_add(1);
119pub const ZSTD_NO_FORWARD_PROGRESS_MAX: core::ffi::c_int = 16;
120pub const ZSTD_VERSION_MAJOR: core::ffi::c_int = 1;
121pub const ZSTD_VERSION_MINOR: core::ffi::c_int = 5;
122pub const ZSTD_VERSION_RELEASE: core::ffi::c_int = 8;
123pub const ZSTD_VERSION_NUMBER: core::ffi::c_int =
124 ZSTD_VERSION_MAJOR * 100 * 100 + ZSTD_VERSION_MINOR * 100 + ZSTD_VERSION_RELEASE;
125pub const ZSTD_MAGICNUMBER: core::ffi::c_uint = 0xfd2fb528;
126pub const ZSTD_MAGIC_DICTIONARY: core::ffi::c_uint = 0xec30a437;
127pub const ZSTD_MAGIC_SKIPPABLE_START: core::ffi::c_int = 0x184d2a50;
128pub const ZSTD_MAGIC_SKIPPABLE_MASK: core::ffi::c_uint = 0xfffffff0;
129pub const ZSTD_BLOCKSIZELOG_MAX: core::ffi::c_int = 17;
130pub const ZSTD_BLOCKSIZE_MAX: core::ffi::c_int = (1) << ZSTD_BLOCKSIZELOG_MAX;
131pub const ZSTD_CONTENTSIZE_UNKNOWN: core::ffi::c_ulonglong =
132 (0 as core::ffi::c_ulonglong).wrapping_sub(1);
133pub const ZSTD_CONTENTSIZE_ERROR: core::ffi::c_ulonglong =
134 (0 as core::ffi::c_ulonglong).wrapping_sub(2);
135pub const ZSTD_SKIPPABLEHEADERSIZE: core::ffi::c_int = 8;
136pub const ZSTD_WINDOWLOG_MAX_32: core::ffi::c_int = 30;
137pub const ZSTD_WINDOWLOG_MAX_64: core::ffi::c_int = 31;
138pub const ZSTD_BLOCKSIZE_MAX_MIN: core::ffi::c_int = (1) << 10;
139pub const ZSTD_WINDOWLOG_LIMIT_DEFAULT: core::ffi::c_int = 27;
140pub const ZSTD_d_format: core::ffi::c_int = 1000;
141pub const ZSTD_d_stableOutBuffer: core::ffi::c_int = 1001;
142pub const ZSTD_d_forceIgnoreChecksum: core::ffi::c_int = 1002;
143pub const ZSTD_d_refMultipleDDicts: core::ffi::c_int = 1003;
144pub const ZSTD_d_disableHuffmanAssembly: core::ffi::c_int = 1004;
145pub const ZSTD_d_maxBlockSize: core::ffi::c_int = 1005;
146pub const ZSTD_WINDOWLOG_ABSOLUTEMIN: core::ffi::c_int = 10;
147
148#[inline]
149unsafe fn ZSTD_customMalloc(size: size_t, customMem: ZSTD_customMem) -> *mut core::ffi::c_void {
150 if (customMem.customAlloc).is_some() {
151 return (customMem.customAlloc).unwrap_unchecked()(customMem.opaque, size);
152 }
153 malloc(size)
154}
155#[inline]
156unsafe fn ZSTD_customCalloc(size: size_t, customMem: ZSTD_customMem) -> *mut core::ffi::c_void {
157 if (customMem.customAlloc).is_some() {
158 let ptr = (customMem.customAlloc).unwrap_unchecked()(customMem.opaque, size);
159 ptr::write_bytes(ptr, 0, size);
160 return ptr;
161 }
162 calloc(1, size)
163}
164#[inline]
165unsafe fn ZSTD_customFree(ptr: *mut core::ffi::c_void, customMem: ZSTD_customMem) {
166 if !ptr.is_null() {
167 if (customMem.customFree).is_some() {
168 (customMem.customFree).unwrap_unchecked()(customMem.opaque, ptr);
169 } else {
170 free(ptr);
171 }
172 }
173}
174
175const ZSTDv01_magicNumberLE: u32 = 0x1EB52FFD;
176
177const ZSTDv02_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB522;
178const ZSTDv03_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB523;
179const ZSTDv04_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB524;
180const ZSTDv05_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB525;
181const ZSTDv06_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB526;
182const ZSTDv07_MAGICNUMBER: core::ffi::c_uint = 0xFD2FB527;
183
184#[inline]
185unsafe fn ZSTD_isLegacy(src: *const core::ffi::c_void, srcSize: size_t) -> u32 {
186 is_legacy(unsafe { core::slice::from_raw_parts(src.cast::<u8>(), srcSize) })
187}
188
189fn is_legacy(src: &[u8]) -> u32 {
190 let Some(chunk) = src.first_chunk() else {
191 return 0;
192 };
193
194 match u32::from_le_bytes(*chunk) {
195 ZSTDv01_magicNumberLE => 1,
196 ZSTDv02_MAGICNUMBER => 2,
197 ZSTDv03_MAGICNUMBER => 3,
198 ZSTDv04_MAGICNUMBER => 4,
199 ZSTDv05_MAGICNUMBER => 5,
200 ZSTDv06_MAGICNUMBER => 6,
201 ZSTDv07_MAGICNUMBER => 7,
202 _ => 0,
203 }
204}
205
206#[inline]
207fn get_decompressed_size_legacy(src: &[u8]) -> Option<u64> {
208 let ptr = src.as_ptr().cast();
209
210 match is_legacy(src) {
211 5 => {
212 let mut fParams = ZSTDv05_parameters {
213 srcSize: 0,
214 windowLog: 0,
215 contentLog: 0,
216 hashLog: 0,
217 searchLog: 0,
218 searchLength: 0,
219 targetLength: 0,
220 strategy: ZSTDv05_fast,
221 };
222
223 match unsafe { ZSTDv05_getFrameParams(&mut fParams, ptr, src.len() as _) } {
224 0 => Some(fParams.srcSize as core::ffi::c_ulonglong),
225 _ => None,
226 }
227 }
228 6 => {
229 let mut fParams_0 = ZSTDv06_frameParams_s {
230 frameContentSize: 0,
231 windowLog: 0,
232 };
233
234 match unsafe { ZSTDv06_getFrameParams(&mut fParams_0, ptr, src.len() as _) } {
235 0 => Some(fParams_0.frameContentSize),
236 _ => None,
237 }
238 }
239 7 => {
240 let mut fParams_1 = ZSTDv07_frameParams {
241 frameContentSize: 0,
242 windowSize: 0,
243 dictID: 0,
244 checksumFlag: 0,
245 };
246
247 match unsafe { ZSTDv07_getFrameParams(&mut fParams_1, ptr, src.len() as _) } {
248 0 => Some(fParams_1.frameContentSize),
249 _ => None,
250 }
251 }
252
253 _ => None,
254 }
255}
256#[inline]
257unsafe fn ZSTD_decompressLegacy(
258 mut dst: *mut core::ffi::c_void,
259 dstCapacity: size_t,
260 mut src: *const core::ffi::c_void,
261 compressedSize: size_t,
262 mut dict: *const core::ffi::c_void,
263 dictSize: size_t,
264) -> size_t {
265 let version = ZSTD_isLegacy(src, compressedSize);
266 let mut x: core::ffi::c_char = 0;
267 if dst.is_null() {
268 dst = &mut x as *mut core::ffi::c_char as *mut core::ffi::c_void;
269 }
270 if src.is_null() {
271 src = &mut x as *mut core::ffi::c_char as *const core::ffi::c_void;
272 }
273 if dict.is_null() {
274 dict = &mut x as *mut core::ffi::c_char as *const core::ffi::c_void;
275 }
276 match version {
277 5 => {
278 let mut result: size_t = 0;
279 let zd = ZSTDv05_createDCtx();
280 if zd.is_null() {
281 return Error::memory_allocation.to_error_code();
282 }
283 result = ZSTDv05_decompress_usingDict(
284 &mut *zd,
285 dst,
286 dstCapacity,
287 src,
288 compressedSize,
289 dict,
290 dictSize,
291 );
292 ZSTDv05_freeDCtx(zd);
293 result
294 }
295 6 => {
296 let mut result_0: size_t = 0;
297 let zd_0 = ZSTDv06_createDCtx();
298 if zd_0.is_null() {
299 return Error::memory_allocation.to_error_code();
300 }
301 result_0 = ZSTDv06_decompress_usingDict(
302 zd_0,
303 dst,
304 dstCapacity,
305 src,
306 compressedSize,
307 dict,
308 dictSize,
309 );
310 ZSTDv06_freeDCtx(zd_0);
311 result_0
312 }
313 7 => {
314 let mut result_1: size_t = 0;
315 let zd_1 = ZSTDv07_createDCtx();
316 if zd_1.is_null() {
317 return Error::memory_allocation.to_error_code();
318 }
319 result_1 = ZSTDv07_decompress_usingDict(
320 zd_1,
321 dst,
322 dstCapacity,
323 src,
324 compressedSize,
325 dict,
326 dictSize,
327 );
328 ZSTDv07_freeDCtx(zd_1);
329 result_1
330 }
331 _ => Error::prefix_unknown.to_error_code(),
332 }
333}
334
335#[inline]
336unsafe fn ZSTD_findFrameSizeInfoLegacy(
337 src: *const core::ffi::c_void,
338 srcSize: size_t,
339) -> ZSTD_frameSizeInfo {
340 find_frame_size_info_legacy(if src.is_null() {
341 &[]
342 } else {
343 core::slice::from_raw_parts(src.cast(), srcSize)
344 })
345}
346
347unsafe fn find_frame_size_info_legacy(src: &[u8]) -> ZSTD_frameSizeInfo {
348 let mut frameSizeInfo = ZSTD_frameSizeInfo {
349 nbBlocks: 0,
350 compressedSize: 0,
351 decompressedBound: 0,
352 };
353
354 match is_legacy(src) {
355 5 => {
356 ZSTDv05_findFrameSizeInfoLegacy(
357 src.as_ptr().cast(),
358 src.len(),
359 &mut frameSizeInfo.compressedSize,
360 &mut frameSizeInfo.decompressedBound,
361 );
362 }
363 6 => {
364 ZSTDv06_findFrameSizeInfoLegacy(
365 src.as_ptr().cast(),
366 src.len(),
367 &mut frameSizeInfo.compressedSize,
368 &mut frameSizeInfo.decompressedBound,
369 );
370 }
371 7 => {
372 ZSTDv07_findFrameSizeInfoLegacy(
373 src.as_ptr().cast(),
374 src.len(),
375 &mut frameSizeInfo.compressedSize,
376 &mut frameSizeInfo.decompressedBound,
377 );
378 }
379 _ => {
380 frameSizeInfo.compressedSize = Error::prefix_unknown.to_error_code();
381 frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
382 }
383 }
384
385 if !ERR_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > src.len() {
386 frameSizeInfo.compressedSize = Error::srcSize_wrong.to_error_code();
387 frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
388 }
389
390 if frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR {
391 frameSizeInfo.nbBlocks = (frameSizeInfo.decompressedBound)
392 .wrapping_div(ZSTD_BLOCKSIZE_MAX as core::ffi::c_ulonglong)
393 as size_t;
394 }
395
396 frameSizeInfo
397}
398
399#[inline]
400unsafe fn ZSTD_findFrameCompressedSizeLegacy(
401 src: *const core::ffi::c_void,
402 srcSize: size_t,
403) -> size_t {
404 let frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);
405 frameSizeInfo.compressedSize
406}
407
408#[inline]
409unsafe fn ZSTD_freeLegacyStreamContext(
410 legacyContext: *mut core::ffi::c_void,
411 version: u32,
412) -> size_t {
413 match version {
414 5 => ZBUFFv05_freeDCtx(legacyContext as *mut ZBUFFv05_DCtx),
415 6 => ZBUFFv06_freeDCtx(legacyContext as *mut ZBUFFv06_DCtx),
416 7 => ZBUFFv07_freeDCtx(legacyContext as *mut ZBUFFv07_DCtx),
417 1 | 2 | 3 | _ => Error::version_unsupported.to_error_code(),
418 }
419}
420#[inline]
421unsafe fn ZSTD_initLegacyStream(
422 legacyContext: *mut *mut core::ffi::c_void,
423 prevVersion: u32,
424 newVersion: u32,
425 mut dict: *const core::ffi::c_void,
426 dictSize: size_t,
427) -> size_t {
428 let mut x: core::ffi::c_char = 0;
429 if dict.is_null() {
430 dict = &mut x as *mut core::ffi::c_char as *const core::ffi::c_void;
431 }
432 if prevVersion != newVersion {
433 ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);
434 }
435 match newVersion {
436 5 => {
437 let dctx = if prevVersion != newVersion {
438 ZBUFFv05_createDCtx()
439 } else {
440 *legacyContext as *mut ZBUFFv05_DCtx
441 };
442 if dctx.is_null() {
443 return Error::memory_allocation.to_error_code();
444 }
445 ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize);
446 *legacyContext = dctx as *mut core::ffi::c_void;
447 0
448 }
449 6 => {
450 let dctx_0 = if prevVersion != newVersion {
451 ZBUFFv06_createDCtx()
452 } else {
453 *legacyContext as *mut ZBUFFv06_DCtx
454 };
455 if dctx_0.is_null() {
456 return Error::memory_allocation.to_error_code();
457 }
458 ZBUFFv06_decompressInitDictionary(dctx_0, dict, dictSize);
459 *legacyContext = dctx_0 as *mut core::ffi::c_void;
460 0
461 }
462 7 => {
463 let dctx_1 = if prevVersion != newVersion {
464 ZBUFFv07_createDCtx()
465 } else {
466 *legacyContext as *mut ZBUFFv07_DCtx
467 };
468 if dctx_1.is_null() {
469 return Error::memory_allocation.to_error_code();
470 }
471 ZBUFFv07_decompressInitDictionary(dctx_1, dict, dictSize);
472 *legacyContext = dctx_1 as *mut core::ffi::c_void;
473 0
474 }
475 1 | 2 | 3 | _ => 0,
476 }
477}
478
479#[inline]
480unsafe fn ZSTD_decompressLegacyStream(
481 legacyContext: *mut core::ffi::c_void,
482 version: u32,
483 output: &mut ZSTD_outBuffer,
484 input: &mut ZSTD_inBuffer,
485) -> size_t {
486 static mut x: core::ffi::c_char = 0;
487 if (output.dst).is_null() {
488 output.dst = &raw mut x as *mut core::ffi::c_void;
489 }
490 if (input.src).is_null() {
491 input.src = &raw mut x as *const core::ffi::c_void;
492 }
493 match version {
494 5 => {
495 let dctx = legacyContext as *mut ZBUFFv05_DCtx;
496 let src =
497 (input.src as *const core::ffi::c_char).add(input.pos) as *const core::ffi::c_void;
498 let mut readSize = (input.size).wrapping_sub(input.pos);
499 let dst =
500 (output.dst as *mut core::ffi::c_char).add(output.pos) as *mut core::ffi::c_void;
501 let mut decodedSize = (output.size).wrapping_sub(output.pos);
502 let hintSize =
503 ZBUFFv05_decompressContinue(&mut *dctx, dst, &mut decodedSize, src, &mut readSize);
504 output.pos = (output.pos).wrapping_add(decodedSize);
505 input.pos = (input.pos).wrapping_add(readSize);
506 hintSize
507 }
508 6 => {
509 let dctx_0 = legacyContext as *mut ZBUFFv06_DCtx;
510 let src_0 =
511 (input.src as *const core::ffi::c_char).add(input.pos) as *const core::ffi::c_void;
512 let mut readSize_0 = (input.size).wrapping_sub(input.pos);
513 let dst_0 =
514 (output.dst as *mut core::ffi::c_char).add(output.pos) as *mut core::ffi::c_void;
515 let mut decodedSize_0 = (output.size).wrapping_sub(output.pos);
516 let hintSize_0 = ZBUFFv06_decompressContinue(
517 dctx_0,
518 dst_0,
519 &mut decodedSize_0,
520 src_0,
521 &mut readSize_0,
522 );
523 output.pos = (output.pos).wrapping_add(decodedSize_0);
524 input.pos = (input.pos).wrapping_add(readSize_0);
525 hintSize_0
526 }
527 7 => {
528 let dctx_1 = legacyContext as *mut ZBUFFv07_DCtx;
529 let src_1 =
530 (input.src as *const core::ffi::c_char).add(input.pos) as *const core::ffi::c_void;
531 let mut readSize_1 = (input.size).wrapping_sub(input.pos);
532 let dst_1 =
533 (output.dst as *mut core::ffi::c_char).add(output.pos) as *mut core::ffi::c_void;
534 let mut decodedSize_1 = (output.size).wrapping_sub(output.pos);
535 let hintSize_1 = ZBUFFv07_decompressContinue(
536 dctx_1,
537 dst_1,
538 &mut decodedSize_1,
539 src_1,
540 &mut readSize_1,
541 );
542 output.pos = (output.pos).wrapping_add(decodedSize_1);
543 input.pos = (input.pos).wrapping_add(readSize_1);
544 hintSize_1
545 }
546 1 | 2 | 3 | _ => Error::version_unsupported.to_error_code(),
547 }
548}
549
550pub const DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT: core::ffi::c_int = 4;
551pub const DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT: core::ffi::c_int = 3;
552pub const DDICT_HASHSET_TABLE_BASE_SIZE: core::ffi::c_int = 64;
553pub const DDICT_HASHSET_RESIZE_FACTOR: core::ffi::c_int = 2;
554
555fn ZSTD_DDictHashSet_getIndex(hashSet: &ZSTD_DDictHashSet, dictID: u32) -> size_t {
556 let hash = ZSTD_XXH64_slice(&dictID.to_ne_bytes(), 0);
557 hash as size_t & (hashSet.ddictPtrTableSize).wrapping_sub(1)
558}
559
560unsafe fn ZSTD_DDictHashSet_emplaceDDict(
561 hashSet: &mut ZSTD_DDictHashSet,
562 ddict: *const ZSTD_DDict,
563) -> size_t {
564 let dictID = ZSTD_getDictID_fromDDict(ddict);
565 let mut idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
566 let idxRangeMask = (hashSet.ddictPtrTableSize).wrapping_sub(1);
567 if hashSet.ddictPtrCount == hashSet.ddictPtrTableSize {
568 return Error::GENERIC.to_error_code();
569 }
570 while !(*(hashSet.ddictPtrTable).add(idx)).is_null() {
571 if ZSTD_getDictID_fromDDict(*(hashSet.ddictPtrTable).add(idx)) == dictID {
572 let fresh0 = &mut (*(hashSet.ddictPtrTable).add(idx));
573 *fresh0 = ddict;
574 return 0;
575 }
576 idx &= idxRangeMask;
577 idx = idx.wrapping_add(1);
578 }
579 let fresh1 = &mut (*(hashSet.ddictPtrTable).add(idx));
580 *fresh1 = ddict;
581 hashSet.ddictPtrCount = (hashSet.ddictPtrCount).wrapping_add(1);
582 hashSet.ddictPtrCount;
583 0
584}
585
586unsafe fn ZSTD_DDictHashSet_expand(
587 hashSet: &mut ZSTD_DDictHashSet,
588 customMem: ZSTD_customMem,
589) -> size_t {
590 let newTableSize = hashSet.ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR as size_t;
591 let newTable = ZSTD_customCalloc(
592 (::core::mem::size_of::<*mut ZSTD_DDict>()).wrapping_mul(newTableSize),
593 customMem,
594 ) as *mut *const ZSTD_DDict;
595 let oldTable = hashSet.ddictPtrTable;
596 let oldTableSize = hashSet.ddictPtrTableSize;
597 let mut i: size_t = 0;
598 if newTable.is_null() {
599 return Error::memory_allocation.to_error_code();
600 }
601 hashSet.ddictPtrTable = newTable;
602 hashSet.ddictPtrTableSize = newTableSize;
603 hashSet.ddictPtrCount = 0;
604 i = 0;
605 while i < oldTableSize {
606 if !(*oldTable.add(i)).is_null() {
607 let err_code = ZSTD_DDictHashSet_emplaceDDict(hashSet, *oldTable.add(i));
608 if ERR_isError(err_code) {
609 return err_code;
610 }
611 }
612 i = i.wrapping_add(1);
613 }
614 ZSTD_customFree(oldTable as *mut core::ffi::c_void, customMem);
615 0
616}
617
618unsafe fn ZSTD_DDictHashSet_getDDict(
619 hashSet: &mut ZSTD_DDictHashSet,
620 dictID: u32,
621) -> *const ZSTD_DDict {
622 let mut idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
623 let idxRangeMask = (hashSet.ddictPtrTableSize).wrapping_sub(1);
624 loop {
625 let currDictID = ZSTD_getDictID_fromDDict(*(hashSet.ddictPtrTable).add(idx)) as size_t;
626 if currDictID == dictID as size_t || currDictID == 0 {
627 break;
628 }
629 idx &= idxRangeMask;
630 idx = idx.wrapping_add(1);
631 }
632 *(hashSet.ddictPtrTable).add(idx)
633}
634
635unsafe fn ZSTD_createDDictHashSet(customMem: ZSTD_customMem) -> *mut ZSTD_DDictHashSet {
636 let ret = ZSTD_customMalloc(::core::mem::size_of::<ZSTD_DDictHashSet>(), customMem)
637 as *mut ZSTD_DDictHashSet;
638 if ret.is_null() {
639 return core::ptr::null_mut();
640 }
641 (*ret).ddictPtrTable = ZSTD_customCalloc(
642 (DDICT_HASHSET_TABLE_BASE_SIZE as size_t)
643 .wrapping_mul(::core::mem::size_of::<*mut ZSTD_DDict>()),
644 customMem,
645 ) as *mut *const ZSTD_DDict;
646 if ((*ret).ddictPtrTable).is_null() {
647 ZSTD_customFree(ret as *mut core::ffi::c_void, customMem);
648 return core::ptr::null_mut();
649 }
650 (*ret).ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE as size_t;
651 (*ret).ddictPtrCount = 0;
652 ret
653}
654
655unsafe fn ZSTD_freeDDictHashSet(hashSet: *mut ZSTD_DDictHashSet, customMem: ZSTD_customMem) {
656 if !hashSet.is_null() && !((*hashSet).ddictPtrTable).is_null() {
657 ZSTD_customFree(
658 (*hashSet).ddictPtrTable as *mut core::ffi::c_void,
659 customMem,
660 );
661 }
662 if !hashSet.is_null() {
663 ZSTD_customFree(hashSet as *mut core::ffi::c_void, customMem);
664 }
665}
666unsafe fn ZSTD_DDictHashSet_addDDict(
667 hashSet: &mut ZSTD_DDictHashSet,
668 ddict: *const ZSTD_DDict,
669 customMem: ZSTD_customMem,
670) -> size_t {
671 if hashSet.ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT as size_t
672 / hashSet.ddictPtrTableSize
673 * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT as size_t
674 != 0
675 {
676 let err_code = ZSTD_DDictHashSet_expand(hashSet, customMem);
677 if ERR_isError(err_code) {
678 return err_code;
679 }
680 }
681 let err_code_0 = ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict);
682 if ERR_isError(err_code_0) {
683 return err_code_0;
684 }
685 0
686}
687#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_sizeof_DCtx))]
688pub unsafe extern "C" fn ZSTD_sizeof_DCtx(dctx: *const ZSTD_DCtx) -> size_t {
689 if dctx.is_null() {
690 return 0;
691 }
692 (::core::mem::size_of::<ZSTD_DCtx>())
693 .wrapping_add(ZSTD_sizeof_DDict((*dctx).ddictLocal))
694 .wrapping_add((*dctx).inBuffSize)
695 .wrapping_add((*dctx).outBuffSize)
696}
697#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_estimateDCtxSize))]
698pub unsafe extern "C" fn ZSTD_estimateDCtxSize() -> size_t {
699 ::core::mem::size_of::<ZSTD_DCtx>()
700}
701
702const fn ZSTD_startingInputLength(format: Format) -> size_t {
703 match format {
704 Format::ZSTD_f_zstd1 => 5,
705 Format::ZSTD_f_zstd1_magicless => 1,
706 }
707}
708
709unsafe fn ZSTD_DCtx_resetParameters(dctx: *mut ZSTD_DCtx) {
710 (*dctx).format = Format::ZSTD_f_zstd1;
711 (*dctx).maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT as size_t;
712 (*dctx).outBufferMode = BufferMode::Buffered;
713 (*dctx).forceIgnoreChecksum = ZSTD_d_validateChecksum;
714 (*dctx).refMultipleDDicts = MultipleDDicts::Single;
715 (*dctx).disableHufAsm = 0;
716 (*dctx).maxBlockSizeParam = 0;
717}
718
719unsafe fn ZSTD_initDCtx_internal(dctx: *mut ZSTD_DCtx) {
720 (*dctx).staticSize = 0;
721 (*dctx).ddict = core::ptr::null();
722 (*dctx).ddictLocal = core::ptr::null_mut();
723 (*dctx).dictEnd = core::ptr::null();
724 (*dctx).ddictIsCold = 0;
725 (*dctx).dictUses = ZSTD_dont_use;
726 (*dctx).inBuff = core::ptr::null_mut();
727 (*dctx).inBuffSize = 0;
728 (*dctx).outBuffSize = 0;
729 (*dctx).streamStage = StreamStage::Init;
730 (*dctx).legacyContext = core::ptr::null_mut();
731 (*dctx).previousLegacyVersion = 0;
732 (*dctx).noForwardProgress = 0;
733 (*dctx).oversizedDuration = 0;
734 (*dctx).isFrameDecompression = 1;
735 (*dctx).bmi2 = ZSTD_cpuSupportsBmi2() as _;
736 (*dctx).ddictSet = core::ptr::null_mut();
737 ZSTD_DCtx_resetParameters(dctx);
738}
739
740#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_initStaticDCtx))]
741pub unsafe extern "C" fn ZSTD_initStaticDCtx(
742 workspace: *mut core::ffi::c_void,
743 workspaceSize: size_t,
744) -> *mut ZSTD_DCtx {
745 let dctx = workspace as *mut ZSTD_DCtx;
746 if workspace as size_t & 7 != 0 {
747 return core::ptr::null_mut();
748 }
749 if workspaceSize < ::core::mem::size_of::<ZSTD_DCtx>() {
750 return core::ptr::null_mut();
751 }
752 ZSTD_initDCtx_internal(dctx);
753 (*dctx).staticSize = workspaceSize;
754 (*dctx).inBuff = dctx.offset(1) as *mut core::ffi::c_char;
755 dctx
756}
757
758unsafe fn ZSTD_createDCtx_internal(customMem: ZSTD_customMem) -> *mut ZSTD_DCtx {
759 if (customMem.customAlloc).is_none() ^ (customMem.customFree).is_none() {
760 return core::ptr::null_mut();
761 }
762
763 let dctx = ZSTD_customMalloc(::core::mem::size_of::<ZSTD_DCtx>(), customMem) as *mut ZSTD_DCtx;
764 if dctx.is_null() {
765 return core::ptr::null_mut();
766 }
767
768 (*dctx).customMem = customMem;
769 ZSTD_initDCtx_internal(dctx);
770 dctx
771}
772
773#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_createDCtx_advanced))]
774pub unsafe extern "C" fn ZSTD_createDCtx_advanced(customMem: ZSTD_customMem) -> *mut ZSTD_DCtx {
775 ZSTD_createDCtx_internal(customMem)
776}
777#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_createDCtx))]
778pub unsafe extern "C" fn ZSTD_createDCtx() -> *mut ZSTD_DCtx {
779 ZSTD_createDCtx_internal(ZSTD_defaultCMem)
780}
781unsafe fn ZSTD_clearDict(dctx: *mut ZSTD_DCtx) {
782 ZSTD_freeDDict((*dctx).ddictLocal);
783 (*dctx).ddictLocal = core::ptr::null_mut();
784 (*dctx).ddict = core::ptr::null();
785 (*dctx).dictUses = ZSTD_dont_use;
786}
787#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_freeDCtx))]
788pub unsafe extern "C" fn ZSTD_freeDCtx(dctx: *mut ZSTD_DCtx) -> size_t {
789 if dctx.is_null() {
790 return 0;
791 }
792 if (*dctx).staticSize != 0 {
793 return Error::memory_allocation.to_error_code();
794 }
795 let cMem = (*dctx).customMem;
796 ZSTD_clearDict(dctx);
797 ZSTD_customFree((*dctx).inBuff as *mut core::ffi::c_void, cMem);
798 (*dctx).inBuff = core::ptr::null_mut();
799 if !((*dctx).legacyContext).is_null() {
800 ZSTD_freeLegacyStreamContext((*dctx).legacyContext, (*dctx).previousLegacyVersion);
801 }
802 if !((*dctx).ddictSet).is_null() {
803 ZSTD_freeDDictHashSet((*dctx).ddictSet, cMem);
804 (*dctx).ddictSet = core::ptr::null_mut();
805 }
806 ZSTD_customFree(dctx as *mut core::ffi::c_void, cMem);
807 0
808}
809#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_copyDCtx))]
810pub unsafe extern "C" fn ZSTD_copyDCtx(dstDCtx: *mut ZSTD_DCtx, srcDCtx: *const ZSTD_DCtx) {
811 let toCopy = (&mut (*dstDCtx).inBuff as *mut *mut core::ffi::c_char as *mut core::ffi::c_char)
812 .offset_from(dstDCtx as *mut core::ffi::c_char) as core::ffi::c_long
813 as size_t;
814 libc::memcpy(
815 dstDCtx as *mut core::ffi::c_void,
816 srcDCtx as *const core::ffi::c_void,
817 toCopy as libc::size_t,
818 );
819}
820unsafe fn ZSTD_DCtx_selectFrameDDict(dctx: *mut ZSTD_DCtx) {
821 if !((*dctx).ddict).is_null() {
822 let frameDDict =
823 ZSTD_DDictHashSet_getDDict((*dctx).ddictSet.as_mut().unwrap(), (*dctx).fParams.dictID);
824 if !frameDDict.is_null() {
825 ZSTD_clearDict(dctx);
826 (*dctx).dictID = (*dctx).fParams.dictID;
827 (*dctx).ddict = frameDDict;
828 (*dctx).dictUses = ZSTD_use_indefinitely;
829 }
830 }
831}
832
833#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_isFrame))]
834pub unsafe extern "C" fn ZSTD_isFrame(
835 buffer: *const core::ffi::c_void,
836 size: size_t,
837) -> core::ffi::c_uint {
838 let src = if buffer.is_null() {
839 &[]
840 } else {
841 core::slice::from_raw_parts(buffer.cast(), size)
842 };
843
844 is_frame(src) as core::ffi::c_uint
845}
846
847fn is_frame(src: &[u8]) -> bool {
848 let [a, b, c, d] = *src else {
849 return false;
850 };
851
852 let magic = u32::from_le_bytes([a, b, c, d]);
853 if magic == ZSTD_MAGICNUMBER {
854 return true;
855 }
856
857 if magic & ZSTD_MAGIC_SKIPPABLE_MASK == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint {
858 return true;
859 }
860
861 if is_legacy(src) != 0 {
862 return true;
863 }
864
865 false
866}
867
868#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_isSkippableFrame))]
869pub unsafe extern "C" fn ZSTD_isSkippableFrame(
870 buffer: *const core::ffi::c_void,
871 size: size_t,
872) -> core::ffi::c_uint {
873 let src = if buffer.is_null() {
874 &[]
875 } else {
876 core::slice::from_raw_parts(buffer.cast(), size)
877 };
878
879 is_skippable_frame(src) as core::ffi::c_uint
880}
881
882fn is_skippable_frame(src: &[u8]) -> bool {
883 let [a, b, c, d] = *src else {
884 return false;
885 };
886
887 let magic = u32::from_le_bytes([a, b, c, d]);
888 if magic & ZSTD_MAGIC_SKIPPABLE_MASK == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint {
889 return true;
890 }
891
892 false
893}
894
895fn frame_header_size_internal(src: &[u8], format: Format) -> usize {
896 static ZSTD_fcs_fieldSize: [u8; 4] = [0, 2, 4, 8];
897 static ZSTD_did_fieldSize: [u8; 4] = [0, 1, 2, 4];
898
899 let minInputSize = ZSTD_startingInputLength(format);
900 let Some([.., fhd]) = src.get(..minInputSize as usize) else {
901 return Error::srcSize_wrong.to_error_code();
902 };
903
904 let dictID = fhd & 0b11;
905 let singleSegment = (fhd >> 5 & 1) != 0;
906 let fcsId = fhd >> 6;
907
908 minInputSize
909 + usize::from(!singleSegment)
910 + usize::from(ZSTD_did_fieldSize[usize::from(dictID)])
911 + usize::from(ZSTD_fcs_fieldSize[usize::from(fcsId)])
912 + usize::from(singleSegment && fcsId == 0)
913}
914
915#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_frameHeaderSize))]
916pub unsafe extern "C" fn ZSTD_frameHeaderSize(
917 src: *const core::ffi::c_void,
918 srcSize: size_t,
919) -> size_t {
920 let src = if src.is_null() {
921 &[]
922 } else {
923 core::slice::from_raw_parts(src.cast(), srcSize)
924 };
925
926 frame_header_size_internal(src, Format::ZSTD_f_zstd1)
927}
928
929#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getFrameHeader))]
930pub unsafe extern "C" fn ZSTD_getFrameHeader(
931 zfhPtr: *mut ZSTD_FrameHeader,
932 src: *const core::ffi::c_void,
933 srcSize: size_t,
934) -> size_t {
935 ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, Format::ZSTD_f_zstd1 as _)
936}
937
938fn get_frame_header(zfhPtr: &mut ZSTD_FrameHeader, src: &[u8]) -> size_t {
939 get_frame_header_advanced(zfhPtr, src, Format::ZSTD_f_zstd1)
940}
941
942#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getFrameHeader_advanced))]
943pub unsafe extern "C" fn ZSTD_getFrameHeader_advanced(
944 zfhPtr: *mut ZSTD_FrameHeader,
945 src: *const core::ffi::c_void,
946 srcSize: size_t,
947 format: ZSTD_format_e,
948) -> size_t {
949 unsafe { zfhPtr.write(ZSTD_FrameHeader::default()) };
951
952 let Some(zfhPtr) = zfhPtr.as_mut() else {
953 return Error::GENERIC.to_error_code();
954 };
955
956 let Ok(format) = Format::try_from(format) else {
958 return Error::GENERIC.to_error_code();
959 };
960
961 if srcSize > 0 && src.is_null() {
962 return Error::GENERIC.to_error_code();
963 }
964
965 get_frame_header_advanced(
966 zfhPtr,
967 if src.is_null() {
968 &[]
969 } else {
970 core::slice::from_raw_parts(src as *const u8, srcSize)
971 },
972 format,
973 )
974}
975
976fn get_frame_header_advanced(zfhPtr: &mut ZSTD_FrameHeader, src: &[u8], format: Format) -> size_t {
977 let minInputSize = ZSTD_startingInputLength(format);
978 if src.len() < minInputSize as usize {
979 if !src.is_empty()
980 && format != Format::ZSTD_f_zstd1_magicless
981 && src != &ZSTD_MAGICNUMBER.to_le_bytes()[..src.len()]
982 {
983 let mut hbuf = ZSTD_MAGIC_SKIPPABLE_START.to_le_bytes();
984 hbuf[..src.len()].copy_from_slice(src);
985 if u32::from_le_bytes(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK
986 != ZSTD_MAGIC_SKIPPABLE_START as u32
987 {
988 return Error::prefix_unknown.to_error_code();
989 }
990 }
991 return minInputSize;
992 }
993
994 let first_word = u32::from_le_bytes(*src.first_chunk().unwrap());
995
996 if format != Format::ZSTD_f_zstd1_magicless && first_word != ZSTD_MAGICNUMBER {
997 if first_word & ZSTD_MAGIC_SKIPPABLE_MASK == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
998 {
999 if src.len() < ZSTD_SKIPPABLEHEADERSIZE as usize {
1000 return ZSTD_SKIPPABLEHEADERSIZE as size_t;
1001 }
1002
1003 let dictID = first_word.wrapping_sub(ZSTD_MAGIC_SKIPPABLE_START as u32);
1004 let frameContentSize =
1005 u32::from_le_bytes(*src[ZSTD_FRAMEIDSIZE..].first_chunk().unwrap());
1006
1007 *zfhPtr = ZSTD_FrameHeader {
1008 frameContentSize: u64::from(frameContentSize),
1009 windowSize: 0,
1010 blockSizeMax: 0,
1011 frameType: ZSTD_skippableFrame,
1012 headerSize: ZSTD_SKIPPABLEHEADERSIZE as core::ffi::c_uint,
1013 dictID,
1014 checksumFlag: 0,
1015 _reserved1: 0,
1016 _reserved2: 0,
1017 };
1018
1019 return 0;
1020 }
1021 return Error::prefix_unknown.to_error_code();
1022 }
1023
1024 let fhsize = frame_header_size_internal(src, format);
1025 if src.len() < fhsize {
1026 return fhsize;
1027 }
1028
1029 let fhdByte = src[minInputSize as usize - 1];
1030 let dictIDSizeCode = fhdByte & 0b11;
1031 let checksumFlag = u32::from(fhdByte) >> 2 & 1;
1032 let singleSegment = (u32::from(fhdByte) >> 5 & 1) != 0;
1033 let fcsID = (u32::from(fhdByte) >> 6) as u32;
1034
1035 let mut windowSize = 0;
1036
1037 if fhdByte & 0x8 != 0 {
1038 return Error::frameParameter_unsupported.to_error_code();
1039 }
1040
1041 let mut pos = minInputSize as usize;
1042 if !singleSegment {
1043 let wlByte = src[pos];
1044 pos += 1;
1045 let windowLog = ((i32::from(wlByte) / 8) + ZSTD_WINDOWLOG_ABSOLUTEMIN) as u32;
1046
1047 if windowLog > (if size_of::<usize>() == 4 { 30 } else { 31 }) as u32 {
1048 return Error::frameParameter_windowTooLarge.to_error_code();
1049 }
1050
1051 windowSize = 1u64 << windowLog;
1052 windowSize = windowSize.wrapping_add((windowSize / 8) * (wlByte & 7) as u64);
1053 }
1054
1055 let dictID;
1056 match dictIDSizeCode {
1057 1 => {
1058 dictID = u32::from(src[pos]);
1059 pos += 1;
1060 }
1061 2 => {
1062 dictID = u32::from(u16::from_le_bytes(src[pos..][..2].try_into().unwrap()));
1063 pos += 2;
1064 }
1065 3 => {
1066 dictID = u32::from_le_bytes(src[pos..][..4].try_into().unwrap());
1067 pos += 4;
1068 }
1069 _ => {
1070 dictID = 0;
1071 }
1072 }
1073
1074 let frameContentSize = match fcsID {
1075 1 => u64::from(u16::from_le_bytes(src[pos..][..2].try_into().unwrap())) + 256,
1076 2 => u64::from(u32::from_le_bytes(src[pos..][..4].try_into().unwrap())),
1077 3 => u64::from_le_bytes(src[pos..][..8].try_into().unwrap()),
1078 _ if singleSegment => u64::from(src[pos]),
1079 _ => ZSTD_CONTENTSIZE_UNKNOWN,
1080 };
1081
1082 if singleSegment {
1083 windowSize = frameContentSize;
1084 }
1085
1086 *zfhPtr = ZSTD_FrameHeader {
1087 frameContentSize: frameContentSize as core::ffi::c_ulonglong,
1088 windowSize: windowSize as core::ffi::c_ulonglong,
1089 blockSizeMax: Ord::min(windowSize, 1 << 17) as u32,
1090 frameType: ZSTD_frame,
1091 headerSize: fhsize as u32,
1092 dictID,
1093 checksumFlag,
1094 _reserved1: 0,
1095 _reserved2: 0,
1096 };
1097
1098 0
1099}
1100
1101#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getFrameContentSize))]
1102pub unsafe extern "C" fn ZSTD_getFrameContentSize(
1103 src: *const core::ffi::c_void,
1104 srcSize: size_t,
1105) -> core::ffi::c_ulonglong {
1106 let src = if src.is_null() {
1107 &[]
1108 } else {
1109 core::slice::from_raw_parts(src.cast(), srcSize)
1110 };
1111
1112 get_frame_content_size(src)
1113}
1114
1115fn get_frame_content_size(src: &[u8]) -> u64 {
1116 if is_legacy(src) != 0 {
1117 return match get_decompressed_size_legacy(src) {
1118 None | Some(0) => ZSTD_CONTENTSIZE_UNKNOWN,
1119 Some(decompressed_size) => decompressed_size,
1120 };
1121 }
1122
1123 let mut zfh = ZSTD_FrameHeader::default();
1124 if get_frame_header_advanced(&mut zfh, src, Format::ZSTD_f_zstd1) != 0 {
1125 return ZSTD_CONTENTSIZE_ERROR;
1126 }
1127
1128 if zfh.frameType == ZSTD_skippableFrame {
1129 0
1130 } else {
1131 zfh.frameContentSize
1132 }
1133}
1134
1135unsafe fn readSkippableFrameSize(src: *const core::ffi::c_void, srcSize: size_t) -> size_t {
1136 read_skippable_frame_size(if src.is_null() {
1137 &[]
1138 } else {
1139 core::slice::from_raw_parts(src.cast(), srcSize)
1140 })
1141}
1142
1143fn read_skippable_frame_size(src: &[u8]) -> size_t {
1144 let skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE as usize;
1145
1146 let [_, _, _, _, a, b, c, d, ..] = *src else {
1147 return Error::srcSize_wrong.to_error_code();
1148 };
1149
1150 let size = u32::from_le_bytes([a, b, c, d]);
1151
1152 if size.wrapping_add(8) < size {
1153 return Error::frameParameter_unsupported.to_error_code();
1154 }
1155
1156 let skippableSize = skippableHeaderSize.wrapping_add(size as usize);
1157 if skippableSize > src.len() {
1158 return Error::srcSize_wrong.to_error_code();
1159 }
1160
1161 skippableSize
1162}
1163
1164#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_readSkippableFrame))]
1165pub unsafe extern "C" fn ZSTD_readSkippableFrame(
1166 dst: *mut core::ffi::c_void,
1167 dstCapacity: size_t,
1168 magicVariant: *mut core::ffi::c_uint,
1169 src: *const core::ffi::c_void,
1170 srcSize: size_t,
1171) -> size_t {
1172 if srcSize < 8 {
1173 return Error::srcSize_wrong.to_error_code();
1174 }
1175 let magicNumber = MEM_readLE32(src);
1176 let skippableFrameSize = readSkippableFrameSize(src, srcSize);
1177 let skippableContentSize = skippableFrameSize.wrapping_sub(ZSTD_SKIPPABLEHEADERSIZE as size_t);
1178 if ZSTD_isSkippableFrame(src, srcSize) == 0 {
1179 return Error::frameParameter_unsupported.to_error_code();
1180 }
1181 if skippableFrameSize < 8 || skippableFrameSize > srcSize {
1182 return Error::srcSize_wrong.to_error_code();
1183 }
1184 if skippableContentSize > dstCapacity {
1185 return Error::dstSize_tooSmall.to_error_code();
1186 }
1187 if skippableContentSize > 0 && !dst.is_null() {
1188 libc::memcpy(
1189 dst,
1190 (src as *const u8).offset(8) as *const core::ffi::c_void,
1191 skippableContentSize as libc::size_t,
1192 );
1193 }
1194 if !magicVariant.is_null() {
1195 *magicVariant = magicNumber.wrapping_sub(ZSTD_MAGIC_SKIPPABLE_START as u32);
1196 }
1197 skippableContentSize
1198}
1199
1200#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_findDecompressedSize))]
1201pub unsafe extern "C" fn ZSTD_findDecompressedSize(
1202 src: *const core::ffi::c_void,
1203 srcSize: size_t,
1204) -> core::ffi::c_ulonglong {
1205 let src = if src.is_null() {
1206 &[]
1207 } else {
1208 core::slice::from_raw_parts(src.cast(), srcSize)
1209 };
1210
1211 find_decompressed_size(src)
1212}
1213
1214fn find_decompressed_size(mut src: &[u8]) -> u64 {
1215 let mut totalDstSize = 0u64;
1216
1217 while let [a, b, c, d, _, ..] = *src {
1218 let magicNumber = u32::from_le_bytes([a, b, c, d]);
1219 if magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK
1220 == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
1221 {
1222 let skippableSize = read_skippable_frame_size(src);
1223 if ERR_isError(skippableSize) {
1224 return ZSTD_CONTENTSIZE_ERROR;
1225 }
1226 src = &src[skippableSize..];
1227 } else {
1228 let fcs = get_frame_content_size(src);
1229 if fcs >= ZSTD_CONTENTSIZE_ERROR {
1230 return fcs;
1231 }
1232 if totalDstSize.wrapping_add(fcs) < totalDstSize {
1233 return ZSTD_CONTENTSIZE_ERROR;
1234 }
1235 totalDstSize = totalDstSize.wrapping_add(fcs);
1236 let frameSrcSize = ZSTD_findFrameCompressedSize_advanced(src, Format::ZSTD_f_zstd1);
1237 if ERR_isError(frameSrcSize) {
1238 return ZSTD_CONTENTSIZE_ERROR;
1239 }
1240 src = &src[frameSrcSize..];
1241 }
1242 }
1243
1244 if !src.is_empty() {
1245 return ZSTD_CONTENTSIZE_ERROR;
1246 }
1247
1248 totalDstSize
1249}
1250
1251#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getDecompressedSize))]
1252pub unsafe extern "C" fn ZSTD_getDecompressedSize(
1253 src: *const core::ffi::c_void,
1254 srcSize: size_t,
1255) -> core::ffi::c_ulonglong {
1256 let ret = ZSTD_getFrameContentSize(src, srcSize);
1257 if ret >= ZSTD_CONTENTSIZE_ERROR {
1258 0
1259 } else {
1260 ret
1261 }
1262}
1263
1264unsafe fn ZSTD_decodeFrameHeader(dctx: *mut ZSTD_DCtx, src: &[u8]) -> size_t {
1265 let result = get_frame_header_advanced(&mut (*dctx).fParams, src, (*dctx).format);
1266 if ERR_isError(result) {
1267 return result;
1268 }
1269 if result > 0 {
1270 return Error::srcSize_wrong.to_error_code();
1271 }
1272 if (*dctx).refMultipleDDicts == MultipleDDicts::Multiple && !((*dctx).ddictSet).is_null() {
1273 ZSTD_DCtx_selectFrameDDict(dctx);
1274 }
1275 if (*dctx).fParams.dictID != 0 && (*dctx).dictID != (*dctx).fParams.dictID {
1276 return Error::dictionary_wrong.to_error_code();
1277 }
1278 (*dctx).validateChecksum =
1279 ((*dctx).fParams.checksumFlag != 0 && (*dctx).forceIgnoreChecksum as u64 == 0) as u32;
1280 if (*dctx).validateChecksum != 0 {
1281 ZSTD_XXH64_reset(&mut (*dctx).xxhState, 0);
1282 }
1283 (*dctx).processedCSize = ((*dctx).processedCSize as size_t).wrapping_add(src.len()) as u64;
1284 0
1285}
1286
1287fn ZSTD_errorFrameSizeInfo(ret: size_t) -> ZSTD_frameSizeInfo {
1288 ZSTD_frameSizeInfo {
1289 nbBlocks: 0,
1290 compressedSize: ret,
1291 decompressedBound: ZSTD_CONTENTSIZE_ERROR,
1292 }
1293}
1294
1295fn find_frame_size_info(src: &[u8], format: Format) -> ZSTD_frameSizeInfo {
1296 let mut frameSizeInfo = ZSTD_frameSizeInfo {
1297 nbBlocks: 0,
1298 compressedSize: 0,
1299 decompressedBound: 0,
1300 };
1301
1302 if format == Format::ZSTD_f_zstd1 && is_legacy(src) != 0 {
1303 return unsafe { find_frame_size_info_legacy(src) };
1304 }
1305
1306 if format == Format::ZSTD_f_zstd1
1307 && src.len() >= ZSTD_SKIPPABLEHEADERSIZE as usize
1308 && u32::from_le_bytes(*src.first_chunk().unwrap()) & ZSTD_MAGIC_SKIPPABLE_MASK
1309 == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
1310 {
1311 frameSizeInfo.compressedSize = read_skippable_frame_size(src);
1312 frameSizeInfo
1313 } else {
1314 let mut ip = 0;
1315 let mut remainingSize = src.len();
1316 let mut nbBlocks = 0usize;
1317 let mut zfh = ZSTD_FrameHeader {
1318 frameContentSize: 0,
1319 windowSize: 0,
1320 blockSizeMax: 0,
1321 frameType: ZSTD_frame,
1322 headerSize: 0,
1323 dictID: 0,
1324 checksumFlag: 0,
1325 _reserved1: 0,
1326 _reserved2: 0,
1327 };
1328 let ret = get_frame_header_advanced(&mut zfh, src, format);
1329 if ERR_isError(ret) {
1330 return ZSTD_errorFrameSizeInfo(ret);
1331 }
1332 if ret > 0 {
1333 return ZSTD_errorFrameSizeInfo(Error::srcSize_wrong.to_error_code());
1334 }
1335 ip += zfh.headerSize as usize;
1336 remainingSize = remainingSize.wrapping_sub(zfh.headerSize as size_t);
1337 loop {
1338 let mut blockProperties = blockProperties_t {
1339 blockType: BlockType::Raw,
1340 lastBlock: 0,
1341 origSize: 0,
1342 };
1343 let cBlockSize = unsafe {
1344 ZSTD_getcBlockSize(
1345 src[ip..].as_ptr().cast(),
1346 remainingSize,
1347 &mut blockProperties,
1348 )
1349 };
1350 if ERR_isError(cBlockSize) {
1351 return ZSTD_errorFrameSizeInfo(cBlockSize);
1352 }
1353 if ZSTD_blockHeaderSize.wrapping_add(cBlockSize) > remainingSize {
1354 return ZSTD_errorFrameSizeInfo(Error::srcSize_wrong.to_error_code());
1355 }
1356 ip += ZSTD_blockHeaderSize.wrapping_add(cBlockSize) as usize;
1357 remainingSize =
1358 remainingSize.wrapping_sub(ZSTD_blockHeaderSize.wrapping_add(cBlockSize));
1359 nbBlocks = nbBlocks.wrapping_add(1);
1360 if blockProperties.lastBlock != 0 {
1361 break;
1362 }
1363 }
1364 if zfh.checksumFlag != 0 {
1365 if remainingSize < 4 {
1366 return ZSTD_errorFrameSizeInfo(Error::srcSize_wrong.to_error_code());
1367 }
1368 ip += 4;
1369 }
1370 frameSizeInfo.nbBlocks = nbBlocks;
1371 frameSizeInfo.compressedSize = ip as size_t;
1372 frameSizeInfo.decompressedBound = if zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN {
1373 zfh.frameContentSize
1374 } else {
1375 (nbBlocks as core::ffi::c_ulonglong)
1376 .wrapping_mul(zfh.blockSizeMax as core::ffi::c_ulonglong)
1377 };
1378 frameSizeInfo
1379 }
1380}
1381
1382fn ZSTD_findFrameCompressedSize_advanced(src: &[u8], format: Format) -> size_t {
1383 find_frame_size_info(src, format).compressedSize
1384}
1385
1386#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_findFrameCompressedSize))]
1387pub unsafe extern "C" fn ZSTD_findFrameCompressedSize(
1388 src: *const core::ffi::c_void,
1389 srcSize: size_t,
1390) -> size_t {
1391 let src = if src.is_null() {
1392 &[]
1393 } else {
1394 core::slice::from_raw_parts(src.cast(), srcSize)
1395 };
1396
1397 ZSTD_findFrameCompressedSize_advanced(src, Format::ZSTD_f_zstd1)
1398}
1399
1400#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressBound))]
1401pub unsafe extern "C" fn ZSTD_decompressBound(
1402 src: *const core::ffi::c_void,
1403 srcSize: size_t,
1404) -> core::ffi::c_ulonglong {
1405 decompress_bound(if src.is_null() {
1406 &[]
1407 } else {
1408 core::slice::from_raw_parts(src.cast(), srcSize)
1409 })
1410}
1411
1412fn decompress_bound(mut src: &[u8]) -> core::ffi::c_ulonglong {
1413 let mut bound = 0;
1414
1415 while !src.is_empty() {
1416 let frameSizeInfo = find_frame_size_info(src, Format::ZSTD_f_zstd1);
1417 let compressedSize = frameSizeInfo.compressedSize;
1418 let decompressedBound = frameSizeInfo.decompressedBound;
1419 if ERR_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR {
1420 return ZSTD_CONTENTSIZE_ERROR;
1421 }
1422 src = &src[compressedSize as usize..];
1423 bound += decompressedBound;
1424 }
1425
1426 bound
1427}
1428
1429#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressionMargin))]
1430pub unsafe extern "C" fn ZSTD_decompressionMargin(
1431 src: *const core::ffi::c_void,
1432 srcSize: size_t,
1433) -> size_t {
1434 decompression_margin(if src.is_null() {
1435 &[]
1436 } else {
1437 core::slice::from_raw_parts(src.cast(), srcSize)
1438 })
1439}
1440
1441fn decompression_margin(mut src: &[u8]) -> size_t {
1442 let mut margin = 0;
1443 let mut maxBlockSize = 0;
1444
1445 while !src.is_empty() {
1447 let frameSizeInfo = find_frame_size_info(src, Format::ZSTD_f_zstd1);
1448 let compressedSize = frameSizeInfo.compressedSize;
1449 let decompressedBound = frameSizeInfo.decompressedBound;
1450
1451 let mut zfh = ZSTD_FrameHeader::default();
1452 let err_code = get_frame_header(&mut zfh, src);
1453 if ERR_isError(err_code) {
1454 return err_code;
1455 }
1456
1457 if ERR_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR {
1458 return Error::corruption_detected.to_error_code();
1459 }
1460
1461 if zfh.frameType as core::ffi::c_uint == ZSTD_frame as core::ffi::c_uint {
1462 margin += zfh.headerSize as size_t;
1464 margin += if zfh.checksumFlag != 0 { 4 } else { 0 };
1465 margin += 3 * frameSizeInfo.nbBlocks;
1466 maxBlockSize = Ord::max(maxBlockSize, zfh.blockSizeMax)
1467 } else {
1468 assert!(zfh.frameType == ZSTD_skippableFrame);
1469 margin += compressedSize;
1471 }
1472
1473 src = &src[compressedSize as usize..];
1474 }
1475
1476 margin += maxBlockSize as size_t;
1478
1479 margin
1480}
1481
1482#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_insertBlock))]
1483pub unsafe extern "C" fn ZSTD_insertBlock(
1484 dctx: *mut ZSTD_DCtx,
1485 blockStart: *const core::ffi::c_void,
1486 blockSize: size_t,
1487) -> size_t {
1488 ZSTD_checkContinuity(dctx, blockStart, blockSize);
1489 (*dctx).previousDstEnd =
1490 (blockStart as *const core::ffi::c_char).add(blockSize) as *const core::ffi::c_void;
1491 blockSize
1492}
1493unsafe fn ZSTD_copyRawBlock(
1494 dst: *mut core::ffi::c_void,
1495 dstCapacity: size_t,
1496 src: *const core::ffi::c_void,
1497 srcSize: size_t,
1498) -> size_t {
1499 if srcSize > dstCapacity {
1500 return Error::dstSize_tooSmall.to_error_code();
1501 }
1502 if dst.is_null() {
1503 if srcSize == 0 {
1504 return 0;
1505 }
1506 return Error::dstBuffer_null.to_error_code();
1507 }
1508 libc::memmove(dst, src, srcSize as libc::size_t);
1509 srcSize
1510}
1511unsafe fn ZSTD_setRleBlock(
1512 dst: *mut core::ffi::c_void,
1513 dstCapacity: size_t,
1514 b: u8,
1515 regenSize: size_t,
1516) -> size_t {
1517 if regenSize > dstCapacity {
1518 return Error::dstSize_tooSmall.to_error_code();
1519 }
1520 if dst.is_null() {
1521 if regenSize == 0 {
1522 return 0;
1523 }
1524 return Error::dstBuffer_null.to_error_code();
1525 }
1526 ptr::write_bytes(dst, b, regenSize);
1527 regenSize
1528}
1529unsafe fn ZSTD_DCtx_trace_end(
1530 dctx: *const ZSTD_DCtx,
1531 uncompressedSize: u64,
1532 compressedSize: u64,
1533 streaming: core::ffi::c_int,
1534) {
1535 if (*dctx).traceCtx != 0 {
1536 let mut trace = ZSTD_Trace {
1537 version: 0,
1538 streaming: 0,
1539 dictionaryID: 0,
1540 dictionaryIsCold: 0,
1541 dictionarySize: 0,
1542 uncompressedSize: 0,
1543 compressedSize: 0,
1544 params: core::ptr::null::<ZSTD_CCtx_params_s>(),
1545 cctx: core::ptr::null::<ZSTD_CCtx_s>(),
1546 dctx: core::ptr::null::<ZSTD_DCtx_s>(),
1547 };
1548 ptr::write_bytes(
1549 &mut trace as *mut ZSTD_Trace as *mut u8,
1550 0,
1551 ::core::mem::size_of::<ZSTD_Trace>(),
1552 );
1553 trace.version = ZSTD_VERSION_NUMBER as core::ffi::c_uint;
1554 trace.streaming = streaming;
1555 if !((*dctx).ddict).is_null() {
1556 trace.dictionaryID = ZSTD_getDictID_fromDDict((*dctx).ddict);
1557 trace.dictionarySize = ZSTD_DDict_dictSize((*dctx).ddict);
1558 trace.dictionaryIsCold = (*dctx).ddictIsCold;
1559 }
1560 trace.uncompressedSize = uncompressedSize as size_t;
1561 trace.compressedSize = compressedSize as size_t;
1562 trace.dctx = dctx;
1563 ZSTD_trace_decompress_end((*dctx).traceCtx, &mut trace);
1564 }
1565}
1566unsafe fn ZSTD_decompressFrame(
1567 dctx: *mut ZSTD_DCtx,
1568 dst: *mut core::ffi::c_void,
1569 dstCapacity: size_t,
1570 srcPtr: &mut &[u8],
1571) -> size_t {
1572 let ilen = srcPtr.len();
1573 let ip = srcPtr;
1574 let ostart = dst as *mut u8;
1575 let oend = if dstCapacity != 0 {
1576 ostart.add(dstCapacity)
1577 } else {
1578 ostart
1579 };
1580 let mut op = ostart;
1581 if ip.len()
1582 < (match (*dctx).format {
1583 Format::ZSTD_f_zstd1 => 6usize,
1584 Format::ZSTD_f_zstd1_magicless => 2,
1585 })
1586 .wrapping_add(ZSTD_blockHeaderSize)
1587 {
1588 return Error::srcSize_wrong.to_error_code();
1589 }
1590 let frameHeaderSize = frame_header_size_internal(ip, (*dctx).format);
1591 if ERR_isError(frameHeaderSize) {
1592 return frameHeaderSize;
1593 }
1594 if ip.len() < frameHeaderSize.wrapping_add(ZSTD_blockHeaderSize) {
1595 return Error::srcSize_wrong.to_error_code();
1596 }
1597 let err_code = ZSTD_decodeFrameHeader(dctx, &ip[..frameHeaderSize]);
1598 if ERR_isError(err_code) {
1599 return err_code;
1600 }
1601 *ip = &ip[frameHeaderSize..];
1602 if (*dctx).maxBlockSizeParam != 0 {
1603 (*dctx).fParams.blockSizeMax =
1604 if (*dctx).fParams.blockSizeMax < (*dctx).maxBlockSizeParam as core::ffi::c_uint {
1605 (*dctx).fParams.blockSizeMax
1606 } else {
1607 (*dctx).maxBlockSizeParam as core::ffi::c_uint
1608 };
1609 }
1610 loop {
1611 let mut oBlockEnd = oend;
1612 let mut decodedSize: size_t = 0;
1613
1614 let (blockProperties, cBlockSize) = match getc_block_size(ip) {
1615 Ok(ret) => ret,
1616 Err(e) => return e.to_error_code(),
1617 };
1618
1619 *ip = &ip[ZSTD_blockHeaderSize..];
1620 if cBlockSize > ip.len() {
1621 return Error::srcSize_wrong.to_error_code();
1622 }
1623 if ip.as_ptr() >= op as *const u8 && ip.as_ptr() < oBlockEnd as *const u8 {
1624 oBlockEnd = op.offset(ip.as_ptr().offset_from(op) as core::ffi::c_long as isize);
1625 }
1626 match blockProperties.blockType {
1627 BlockType::Raw => {
1628 decodedSize = ZSTD_copyRawBlock(
1629 op as *mut core::ffi::c_void,
1630 oend.offset_from(op) as size_t,
1631 ip.as_ptr().cast(),
1632 cBlockSize,
1633 );
1634 }
1635 BlockType::Rle => {
1636 decodedSize = ZSTD_setRleBlock(
1637 op as *mut core::ffi::c_void,
1638 oBlockEnd.offset_from(op) as size_t,
1639 ip[0],
1640 blockProperties.origSize as size_t,
1641 );
1642 }
1643 BlockType::Compressed => {
1644 decodedSize = ZSTD_decompressBlock_internal(
1645 dctx,
1646 op as *mut core::ffi::c_void,
1647 oBlockEnd.offset_from(op) as size_t,
1648 ip.as_ptr().cast(),
1649 cBlockSize,
1650 not_streaming,
1651 );
1652 }
1653 BlockType::Reserved => {
1654 return Error::corruption_detected.to_error_code();
1655 }
1656 }
1657 let err_code_0 = decodedSize;
1658 if ERR_isError(err_code_0) {
1659 return err_code_0;
1660 }
1661 if (*dctx).validateChecksum != 0 {
1662 ZSTD_XXH64_update(
1663 &mut (*dctx).xxhState,
1664 op as *const core::ffi::c_void,
1665 decodedSize,
1666 );
1667 }
1668 if decodedSize != 0 {
1669 op = op.add(decodedSize);
1670 }
1671 *ip = &ip[cBlockSize..];
1672 if blockProperties.lastBlock != 0 {
1673 break;
1674 }
1675 }
1676 if (*dctx).fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
1677 && op.offset_from(ostart) as core::ffi::c_long as u64 as core::ffi::c_ulonglong
1678 != (*dctx).fParams.frameContentSize
1679 {
1680 return Error::corruption_detected.to_error_code();
1681 }
1682 if (*dctx).fParams.checksumFlag != 0 {
1683 let [a, b, c, d, ..] = **ip else {
1684 return Error::checksum_wrong.to_error_code();
1685 };
1686
1687 if (*dctx).forceIgnoreChecksum == 0 {
1688 if u32::from_le_bytes([a, b, c, d]) != ZSTD_XXH64_digest(&mut (*dctx).xxhState) as u32 {
1689 return Error::checksum_wrong.to_error_code();
1690 }
1691 }
1692
1693 *ip = &ip[4..];
1694 }
1695
1696 ZSTD_DCtx_trace_end(
1697 dctx,
1698 op.offset_from(ostart) as core::ffi::c_long as u64,
1699 (ilen - ip.len()) as u64,
1700 0,
1701 );
1702
1703 op.offset_from(ostart) as size_t
1704}
1705
1706unsafe fn ZSTD_decompressMultiFrame(
1707 dctx: *mut ZSTD_DCtx,
1708 mut dst: *mut core::ffi::c_void,
1709 mut dstCapacity: size_t,
1710 mut src: &[u8],
1711 mut dict: *const core::ffi::c_void,
1712 mut dictSize: size_t,
1713 ddict: Option<&ZSTD_DDict>,
1714) -> size_t {
1715 let dststart = dst;
1716 let mut more_than_one_frame = false;
1717
1718 if let Some(ddict) = ddict {
1719 dict = ZSTD_DDict_dictContent(ddict);
1720 dictSize = ZSTD_DDict_dictSize(ddict);
1721 }
1722
1723 while src.len() >= ZSTD_startingInputLength((*dctx).format) {
1724 if (*dctx).format == Format::ZSTD_f_zstd1 && is_legacy(src) != 0 {
1725 let frameSize;
1726 {
1727 let srcSize = src.len();
1728 let src = src.as_ptr().cast();
1729
1730 let mut decodedSize: size_t = 0;
1731 frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
1732 if ERR_isError(frameSize) {
1733 return frameSize;
1734 }
1735 if (*dctx).staticSize != 0 {
1736 return Error::memory_allocation.to_error_code();
1737 }
1738 decodedSize =
1739 ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
1740 if ERR_isError(decodedSize) {
1741 return decodedSize;
1742 }
1743 let expectedSize = ZSTD_getFrameContentSize(src, srcSize);
1744 if expectedSize == ZSTD_CONTENTSIZE_ERROR {
1745 return Error::corruption_detected.to_error_code();
1746 }
1747 if expectedSize != ZSTD_CONTENTSIZE_UNKNOWN
1748 && expectedSize != decodedSize as core::ffi::c_ulonglong
1749 {
1750 return Error::corruption_detected.to_error_code();
1751 }
1752 dst = (dst as *mut u8).add(decodedSize) as *mut core::ffi::c_void;
1753 dstCapacity = dstCapacity.wrapping_sub(decodedSize);
1754 }
1755 src = &src[frameSize..];
1756 } else {
1757 if (*dctx).format == Format::ZSTD_f_zstd1 && src.len() >= 4 {
1758 let magicNumber = u32::from_le_bytes(*src.first_chunk().unwrap());
1759 if magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK
1760 == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
1761 {
1762 let skippableSize = read_skippable_frame_size(src);
1763 let err_code = skippableSize;
1764 if ERR_isError(err_code) {
1765 return err_code;
1766 }
1767 src = &src[skippableSize..];
1768 continue;
1769 }
1770 }
1771 if let Some(ddict) = ddict {
1772 let err_code_0 = ZSTD_decompressBegin_usingDDict(dctx, ddict);
1773 if ERR_isError(err_code_0) {
1774 return err_code_0;
1775 }
1776 } else {
1777 let err_code_1 = ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
1778 if ERR_isError(err_code_1) {
1779 return err_code_1;
1780 }
1781 }
1782 ZSTD_checkContinuity(dctx, dst, dstCapacity);
1783 let res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &mut src);
1784 if ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown && more_than_one_frame {
1785 return Error::srcSize_wrong.to_error_code();
1786 }
1787 if ERR_isError(res) {
1788 return res;
1789 }
1790 if res != 0 {
1791 dst = (dst as *mut u8).add(res) as *mut core::ffi::c_void;
1792 }
1793 dstCapacity = dstCapacity.wrapping_sub(res);
1794 more_than_one_frame = true;
1795 }
1796 }
1797
1798 if !src.is_empty() {
1799 return Error::srcSize_wrong.to_error_code();
1800 }
1801
1802 (dst as *mut u8).offset_from(dststart as *mut u8) as size_t
1803}
1804
1805#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompress_usingDict))]
1806pub unsafe extern "C" fn ZSTD_decompress_usingDict(
1807 dctx: *mut ZSTD_DCtx,
1808 dst: *mut core::ffi::c_void,
1809 dstCapacity: size_t,
1810 src: *const core::ffi::c_void,
1811 srcSize: size_t,
1812 dict: *const core::ffi::c_void,
1813 dictSize: size_t,
1814) -> size_t {
1815 let src = if src.is_null() {
1816 &[]
1817 } else {
1818 core::slice::from_raw_parts(src.cast::<u8>(), srcSize)
1819 };
1820 ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, dict, dictSize, None)
1821}
1822
1823unsafe fn ZSTD_getDDict(dctx: *mut ZSTD_DCtx) -> *const ZSTD_DDict {
1824 match (*dctx).dictUses as core::ffi::c_int {
1825 -1 => (*dctx).ddict,
1826 1 => {
1827 (*dctx).dictUses = ZSTD_dont_use;
1828 (*dctx).ddict
1829 }
1830 0 | _ => {
1831 ZSTD_clearDict(dctx);
1832 core::ptr::null()
1833 }
1834 }
1835}
1836
1837#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressDCtx))]
1838pub unsafe extern "C" fn ZSTD_decompressDCtx(
1839 dctx: *mut ZSTD_DCtx,
1840 dst: *mut core::ffi::c_void,
1841 dstCapacity: size_t,
1842 src: *const core::ffi::c_void,
1843 srcSize: size_t,
1844) -> size_t {
1845 ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx))
1846}
1847
1848#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompress))]
1849pub unsafe extern "C" fn ZSTD_decompress(
1850 dst: *mut core::ffi::c_void,
1851 dstCapacity: size_t,
1852 src: *const core::ffi::c_void,
1853 srcSize: size_t,
1854) -> size_t {
1855 let mut regenSize: size_t = 0;
1856 let dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
1857 if dctx.is_null() {
1858 return Error::memory_allocation.to_error_code();
1859 }
1860 regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
1861 ZSTD_freeDCtx(dctx);
1862 regenSize
1863}
1864
1865#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_nextSrcSizeToDecompress))]
1866pub unsafe extern "C" fn ZSTD_nextSrcSizeToDecompress(dctx: *mut ZSTD_DCtx) -> size_t {
1867 (*dctx).expected
1868}
1869
1870unsafe fn ZSTD_nextSrcSizeToDecompressWithInputSize(
1871 dctx: *mut ZSTD_DCtx,
1872 inputSize: size_t,
1873) -> size_t {
1874 match (*dctx).stage {
1875 DecompressStage::DecompressBlock | DecompressStage::DecompressLastBlock => {
1876 Ord::clamp(1, inputSize, (*dctx).expected)
1877 }
1878 _ => (*dctx).expected,
1879 }
1880}
1881
1882#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_nextInputType))]
1883pub unsafe extern "C" fn ZSTD_nextInputType(dctx: *mut ZSTD_DCtx) -> ZSTD_nextInputType_e {
1884 (*dctx).stage.to_next_input_type() as ZSTD_nextInputType_e
1885}
1886
1887unsafe fn ZSTD_isSkipFrame(dctx: *mut ZSTD_DCtx) -> core::ffi::c_int {
1888 matches!((*dctx).stage, DecompressStage::SkipFrame) as core::ffi::c_int
1889}
1890
1891#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressContinue))]
1892pub unsafe extern "C" fn ZSTD_decompressContinue(
1893 dctx: *mut ZSTD_DCtx,
1894 dst: *mut core::ffi::c_void,
1895 dstCapacity: size_t,
1896 src: *const core::ffi::c_void,
1897 srcSize: size_t,
1898) -> size_t {
1899 if srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize) {
1900 return Error::srcSize_wrong.to_error_code();
1901 }
1902 ZSTD_checkContinuity(dctx, dst, dstCapacity);
1903 (*dctx).processedCSize = ((*dctx).processedCSize as size_t).wrapping_add(srcSize) as u64;
1904 match (*dctx).stage {
1905 DecompressStage::GetFrameHeaderSize => {
1906 if (*dctx).format == Format::ZSTD_f_zstd1
1907 && MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK
1908 == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
1909 {
1910 libc::memcpy(
1911 ((*dctx).headerBuffer).as_mut_ptr() as *mut core::ffi::c_void,
1912 src,
1913 srcSize as libc::size_t,
1914 );
1915 (*dctx).expected = (ZSTD_SKIPPABLEHEADERSIZE as size_t).wrapping_sub(srcSize);
1916 (*dctx).stage = DecompressStage::DecodeSkippableHeader;
1917 return 0;
1918 }
1919 let src_slice = core::slice::from_raw_parts(src.cast(), srcSize);
1920 (*dctx).headerSize = frame_header_size_internal(src_slice, (*dctx).format);
1921 if ERR_isError((*dctx).headerSize) {
1922 return (*dctx).headerSize;
1923 }
1924 libc::memcpy(
1925 ((*dctx).headerBuffer).as_mut_ptr() as *mut core::ffi::c_void,
1926 src,
1927 srcSize as libc::size_t,
1928 );
1929 (*dctx).expected = ((*dctx).headerSize).wrapping_sub(srcSize);
1930 (*dctx).stage = DecompressStage::DecodeFrameHeader;
1931 0
1932 }
1933 DecompressStage::DecodeFrameHeader => {
1934 libc::memcpy(
1935 ((*dctx).headerBuffer)
1936 .as_mut_ptr()
1937 .add(((*dctx).headerSize).wrapping_sub(srcSize))
1938 as *mut core::ffi::c_void,
1939 src,
1940 srcSize as libc::size_t,
1941 );
1942 let err_code =
1943 ZSTD_decodeFrameHeader(dctx, &(&(*dctx).headerBuffer)[..(*dctx).headerSize]);
1944 if ERR_isError(err_code) {
1945 return err_code;
1946 }
1947 (*dctx).expected = ZSTD_blockHeaderSize;
1948 (*dctx).stage = DecompressStage::DecodeBlockHeader;
1949 0
1950 }
1951 DecompressStage::DecodeBlockHeader => {
1952 let mut bp = blockProperties_t {
1953 blockType: BlockType::Raw,
1954 lastBlock: 0,
1955 origSize: 0,
1956 };
1957 let cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &mut bp);
1958 if ERR_isError(cBlockSize) {
1959 return cBlockSize;
1960 }
1961 if cBlockSize > (*dctx).fParams.blockSizeMax as size_t {
1962 return Error::corruption_detected.to_error_code();
1963 }
1964 (*dctx).expected = cBlockSize;
1965 (*dctx).bType = bp.blockType;
1966 (*dctx).rleSize = bp.origSize as size_t;
1967 if cBlockSize != 0 {
1968 (*dctx).stage = match bp.lastBlock {
1969 0 => DecompressStage::DecompressBlock,
1970 _ => DecompressStage::DecompressLastBlock,
1971 };
1972 return 0;
1973 }
1974 if bp.lastBlock != 0 {
1975 if (*dctx).fParams.checksumFlag != 0 {
1976 (*dctx).expected = 4;
1977 (*dctx).stage = DecompressStage::CheckChecksum;
1978 } else {
1979 (*dctx).expected = 0;
1980 (*dctx).stage = DecompressStage::GetFrameHeaderSize;
1981 }
1982 } else {
1983 (*dctx).expected = ZSTD_blockHeaderSize;
1984 (*dctx).stage = DecompressStage::DecodeBlockHeader;
1985 }
1986 0
1987 }
1988
1989 DecompressStage::DecompressBlock | DecompressStage::DecompressLastBlock => {
1990 let mut rSize: size_t = 0;
1991 match (*dctx).bType {
1992 BlockType::Compressed => {
1993 rSize = ZSTD_decompressBlock_internal(
1994 dctx,
1995 dst,
1996 dstCapacity,
1997 src,
1998 srcSize,
1999 is_streaming,
2000 );
2001 (*dctx).expected = 0;
2002 }
2003 BlockType::Raw => {
2004 rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
2005 let err_code_0 = rSize;
2006 if ERR_isError(err_code_0) {
2007 return err_code_0;
2008 }
2009 (*dctx).expected = ((*dctx).expected).wrapping_sub(rSize);
2010 }
2011 BlockType::Rle => {
2012 rSize =
2013 ZSTD_setRleBlock(dst, dstCapacity, *(src as *const u8), (*dctx).rleSize);
2014 (*dctx).expected = 0;
2015 }
2016 BlockType::Reserved => {
2017 return Error::corruption_detected.to_error_code();
2018 }
2019 }
2020 let err_code_1 = rSize;
2021 if ERR_isError(err_code_1) {
2022 return err_code_1;
2023 }
2024 if rSize > (*dctx).fParams.blockSizeMax as size_t {
2025 return Error::corruption_detected.to_error_code();
2026 }
2027 (*dctx).decodedSize = ((*dctx).decodedSize as size_t).wrapping_add(rSize) as u64 as u64;
2028 if (*dctx).validateChecksum != 0 {
2029 ZSTD_XXH64_update(&mut (*dctx).xxhState, dst, rSize as usize);
2030 }
2031 (*dctx).previousDstEnd =
2032 (dst as *mut core::ffi::c_char).add(rSize) as *const core::ffi::c_void;
2033 if (*dctx).expected > 0 {
2034 return rSize;
2035 }
2036 if (*dctx).stage == DecompressStage::DecompressLastBlock {
2037 if (*dctx).fParams.frameContentSize != (0 as core::ffi::c_ulonglong).wrapping_sub(1)
2038 && (*dctx).decodedSize as core::ffi::c_ulonglong
2039 != (*dctx).fParams.frameContentSize
2040 {
2041 return Error::corruption_detected.to_error_code();
2042 }
2043 if (*dctx).fParams.checksumFlag != 0 {
2044 (*dctx).expected = 4;
2045 (*dctx).stage = DecompressStage::CheckChecksum;
2046 } else {
2047 ZSTD_DCtx_trace_end(dctx, (*dctx).decodedSize, (*dctx).processedCSize, 1);
2048 (*dctx).expected = 0;
2049 (*dctx).stage = DecompressStage::GetFrameHeaderSize;
2050 }
2051 } else {
2052 (*dctx).stage = DecompressStage::DecodeBlockHeader;
2053 (*dctx).expected = ZSTD_blockHeaderSize;
2054 }
2055 rSize
2056 }
2057 DecompressStage::CheckChecksum => {
2058 if (*dctx).validateChecksum != 0 {
2059 let h32 = ZSTD_XXH64_digest(&mut (*dctx).xxhState) as u32;
2060 let check32 = MEM_readLE32(src);
2061 if check32 != h32 {
2062 return Error::checksum_wrong.to_error_code();
2063 }
2064 }
2065 ZSTD_DCtx_trace_end(dctx, (*dctx).decodedSize, (*dctx).processedCSize, 1);
2066 (*dctx).expected = 0;
2067 (*dctx).stage = DecompressStage::GetFrameHeaderSize;
2068 0
2069 }
2070 DecompressStage::DecodeSkippableHeader => {
2071 libc::memcpy(
2072 ((*dctx).headerBuffer)
2073 .as_mut_ptr()
2074 .add((8 as size_t).wrapping_sub(srcSize))
2075 as *mut core::ffi::c_void,
2076 src,
2077 srcSize as libc::size_t,
2078 );
2079 (*dctx).expected =
2080 MEM_readLE32(((*dctx).headerBuffer).as_mut_ptr().add(ZSTD_FRAMEIDSIZE)
2081 as *const core::ffi::c_void) as size_t;
2082 (*dctx).stage = DecompressStage::SkipFrame;
2083 0
2084 }
2085 DecompressStage::SkipFrame => {
2086 (*dctx).expected = 0;
2087 (*dctx).stage = DecompressStage::GetFrameHeaderSize;
2088 0
2089 }
2090 }
2091}
2092
2093pub unsafe fn ZSTD_loadDEntropy(entropy: &mut ZSTD_entropyDTables_t, dict: &[u8]) -> size_t {
2094 let Some((_, mut dictPtr)) = dict.split_at_checked(8) else {
2095 return Error::dictionary_corrupted.to_error_code();
2096 };
2097
2098 const _: () = assert!(
2099 size_of::<crate::lib::decompress::SymbolTable<512>>()
2100 >= size_of::<HUF_ReadDTableX2_Workspace>()
2101 );
2102 const _: () = assert!(
2103 align_of::<crate::lib::decompress::SymbolTable<512>>()
2104 >= align_of::<HUF_ReadDTableX2_Workspace>()
2105 );
2106
2107 let workspace = &mut entropy.LLTable;
2108 let wksp: &mut HUF_ReadDTableX2_Workspace = unsafe { core::mem::transmute(workspace) };
2109
2110 let hSize = HUF_readDTableX2_wksp(&mut entropy.hufTable, dictPtr, wksp, 0);
2111 if ERR_isError(hSize) {
2112 return Error::dictionary_corrupted.to_error_code();
2113 }
2114
2115 dictPtr = &dictPtr[hSize..];
2116 let mut offcodeNCount: [core::ffi::c_short; 32] = [0; 32];
2117 let mut offcodeMaxValue = MaxOff as core::ffi::c_uint;
2118 let mut offcodeLog: core::ffi::c_uint = 0;
2119 let offcodeHeaderSize = FSE_readNCount_slice(
2120 &mut offcodeNCount,
2121 &mut offcodeMaxValue,
2122 &mut offcodeLog,
2123 dictPtr,
2124 );
2125
2126 let Ok(offcodeHeaderSize) = offcodeHeaderSize else {
2127 return Error::dictionary_corrupted.to_error_code();
2128 };
2129 if offcodeMaxValue > 31 {
2130 return Error::dictionary_corrupted.to_error_code();
2131 }
2132 if offcodeLog > 8 {
2133 return Error::dictionary_corrupted.to_error_code();
2134 }
2135 ZSTD_buildFSETable(
2136 &mut entropy.OFTable,
2137 &offcodeNCount[..=offcodeMaxValue as usize],
2138 &OF_base,
2139 &OF_bits,
2140 offcodeLog,
2141 &mut entropy.workspace,
2142 false,
2143 );
2144 dictPtr = &dictPtr[offcodeHeaderSize..];
2145 let mut matchlengthNCount: [core::ffi::c_short; 53] = [0; 53];
2146 let mut matchlengthMaxValue = MaxML as core::ffi::c_uint;
2147 let mut matchlengthLog: core::ffi::c_uint = 0;
2148 let matchlengthHeaderSize = FSE_readNCount_slice(
2149 &mut matchlengthNCount,
2150 &mut matchlengthMaxValue,
2151 &mut matchlengthLog,
2152 dictPtr,
2153 );
2154 let Ok(matchlengthHeaderSize) = matchlengthHeaderSize else {
2155 return Error::dictionary_corrupted.to_error_code();
2156 };
2157 if matchlengthMaxValue > 52 {
2158 return Error::dictionary_corrupted.to_error_code();
2159 }
2160 if matchlengthLog > 9 {
2161 return Error::dictionary_corrupted.to_error_code();
2162 }
2163 ZSTD_buildFSETable(
2164 &mut entropy.MLTable,
2165 &matchlengthNCount[..=matchlengthMaxValue as usize],
2166 &ML_base,
2167 &ML_bits,
2168 matchlengthLog,
2169 &mut entropy.workspace,
2170 false,
2171 );
2172 dictPtr = &dictPtr[matchlengthHeaderSize..];
2173 let mut litlengthNCount: [core::ffi::c_short; 36] = [0; 36];
2174 let mut litlengthMaxValue = MaxLL as core::ffi::c_uint;
2175 let mut litlengthLog: core::ffi::c_uint = 0;
2176 let litlengthHeaderSize = FSE_readNCount_slice(
2177 &mut litlengthNCount,
2178 &mut litlengthMaxValue,
2179 &mut litlengthLog,
2180 dictPtr,
2181 );
2182 let Ok(litlengthHeaderSize) = litlengthHeaderSize else {
2183 return Error::dictionary_corrupted.to_error_code();
2184 };
2185 if litlengthMaxValue > 35 {
2186 return Error::dictionary_corrupted.to_error_code();
2187 }
2188 if litlengthLog > 9 {
2189 return Error::dictionary_corrupted.to_error_code();
2190 }
2191 ZSTD_buildFSETable(
2192 &mut entropy.LLTable,
2193 &litlengthNCount[..=litlengthMaxValue as usize],
2194 &LL_base,
2195 &LL_bits,
2196 litlengthLog,
2197 &mut entropy.workspace,
2198 false,
2199 );
2200 dictPtr = &dictPtr[litlengthHeaderSize..];
2201 let Some((chunk, dict_content)) = dictPtr.split_first_chunk::<12>() else {
2202 return Error::dictionary_corrupted.to_error_code();
2203 };
2204
2205 let dict_content_size = dict_content.len();
2206 for (i, rep) in chunk.as_chunks::<4>().0.iter().enumerate() {
2207 let rep = u32::from_le_bytes(*rep);
2208 if rep == 0 || rep as size_t > dict_content_size {
2209 return Error::dictionary_corrupted.to_error_code();
2210 }
2211 entropy.rep[i] = rep;
2212 }
2213
2214 dict.len() - dict_content_size
2215}
2216
2217unsafe fn ZSTD_refDictContent(dctx: *mut ZSTD_DCtx, dict: &[u8]) -> size_t {
2218 (*dctx).dictEnd = (*dctx).previousDstEnd;
2219 (*dctx).virtualStart = dict
2220 .as_ptr()
2221 .sub((((*dctx).previousDstEnd).byte_offset_from((*dctx).prefixStart)) as usize)
2222 .cast();
2223 (*dctx).prefixStart = dict.as_ptr().cast();
2224 (*dctx).previousDstEnd = dict.as_ptr_range().end.cast();
2225
2226 0
2227}
2228
2229unsafe fn ZSTD_decompress_insertDictionary(dctx: *mut ZSTD_DCtx, dict: &[u8]) -> size_t {
2230 let ([magic, dict_id, ..], _) = dict.as_chunks::<4>() else {
2231 return ZSTD_refDictContent(dctx, dict);
2232 };
2233
2234 let magic = u32::from_le_bytes(*magic);
2235 if magic != ZSTD_MAGIC_DICTIONARY {
2236 return ZSTD_refDictContent(dctx, dict);
2237 }
2238 (*dctx).dictID = u32::from_le_bytes(*dict_id);
2239 let eSize = ZSTD_loadDEntropy(&mut (*dctx).entropy, dict);
2240 if ERR_isError(eSize) {
2241 return Error::dictionary_corrupted.to_error_code();
2242 }
2243
2244 (*dctx).fseEntropy = 1;
2245 (*dctx).litEntropy = (*dctx).fseEntropy;
2246
2247 ZSTD_refDictContent(dctx, &dict[eSize..])
2248}
2249
2250#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressBegin))]
2251pub unsafe extern "C" fn ZSTD_decompressBegin(dctx: *mut ZSTD_DCtx) -> size_t {
2252 (*dctx).traceCtx = ZSTD_trace_decompress_begin(dctx);
2253 (*dctx).expected = ZSTD_startingInputLength((*dctx).format);
2254 (*dctx).stage = DecompressStage::GetFrameHeaderSize;
2255 (*dctx).processedCSize = 0;
2256 (*dctx).decodedSize = 0;
2257 (*dctx).previousDstEnd = core::ptr::null();
2258 (*dctx).prefixStart = core::ptr::null();
2259 (*dctx).virtualStart = core::ptr::null();
2260 (*dctx).dictEnd = core::ptr::null();
2261 (*dctx).entropy.hufTable.description = DTableDesc::from_u32(12 * 0x1000001);
2262 (*dctx).fseEntropy = 0;
2263 (*dctx).litEntropy = (*dctx).fseEntropy;
2264 (*dctx).dictID = 0;
2265 (*dctx).bType = BlockType::Reserved;
2266 (*dctx).isFrameDecompression = 1;
2267 libc::memcpy(
2268 ((*dctx).entropy.rep).as_mut_ptr() as *mut core::ffi::c_void,
2269 repStartValue.as_ptr() as *const core::ffi::c_void,
2270 ::core::mem::size_of::<[u32; 3]>() as libc::size_t,
2271 );
2272 (*dctx).LLTptr = ((*dctx).entropy.LLTable).as_mut_ptr();
2273 (*dctx).MLTptr = ((*dctx).entropy.MLTable).as_mut_ptr();
2274 (*dctx).OFTptr = ((*dctx).entropy.OFTable).as_mut_ptr();
2275 (*dctx).HUFptr = &raw const (*dctx).entropy.hufTable;
2276 0
2277}
2278
2279#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressBegin_usingDict))]
2280pub unsafe extern "C" fn ZSTD_decompressBegin_usingDict(
2281 dctx: *mut ZSTD_DCtx,
2282 dict: *const core::ffi::c_void,
2283 dictSize: size_t,
2284) -> size_t {
2285 let err_code = ZSTD_decompressBegin(dctx);
2286 if ERR_isError(err_code) {
2287 return err_code;
2288 }
2289
2290 if dict.is_null() || dictSize == 0 {
2291 return 0;
2292 }
2293
2294 let dict = core::slice::from_raw_parts(dict.cast::<u8>(), dictSize);
2295 if ERR_isError(ZSTD_decompress_insertDictionary(dctx, dict)) {
2296 return Error::dictionary_corrupted.to_error_code();
2297 }
2298
2299 0
2300}
2301
2302#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressBegin_usingDDict))]
2303pub unsafe extern "C" fn ZSTD_decompressBegin_usingDDict(
2304 dctx: *mut ZSTD_DCtx,
2305 ddict: *const ZSTD_DDict,
2306) -> size_t {
2307 if !ddict.is_null() {
2308 let dictStart = ZSTD_DDict_dictContent(ddict) as *const core::ffi::c_char;
2309 let dictSize = ZSTD_DDict_dictSize(ddict);
2310 let dictEnd = dictStart.add(dictSize) as *const core::ffi::c_void;
2311 (*dctx).ddictIsCold = ((*dctx).dictEnd != dictEnd) as core::ffi::c_int;
2312 }
2313 let err_code = ZSTD_decompressBegin(dctx);
2314 if ERR_isError(err_code) {
2315 return err_code;
2316 }
2317 if !ddict.is_null() {
2318 ZSTD_copyDDictParameters(dctx, ddict);
2319 }
2320 0
2321}
2322#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getDictID_fromDict))]
2323pub unsafe extern "C" fn ZSTD_getDictID_fromDict(
2324 dict: *const core::ffi::c_void,
2325 dictSize: size_t,
2326) -> core::ffi::c_uint {
2327 if dictSize < 8 {
2328 return 0;
2329 }
2330 if MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY {
2331 return 0;
2332 }
2333 MEM_readLE32(
2334 (dict as *const core::ffi::c_char).add(ZSTD_FRAMEIDSIZE) as *const core::ffi::c_void
2335 )
2336}
2337#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_getDictID_fromFrame))]
2338pub unsafe extern "C" fn ZSTD_getDictID_fromFrame(
2339 src: *const core::ffi::c_void,
2340 srcSize: size_t,
2341) -> core::ffi::c_uint {
2342 let mut zfp = {
2343 ZSTD_FrameHeader {
2344 frameContentSize: 0,
2345 windowSize: 0,
2346 blockSizeMax: 0,
2347 frameType: ZSTD_frame,
2348 headerSize: 0,
2349 dictID: 0,
2350 checksumFlag: 0,
2351 _reserved1: 0,
2352 _reserved2: 0,
2353 }
2354 };
2355 let hError = ZSTD_getFrameHeader(&mut zfp, src, srcSize);
2356 if ERR_isError(hError) {
2357 return 0;
2358 }
2359 zfp.dictID
2360}
2361
2362#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompress_usingDDict))]
2363pub unsafe extern "C" fn ZSTD_decompress_usingDDict(
2364 dctx: *mut ZSTD_DCtx,
2365 dst: *mut core::ffi::c_void,
2366 dstCapacity: size_t,
2367 src: *const core::ffi::c_void,
2368 srcSize: size_t,
2369 ddict: *const ZSTD_DDict,
2370) -> size_t {
2371 let src = if src.is_null() {
2372 &[]
2373 } else {
2374 core::slice::from_raw_parts(src.cast::<u8>(), srcSize)
2375 };
2376
2377 ZSTD_decompressMultiFrame(
2378 dctx,
2379 dst,
2380 dstCapacity,
2381 src,
2382 core::ptr::null(),
2383 0,
2384 ddict.as_ref(),
2385 )
2386}
2387
2388#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_createDStream))]
2389pub unsafe extern "C" fn ZSTD_createDStream() -> *mut ZSTD_DStream {
2390 ZSTD_createDCtx_internal(ZSTD_defaultCMem)
2391}
2392#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_initStaticDStream))]
2393pub unsafe extern "C" fn ZSTD_initStaticDStream(
2394 workspace: *mut core::ffi::c_void,
2395 workspaceSize: size_t,
2396) -> *mut ZSTD_DStream {
2397 ZSTD_initStaticDCtx(workspace, workspaceSize)
2398}
2399#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_createDStream_advanced))]
2400pub unsafe extern "C" fn ZSTD_createDStream_advanced(
2401 customMem: ZSTD_customMem,
2402) -> *mut ZSTD_DStream {
2403 ZSTD_createDCtx_internal(customMem)
2404}
2405#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_freeDStream))]
2406pub unsafe extern "C" fn ZSTD_freeDStream(zds: *mut ZSTD_DStream) -> size_t {
2407 ZSTD_freeDCtx(zds)
2408}
2409#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DStreamInSize))]
2410pub unsafe extern "C" fn ZSTD_DStreamInSize() -> size_t {
2411 (ZSTD_BLOCKSIZE_MAX as size_t).wrapping_add(ZSTD_blockHeaderSize)
2412}
2413#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DStreamOutSize))]
2414pub unsafe extern "C" fn ZSTD_DStreamOutSize() -> size_t {
2415 ZSTD_BLOCKSIZE_MAX as size_t
2416}
2417#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_loadDictionary_advanced))]
2418pub unsafe extern "C" fn ZSTD_DCtx_loadDictionary_advanced(
2419 dctx: *mut ZSTD_DCtx,
2420 dict: *const core::ffi::c_void,
2421 dictSize: size_t,
2422 dictLoadMethod: ZSTD_dictLoadMethod_e,
2423 dictContentType: ZSTD_dictContentType_e,
2424) -> size_t {
2425 if (*dctx).streamStage != StreamStage::Init {
2426 return Error::stage_wrong.to_error_code();
2427 }
2428 ZSTD_clearDict(dctx);
2429 if !dict.is_null() && dictSize != 0 {
2430 (*dctx).ddictLocal = ZSTD_createDDict_advanced(
2431 dict,
2432 dictSize,
2433 dictLoadMethod,
2434 dictContentType,
2435 (*dctx).customMem,
2436 );
2437 if ((*dctx).ddictLocal).is_null() {
2438 return Error::memory_allocation.to_error_code();
2439 }
2440 (*dctx).ddict = (*dctx).ddictLocal;
2441 (*dctx).dictUses = ZSTD_use_indefinitely;
2442 }
2443 0
2444}
2445#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_loadDictionary_byReference))]
2446pub unsafe extern "C" fn ZSTD_DCtx_loadDictionary_byReference(
2447 dctx: *mut ZSTD_DCtx,
2448 dict: *const core::ffi::c_void,
2449 dictSize: size_t,
2450) -> size_t {
2451 ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto)
2452}
2453#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_loadDictionary))]
2454pub unsafe extern "C" fn ZSTD_DCtx_loadDictionary(
2455 dctx: *mut ZSTD_DCtx,
2456 dict: *const core::ffi::c_void,
2457 dictSize: size_t,
2458) -> size_t {
2459 ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto)
2460}
2461#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_refPrefix_advanced))]
2462pub unsafe extern "C" fn ZSTD_DCtx_refPrefix_advanced(
2463 dctx: *mut ZSTD_DCtx,
2464 prefix: *const core::ffi::c_void,
2465 prefixSize: size_t,
2466 dictContentType: ZSTD_dictContentType_e,
2467) -> size_t {
2468 let err_code = ZSTD_DCtx_loadDictionary_advanced(
2469 dctx,
2470 prefix,
2471 prefixSize,
2472 ZSTD_dlm_byRef,
2473 dictContentType,
2474 );
2475 if ERR_isError(err_code) {
2476 return err_code;
2477 }
2478 (*dctx).dictUses = ZSTD_use_once;
2479 0
2480}
2481#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_refPrefix))]
2482pub unsafe extern "C" fn ZSTD_DCtx_refPrefix(
2483 dctx: *mut ZSTD_DCtx,
2484 prefix: *const core::ffi::c_void,
2485 prefixSize: size_t,
2486) -> size_t {
2487 ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent)
2488}
2489#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_initDStream_usingDict))]
2490pub unsafe extern "C" fn ZSTD_initDStream_usingDict(
2491 zds: *mut ZSTD_DStream,
2492 dict: *const core::ffi::c_void,
2493 dictSize: size_t,
2494) -> size_t {
2495 let err_code = ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
2496 if ERR_isError(err_code) {
2497 return err_code;
2498 }
2499 let err_code_0 = ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
2500 if ERR_isError(err_code_0) {
2501 return err_code_0;
2502 }
2503 ZSTD_startingInputLength((*zds).format)
2504}
2505#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_initDStream))]
2506pub unsafe extern "C" fn ZSTD_initDStream(zds: *mut ZSTD_DStream) -> size_t {
2507 let err_code = ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
2508 if ERR_isError(err_code) {
2509 return err_code;
2510 }
2511 let err_code_0 = ZSTD_DCtx_refDDict(zds, core::ptr::null::<ZSTD_DDict>());
2512 if ERR_isError(err_code_0) {
2513 return err_code_0;
2514 }
2515 ZSTD_startingInputLength((*zds).format)
2516}
2517#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_initDStream_usingDDict))]
2518pub unsafe extern "C" fn ZSTD_initDStream_usingDDict(
2519 dctx: *mut ZSTD_DStream,
2520 ddict: *const ZSTD_DDict,
2521) -> size_t {
2522 let err_code = ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
2523 if ERR_isError(err_code) {
2524 return err_code;
2525 }
2526 let err_code_0 = ZSTD_DCtx_refDDict(dctx, ddict);
2527 if ERR_isError(err_code_0) {
2528 return err_code_0;
2529 }
2530 ZSTD_startingInputLength((*dctx).format)
2531}
2532#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_resetDStream))]
2533pub unsafe extern "C" fn ZSTD_resetDStream(dctx: *mut ZSTD_DStream) -> size_t {
2534 let err_code = ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
2535 if ERR_isError(err_code) {
2536 return err_code;
2537 }
2538 ZSTD_startingInputLength((*dctx).format)
2539}
2540
2541#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_refDDict))]
2542pub unsafe extern "C" fn ZSTD_DCtx_refDDict(
2543 dctx: *mut ZSTD_DCtx,
2544 ddict: *const ZSTD_DDict,
2545) -> size_t {
2546 if (*dctx).streamStage != StreamStage::Init {
2547 return Error::stage_wrong.to_error_code();
2548 }
2549 ZSTD_clearDict(dctx);
2550
2551 if !ddict.is_null() {
2552 (*dctx).ddict = ddict;
2553 (*dctx).dictUses = ZSTD_use_indefinitely;
2554 if (*dctx).refMultipleDDicts == MultipleDDicts::Multiple {
2555 if ((*dctx).ddictSet).is_null() {
2556 (*dctx).ddictSet = ZSTD_createDDictHashSet((*dctx).customMem);
2557 }
2558
2559 let Some(ddictSet) = (*dctx).ddictSet.as_mut() else {
2560 return Error::memory_allocation.to_error_code();
2561 };
2562
2563 let err_code = ZSTD_DDictHashSet_addDDict(ddictSet, ddict, (*dctx).customMem);
2564 if ERR_isError(err_code) {
2565 return err_code;
2566 }
2567 }
2568 }
2569
2570 0
2571}
2572
2573#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_setMaxWindowSize))]
2574pub unsafe extern "C" fn ZSTD_DCtx_setMaxWindowSize(
2575 dctx: *mut ZSTD_DCtx,
2576 maxWindowSize: size_t,
2577) -> size_t {
2578 let bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
2579 let min = (1) << bounds.lowerBound;
2580 let max = (1) << bounds.upperBound;
2581 if (*dctx).streamStage != StreamStage::Init {
2582 return Error::stage_wrong.to_error_code();
2583 }
2584 if maxWindowSize < min {
2585 return Error::parameter_outOfBound.to_error_code();
2586 }
2587 if maxWindowSize > max {
2588 return Error::parameter_outOfBound.to_error_code();
2589 }
2590 (*dctx).maxWindowSize = maxWindowSize;
2591 0
2592}
2593#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_setFormat))]
2594pub unsafe extern "C" fn ZSTD_DCtx_setFormat(
2595 dctx: *mut ZSTD_DCtx,
2596 format: ZSTD_format_e,
2597) -> size_t {
2598 ZSTD_DCtx_setParameter(
2599 dctx,
2600 ZSTD_d_format as ZSTD_dParameter,
2601 format as core::ffi::c_int,
2602 )
2603}
2604#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_dParam_getBounds))]
2605pub unsafe extern "C" fn ZSTD_dParam_getBounds(dParam: ZSTD_dParameter) -> ZSTD_bounds {
2606 let mut bounds = {
2607 ZSTD_bounds {
2608 error: 0,
2609 lowerBound: 0,
2610 upperBound: 0,
2611 }
2612 };
2613 match dParam as core::ffi::c_uint {
2614 100 => {
2615 bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
2616 bounds.upperBound = if ::core::mem::size_of::<size_t>() == 4 {
2617 ZSTD_WINDOWLOG_MAX_32
2618 } else {
2619 ZSTD_WINDOWLOG_MAX_64
2620 };
2621 return bounds;
2622 }
2623 1000 => {
2624 bounds.lowerBound = Format::ZSTD_f_zstd1 as core::ffi::c_int;
2625 bounds.upperBound = Format::ZSTD_f_zstd1_magicless as core::ffi::c_int;
2626 return bounds;
2627 }
2628 1001 => {
2629 bounds.lowerBound = BufferMode::Buffered as core::ffi::c_int;
2630 bounds.upperBound = BufferMode::Stable as core::ffi::c_int;
2631 return bounds;
2632 }
2633 1002 => {
2634 bounds.lowerBound = ZSTD_d_validateChecksum as core::ffi::c_int;
2635 bounds.upperBound = ZSTD_d_ignoreChecksum as core::ffi::c_int;
2636 return bounds;
2637 }
2638 1003 => {
2639 bounds.lowerBound = MultipleDDicts::Single as core::ffi::c_int;
2640 bounds.upperBound = MultipleDDicts::Multiple as core::ffi::c_int;
2641 return bounds;
2642 }
2643 1004 => {
2644 bounds.lowerBound = 0;
2645 bounds.upperBound = 1;
2646 return bounds;
2647 }
2648 1005 => {
2649 bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
2650 bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
2651 return bounds;
2652 }
2653 _ => {}
2654 }
2655 bounds.error = Error::parameter_unsupported.to_error_code();
2656 bounds
2657}
2658unsafe fn ZSTD_dParam_withinBounds(
2659 dParam: ZSTD_dParameter,
2660 value: core::ffi::c_int,
2661) -> core::ffi::c_int {
2662 let bounds = ZSTD_dParam_getBounds(dParam);
2663 if ERR_isError(bounds.error) {
2664 return 0;
2665 }
2666 if value < bounds.lowerBound {
2667 return 0;
2668 }
2669 if value > bounds.upperBound {
2670 return 0;
2671 }
2672 1
2673}
2674
2675#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_getParameter))]
2676pub unsafe extern "C" fn ZSTD_DCtx_getParameter(
2677 dctx: *mut ZSTD_DCtx,
2678 param: ZSTD_dParameter,
2679 value: *mut core::ffi::c_int,
2680) -> size_t {
2681 match param as core::ffi::c_uint {
2682 100 => {
2683 *value = (*dctx).maxWindowSize.ilog2() as i32;
2684 0
2685 }
2686 1000 => {
2687 *value = (*dctx).format as core::ffi::c_int;
2688 0
2689 }
2690 1001 => {
2691 *value = (*dctx).outBufferMode as core::ffi::c_int;
2692 0
2693 }
2694 1002 => {
2695 *value = (*dctx).forceIgnoreChecksum as core::ffi::c_int;
2696 0
2697 }
2698 1003 => {
2699 *value = (*dctx).refMultipleDDicts as core::ffi::c_int;
2700 0
2701 }
2702 1004 => {
2703 *value = (*dctx).disableHufAsm;
2704 0
2705 }
2706 1005 => {
2707 *value = (*dctx).maxBlockSizeParam;
2708 0
2709 }
2710 _ => Error::parameter_unsupported.to_error_code(),
2711 }
2712}
2713
2714#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_setParameter))]
2715pub unsafe extern "C" fn ZSTD_DCtx_setParameter(
2716 dctx: *mut ZSTD_DCtx,
2717 dParam: ZSTD_dParameter,
2718 mut value: core::ffi::c_int,
2719) -> size_t {
2720 if (*dctx).streamStage != StreamStage::Init {
2721 return Error::stage_wrong.to_error_code();
2722 }
2723 match dParam as core::ffi::c_uint {
2724 100 => {
2725 if value == 0 {
2726 value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
2727 }
2728 if ZSTD_dParam_withinBounds(ZSTD_d_windowLogMax, value) == 0 {
2729 return Error::parameter_outOfBound.to_error_code();
2730 }
2731 (*dctx).maxWindowSize = (1) << value;
2732 return 0;
2733 }
2734 1000 => {
2735 let Ok(format) = Format::try_from(value as ZSTD_format_e) else {
2736 return Error::parameter_outOfBound.to_error_code();
2737 };
2738
2739 (*dctx).format = format;
2740
2741 return 0;
2742 }
2743 1001 => {
2744 let Ok(value) = BufferMode::try_from(value as u32) else {
2745 return Error::parameter_outOfBound.to_error_code();
2746 };
2747 (*dctx).outBufferMode = value;
2748 return 0;
2749 }
2750 1002 => {
2751 if ZSTD_dParam_withinBounds(ZSTD_d_experimentalParam3, value) == 0 {
2752 return Error::parameter_outOfBound.to_error_code();
2753 }
2754 (*dctx).forceIgnoreChecksum = value as ZSTD_forceIgnoreChecksum_e;
2755 return 0;
2756 }
2757 1003 => {
2758 let Ok(value) = MultipleDDicts::try_from(value as u32) else {
2759 return Error::parameter_outOfBound.to_error_code();
2760 };
2761 if (*dctx).staticSize != 0 {
2762 return Error::parameter_unsupported.to_error_code();
2763 }
2764 (*dctx).refMultipleDDicts = value;
2765 return 0;
2766 }
2767 1004 => {
2768 if ZSTD_dParam_withinBounds(ZSTD_d_experimentalParam5, value) == 0 {
2769 return Error::parameter_outOfBound.to_error_code();
2770 }
2771 (*dctx).disableHufAsm = (value != 0) as core::ffi::c_int;
2772 return 0;
2773 }
2774 1005 => {
2775 if value != 0 && ZSTD_dParam_withinBounds(ZSTD_d_experimentalParam6, value) == 0 {
2776 return Error::parameter_outOfBound.to_error_code();
2777 }
2778 (*dctx).maxBlockSizeParam = value;
2779 return 0;
2780 }
2781 _ => {}
2782 }
2783 Error::parameter_unsupported.to_error_code()
2784}
2785#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_DCtx_reset))]
2786pub unsafe extern "C" fn ZSTD_DCtx_reset(
2787 dctx: *mut ZSTD_DCtx,
2788 reset: ZSTD_ResetDirective,
2789) -> size_t {
2790 if reset as core::ffi::c_uint
2791 == ZSTD_reset_session_only as core::ffi::c_int as core::ffi::c_uint
2792 || reset as core::ffi::c_uint
2793 == ZSTD_reset_session_and_parameters as core::ffi::c_int as core::ffi::c_uint
2794 {
2795 (*dctx).streamStage = StreamStage::Init;
2796 (*dctx).noForwardProgress = 0;
2797 (*dctx).isFrameDecompression = 1;
2798 }
2799 if reset as core::ffi::c_uint == ZSTD_reset_parameters as core::ffi::c_int as core::ffi::c_uint
2800 || reset as core::ffi::c_uint
2801 == ZSTD_reset_session_and_parameters as core::ffi::c_int as core::ffi::c_uint
2802 {
2803 if (*dctx).streamStage != StreamStage::Init {
2804 return Error::stage_wrong.to_error_code();
2805 }
2806 ZSTD_clearDict(dctx);
2807 ZSTD_DCtx_resetParameters(dctx);
2808 }
2809 0
2810}
2811#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_sizeof_DStream))]
2812pub unsafe extern "C" fn ZSTD_sizeof_DStream(dctx: *const ZSTD_DStream) -> size_t {
2813 ZSTD_sizeof_DCtx(dctx)
2814}
2815unsafe fn ZSTD_decodingBufferSize_internal(
2816 windowSize: core::ffi::c_ulonglong,
2817 frameContentSize: core::ffi::c_ulonglong,
2818 blockSizeMax: size_t,
2819) -> size_t {
2820 let blockSize = if ((if windowSize < ((1) << 17) as core::ffi::c_ulonglong {
2821 windowSize
2822 } else {
2823 ((1) << 17) as core::ffi::c_ulonglong
2824 }) as size_t)
2825 < blockSizeMax
2826 {
2827 (if windowSize < ((1) << 17) as core::ffi::c_ulonglong {
2828 windowSize
2829 } else {
2830 ((1) << 17) as core::ffi::c_ulonglong
2831 }) as size_t
2832 } else {
2833 blockSizeMax
2834 };
2835 let neededRBSize = windowSize
2836 .wrapping_add((blockSize * 2) as core::ffi::c_ulonglong)
2837 .wrapping_add((WILDCOPY_OVERLENGTH * 2) as core::ffi::c_ulonglong);
2838 let neededSize = if frameContentSize < neededRBSize {
2839 frameContentSize
2840 } else {
2841 neededRBSize
2842 };
2843 let minRBSize = neededSize as size_t;
2844 if minRBSize as core::ffi::c_ulonglong != neededSize {
2845 return Error::frameParameter_windowTooLarge.to_error_code();
2846 }
2847 minRBSize
2848}
2849#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decodingBufferSize_min))]
2850pub unsafe extern "C" fn ZSTD_decodingBufferSize_min(
2851 windowSize: core::ffi::c_ulonglong,
2852 frameContentSize: core::ffi::c_ulonglong,
2853) -> size_t {
2854 ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX as size_t)
2855}
2856#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_estimateDStreamSize))]
2857pub unsafe extern "C" fn ZSTD_estimateDStreamSize(windowSize: size_t) -> size_t {
2858 let blockSize = if windowSize < ((1) << 17) as size_t {
2859 windowSize
2860 } else {
2861 ((1) << 17) as size_t
2862 };
2863 let inBuffSize = blockSize;
2864 let outBuffSize = ZSTD_decodingBufferSize_min(
2865 windowSize as core::ffi::c_ulonglong,
2866 ZSTD_CONTENTSIZE_UNKNOWN,
2867 );
2868 (ZSTD_estimateDCtxSize())
2869 .wrapping_add(inBuffSize)
2870 .wrapping_add(outBuffSize)
2871}
2872#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_estimateDStreamSize_fromFrame))]
2873pub unsafe extern "C" fn ZSTD_estimateDStreamSize_fromFrame(
2874 src: *const core::ffi::c_void,
2875 srcSize: size_t,
2876) -> size_t {
2877 let windowSizeMax = (1)
2878 << (if ::core::mem::size_of::<size_t>() == 4 {
2879 ZSTD_WINDOWLOG_MAX_32
2880 } else {
2881 ZSTD_WINDOWLOG_MAX_64
2882 });
2883 let mut zfh = ZSTD_FrameHeader {
2884 frameContentSize: 0,
2885 windowSize: 0,
2886 blockSizeMax: 0,
2887 frameType: ZSTD_frame,
2888 headerSize: 0,
2889 dictID: 0,
2890 checksumFlag: 0,
2891 _reserved1: 0,
2892 _reserved2: 0,
2893 };
2894 let err = ZSTD_getFrameHeader(&mut zfh, src, srcSize);
2895 if ERR_isError(err) {
2896 return err;
2897 }
2898 if err > 0 {
2899 return Error::srcSize_wrong.to_error_code();
2900 }
2901 if zfh.windowSize > windowSizeMax as core::ffi::c_ulonglong {
2902 return Error::frameParameter_windowTooLarge.to_error_code();
2903 }
2904 ZSTD_estimateDStreamSize(zfh.windowSize as size_t)
2905}
2906unsafe fn ZSTD_DCtx_isOverflow(
2907 zds: *mut ZSTD_DStream,
2908 neededInBuffSize: size_t,
2909 neededOutBuffSize: size_t,
2910) -> core::ffi::c_int {
2911 (((*zds).inBuffSize).wrapping_add((*zds).outBuffSize)
2912 >= neededInBuffSize.wrapping_add(neededOutBuffSize)
2913 * ZSTD_WORKSPACETOOLARGE_FACTOR as size_t) as core::ffi::c_int
2914}
2915unsafe fn ZSTD_DCtx_updateOversizedDuration(
2916 zds: *mut ZSTD_DStream,
2917 neededInBuffSize: size_t,
2918 neededOutBuffSize: size_t,
2919) {
2920 if ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize) != 0 {
2921 (*zds).oversizedDuration = ((*zds).oversizedDuration).wrapping_add(1);
2922 (*zds).oversizedDuration;
2923 } else {
2924 (*zds).oversizedDuration = 0;
2925 };
2926}
2927unsafe fn ZSTD_DCtx_isOversizedTooLong(zds: *mut ZSTD_DStream) -> core::ffi::c_int {
2928 ((*zds).oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION as size_t) as core::ffi::c_int
2929}
2930unsafe fn ZSTD_checkOutBuffer(zds: *const ZSTD_DStream, output: *const ZSTD_outBuffer) -> size_t {
2931 if (*zds).outBufferMode != BufferMode::Stable {
2932 return 0;
2933 }
2934 if (*zds).streamStage == StreamStage::Init {
2935 return 0;
2936 }
2937 let expect = (*zds).expectedOutBuffer;
2938 if expect.dst == (*output).dst && expect.pos == (*output).pos && expect.size == (*output).size {
2939 return 0;
2940 }
2941 Error::dstBuffer_wrong.to_error_code()
2942}
2943unsafe fn ZSTD_decompressContinueStream(
2944 zds: *mut ZSTD_DStream,
2945 op: *mut *mut core::ffi::c_char,
2946 oend: *mut core::ffi::c_char,
2947 src: *const core::ffi::c_void,
2948 srcSize: size_t,
2949) -> size_t {
2950 let isSkipFrame = ZSTD_isSkipFrame(zds);
2951 if (*zds).outBufferMode == BufferMode::Buffered {
2952 let dstSize = if isSkipFrame != 0 {
2953 0
2954 } else {
2955 ((*zds).outBuffSize).wrapping_sub((*zds).outStart)
2956 };
2957 let decodedSize = ZSTD_decompressContinue(
2958 zds,
2959 ((*zds).outBuff).add((*zds).outStart) as *mut core::ffi::c_void,
2960 dstSize,
2961 src,
2962 srcSize,
2963 );
2964 let err_code = decodedSize;
2965 if ERR_isError(err_code) {
2966 return err_code;
2967 }
2968 if decodedSize == 0 && isSkipFrame == 0 {
2969 (*zds).streamStage = StreamStage::Read;
2970 } else {
2971 (*zds).outEnd = ((*zds).outStart).wrapping_add(decodedSize);
2972 (*zds).streamStage = StreamStage::Flush;
2973 }
2974 } else {
2975 let dstSize_0 = if isSkipFrame != 0 {
2976 0
2977 } else {
2978 oend.offset_from(*op) as size_t
2979 };
2980 let decodedSize_0 =
2981 ZSTD_decompressContinue(zds, *op as *mut core::ffi::c_void, dstSize_0, src, srcSize);
2982 let err_code_0 = decodedSize_0;
2983 if ERR_isError(err_code_0) {
2984 return err_code_0;
2985 }
2986 *op = (*op).add(decodedSize_0);
2987 (*zds).streamStage = StreamStage::Read;
2988 }
2989 0
2990}
2991
2992#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressStream))]
2993pub unsafe extern "C" fn ZSTD_decompressStream(
2994 zds: *mut ZSTD_DStream,
2995 output: *mut ZSTD_outBuffer,
2996 input: *mut ZSTD_inBuffer,
2997) -> size_t {
2998 let output = output.as_mut().unwrap();
2999 let input = input.as_mut().unwrap();
3000
3001 let src = input.src as *const core::ffi::c_char;
3002 let istart = if input.pos != 0 {
3003 src.add(input.pos)
3004 } else {
3005 src
3006 };
3007 let iend = if input.size != 0 {
3008 src.add(input.size)
3009 } else {
3010 src
3011 };
3012 let mut ip = istart;
3013 let dst = output.dst as *mut core::ffi::c_char;
3014 let ostart = if output.pos != 0 {
3015 dst.add(output.pos)
3016 } else {
3017 dst
3018 };
3019 let oend = if output.size != 0 {
3020 dst.add(output.size)
3021 } else {
3022 dst
3023 };
3024 let mut op = ostart;
3025 let mut some_more_work = true;
3026 if input.pos > input.size {
3027 return Error::srcSize_wrong.to_error_code();
3028 }
3029 if output.pos > output.size {
3030 return Error::dstSize_tooSmall.to_error_code();
3031 }
3032 let err_code = ZSTD_checkOutBuffer(zds, output);
3033 if ERR_isError(err_code) {
3034 return err_code;
3035 }
3036
3037 while some_more_work {
3038 #[derive(Eq, PartialEq)]
3039 enum Block {
3040 LoadHeader,
3041 Read,
3042 Load,
3043 }
3044 let mut current_block: Block;
3045 match (*zds).streamStage {
3046 StreamStage::Init => {
3047 (*zds).streamStage = StreamStage::LoadHeader;
3048 (*zds).outEnd = 0;
3049 (*zds).outStart = (*zds).outEnd;
3050 (*zds).inPos = (*zds).outStart;
3051 (*zds).lhSize = (*zds).inPos;
3052 (*zds).legacyVersion = 0;
3053 (*zds).hostageByte = 0;
3054 (*zds).expectedOutBuffer = *output;
3055 current_block = Block::LoadHeader;
3056 }
3057 StreamStage::LoadHeader => {
3058 current_block = Block::LoadHeader;
3059 }
3060 StreamStage::Read => {
3061 current_block = Block::Read;
3062 }
3063 StreamStage::Load => {
3064 current_block = Block::Load;
3065 }
3066 StreamStage::Flush => {
3067 let toFlushSize = ((*zds).outEnd).wrapping_sub((*zds).outStart);
3068 let flushedSize = ZSTD_limitCopy(
3069 op as *mut core::ffi::c_void,
3070 oend.offset_from(op) as size_t,
3071 ((*zds).outBuff).add((*zds).outStart) as *const core::ffi::c_void,
3072 toFlushSize,
3073 );
3074
3075 op = if !op.is_null() {
3076 op.add(flushedSize)
3077 } else {
3078 op
3079 };
3080
3081 (*zds).outStart = ((*zds).outStart).wrapping_add(flushedSize);
3082 if flushedSize == toFlushSize {
3083 (*zds).streamStage = StreamStage::Read;
3085 if ((*zds).outBuffSize as core::ffi::c_ulonglong)
3086 < (*zds).fParams.frameContentSize
3087 && ((*zds).outStart).wrapping_add((*zds).fParams.blockSizeMax as size_t)
3088 > (*zds).outBuffSize
3089 {
3090 (*zds).outEnd = 0;
3091 (*zds).outStart = 0;
3092 }
3093 continue;
3094 }
3095
3096 some_more_work = false;
3098 continue;
3099 }
3100 }
3101 if current_block == Block::LoadHeader {
3102 drop(current_block);
3103
3104 if (*zds).legacyVersion != 0 {
3105 if (*zds).staticSize != 0 {
3106 return Error::memory_allocation.to_error_code();
3107 }
3108 let hint = ZSTD_decompressLegacyStream(
3109 (*zds).legacyContext,
3110 (*zds).legacyVersion,
3111 output,
3112 input,
3113 );
3114 if hint == 0 {
3115 (*zds).streamStage = StreamStage::Init;
3116 }
3117 return hint;
3118 }
3119
3120 let hSize = get_frame_header_advanced(
3121 &mut (*zds).fParams,
3122 &(&(*zds).headerBuffer)[..(*zds).lhSize],
3123 (*zds).format,
3124 );
3125 if (*zds).refMultipleDDicts != MultipleDDicts::Single && !(*zds).ddictSet.is_null() {
3126 ZSTD_DCtx_selectFrameDDict(zds);
3127 }
3128 if ERR_isError(hSize) {
3129 let legacyVersion = ZSTD_isLegacy(
3130 istart as *const core::ffi::c_void,
3131 iend.offset_from(istart) as size_t,
3132 );
3133 if legacyVersion != 0 {
3134 let ddict = ZSTD_getDDict(zds);
3135 let dict = if !ddict.is_null() {
3136 ZSTD_DDict_dictContent(ddict)
3137 } else {
3138 core::ptr::null()
3139 };
3140 let dictSize = if !ddict.is_null() {
3141 ZSTD_DDict_dictSize(ddict)
3142 } else {
3143 0
3144 };
3145 if (*zds).staticSize != 0 {
3146 return Error::memory_allocation.to_error_code();
3147 }
3148 let err_code = ZSTD_initLegacyStream(
3149 &mut (*zds).legacyContext,
3150 (*zds).previousLegacyVersion,
3151 legacyVersion,
3152 dict,
3153 dictSize,
3154 );
3155 if ERR_isError(err_code) {
3156 return err_code;
3157 }
3158 (*zds).previousLegacyVersion = legacyVersion;
3159 (*zds).legacyVersion = (*zds).previousLegacyVersion;
3160 let hint = ZSTD_decompressLegacyStream(
3161 (*zds).legacyContext,
3162 legacyVersion,
3163 output,
3164 input,
3165 );
3166 if hint == 0 {
3167 (*zds).streamStage = StreamStage::Init;
3168 }
3169 return hint;
3170 }
3171
3172 return hSize;
3174 }
3175
3176 if hSize != 0 {
3177 let toLoad = hSize - (*zds).lhSize; let remainingInput = iend.offset_from(ip) as size_t;
3180 if toLoad > remainingInput {
3181 if remainingInput > 0 {
3183 libc::memcpy(
3184 ((*zds).headerBuffer).as_mut_ptr().add((*zds).lhSize)
3185 as *mut core::ffi::c_void,
3186 ip as *const core::ffi::c_void,
3187 remainingInput as libc::size_t,
3188 );
3189 (*zds).lhSize = ((*zds).lhSize).wrapping_add(remainingInput);
3190 }
3191 input.pos = input.size;
3192 let err_code = get_frame_header_advanced(
3194 &mut (*zds).fParams,
3195 &(&(*zds).headerBuffer)[..(*zds).lhSize],
3196 (*zds).format,
3197 );
3198 if ERR_isError(err_code) {
3199 return err_code;
3200 }
3201 return std::cmp::max(ZSTD_FRAMEHEADERSIZE_MIN((*zds).format), hSize)
3203 .wrapping_sub((*zds).lhSize)
3204 .wrapping_add(ZSTD_blockHeaderSize);
3205 }
3206 assert!(!ip.is_null());
3207 libc::memcpy(
3208 ((*zds).headerBuffer).as_mut_ptr().add((*zds).lhSize) as *mut core::ffi::c_void,
3209 ip as *const core::ffi::c_void,
3210 toLoad as libc::size_t,
3211 );
3212 (*zds).lhSize = hSize;
3213 ip = ip.add(toLoad);
3214 continue;
3215 } else {
3216 if (*zds).fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
3218 && (*zds).fParams.frameType != ZSTD_skippableFrame
3219 && oend.offset_from(op) as size_t as core::ffi::c_ulonglong
3220 >= (*zds).fParams.frameContentSize
3221 {
3222 let cSize = ZSTD_findFrameCompressedSize_advanced(
3223 core::slice::from_raw_parts(
3224 istart.cast(),
3225 iend.offset_from(istart) as usize,
3226 ),
3227 (*zds).format,
3228 );
3229 if cSize <= iend.offset_from(istart) as size_t {
3230 let decompressedSize = ZSTD_decompress_usingDDict(
3231 zds,
3232 op as *mut core::ffi::c_void,
3233 oend.offset_from(op) as size_t,
3234 istart as *const core::ffi::c_void,
3235 cSize,
3236 ZSTD_getDDict(zds),
3237 );
3238 if ERR_isError(decompressedSize) {
3239 return decompressedSize;
3240 }
3241 assert!(!istart.is_null());
3242 ip = istart.add(cSize);
3243 op = if !op.is_null() {
3244 op.add(decompressedSize)
3245 } else {
3246 op
3248 };
3249 (*zds).expected = 0;
3250 (*zds).streamStage = StreamStage::Init;
3251 some_more_work = false;
3252 continue;
3253 }
3254 }
3255
3256 if (*zds).outBufferMode == BufferMode::Stable
3258 && (*zds).fParams.frameType != ZSTD_skippableFrame
3259 && (*zds).fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
3260 && (oend.offset_from(op) as size_t as core::ffi::c_ulonglong)
3261 < (*zds).fParams.frameContentSize
3262 {
3263 return Error::dstSize_tooSmall.to_error_code();
3264 }
3265 let err_code = ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds));
3266 if ERR_isError(err_code) {
3267 return err_code;
3268 }
3269 if (*zds).format == Format::ZSTD_f_zstd1
3270 && MEM_readLE32(((*zds).headerBuffer).as_mut_ptr() as *const core::ffi::c_void)
3271 & ZSTD_MAGIC_SKIPPABLE_MASK
3272 == ZSTD_MAGIC_SKIPPABLE_START as core::ffi::c_uint
3273 {
3274 (*zds).expected =
3276 MEM_readLE32(((*zds).headerBuffer).as_mut_ptr().add(ZSTD_FRAMEIDSIZE)
3277 as *const core::ffi::c_void) as size_t;
3278 (*zds).stage = DecompressStage::SkipFrame;
3279 } else {
3280 let err_code =
3281 ZSTD_decodeFrameHeader(zds, &((&(*zds).headerBuffer)[..(*zds).lhSize]));
3282 if ERR_isError(err_code) {
3283 return err_code;
3284 }
3285 (*zds).expected = ZSTD_blockHeaderSize;
3286 (*zds).stage = DecompressStage::DecodeBlockHeader;
3287 }
3288
3289 (*zds).fParams.windowSize = std::cmp::min(
3291 (*zds).fParams.windowSize,
3292 (1 << ZSTD_WINDOWLOG_ABSOLUTEMIN) as core::ffi::c_ulonglong,
3293 );
3294 if (*zds).fParams.windowSize > (*zds).maxWindowSize as core::ffi::c_ulonglong {
3295 return Error::frameParameter_windowTooLarge.to_error_code();
3296 }
3297 if (*zds).maxBlockSizeParam != 0 {
3298 (*zds).fParams.blockSizeMax = std::cmp::min(
3299 (*zds).fParams.blockSizeMax,
3300 (*zds).maxBlockSizeParam as core::ffi::c_uint,
3301 );
3302 }
3303
3304 let neededInBuffSize = std::cmp::max((*zds).fParams.blockSizeMax, 4) as size_t;
3306 let neededOutBuffSize = if (*zds).outBufferMode == BufferMode::Buffered {
3307 ZSTD_decodingBufferSize_internal(
3308 (*zds).fParams.windowSize,
3309 (*zds).fParams.frameContentSize,
3310 (*zds).fParams.blockSizeMax as size_t,
3311 )
3312 } else {
3313 0
3314 };
3315
3316 ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
3317
3318 let tooSmall = ((*zds).inBuffSize < neededInBuffSize
3319 || (*zds).outBuffSize < neededOutBuffSize)
3320 as core::ffi::c_int;
3321 let tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
3322
3323 if tooSmall != 0 || tooLarge != 0 {
3324 let bufferSize = neededInBuffSize.wrapping_add(neededOutBuffSize);
3325 if (*zds).staticSize != 0 {
3326 assert!((*zds).staticSize >= size_of::<ZSTD_DCtx>()); if bufferSize > (*zds).staticSize - size_of::<ZSTD_DCtx>() {
3329 return Error::dictionary_corrupted.to_error_code();
3330 }
3331 } else {
3332 ZSTD_customFree((*zds).inBuff as *mut core::ffi::c_void, (*zds).customMem);
3333 (*zds).inBuffSize = 0;
3334 (*zds).outBuffSize = 0;
3335 (*zds).inBuff = ZSTD_customMalloc(bufferSize, (*zds).customMem)
3336 as *mut core::ffi::c_char;
3337 if (*zds).inBuff.is_null() {
3338 return Error::dictionary_corrupted.to_error_code();
3339 }
3340 }
3341 (*zds).inBuffSize = neededInBuffSize;
3342 (*zds).outBuff = ((*zds).inBuff).add((*zds).inBuffSize);
3343 (*zds).outBuffSize = neededOutBuffSize;
3344 }
3345 (*zds).streamStage = StreamStage::Read;
3346 current_block = Block::Read;
3347 }
3348 }
3349
3350 if current_block == Block::Read {
3351 drop(current_block);
3352
3353 let neededInSize =
3354 ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend.offset_from(ip) as size_t);
3355 if neededInSize == 0 {
3356 (*zds).streamStage = StreamStage::Init;
3357 some_more_work = false;
3358 continue;
3359 } else if iend.offset_from(ip) as size_t >= neededInSize {
3360 let err_code_4 = ZSTD_decompressContinueStream(
3362 zds,
3363 &mut op,
3364 oend,
3365 ip as *const core::ffi::c_void,
3366 neededInSize,
3367 );
3368 if ERR_isError(err_code_4) {
3369 return err_code_4;
3370 }
3371 assert!(!ip.is_null());
3372 ip = ip.add(neededInSize);
3373 continue;
3375 } else if ip == iend {
3376 some_more_work = false;
3378 continue;
3379 } else {
3380 (*zds).streamStage = StreamStage::Load;
3381 current_block = Block::Load;
3382 }
3383 }
3384
3385 if current_block == Block::Load {
3386 drop(current_block);
3387
3388 let neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
3389 let toLoad_0 = neededInSize.wrapping_sub((*zds).inPos);
3390 let isSkipFrame = ZSTD_isSkipFrame(zds);
3391 let mut loadedSize: size_t = 0;
3392 assert!(
3394 neededInSize
3395 == ZSTD_nextSrcSizeToDecompressWithInputSize(
3396 zds,
3397 iend.offset_from(ip) as usize
3398 )
3399 );
3400 if isSkipFrame != 0 {
3401 loadedSize = std::cmp::min(toLoad_0, iend.offset_from(ip) as size_t);
3402 } else {
3403 if toLoad_0 > ((*zds).inBuffSize).wrapping_sub((*zds).inPos) {
3404 return Error::corruption_detected.to_error_code();
3405 }
3406 loadedSize = ZSTD_limitCopy(
3407 ((*zds).inBuff).add((*zds).inPos) as *mut core::ffi::c_void,
3408 toLoad_0,
3409 ip as *const core::ffi::c_void,
3410 iend.offset_from(ip) as size_t,
3411 );
3412 }
3413 if loadedSize != 0 {
3414 ip = ip.add(loadedSize);
3416 (*zds).inPos = ((*zds).inPos).wrapping_add(loadedSize);
3417 }
3418 if loadedSize < toLoad_0 {
3419 some_more_work = false;
3421 } else {
3422 (*zds).inPos = 0; let err_code_5 = ZSTD_decompressContinueStream(
3425 zds,
3426 &mut op,
3427 oend,
3428 (*zds).inBuff as *const core::ffi::c_void,
3429 neededInSize,
3430 );
3431 if ERR_isError(err_code_5) {
3432 return err_code_5;
3433 }
3434 }
3436 }
3437 }
3438
3439 input.pos = ip.offset_from(input.src as *const core::ffi::c_char) as size_t;
3441 output.pos = op.offset_from(output.dst as *mut core::ffi::c_char) as size_t;
3442
3443 (*zds).expectedOutBuffer = *output;
3445
3446 if ip == istart && op == ostart {
3447 (*zds).noForwardProgress += 1;
3449 (*zds).noForwardProgress;
3450 if (*zds).noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX {
3451 if op == oend {
3452 return Error::noForwardProgress_destFull.to_error_code();
3453 }
3454 if ip == iend {
3455 return Error::noForwardProgress_inputEmpty.to_error_code();
3456 }
3457 unreachable!();
3458 }
3459 } else {
3460 (*zds).noForwardProgress = 0;
3461 }
3462
3463 let mut nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
3464 if nextSrcSizeHint == 0 {
3465 if (*zds).outEnd == (*zds).outStart {
3467 if (*zds).hostageByte != 0 {
3469 if input.pos >= input.size {
3470 (*zds).streamStage = StreamStage::Read;
3472 return 1;
3473 }
3474 input.pos = (input.pos).wrapping_add(1);
3476 }
3477 return 0;
3478 }
3479 if (*zds).hostageByte == 0 {
3480 input.pos = (input.pos).wrapping_sub(1);
3484 (*zds).hostageByte = 1;
3485 }
3486 return 1;
3487 }
3488 nextSrcSizeHint = nextSrcSizeHint.wrapping_add(
3490 ZSTD_blockHeaderSize
3491 * ((*zds).stage.to_next_input_type() == NextInputType::Block) as size_t,
3492 );
3493 assert!((*zds).inPos <= nextSrcSizeHint);
3494 nextSrcSizeHint = nextSrcSizeHint.wrapping_sub((*zds).inPos);
3496 nextSrcSizeHint
3497}
3498
3499#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressStream_simpleArgs))]
3500pub unsafe extern "C" fn ZSTD_decompressStream_simpleArgs(
3501 dctx: *mut ZSTD_DCtx,
3502 dst: *mut core::ffi::c_void,
3503 dstCapacity: size_t,
3504 dstPos: *mut size_t,
3505 src: *const core::ffi::c_void,
3506 srcSize: size_t,
3507 srcPos: *mut size_t,
3508) -> size_t {
3509 let mut output = ZSTD_outBuffer_s {
3510 dst: core::ptr::null_mut::<core::ffi::c_void>(),
3511 size: 0,
3512 pos: 0,
3513 };
3514 let mut input = ZSTD_inBuffer_s {
3515 src: core::ptr::null::<core::ffi::c_void>(),
3516 size: 0,
3517 pos: 0,
3518 };
3519 output.dst = dst;
3520 output.size = dstCapacity;
3521 output.pos = *dstPos;
3522 input.src = src;
3523 input.size = srcSize;
3524 input.pos = *srcPos;
3525 let cErr = ZSTD_decompressStream(dctx, &mut output, &mut input);
3526 *dstPos = output.pos;
3527 *srcPos = input.pos;
3528 cErr
3529}
3530
3531#[cfg(test)]
3532mod tests {
3533 use super::*;
3534 use quickcheck::quickcheck;
3535
3536 #[test]
3537 fn decompress_bound_null() {
3538 assert_eq!(unsafe { ZSTD_decompressBound(core::ptr::null(), 0) }, 0);
3539 }
3540
3541 quickcheck! {
3542 #[cfg(not(miri))]
3543 fn decompress_bound_quickcheck(input: Vec<u8>) -> bool {
3544 unsafe {
3545 let expected = zstd_sys::ZSTD_decompressBound(input.as_ptr().cast(), input.len() );
3546 let actual = super::ZSTD_decompressBound(input.as_ptr().cast(), input.len());
3547
3548 assert_eq!(expected, actual);
3549 expected == actual
3550 }
3551 }
3552 }
3553
3554 #[test]
3555 fn decompression_margin_null() {
3556 assert_eq!(unsafe { ZSTD_decompressionMargin(core::ptr::null(), 0) }, 0);
3557 }
3558
3559 quickcheck! {
3560 #[cfg(not(miri))]
3561 fn decompression_margin_quickcheck(input: Vec<u8>) -> bool {
3562 unsafe {
3563 let expected = zstd_sys::ZSTD_decompressionMargin(input.as_ptr().cast(), input.len() );
3564 let actual = super::ZSTD_decompressionMargin(input.as_ptr().cast(), input.len());
3565
3566 assert_eq!(expected, actual);
3567 expected == actual
3568 }
3569 }
3570 }
3571}