1use core::arch::asm;
2use core::ptr;
3
4use libc::{ptrdiff_t, size_t};
5
6use crate::lib::common::bitstream::BIT_DStream_t;
7use crate::lib::common::entropy_common::FSE_readNCount_slice;
8use crate::lib::common::error_private::{ERR_isError, Error};
9use crate::lib::common::huf::{HUF_flags_bmi2, HUF_flags_disableAsm};
10use crate::lib::common::mem::{MEM_32bits, MEM_64bits, MEM_readLE24};
11use crate::lib::common::zstd_internal::{
12 LLFSELog, LL_bits, MLFSELog, ML_bits, MaxFSELog, MaxLL, MaxLLBits, MaxML, MaxMLBits, MaxOff,
13 MaxSeq, OffFSELog, Overlap, ZSTD_copy16, ZSTD_wildcopy, LL_DEFAULTNORMLOG, ML_DEFAULTNORMLOG,
14 OF_DEFAULTNORMLOG, WILDCOPY_OVERLENGTH, WILDCOPY_VECLEN, ZSTD_REP_NUM,
15};
16use crate::lib::decompress::huf_decompress::{
17 HUF_decompress1X1_DCtx_wksp, HUF_decompress1X_usingDTable, HUF_decompress4X_usingDTable,
18};
19use crate::lib::decompress::huf_decompress::{HUF_decompress4X_hufOnly_wksp, Writer};
20use crate::lib::decompress::{blockProperties_t, BlockType, SymbolTable};
21use crate::lib::decompress::{
22 LL_base, LitLocation, ML_base, OF_base, OF_bits, Workspace, ZSTD_DCtx, ZSTD_DCtx_s,
23 ZSTD_seqSymbol, ZSTD_seqSymbol_header,
24};
25
26pub type BIT_DStream_status = core::ffi::c_uint;
27pub const BIT_DStream_overflow: BIT_DStream_status = 3;
28pub const BIT_DStream_completed: BIT_DStream_status = 2;
29pub const BIT_DStream_endOfBuffer: BIT_DStream_status = 1;
30pub const BIT_DStream_unfinished: BIT_DStream_status = 0;
31pub type C2RustUnnamed_0 = core::ffi::c_uint;
32
33pub type streaming_operation = core::ffi::c_uint;
34pub const is_streaming: streaming_operation = 1;
35pub const not_streaming: streaming_operation = 0;
36
37#[derive(Debug, Copy, Clone, PartialEq, Eq)]
38enum StreamingOperation {
39 NotStreaming = 0,
40 IsStreaming = 1,
41}
42
43impl TryFrom<u32> for StreamingOperation {
44 type Error = ();
45
46 fn try_from(value: u32) -> Result<Self, Self::Error> {
47 match value {
48 0 => Ok(Self::NotStreaming),
49 1 => Ok(Self::IsStreaming),
50 _ => Err(()),
51 }
52 }
53}
54
55#[derive(Debug, Copy, Clone, PartialEq, Eq)]
56enum Offset {
57 Regular = 0,
58 Long = 1,
59}
60
61#[repr(C)]
62pub struct seqState_t {
63 DStream: BIT_DStream_t,
64 stateLL: ZSTD_fseState,
65 stateOffb: ZSTD_fseState,
66 stateML: ZSTD_fseState,
67 prevOffset: [size_t; 3],
68}
69#[repr(C)]
70pub struct ZSTD_fseState {
71 pub state: size_t,
72 pub table: *const ZSTD_seqSymbol,
73}
74#[derive(Copy, Clone, Default)]
75#[repr(C)]
76pub struct seq_t {
77 pub litLength: size_t,
78 pub matchLength: size_t,
79 pub offset: size_t,
80}
81
82#[derive(Copy, Clone)]
83#[repr(C)]
84pub struct ZSTD_OffsetInfo {
85 pub longOffsetShare: core::ffi::c_uint,
86 pub maxNbAdditionalBits: core::ffi::c_uint,
87}
88
89#[repr(u32)]
90enum SymbolEncodingType_e {
91 set_basic = 0,
92 set_rle = 1,
93 set_compressed = 2,
94 set_repeat = 3,
95}
96
97impl TryFrom<u8> for SymbolEncodingType_e {
98 type Error = ();
99
100 fn try_from(value: u8) -> Result<Self, Self::Error> {
101 match value {
102 0 => Ok(SymbolEncodingType_e::set_basic),
103 1 => Ok(SymbolEncodingType_e::set_rle),
104 2 => Ok(SymbolEncodingType_e::set_compressed),
105 3 => Ok(SymbolEncodingType_e::set_repeat),
106 _ => Err(()),
107 }
108 }
109}
110
111pub const CACHELINE_SIZE: core::ffi::c_int = 64;
112
113#[inline]
114unsafe fn ZSTD_maybeNullPtrAdd(
115 ptr: *mut core::ffi::c_void,
116 add: ptrdiff_t,
117) -> *mut core::ffi::c_void {
118 if add > 0 {
119 (ptr as *mut core::ffi::c_char).offset(add) as *mut core::ffi::c_void
120 } else {
121 ptr
122 }
123}
124
125pub const STREAM_ACCUMULATOR_MIN: core::ffi::c_int = match size_of::<usize>() {
126 4 => STREAM_ACCUMULATOR_MIN_32,
127 8 => STREAM_ACCUMULATOR_MIN_64,
128 _ => unreachable!(),
129};
130pub const STREAM_ACCUMULATOR_MIN_32: core::ffi::c_int = 25;
131pub const STREAM_ACCUMULATOR_MIN_64: core::ffi::c_int = 57;
132
133pub const ZSTD_BLOCKSIZELOG_MAX: core::ffi::c_int = 17;
134pub const ZSTD_BLOCKSIZE_MAX: core::ffi::c_int = (1) << ZSTD_BLOCKSIZELOG_MAX;
135
136pub const ZSTD_WINDOWLOG_MAX: core::ffi::c_int = match size_of::<usize>() {
137 4 => ZSTD_WINDOWLOG_MAX_32,
138 8 => ZSTD_WINDOWLOG_MAX_64,
139 _ => unreachable!(),
140};
141pub const ZSTD_WINDOWLOG_MAX_32: core::ffi::c_int = 30;
142pub const ZSTD_WINDOWLOG_MAX_64: core::ffi::c_int = 31;
143
144#[inline]
145unsafe fn ZSTD_DCtx_get_bmi2(dctx: *const ZSTD_DCtx_s) -> core::ffi::c_int {
146 (*dctx).bmi2
147}
148
149pub const ZSTD_BLOCKHEADERSIZE: core::ffi::c_int = 3;
150static ZSTD_blockHeaderSize: size_t = ZSTD_BLOCKHEADERSIZE as size_t;
151pub const LONGNBSEQ: core::ffi::c_int = 0x7f00 as core::ffi::c_int;
152
153impl ZSTD_DCtx {
154 fn block_size_max(&self) -> usize {
155 if self.isFrameDecompression != 0 {
156 self.fParams.blockSizeMax as usize
157 } else {
158 ZSTD_BLOCKSIZE_MAX as usize
159 }
160 }
161}
162
163pub unsafe fn ZSTD_getcBlockSize(
164 src: *const core::ffi::c_void,
165 srcSize: size_t,
166 bpPtr: &mut blockProperties_t,
167) -> size_t {
168 if srcSize < ZSTD_blockHeaderSize {
169 return Error::srcSize_wrong.to_error_code();
170 }
171 let cBlockHeader = MEM_readLE24(src);
172 let cSize = cBlockHeader >> 3;
173
174 bpPtr.lastBlock = cBlockHeader & 1;
175 bpPtr.blockType = BlockType::from(cBlockHeader >> 1 & 0b11);
176 bpPtr.origSize = cSize;
177
178 match bpPtr.blockType {
179 BlockType::Raw | BlockType::Compressed => cSize as size_t,
180 BlockType::Rle => 1,
181 BlockType::Reserved => Error::corruption_detected.to_error_code(),
182 }
183}
184
185pub fn getc_block_size(src: &[u8]) -> Result<(blockProperties_t, usize), Error> {
186 let [a, b, c, ..] = *src else {
187 return Err(Error::srcSize_wrong);
188 };
189
190 let cBlockHeader = u32::from_le_bytes([a, b, c, 0]);
191 let cSize = cBlockHeader >> 3;
192
193 let bp = blockProperties_t {
194 lastBlock: cBlockHeader & 1,
195 blockType: BlockType::from(cBlockHeader >> 1 & 0b11),
196 origSize: cSize,
197 };
198
199 match bp.blockType {
200 BlockType::Raw | BlockType::Compressed => Ok((bp, cSize as size_t)),
201 BlockType::Rle => Ok((bp, 1)),
202 BlockType::Reserved => Err(Error::corruption_detected),
203 }
204}
205
206unsafe fn ZSTD_allocateLiteralsBuffer(
207 dctx: &mut ZSTD_DCtx,
208 mut dst: Writer<'_>,
209 litSize: usize,
210 streaming: StreamingOperation,
211 expectedWriteSize: usize,
212 split_immediately: bool,
213) {
214 let dstCapacity = dst.capacity();
215 let dst = dst.as_mut_ptr();
216
217 let blockSizeMax = dctx.block_size_max();
218 if streaming == StreamingOperation::NotStreaming
219 && dstCapacity
220 > blockSizeMax
221 .wrapping_add(WILDCOPY_OVERLENGTH)
222 .wrapping_add(litSize)
223 .wrapping_add(WILDCOPY_OVERLENGTH)
224 {
225 dctx.litBuffer = dst.add(blockSizeMax).add(WILDCOPY_OVERLENGTH);
226 dctx.litBufferEnd = dctx.litBuffer.add(litSize);
227 dctx.litBufferLocation = LitLocation::ZSTD_in_dst;
228 } else if litSize <= ZSTD_LITBUFFEREXTRASIZE {
229 dctx.litBuffer = (dctx.litExtraBuffer).as_mut_ptr();
230 dctx.litBufferEnd = dctx.litBuffer.add(litSize);
231 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
232 } else {
233 if split_immediately {
234 dctx.litBuffer = dst
235 .add(expectedWriteSize)
236 .sub(litSize)
237 .add(ZSTD_LITBUFFEREXTRASIZE)
238 .sub(WILDCOPY_OVERLENGTH);
239 dctx.litBufferEnd = dctx.litBuffer.add(litSize).sub(ZSTD_LITBUFFEREXTRASIZE);
240 } else {
241 dctx.litBuffer = dst.add(expectedWriteSize).sub(litSize);
242 dctx.litBufferEnd = dst.add(expectedWriteSize);
243 }
244 dctx.litBufferLocation = LitLocation::ZSTD_split;
245 };
246}
247
248const ZSTD_LBMIN: usize = 64;
249const ZSTD_LBMAX: usize = 128 << 10;
250
251const ZSTD_DECODER_INTERNAL_BUFFER: usize = 1 << 16;
252
253const ZSTD_LITBUFFEREXTRASIZE: usize = {
254 if ZSTD_DECODER_INTERNAL_BUFFER < ZSTD_LBMIN {
256 ZSTD_LBMIN
257 } else if ZSTD_DECODER_INTERNAL_BUFFER > ZSTD_LBMAX {
258 ZSTD_LBMAX
259 } else {
260 ZSTD_DECODER_INTERNAL_BUFFER
261 }
262};
263
264unsafe fn ZSTD_decodeLiteralsBlock(
265 dctx: &mut ZSTD_DCtx,
266 src: &[u8],
267 dst: Writer<'_>,
268 streaming: StreamingOperation,
269) -> size_t {
270 const MIN_CBLOCK_SIZE: usize = 1 + 1;
272 if src.len() < MIN_CBLOCK_SIZE {
273 return Error::corruption_detected.to_error_code();
274 }
275
276 let blockSizeMax = dctx.block_size_max();
277
278 let litEncType = SymbolEncodingType_e::try_from(src[0] & 0b11).unwrap();
279 match litEncType {
280 SymbolEncodingType_e::set_repeat if dctx.litEntropy == 0 => {
281 return Error::dictionary_corrupted.to_error_code();
282 }
283 SymbolEncodingType_e::set_repeat | SymbolEncodingType_e::set_compressed => {}
284 SymbolEncodingType_e::set_basic => {
285 let (lhSize, litSize) = match src[0] >> 2 & 0b11 {
286 1 => (2usize, (u16::from_le_bytes([src[0], src[1]]) >> 4) as usize),
287 3 => {
288 let [a, b, c, ..] = *src else {
289 return Error::corruption_detected.to_error_code();
290 };
291
292 (3, (u32::from_le_bytes([a, b, c, 0]) >> 4) as usize)
293 }
294 _ => (1, (src[0] >> 3) as usize),
295 };
296
297 if litSize > 0 && dst.is_null() {
298 return Error::dstSize_tooSmall.to_error_code();
299 }
300 if litSize > blockSizeMax {
301 return Error::corruption_detected.to_error_code();
302 }
303
304 let expectedWriteSize = Ord::min(dst.capacity(), blockSizeMax);
305 if expectedWriteSize < litSize {
306 return Error::dstSize_tooSmall.to_error_code();
307 }
308
309 ZSTD_allocateLiteralsBuffer(dctx, dst, litSize, streaming, expectedWriteSize, true);
310
311 if lhSize + litSize + WILDCOPY_OVERLENGTH > src.len() {
312 if litSize.wrapping_add(lhSize) > src.len() {
313 return Error::corruption_detected.to_error_code();
314 }
315 if dctx.litBufferLocation == LitLocation::ZSTD_split {
316 libc::memcpy(
317 dctx.litBuffer as *mut core::ffi::c_void,
318 src[lhSize..].as_ptr().cast(),
319 litSize.wrapping_sub(ZSTD_LITBUFFEREXTRASIZE),
320 );
321
322 dctx.litExtraBuffer[..ZSTD_LITBUFFEREXTRASIZE].copy_from_slice(
323 &src[lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE..]
324 [..ZSTD_LITBUFFEREXTRASIZE],
325 );
326 } else {
327 libc::memcpy(
328 dctx.litBuffer as *mut core::ffi::c_void,
329 src[lhSize..].as_ptr().cast(),
330 litSize as libc::size_t,
331 );
332 }
333 dctx.litPtr = dctx.litBuffer;
334 dctx.litSize = litSize;
335 return lhSize.wrapping_add(litSize);
336 }
337
338 dctx.litPtr = src[lhSize..].as_ptr();
339 dctx.litSize = litSize;
340 dctx.litBufferEnd = (dctx.litPtr).add(litSize);
341 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
342
343 return lhSize.wrapping_add(litSize);
344 }
345 SymbolEncodingType_e::set_rle => {
346 let (lhSize, litSize) = match src[0] >> 2 & 0b11 {
347 1 => {
348 let [a, b, _, ..] = *src else {
349 return Error::corruption_detected.to_error_code();
350 };
351
352 (2usize, (u16::from_le_bytes([a, b]) >> 4) as usize)
353 }
354 3 => {
355 let [a, b, c, _, ..] = *src else {
356 return Error::corruption_detected.to_error_code();
357 };
358
359 (3, (u32::from_le_bytes([a, b, c, 0]) >> 4) as usize)
360 }
361 _ => (1, (src[0] >> 3) as usize),
362 };
363
364 if litSize > 0 && dst.is_null() {
365 return Error::dstSize_tooSmall.to_error_code();
366 }
367 if litSize > blockSizeMax {
368 return Error::corruption_detected.to_error_code();
369 }
370
371 let expectedWriteSize = Ord::min(dst.capacity(), blockSizeMax);
372 if expectedWriteSize < litSize {
373 return Error::dstSize_tooSmall.to_error_code();
374 }
375
376 ZSTD_allocateLiteralsBuffer(dctx, dst, litSize, streaming, expectedWriteSize, true);
377
378 if dctx.litBufferLocation == LitLocation::ZSTD_split {
379 ptr::write_bytes(
380 dctx.litBuffer as *mut u8,
381 src[lhSize],
382 litSize.wrapping_sub(ZSTD_LITBUFFEREXTRASIZE),
383 );
384 dctx.litExtraBuffer[..ZSTD_LITBUFFEREXTRASIZE].fill(src[lhSize]);
385 } else {
386 ptr::write_bytes(dctx.litBuffer as *mut u8, src[lhSize], litSize);
387 }
388 dctx.litPtr = dctx.litBuffer;
389 dctx.litSize = litSize;
390 return lhSize.wrapping_add(1);
391 }
392 }
393
394 let [a, b, c, d, size_correction, ..] = *src else {
395 return Error::corruption_detected.to_error_code();
396 };
397 let lhc = u32::from_le_bytes([a, b, c, d]) as usize;
398
399 let flags = {
400 let bmi_flag = match ZSTD_DCtx_get_bmi2(dctx) {
401 0 => 0,
402 _ => HUF_flags_bmi2 as core::ffi::c_int,
403 };
404
405 let disable_asm_flag = match dctx.disableHufAsm {
406 0 => 0,
407 _ => HUF_flags_disableAsm as core::ffi::c_int,
408 };
409
410 bmi_flag | disable_asm_flag
411 };
412
413 let lhlCode = (src[0] >> 2 & 0b11) as u32;
414 let singleStream = lhlCode == 0;
415
416 let (lhSize, litSize, litCSize) = match lhlCode {
417 2 => (4, lhc >> 4 & 0x3fff, lhc >> 18),
418 3 => (
419 5,
420 lhc >> 4 & 0x3ffff,
421 (lhc >> 22) + ((size_correction as usize) << 10),
422 ),
423 _ => (3, lhc >> 4 & 0x3ff, lhc >> 14 & 0x3ff),
424 };
425
426 if litSize > 0 && dst.is_null() {
427 return Error::dstSize_tooSmall.to_error_code();
428 }
429 if litSize > blockSizeMax {
430 return Error::corruption_detected.to_error_code();
431 }
432 if !singleStream && litSize < 6 {
433 return Error::literals_headerWrong.to_error_code();
434 }
435 if litCSize.wrapping_add(lhSize) > src.len() {
436 return Error::corruption_detected.to_error_code();
437 }
438
439 let expectedWriteSize = Ord::min(dst.capacity(), blockSizeMax);
440 if expectedWriteSize < litSize {
441 return Error::dstSize_tooSmall.to_error_code();
442 }
443
444 ZSTD_allocateLiteralsBuffer(dctx, dst, litSize, streaming, expectedWriteSize, false);
445
446 if dctx.ddictIsCold != 0 && litSize > 768 {
448 prefetch_val(dctx.HUFptr);
450 }
451
452 let hufSuccess = if let SymbolEncodingType_e::set_repeat = litEncType {
453 if singleStream {
454 HUF_decompress1X_usingDTable(
455 Writer::from_raw_parts(dctx.litBuffer, litSize as _),
456 &src[lhSize..][..litCSize],
457 dctx.HUFptr.as_ref().unwrap(),
458 flags,
459 )
460 } else {
461 HUF_decompress4X_usingDTable(
462 Writer::from_raw_parts(dctx.litBuffer, litSize as _),
463 &src[lhSize..][..litCSize],
464 dctx.HUFptr.as_ref().unwrap(),
465 flags,
466 )
467 }
468 } else if singleStream {
469 HUF_decompress1X1_DCtx_wksp(
470 &mut dctx.entropy.hufTable,
471 Writer::from_raw_parts(dctx.litBuffer, litSize as _),
472 &src[lhSize..][..litCSize],
473 &mut dctx.workspace,
474 flags,
475 )
476 } else {
477 HUF_decompress4X_hufOnly_wksp(
478 &mut dctx.entropy.hufTable,
479 Writer::from_raw_parts(dctx.litBuffer, litSize as _),
480 &src[lhSize..][..litCSize],
481 &mut dctx.workspace,
482 flags,
483 )
484 };
485
486 if dctx.litBufferLocation == LitLocation::ZSTD_split {
487 libc::memcpy(
488 (dctx.litExtraBuffer).as_mut_ptr() as *mut core::ffi::c_void,
489 (dctx.litBufferEnd).sub(ZSTD_LITBUFFEREXTRASIZE) as *const core::ffi::c_void,
490 ZSTD_LITBUFFEREXTRASIZE,
491 );
492 libc::memmove(
493 (dctx.litBuffer).add(ZSTD_LITBUFFEREXTRASIZE).sub(32) as *mut core::ffi::c_void,
494 dctx.litBuffer as *const core::ffi::c_void,
495 litSize.wrapping_sub(ZSTD_LITBUFFEREXTRASIZE),
496 );
497 dctx.litBuffer = (dctx.litBuffer).add(ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH);
498 dctx.litBufferEnd = (dctx.litBufferEnd).sub(WILDCOPY_OVERLENGTH);
499 }
500
501 if ERR_isError(hufSuccess) {
502 return Error::corruption_detected.to_error_code();
503 }
504
505 dctx.litPtr = dctx.litBuffer;
506 dctx.litSize = litSize;
507 dctx.litEntropy = 1;
508
509 if let SymbolEncodingType_e::set_compressed = litEncType {
510 dctx.HUFptr = &raw const dctx.entropy.hufTable;
511 }
512
513 litCSize.wrapping_add(lhSize)
514}
515
516pub unsafe fn ZSTD_decodeLiteralsBlock_wrapper(
517 dctx: *mut ZSTD_DCtx,
518 src: *const core::ffi::c_void,
519 srcSize: size_t,
520 dst: *mut core::ffi::c_void,
521 dstCapacity: size_t,
522) -> size_t {
523 let Some(dctx) = dctx.as_mut() else {
524 return Error::GENERIC.to_error_code();
525 };
526
527 let src = if src.is_null() {
528 &[]
529 } else {
530 core::slice::from_raw_parts(src.cast::<u8>(), srcSize)
531 };
532
533 let dst = Writer::from_raw_parts(dst.cast::<u8>(), dstCapacity);
535
536 dctx.isFrameDecompression = 0;
537
538 ZSTD_decodeLiteralsBlock(dctx, src, dst, StreamingOperation::NotStreaming)
539}
540
541const fn sequence_symbol(
542 nextState: u16,
543 nbAdditionalBits: u8,
544 nbBits: u8,
545 baseValue: u32,
546) -> ZSTD_seqSymbol {
547 ZSTD_seqSymbol {
548 nextState,
549 nbAdditionalBits,
550 nbBits,
551 baseValue,
552 }
553}
554
555#[rustfmt::skip]
557static LL_defaultDTable: [ZSTD_seqSymbol; (1 << LL_DEFAULTNORMLOG) + 1] = [
558 sequence_symbol(1, 1, 1, LL_DEFAULTNORMLOG),
560 sequence_symbol( 0, 0, 4, 0), sequence_symbol(16, 0, 4, 0),
562 sequence_symbol(32, 0, 5, 1), sequence_symbol( 0, 0, 5, 3),
563 sequence_symbol( 0, 0, 5, 4), sequence_symbol( 0, 0, 5, 6),
564 sequence_symbol( 0, 0, 5, 7), sequence_symbol( 0, 0, 5, 9),
565 sequence_symbol( 0, 0, 5, 10), sequence_symbol( 0, 0, 5, 12),
566 sequence_symbol( 0, 0, 6, 14), sequence_symbol( 0, 1, 5, 16),
567 sequence_symbol( 0, 1, 5, 20), sequence_symbol( 0, 1, 5, 22),
568 sequence_symbol( 0, 2, 5, 28), sequence_symbol( 0, 3, 5, 32),
569 sequence_symbol( 0, 4, 5, 48), sequence_symbol(32, 6, 5, 64),
570 sequence_symbol( 0, 7, 5, 128), sequence_symbol( 0, 8, 6, 256),
571 sequence_symbol( 0, 10, 6, 1024), sequence_symbol( 0, 12, 6, 4096),
572 sequence_symbol(32, 0, 4, 0), sequence_symbol( 0, 0, 4, 1),
573 sequence_symbol( 0, 0, 5, 2), sequence_symbol(32, 0, 5, 4),
574 sequence_symbol( 0, 0, 5, 5), sequence_symbol(32, 0, 5, 7),
575 sequence_symbol( 0, 0, 5, 8), sequence_symbol(32, 0, 5, 10),
576 sequence_symbol( 0, 0, 5, 11), sequence_symbol( 0, 0, 6, 13),
577 sequence_symbol(32, 1, 5, 16), sequence_symbol( 0, 1, 5, 18),
578 sequence_symbol(32, 1, 5, 22), sequence_symbol( 0, 2, 5, 24),
579 sequence_symbol(32, 3, 5, 32), sequence_symbol( 0, 3, 5, 40),
580 sequence_symbol( 0, 6, 4, 64), sequence_symbol(16, 6, 4, 64),
581 sequence_symbol(32, 7, 5, 128), sequence_symbol( 0, 9, 6, 512),
582 sequence_symbol( 0, 11, 6, 2048), sequence_symbol(48, 0, 4, 0),
583 sequence_symbol(16, 0, 4, 1), sequence_symbol(32, 0, 5, 2),
584 sequence_symbol(32, 0, 5, 3), sequence_symbol(32, 0, 5, 5),
585 sequence_symbol(32, 0, 5, 6), sequence_symbol(32, 0, 5, 8),
586 sequence_symbol(32, 0, 5, 9), sequence_symbol(32, 0, 5, 11),
587 sequence_symbol(32, 0, 5, 12), sequence_symbol( 0, 0, 6, 15),
588 sequence_symbol(32, 1, 5, 18), sequence_symbol(32, 1, 5, 20),
589 sequence_symbol(32, 2, 5, 24), sequence_symbol(32, 2, 5, 28),
590 sequence_symbol(32, 3, 5, 40), sequence_symbol(32, 4, 5, 48),
591 sequence_symbol( 0, 16, 6,65536), sequence_symbol( 0, 15, 6,32768),
592 sequence_symbol( 0, 14, 6,16384), sequence_symbol( 0, 13, 6, 8192),
593];
594
595#[rustfmt::skip]
597static OF_defaultDTable: [ZSTD_seqSymbol; (1 << OF_DEFAULTNORMLOG) + 1] = [
598 sequence_symbol(1, 1, 1, OF_DEFAULTNORMLOG),
600 sequence_symbol( 0, 0, 5, 0), sequence_symbol( 0, 6, 4, 61),
602 sequence_symbol( 0, 9, 5, 509), sequence_symbol( 0, 15, 5,32765),
603 sequence_symbol( 0, 21, 5,2097149), sequence_symbol( 0, 3, 5, 5),
604 sequence_symbol( 0, 7, 4, 125), sequence_symbol( 0, 12, 5, 4093),
605 sequence_symbol( 0, 18, 5,262141), sequence_symbol( 0, 23, 5,8388605),
606 sequence_symbol( 0, 5, 5, 29), sequence_symbol( 0, 8, 4, 253),
607 sequence_symbol( 0, 14, 5,16381), sequence_symbol( 0, 20, 5,1048573),
608 sequence_symbol( 0, 2, 5, 1), sequence_symbol(16, 7, 4, 125),
609 sequence_symbol( 0, 11, 5, 2045), sequence_symbol( 0, 17, 5,131069),
610 sequence_symbol( 0, 22, 5,4194301), sequence_symbol( 0, 4, 5, 13),
611 sequence_symbol(16, 8, 4, 253), sequence_symbol( 0, 13, 5, 8189),
612 sequence_symbol( 0, 19, 5,524285), sequence_symbol( 0, 1, 5, 1),
613 sequence_symbol(16, 6, 4, 61), sequence_symbol( 0, 10, 5, 1021),
614 sequence_symbol( 0, 16, 5,65533), sequence_symbol( 0, 28, 5,268435453),
615 sequence_symbol( 0, 27, 5,134217725), sequence_symbol( 0, 26, 5,67108861),
616 sequence_symbol( 0, 25, 5,33554429), sequence_symbol( 0, 24, 5,16777213),
617];
618
619#[rustfmt::skip]
621static ML_defaultDTable: [ZSTD_seqSymbol; (1 << ML_DEFAULTNORMLOG) + 1] = [
622 sequence_symbol(1, 1, 1, ML_DEFAULTNORMLOG),
624 sequence_symbol( 0, 0, 6, 3), sequence_symbol( 0, 0, 4, 4),
626 sequence_symbol(32, 0, 5, 5), sequence_symbol( 0, 0, 5, 6),
627 sequence_symbol( 0, 0, 5, 8), sequence_symbol( 0, 0, 5, 9),
628 sequence_symbol( 0, 0, 5, 11), sequence_symbol( 0, 0, 6, 13),
629 sequence_symbol( 0, 0, 6, 16), sequence_symbol( 0, 0, 6, 19),
630 sequence_symbol( 0, 0, 6, 22), sequence_symbol( 0, 0, 6, 25),
631 sequence_symbol( 0, 0, 6, 28), sequence_symbol( 0, 0, 6, 31),
632 sequence_symbol( 0, 0, 6, 34), sequence_symbol( 0, 1, 6, 37),
633 sequence_symbol( 0, 1, 6, 41), sequence_symbol( 0, 2, 6, 47),
634 sequence_symbol( 0, 3, 6, 59), sequence_symbol( 0, 4, 6, 83),
635 sequence_symbol( 0, 7, 6, 131), sequence_symbol( 0, 9, 6, 515),
636 sequence_symbol(16, 0, 4, 4), sequence_symbol( 0, 0, 4, 5),
637 sequence_symbol(32, 0, 5, 6), sequence_symbol( 0, 0, 5, 7),
638 sequence_symbol(32, 0, 5, 9), sequence_symbol( 0, 0, 5, 10),
639 sequence_symbol( 0, 0, 6, 12), sequence_symbol( 0, 0, 6, 15),
640 sequence_symbol( 0, 0, 6, 18), sequence_symbol( 0, 0, 6, 21),
641 sequence_symbol( 0, 0, 6, 24), sequence_symbol( 0, 0, 6, 27),
642 sequence_symbol( 0, 0, 6, 30), sequence_symbol( 0, 0, 6, 33),
643 sequence_symbol( 0, 1, 6, 35), sequence_symbol( 0, 1, 6, 39),
644 sequence_symbol( 0, 2, 6, 43), sequence_symbol( 0, 3, 6, 51),
645 sequence_symbol( 0, 4, 6, 67), sequence_symbol( 0, 5, 6, 99),
646 sequence_symbol( 0, 8, 6, 259), sequence_symbol(32, 0, 4, 4),
647 sequence_symbol(48, 0, 4, 4), sequence_symbol(16, 0, 4, 5),
648 sequence_symbol(32, 0, 5, 7), sequence_symbol(32, 0, 5, 8),
649 sequence_symbol(32, 0, 5, 10), sequence_symbol(32, 0, 5, 11),
650 sequence_symbol( 0, 0, 6, 14), sequence_symbol( 0, 0, 6, 17),
651 sequence_symbol( 0, 0, 6, 20), sequence_symbol( 0, 0, 6, 23),
652 sequence_symbol( 0, 0, 6, 26), sequence_symbol( 0, 0, 6, 29),
653 sequence_symbol( 0, 0, 6, 32), sequence_symbol( 0, 16, 6,65539),
654 sequence_symbol( 0, 15, 6,32771), sequence_symbol( 0, 14, 6,16387),
655 sequence_symbol( 0, 13, 6, 8195), sequence_symbol( 0, 12, 6, 4099),
656 sequence_symbol( 0, 11, 6, 2051), sequence_symbol( 0, 10, 6, 1027),
657];
658
659fn ZSTD_buildSeqTable_rle<const N: usize>(dt: &mut SymbolTable<N>, baseValue: u32, nbAddBits: u8) {
660 dt.header = ZSTD_seqSymbol_header {
661 fastMode: 0,
662 tableLog: 0,
663 };
664
665 dt.symbols[0] = ZSTD_seqSymbol {
666 nbBits: 0,
667 nextState: 0,
668 nbAdditionalBits: nbAddBits,
669 baseValue,
670 };
671}
672
673#[inline(always)]
674fn ZSTD_buildFSETable_body<const N: usize>(
675 dt: &mut SymbolTable<N>,
676 normalizedCounter: &[i16],
677 baseValue: &'static [u32],
678 nbAdditionalBits: &'static [u8],
679 tableLog: core::ffi::c_uint,
680 wksp: &mut FseWorkspace,
681) {
682 let tableDecode = &mut dt.symbols;
683 let tableSize = 1usize << tableLog;
684 let mut highThreshold = tableSize.wrapping_sub(1);
685 let mut DTableH = ZSTD_seqSymbol_header {
686 fastMode: 1,
687 tableLog,
688 };
689
690 let largeLimit = ((1) << tableLog.wrapping_sub(1)) as i16;
691
692 for (s, &v) in normalizedCounter.iter().enumerate() {
693 if v == -1 {
694 tableDecode[highThreshold].baseValue = s as u32;
695 highThreshold = highThreshold.wrapping_sub(1);
696 wksp.symbols[s] = 1;
697 } else {
698 if v >= largeLimit {
699 DTableH.fastMode = 0;
700 }
701 wksp.symbols[s] = v as u16;
702 }
703 }
704
705 dt.header = DTableH;
706
707 if highThreshold == tableSize - 1 {
708 let tableMask = tableSize - 1;
709 let step = (tableSize >> 1) + (tableSize >> 3) + 3;
710 let add = 0x101010101010101u64;
711 let mut pos = 0usize;
712 let mut sv = 0u64;
713 for &v in normalizedCounter {
714 let n = v as usize;
715 wksp.spread[pos..][..8].copy_from_slice(&sv.to_le_bytes());
716 let mut i: usize = 8;
717 while i < n {
718 wksp.spread[pos..][i..][..8].copy_from_slice(&sv.to_le_bytes());
719 i += 8;
720 }
721 pos = pos.wrapping_add(n);
722 sv = sv.wrapping_add(add);
723 }
724
725 let mut position = 0usize;
726 for s in (0..tableSize).step_by(2) {
727 for u in 0..2 {
728 let uPosition = position.wrapping_add(u * step) & tableMask;
729 tableDecode[uPosition].baseValue = wksp.spread[s + u] as u32;
730 }
731 position = position.wrapping_add(2 * step) & tableMask;
732 }
733 } else {
734 let tableMask = tableSize - 1;
735 let step = (tableSize >> 1) + (tableSize >> 3) + 3;
736 let mut position = 0usize;
737 for (s, &v) in normalizedCounter.iter().enumerate() {
738 for _ in 0..i32::from(v) {
739 tableDecode[position].baseValue = s as u32;
740 position = position.wrapping_add(step) & tableMask;
741 while core::hint::unlikely(position > highThreshold) {
742 position = position.wrapping_add(step) & tableMask;
743 }
744 }
745 }
746 }
747
748 for u in 0..tableSize {
749 let symbol = tableDecode[u].baseValue as usize;
750 let nextState = wksp.symbols[symbol] as u32;
751 wksp.symbols[symbol] += 1;
752
753 let nbBits = tableLog.wrapping_sub(nextState.ilog2()) as u8;
754
755 tableDecode[u] = ZSTD_seqSymbol {
756 nbBits,
757 nextState: (nextState << nbBits).wrapping_sub(tableSize as u32) as u16,
758 nbAdditionalBits: nbAdditionalBits[symbol],
759 baseValue: baseValue[symbol],
760 };
761 }
762}
763
764fn ZSTD_buildFSETable_body_default<const N: usize>(
765 dt: &mut SymbolTable<N>,
766 normalizedCounter: &[i16],
767 baseValue: &'static [u32],
768 nbAdditionalBits: &'static [u8],
769 tableLog: core::ffi::c_uint,
770 wksp: &mut FseWorkspace,
771) {
772 ZSTD_buildFSETable_body(
773 dt,
774 normalizedCounter,
775 baseValue,
776 nbAdditionalBits,
777 tableLog,
778 wksp,
779 );
780}
781
782fn ZSTD_buildFSETable_body_bmi2<const N: usize>(
783 dt: &mut SymbolTable<N>,
784 normalizedCounter: &[i16],
785 baseValue: &'static [u32],
786 nbAdditionalBits: &'static [u8],
787 tableLog: core::ffi::c_uint,
788 wksp: &mut FseWorkspace,
789) {
790 ZSTD_buildFSETable_body(
791 dt,
792 normalizedCounter,
793 baseValue,
794 nbAdditionalBits,
795 tableLog,
796 wksp,
797 );
798}
799
800#[derive(Copy, Clone)]
801#[repr(C, align(4))]
802pub struct FseWorkspace {
803 symbols: [u16; MaxSeq + 1],
804 spread: [u8; (1 << MaxFSELog) + size_of::<u64>()],
805}
806
807pub fn ZSTD_buildFSETable<const N: usize>(
808 dt: &mut SymbolTable<N>,
809 normalizedCounter: &[i16],
810 baseValue: &'static [u32],
811 nbAdditionalBits: &'static [u8],
812 tableLog: core::ffi::c_uint,
813 wksp: &mut FseWorkspace,
814 bmi2: bool,
815) {
816 if bmi2 {
817 ZSTD_buildFSETable_body_bmi2(
818 dt,
819 normalizedCounter,
820 baseValue,
821 nbAdditionalBits,
822 tableLog,
823 wksp,
824 );
825 } else {
826 ZSTD_buildFSETable_body_default(
827 dt,
828 normalizedCounter,
829 baseValue,
830 nbAdditionalBits,
831 tableLog,
832 wksp,
833 );
834 }
835}
836
837fn ZSTD_buildSeqTable<const N: usize>(
838 DTableSpace: &mut SymbolTable<N>,
839 DTablePtr: &mut *const ZSTD_seqSymbol,
840 type_0: SymbolEncodingType_e,
841 mut max: core::ffi::c_uint,
842 maxLog: u32,
843 src: &[u8],
844 baseValue: &'static [u32],
845 nbAdditionalBits: &'static [u8],
846 defaultTable: &'static [ZSTD_seqSymbol],
847 flagRepeatTable: u32,
848 ddictIsCold: core::ffi::c_int,
849 nbSeq: core::ffi::c_int,
850 wksp: &mut Workspace,
851 bmi2: bool,
852) -> size_t {
853 match type_0 {
854 SymbolEncodingType_e::set_rle => {
855 let [symbol, ..] = *src else {
856 return Error::srcSize_wrong.to_error_code();
857 };
858
859 if u32::from(symbol) > max {
860 return Error::corruption_detected.to_error_code();
861 }
862
863 let baseline = baseValue[usize::from(symbol)];
864 let nbBits = nbAdditionalBits[usize::from(symbol)];
865 ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
866
867 *DTablePtr = DTableSpace.as_mut_ptr();
868 1
869 }
870 SymbolEncodingType_e::set_basic => {
871 *DTablePtr = defaultTable.as_ptr();
872 0
873 }
874 SymbolEncodingType_e::set_repeat => {
875 if flagRepeatTable == 0 {
876 return Error::corruption_detected.to_error_code();
877 }
878 if ddictIsCold != 0 && nbSeq > 24 {
879 let pSize = size_of::<ZSTD_seqSymbol>().wrapping_mul(1 + (1usize << maxLog));
880 prefetch_area(*DTablePtr, pSize);
881 }
882 0
883 }
884 SymbolEncodingType_e::set_compressed => {
885 let mut tableLog: core::ffi::c_uint = 0;
886 let mut norm: [i16; 53] = [0; 53];
887 let Ok(headerSize) = FSE_readNCount_slice(&mut norm, &mut max, &mut tableLog, src)
888 else {
889 return Error::corruption_detected.to_error_code();
890 };
891 if tableLog > maxLog {
892 return Error::corruption_detected.to_error_code();
893 }
894 ZSTD_buildFSETable(
895 DTableSpace,
896 &norm[..=max as usize],
897 baseValue,
898 nbAdditionalBits,
899 tableLog,
900 wksp.as_fse_workspace(),
901 bmi2,
902 );
903 *DTablePtr = DTableSpace.as_mut_ptr();
904 headerSize
905 }
906 }
907}
908
909fn ZSTD_decodeSeqHeaders(
910 dctx: &mut ZSTD_DCtx,
911 nbSeqPtr: &mut core::ffi::c_int,
912 src: &[u8],
913) -> size_t {
914 let mut ip = 0;
915 let [nbSeq, ..] = *src else {
916 return Error::srcSize_wrong.to_error_code();
917 };
918 let mut nbSeq = i32::from(nbSeq);
919 ip += 1;
920 if nbSeq > 0x7f {
921 if nbSeq == 0xff {
922 let [_, a, b, ..] = *src else {
923 return Error::srcSize_wrong.to_error_code();
924 };
925 nbSeq = i32::from(u16::from_le_bytes([a, b])) + LONGNBSEQ;
926 ip += 2;
927 } else {
928 if ip >= src.len() {
929 return Error::srcSize_wrong.to_error_code();
930 }
931 nbSeq = ((nbSeq - 0x80) << 8) + i32::from(src[ip]);
932 ip += 1;
933 }
934 }
935 *nbSeqPtr = nbSeq;
936 if nbSeq == 0 {
937 if ip != src.len() {
938 return Error::corruption_detected.to_error_code();
939 }
940 return ip;
941 }
942
943 if ip + 1 > src.len() {
947 return Error::srcSize_wrong.to_error_code();
948 }
949
950 if src[ip] & 0b11 != 0 {
952 return Error::corruption_detected.to_error_code();
953 }
954
955 let byte = src[ip];
956 let LLtype = SymbolEncodingType_e::try_from(byte >> 6).unwrap();
957 let OFtype = SymbolEncodingType_e::try_from(byte >> 4 & 0b11).unwrap();
958 let MLtype = SymbolEncodingType_e::try_from(byte >> 2 & 0b11).unwrap();
959
960 ip += 1;
963 let llhSize = ZSTD_buildSeqTable(
964 &mut dctx.entropy.LLTable,
965 &mut dctx.LLTptr,
966 LLtype,
967 MaxLL as core::ffi::c_uint,
968 LLFSELog as u32,
969 &src[ip..],
970 &LL_base,
971 &LL_bits,
972 &LL_defaultDTable,
973 dctx.fseEntropy,
974 dctx.ddictIsCold,
975 nbSeq,
976 &mut dctx.workspace,
977 dctx.bmi2 != 0,
978 );
979 if ERR_isError(llhSize) {
980 return Error::corruption_detected.to_error_code();
981 }
982
983 ip += llhSize as usize;
984 let ofhSize = ZSTD_buildSeqTable(
985 &mut dctx.entropy.OFTable,
986 &mut dctx.OFTptr,
987 OFtype,
988 MaxOff as core::ffi::c_uint,
989 OffFSELog as u32,
990 &src[ip..],
991 &OF_base,
992 &OF_bits,
993 &OF_defaultDTable,
994 dctx.fseEntropy,
995 dctx.ddictIsCold,
996 nbSeq,
997 &mut dctx.workspace,
998 dctx.bmi2 != 0,
999 );
1000 if ERR_isError(ofhSize) {
1001 return Error::corruption_detected.to_error_code();
1002 }
1003
1004 ip += ofhSize as usize;
1005 let mlhSize = ZSTD_buildSeqTable(
1006 &mut dctx.entropy.MLTable,
1007 &mut dctx.MLTptr,
1008 MLtype,
1009 MaxML as core::ffi::c_uint,
1010 MLFSELog as u32,
1011 &src[ip..],
1012 &ML_base,
1013 &ML_bits,
1014 &ML_defaultDTable,
1015 dctx.fseEntropy,
1016 dctx.ddictIsCold,
1017 nbSeq,
1018 &mut dctx.workspace,
1019 dctx.bmi2 != 0,
1020 );
1021 if ERR_isError(mlhSize) {
1022 return Error::corruption_detected.to_error_code();
1023 }
1024
1025 ip += mlhSize as usize;
1026
1027 ip
1028}
1029
1030#[inline(always)]
1036unsafe fn ZSTD_overlapCopy8(op: &mut *mut u8, ip: &mut *const u8, offset: size_t) {
1037 if offset < 8 {
1038 *(*op).add(0) = *(*ip).add(0);
1039 *(*op).add(1) = *(*ip).add(1);
1040 *(*op).add(2) = *(*ip).add(2);
1041 *(*op).add(3) = *(*ip).add(3);
1042
1043 static dec32table: [u8; 8] = [0, 1, 2, 1, 4, 4, 4, 4]; *ip = (*ip).add(usize::from(dec32table[offset]));
1045 core::ptr::copy(*ip, (*op).add(4), 4);
1046
1047 static dec64table: [u8; 8] = [8, 8, 8, 7, 8, 9, 10, 11]; *ip = (*ip).sub(usize::from(dec64table[offset]));
1049 } else {
1050 core::ptr::copy(*ip, *op, 8);
1051 }
1052
1053 *ip = (*ip).add(8);
1054 *op = (*op).add(8);
1055
1056 assert!(unsafe { (*op).offset_from(*ip) } >= 8);
1057}
1058
1059unsafe fn ZSTD_safecopy(
1060 mut op: *mut u8,
1061 oend_w: *const u8,
1062 mut ip: *const u8,
1063 mut length: size_t,
1064 ovtype: Overlap,
1065) {
1066 let diff = op as isize - ip as isize;
1067 let oend = op.add(length);
1068 if length < 8 {
1069 while op < oend {
1070 *op = *ip;
1071 ip = ip.add(1);
1072 op = op.add(1);
1073 }
1074 return;
1075 }
1076 if ovtype == Overlap::OverlapSrcBeforeDst {
1077 ZSTD_overlapCopy8(&mut op, &mut ip, diff as size_t);
1078 length = length.wrapping_sub(8);
1079 }
1080 if oend <= oend_w as *mut u8 {
1081 ZSTD_wildcopy(
1082 op as *mut core::ffi::c_void,
1083 ip as *const core::ffi::c_void,
1084 length,
1085 ovtype,
1086 );
1087 return;
1088 }
1089 if op <= oend_w as *mut u8 {
1090 ZSTD_wildcopy(
1091 op as *mut core::ffi::c_void,
1092 ip as *const core::ffi::c_void,
1093 oend_w.offset_from(op) as size_t,
1094 ovtype,
1095 );
1096 ip = ip.offset(oend_w.offset_from(op));
1097 op = op.offset(oend_w.offset_from(op));
1098 }
1099 while op < oend {
1100 *op = *ip;
1101 ip = ip.add(1);
1102 op = op.add(1);
1103 }
1104}
1105
1106unsafe fn ZSTD_safecopyDstBeforeSrc(mut op: *mut u8, mut ip: *const u8, length: size_t) {
1107 let diff = op.offset_from(ip) as ptrdiff_t;
1108 let oend = op.add(length);
1109 if length < 8 || diff > -8 as ptrdiff_t {
1110 while op < oend {
1111 *op = *ip;
1112 ip = ip.offset(1);
1113 op = op.offset(1);
1114 }
1115 return;
1116 }
1117 if op <= oend.sub(WILDCOPY_OVERLENGTH) && diff < -WILDCOPY_VECLEN as ptrdiff_t {
1118 ZSTD_wildcopy(
1119 op as *mut core::ffi::c_void,
1120 ip as *const core::ffi::c_void,
1121 oend.sub(WILDCOPY_OVERLENGTH).offset_from(op) as size_t,
1122 Overlap::NoOverlap,
1123 );
1124 ip = ip.offset(oend.sub(WILDCOPY_OVERLENGTH).offset_from(op));
1125 op = op.offset(oend.sub(WILDCOPY_OVERLENGTH).offset_from(op));
1126 }
1127 while op < oend {
1128 *op = *ip;
1129 ip = ip.offset(1);
1130 op = op.offset(1);
1131 }
1132}
1133
1134#[inline(never)]
1135unsafe fn ZSTD_execSequenceEnd(
1136 mut op: *mut u8,
1137 oend: *mut u8,
1138 mut sequence: seq_t,
1139 litPtr: *mut *const u8,
1140 litLimit: *const u8,
1141 prefixStart: *const u8,
1142 virtualStart: *const u8,
1143 dictEnd: *const u8,
1144) -> size_t {
1145 let oLitEnd = op.add(sequence.litLength);
1146 let sequenceLength = (sequence.litLength).wrapping_add(sequence.matchLength);
1147 let iLitEnd = (*litPtr).add(sequence.litLength);
1148 let mut match_0: *const u8 = oLitEnd.wrapping_sub(sequence.offset);
1149 let oend_w = oend.wrapping_sub(WILDCOPY_OVERLENGTH);
1150 if sequenceLength > oend.offset_from(op) as size_t {
1151 return Error::dstSize_tooSmall.to_error_code();
1152 }
1153 if sequence.litLength > litLimit.offset_from(*litPtr) as size_t {
1154 return Error::corruption_detected.to_error_code();
1155 }
1156 ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, Overlap::NoOverlap);
1157 op = oLitEnd;
1158 *litPtr = iLitEnd;
1159 if sequence.offset > oLitEnd.offset_from(prefixStart) as size_t {
1160 if sequence.offset > oLitEnd.offset_from(virtualStart) as size_t {
1161 return Error::corruption_detected.to_error_code();
1162 }
1163 match_0 = dictEnd.offset(-(prefixStart.offset_from(match_0)));
1164 if match_0.add(sequence.matchLength) <= dictEnd {
1165 libc::memmove(
1166 oLitEnd as *mut core::ffi::c_void,
1167 match_0 as *const core::ffi::c_void,
1168 sequence.matchLength as libc::size_t,
1169 );
1170 return sequenceLength;
1171 }
1172 let length1 = dictEnd.offset_from(match_0) as size_t;
1173 libc::memmove(
1174 oLitEnd as *mut core::ffi::c_void,
1175 match_0 as *const core::ffi::c_void,
1176 length1 as libc::size_t,
1177 );
1178 op = oLitEnd.add(length1);
1179 sequence.matchLength = (sequence.matchLength).wrapping_sub(length1);
1180 match_0 = prefixStart;
1181 }
1182 ZSTD_safecopy(
1183 op,
1184 oend_w,
1185 match_0,
1186 sequence.matchLength,
1187 Overlap::OverlapSrcBeforeDst,
1188 );
1189 sequenceLength
1190}
1191#[inline(never)]
1192unsafe fn ZSTD_execSequenceEndSplitLitBuffer(
1193 mut op: *mut u8,
1194 oend: *mut u8,
1195 oend_w: *const u8,
1196 mut sequence: seq_t,
1197 litPtr: *mut *const u8,
1198 litLimit: *const u8,
1199 prefixStart: *const u8,
1200 virtualStart: *const u8,
1201 dictEnd: *const u8,
1202) -> size_t {
1203 let oLitEnd = op.add(sequence.litLength);
1204 let sequenceLength = (sequence.litLength).wrapping_add(sequence.matchLength);
1205 let iLitEnd = (*litPtr).add(sequence.litLength);
1206 let mut match_0: *const u8 = oLitEnd.offset(-(sequence.offset as isize));
1207 if sequenceLength > oend.offset_from(op) as size_t {
1208 return Error::dstSize_tooSmall.to_error_code();
1209 }
1210 if sequence.litLength > litLimit.offset_from(*litPtr) as size_t {
1211 return Error::corruption_detected.to_error_code();
1212 }
1213 if op > *litPtr as *mut u8 && op < (*litPtr).add(sequence.litLength) as *mut u8 {
1214 return Error::dstSize_tooSmall.to_error_code();
1215 }
1216 ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength);
1217 op = oLitEnd;
1218 *litPtr = iLitEnd;
1219 if sequence.offset > oLitEnd.offset_from(prefixStart) as size_t {
1220 if sequence.offset > oLitEnd.offset_from(virtualStart) as size_t {
1221 return Error::corruption_detected.to_error_code();
1222 }
1223 match_0 = dictEnd.offset(-(prefixStart.offset_from(match_0) as core::ffi::c_long as isize));
1224 if match_0.add(sequence.matchLength) <= dictEnd {
1225 libc::memmove(
1226 oLitEnd as *mut core::ffi::c_void,
1227 match_0 as *const core::ffi::c_void,
1228 sequence.matchLength as libc::size_t,
1229 );
1230 return sequenceLength;
1231 }
1232 let length1 = dictEnd.offset_from(match_0) as size_t;
1233 libc::memmove(
1234 oLitEnd as *mut core::ffi::c_void,
1235 match_0 as *const core::ffi::c_void,
1236 length1 as libc::size_t,
1237 );
1238 op = oLitEnd.add(length1);
1239 sequence.matchLength = (sequence.matchLength).wrapping_sub(length1);
1240 match_0 = prefixStart;
1241 }
1242 ZSTD_safecopy(
1243 op,
1244 oend_w,
1245 match_0,
1246 sequence.matchLength,
1247 Overlap::OverlapSrcBeforeDst,
1248 );
1249 sequenceLength
1250}
1251
1252#[inline(always)]
1253unsafe fn ZSTD_execSequence(
1254 mut op: *mut u8,
1255 oend: *mut u8,
1256 mut sequence: seq_t,
1257 litPtr: &mut *const u8,
1258 litLimit: *const u8,
1259 prefixStart: *const u8,
1260 virtualStart: *const u8,
1261 dictEnd: *const u8,
1262) -> size_t {
1263 let oLitEnd = op.add(sequence.litLength);
1264 let sequenceLength = (sequence.litLength).wrapping_add(sequence.matchLength);
1265 let oMatchEnd = op.add(sequenceLength);
1266 let oend_w = oend.wrapping_sub(WILDCOPY_OVERLENGTH);
1267 let iLitEnd = (*litPtr).add(sequence.litLength);
1268 let mut match_0: *const u8 = oLitEnd.wrapping_offset(-(sequence.offset as isize));
1269 if (iLitEnd > litLimit
1270 || oMatchEnd > oend_w
1271 || MEM_32bits() != 0 && (oend.offset_from(op) as size_t) < sequenceLength.wrapping_add(32))
1272 as core::ffi::c_int as core::ffi::c_long
1273 != 0
1274 {
1275 return ZSTD_execSequenceEnd(
1276 op,
1277 oend,
1278 sequence,
1279 litPtr,
1280 litLimit,
1281 prefixStart,
1282 virtualStart,
1283 dictEnd,
1284 );
1285 }
1286 ZSTD_copy16(
1287 op as *mut core::ffi::c_void,
1288 *litPtr as *const core::ffi::c_void,
1289 );
1290 if (sequence.litLength > 16) as core::ffi::c_int as core::ffi::c_long != 0 {
1291 ZSTD_wildcopy(
1292 op.offset(16) as *mut core::ffi::c_void,
1293 (*litPtr).offset(16) as *const core::ffi::c_void,
1294 (sequence.litLength).wrapping_sub(16),
1295 Overlap::NoOverlap,
1296 );
1297 }
1298 op = oLitEnd;
1299 *litPtr = iLitEnd;
1300 if sequence.offset > oLitEnd.offset_from(prefixStart) as size_t {
1301 if (sequence.offset > oLitEnd.offset_from(virtualStart) as size_t) as core::ffi::c_int
1302 as core::ffi::c_long
1303 != 0
1304 {
1305 return Error::corruption_detected.to_error_code();
1306 }
1307 match_0 = dictEnd.offset(match_0.offset_from(prefixStart) as core::ffi::c_long as isize);
1308 if match_0.add(sequence.matchLength) <= dictEnd {
1309 libc::memmove(
1310 oLitEnd as *mut core::ffi::c_void,
1311 match_0 as *const core::ffi::c_void,
1312 sequence.matchLength as libc::size_t,
1313 );
1314 return sequenceLength;
1315 }
1316 let length1 = dictEnd.offset_from(match_0) as size_t;
1317 libc::memmove(
1318 oLitEnd as *mut core::ffi::c_void,
1319 match_0 as *const core::ffi::c_void,
1320 length1 as libc::size_t,
1321 );
1322 op = oLitEnd.add(length1);
1323 sequence.matchLength = (sequence.matchLength).wrapping_sub(length1);
1324 match_0 = prefixStart;
1325 }
1326 if (sequence.offset >= 16) as core::ffi::c_int as core::ffi::c_long != 0 {
1327 ZSTD_wildcopy(
1328 op as *mut core::ffi::c_void,
1329 match_0 as *const core::ffi::c_void,
1330 sequence.matchLength,
1331 Overlap::NoOverlap,
1332 );
1333 return sequenceLength;
1334 }
1335 ZSTD_overlapCopy8(&mut op, &mut match_0, sequence.offset);
1336 if sequence.matchLength > 8 {
1337 ZSTD_wildcopy(
1338 op as *mut core::ffi::c_void,
1339 match_0 as *const core::ffi::c_void,
1340 (sequence.matchLength).wrapping_sub(8),
1341 Overlap::OverlapSrcBeforeDst,
1342 );
1343 }
1344 sequenceLength
1345}
1346#[inline(always)]
1347unsafe fn ZSTD_execSequenceSplitLitBuffer(
1348 mut op: *mut u8,
1349 oend: *mut u8,
1350 oend_w: *const u8,
1351 mut sequence: seq_t,
1352 litPtr: *mut *const u8,
1353 litLimit: *const u8,
1354 prefixStart: *const u8,
1355 virtualStart: *const u8,
1356 dictEnd: *const u8,
1357) -> size_t {
1358 let oLitEnd = op.add(sequence.litLength);
1359 let sequenceLength = (sequence.litLength).wrapping_add(sequence.matchLength);
1360 let oMatchEnd = op.add(sequenceLength);
1361 let iLitEnd = (*litPtr).add(sequence.litLength);
1362 let mut match_0: *const u8 = oLitEnd.offset(-(sequence.offset as isize));
1363 if (iLitEnd > litLimit
1364 || oMatchEnd > oend_w as *mut u8
1365 || MEM_32bits() != 0 && (oend.offset_from(op) as size_t) < sequenceLength.wrapping_add(32))
1366 as core::ffi::c_int as core::ffi::c_long
1367 != 0
1368 {
1369 return ZSTD_execSequenceEndSplitLitBuffer(
1370 op,
1371 oend,
1372 oend_w,
1373 sequence,
1374 litPtr,
1375 litLimit,
1376 prefixStart,
1377 virtualStart,
1378 dictEnd,
1379 );
1380 }
1381 ZSTD_copy16(
1382 op as *mut core::ffi::c_void,
1383 *litPtr as *const core::ffi::c_void,
1384 );
1385 if (sequence.litLength > 16) as core::ffi::c_int as core::ffi::c_long != 0 {
1386 ZSTD_wildcopy(
1387 op.offset(16) as *mut core::ffi::c_void,
1388 (*litPtr).offset(16) as *const core::ffi::c_void,
1389 (sequence.litLength).wrapping_sub(16),
1390 Overlap::NoOverlap,
1391 );
1392 }
1393 op = oLitEnd;
1394 *litPtr = iLitEnd;
1395 if sequence.offset > oLitEnd.offset_from(prefixStart) as size_t {
1396 if (sequence.offset > oLitEnd.offset_from(virtualStart) as size_t) as core::ffi::c_int
1397 as core::ffi::c_long
1398 != 0
1399 {
1400 return Error::corruption_detected.to_error_code();
1401 }
1402 match_0 = dictEnd.offset(match_0.offset_from(prefixStart) as core::ffi::c_long as isize);
1403 if match_0.add(sequence.matchLength) <= dictEnd {
1404 libc::memmove(
1405 oLitEnd as *mut core::ffi::c_void,
1406 match_0 as *const core::ffi::c_void,
1407 sequence.matchLength as libc::size_t,
1408 );
1409 return sequenceLength;
1410 }
1411 let length1 = dictEnd.offset_from(match_0) as size_t;
1412 libc::memmove(
1413 oLitEnd as *mut core::ffi::c_void,
1414 match_0 as *const core::ffi::c_void,
1415 length1 as libc::size_t,
1416 );
1417 op = oLitEnd.add(length1);
1418 sequence.matchLength = (sequence.matchLength).wrapping_sub(length1);
1419 match_0 = prefixStart;
1420 }
1421 if (sequence.offset >= 16) as core::ffi::c_int as core::ffi::c_long != 0 {
1422 ZSTD_wildcopy(
1423 op as *mut core::ffi::c_void,
1424 match_0 as *const core::ffi::c_void,
1425 sequence.matchLength,
1426 Overlap::NoOverlap,
1427 );
1428 return sequenceLength;
1429 }
1430 ZSTD_overlapCopy8(&mut op, &mut match_0, sequence.offset);
1431 if sequence.matchLength > 8 {
1432 ZSTD_wildcopy(
1433 op as *mut core::ffi::c_void,
1434 match_0 as *const core::ffi::c_void,
1435 (sequence.matchLength).wrapping_sub(8),
1436 Overlap::OverlapSrcBeforeDst,
1437 );
1438 }
1439 sequenceLength
1440}
1441
1442unsafe fn ZSTD_initFseState(
1443 DStatePtr: &mut ZSTD_fseState,
1444 bitD: &mut BIT_DStream_t,
1445 dt: *const ZSTD_seqSymbol,
1446) {
1447 let ptr = dt as *const core::ffi::c_void;
1448 let DTableH = ptr as *const ZSTD_seqSymbol_header;
1449 DStatePtr.state = bitD.read_bits((*DTableH).tableLog) as size_t;
1450 bitD.reload();
1451 DStatePtr.table = dt.offset(1);
1452}
1453
1454#[inline(always)]
1455fn ZSTD_updateFseStateWithDInfo(
1456 DStatePtr: &mut ZSTD_fseState,
1457 bitD: &mut BIT_DStream_t,
1458 nextState: u16,
1459 nbBits: u32,
1460) {
1461 let lowBits = bitD.read_bits(nbBits);
1462 DStatePtr.state = (nextState as size_t).wrapping_add(lowBits as size_t);
1463}
1464
1465const LONG_OFFSETS_MAX_EXTRA_BITS_32: i32 =
1470 ZSTD_WINDOWLOG_MAX_32.saturating_sub(STREAM_ACCUMULATOR_MIN_32);
1471
1472#[inline(always)]
1473unsafe fn ZSTD_decodeSequence(
1474 seqState: &mut seqState_t,
1475 longOffsets: Offset,
1476 is_last_sequence: bool,
1477) -> seq_t {
1478 let mut seq = seq_t {
1479 litLength: 0,
1480 matchLength: 0,
1481 offset: 0,
1482 };
1483 let llDInfo = (seqState.stateLL.table).add(seqState.stateLL.state);
1484 let mlDInfo = (seqState.stateML.table).add(seqState.stateML.state);
1485 let ofDInfo = (seqState.stateOffb.table).add(seqState.stateOffb.state);
1486 seq.matchLength = (*mlDInfo).baseValue as size_t;
1487 seq.litLength = (*llDInfo).baseValue as size_t;
1488 let ofBase = (*ofDInfo).baseValue;
1489 let llBits = (*llDInfo).nbAdditionalBits;
1490 let mlBits = (*mlDInfo).nbAdditionalBits;
1491 let ofBits = (*ofDInfo).nbAdditionalBits;
1492 let totalBits = (llBits as core::ffi::c_int
1493 + mlBits as core::ffi::c_int
1494 + ofBits as core::ffi::c_int) as u8;
1495 let llNext = (*llDInfo).nextState;
1496 let mlNext = (*mlDInfo).nextState;
1497 let ofNext = (*ofDInfo).nextState;
1498 let llnbBits = (*llDInfo).nbBits as u32;
1499 let mlnbBits = (*mlDInfo).nbBits as u32;
1500 let ofnbBits = (*ofDInfo).nbBits as u32;
1501
1502 assert!(llBits <= MaxLLBits);
1503 assert!(mlBits <= MaxMLBits);
1504 assert!(ofBits as core::ffi::c_int <= MaxOff);
1505
1506 let mut offset: size_t = 0;
1507 if ofBits > 1 {
1508 const { assert!(Offset::Long as usize == 1) };
1509 const { assert!(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5) };
1510 const { assert!(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32) };
1511 const { assert!(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits as i32) };
1512
1513 if MEM_32bits() != 0
1514 && longOffsets != Offset::Regular
1515 && ofBits as core::ffi::c_int >= STREAM_ACCUMULATOR_MIN_32
1516 {
1517 let extraBits = LONG_OFFSETS_MAX_EXTRA_BITS_32 as u32;
1520 offset = (ofBase as size_t).wrapping_add(
1521 (seqState
1522 .DStream
1523 .read_bits_fast((ofBits as u32).wrapping_sub(extraBits))
1524 as size_t)
1525 << extraBits,
1526 );
1527 seqState.DStream.reload();
1528 offset = offset.wrapping_add(seqState.DStream.read_bits_fast(extraBits) as size_t);
1529 } else {
1530 offset = (ofBase as size_t).wrapping_add(
1531 seqState.DStream.read_bits_fast(ofBits as core::ffi::c_uint) as size_t,
1532 );
1533 if MEM_32bits() != 0 {
1534 seqState.DStream.reload();
1535 }
1536 }
1537
1538 seqState.prevOffset[2] = seqState.prevOffset[1];
1539 seqState.prevOffset[1] = seqState.prevOffset[0];
1540 seqState.prevOffset[0] = offset;
1541 } else {
1542 let ll0 = usize::from((*llDInfo).baseValue == 0);
1543 if core::hint::likely(ofBits == 0) {
1544 offset = seqState.prevOffset[ll0];
1545 seqState.prevOffset[1] = seqState.prevOffset[usize::from(ll0 == 0)];
1546 seqState.prevOffset[0] = offset;
1547 } else {
1548 offset = (ofBase.wrapping_add(ll0 as u32) as size_t)
1549 .wrapping_add(seqState.DStream.read_bits_fast(1) as size_t);
1550
1551 let mut temp = match offset {
1552 3 => seqState.prevOffset[0] - 1,
1553 _ => seqState.prevOffset[offset as usize],
1554 };
1555 temp = temp.wrapping_sub((temp == 0) as _); if offset != 1 {
1558 seqState.prevOffset[2] = seqState.prevOffset[1];
1559 }
1560 seqState.prevOffset[1] = seqState.prevOffset[0];
1561 seqState.prevOffset[0] = temp;
1562 offset = temp;
1563 }
1564 }
1565 seq.offset = offset;
1566
1567 if mlBits > 0 {
1568 seq.matchLength = seq
1569 .matchLength
1570 .wrapping_add(seqState.DStream.read_bits_fast(mlBits as core::ffi::c_uint) as size_t);
1571 }
1572
1573 if cfg!(target_pointer_width = "32")
1574 && (i32::from(mlBits + llBits)
1575 >= STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32)
1576 {
1577 seqState.DStream.reload();
1578 }
1579 if cfg!(target_pointer_width = "64")
1580 && (totalBits as core::ffi::c_int >= 57 - (9 + 9 + 8)) as core::ffi::c_int
1581 as core::ffi::c_long
1582 != 0
1583 {
1584 seqState.DStream.reload();
1585 }
1586
1587 const { assert!(16 + LLFSELog + MLFSELog + OffFSELog < STREAM_ACCUMULATOR_MIN_64) };
1589
1590 if llBits > 0 {
1591 seq.litLength = (seq.litLength)
1592 .wrapping_add(seqState.DStream.read_bits_fast(llBits as core::ffi::c_uint) as size_t);
1593 }
1594 if MEM_32bits() != 0 {
1595 seqState.DStream.reload();
1596 }
1597
1598 if !is_last_sequence {
1600 ZSTD_updateFseStateWithDInfo(
1601 &mut seqState.stateLL,
1602 &mut seqState.DStream,
1603 llNext,
1604 llnbBits,
1605 );
1606 ZSTD_updateFseStateWithDInfo(
1607 &mut seqState.stateML,
1608 &mut seqState.DStream,
1609 mlNext,
1610 mlnbBits,
1611 );
1612 if MEM_32bits() != 0 {
1613 seqState.DStream.reload();
1614 }
1615 ZSTD_updateFseStateWithDInfo(
1616 &mut seqState.stateOffb,
1617 &mut seqState.DStream,
1618 ofNext,
1619 ofnbBits,
1620 );
1621 seqState.DStream.reload();
1622 }
1623
1624 seq
1625}
1626
1627#[inline(always)]
1628unsafe fn ZSTD_decompressSequences_bodySplitLitBuffer(
1629 dctx: &mut ZSTD_DCtx,
1630 dst: *mut core::ffi::c_void,
1631 maxDstSize: size_t,
1632 seq: &[u8],
1633 mut nbSeq: core::ffi::c_int,
1634 offset: Offset,
1635) -> size_t {
1636 let ostart = dst as *mut u8;
1637 let oend =
1638 ZSTD_maybeNullPtrAdd(ostart as *mut core::ffi::c_void, maxDstSize as ptrdiff_t) as *mut u8;
1639 let mut op = ostart;
1640 let mut litPtr = dctx.litPtr;
1641 let mut litBufferEnd = dctx.litBufferEnd;
1642 let prefixStart = dctx.prefixStart as *const u8;
1643 let vBase = dctx.virtualStart as *const u8;
1644 let dictEnd = dctx.dictEnd as *const u8;
1645 if nbSeq != 0 {
1646 let mut seqState = seqState_t {
1647 DStream: BIT_DStream_t {
1648 bitContainer: 0,
1649 bitsConsumed: 0,
1650 ptr: core::ptr::null::<core::ffi::c_char>(),
1651 start: core::ptr::null::<core::ffi::c_char>(),
1652 limitPtr: core::ptr::null::<core::ffi::c_char>(),
1653 },
1654 stateLL: ZSTD_fseState {
1655 state: 0,
1656 table: core::ptr::null::<ZSTD_seqSymbol>(),
1657 },
1658 stateOffb: ZSTD_fseState {
1659 state: 0,
1660 table: core::ptr::null::<ZSTD_seqSymbol>(),
1661 },
1662 stateML: ZSTD_fseState {
1663 state: 0,
1664 table: core::ptr::null::<ZSTD_seqSymbol>(),
1665 },
1666 prevOffset: [0; 3],
1667 };
1668 dctx.fseEntropy = 1;
1669
1670 seqState.prevOffset = dctx.entropy.rep.map(|v| v as size_t);
1671
1672 seqState.DStream = match BIT_DStream_t::new(seq) {
1673 Ok(v) => v,
1674 Err(_) => return Error::corruption_detected.to_error_code(),
1675 };
1676 ZSTD_initFseState(&mut seqState.stateLL, &mut seqState.DStream, dctx.LLTptr);
1677 ZSTD_initFseState(&mut seqState.stateOffb, &mut seqState.DStream, dctx.OFTptr);
1678 ZSTD_initFseState(&mut seqState.stateML, &mut seqState.DStream, dctx.MLTptr);
1679 let mut sequence = {
1680 seq_t {
1681 litLength: 0,
1682 matchLength: 0,
1683 offset: 0,
1684 }
1685 };
1686
1687 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1688 if !cfg!(miri) {
1689 asm!(".p2align 6", options(preserves_flags, att_syntax));
1690 }
1691
1692 while nbSeq != 0 {
1693 sequence = ZSTD_decodeSequence(&mut seqState, offset, nbSeq == 1);
1694
1695 if litPtr.wrapping_add(sequence.litLength) > dctx.litBufferEnd {
1696 break;
1697 }
1698
1699 let oneSeqSize = ZSTD_execSequenceSplitLitBuffer(
1700 op,
1701 oend,
1702 litPtr.add(sequence.litLength).sub(WILDCOPY_OVERLENGTH),
1703 sequence,
1704 &mut litPtr,
1705 litBufferEnd,
1706 prefixStart,
1707 vBase,
1708 dictEnd,
1709 );
1710
1711 if ERR_isError(oneSeqSize) as core::ffi::c_long != 0 {
1712 return oneSeqSize;
1713 }
1714
1715 op = op.add(oneSeqSize);
1716 nbSeq -= 1;
1717 }
1718
1719 if nbSeq > 0 {
1720 let leftoverLit = (dctx.litBufferEnd).offset_from(litPtr) as size_t;
1721 if leftoverLit != 0 {
1722 if leftoverLit > oend.offset_from(op) as size_t {
1723 return Error::dstSize_tooSmall.to_error_code();
1724 }
1725 ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
1726 sequence.litLength = (sequence.litLength).wrapping_sub(leftoverLit);
1727 op = op.add(leftoverLit);
1728 }
1729 litPtr = dctx.litExtraBuffer.as_mut_ptr();
1730 litBufferEnd = dctx.litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE..].as_mut_ptr();
1731 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
1732 let oneSeqSize_0 = ZSTD_execSequence(
1733 op,
1734 oend,
1735 sequence,
1736 &mut litPtr,
1737 litBufferEnd,
1738 prefixStart,
1739 vBase,
1740 dictEnd,
1741 );
1742 if ERR_isError(oneSeqSize_0) as core::ffi::c_long != 0 {
1743 return oneSeqSize_0;
1744 }
1745 op = op.add(oneSeqSize_0);
1746 nbSeq -= 1;
1747 }
1748 if nbSeq > 0 {
1749 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1750 if !cfg!(miri) {
1751 asm!(".p2align 6", options(preserves_flags, att_syntax));
1752 asm!("nop", options(preserves_flags, att_syntax));
1753 asm!(".p2align 4", options(preserves_flags, att_syntax));
1754 asm!("nop", options(preserves_flags, att_syntax));
1755 asm!(".p2align 3", options(preserves_flags, att_syntax));
1756 }
1757
1758 while nbSeq != 0 {
1759 let sequence_0 = ZSTD_decodeSequence(&mut seqState, offset, nbSeq == 1);
1760 let oneSeqSize_1 = ZSTD_execSequence(
1761 op,
1762 oend,
1763 sequence_0,
1764 &mut litPtr,
1765 litBufferEnd,
1766 prefixStart,
1767 vBase,
1768 dictEnd,
1769 );
1770 if ERR_isError(oneSeqSize_1) as core::ffi::c_long != 0 {
1771 return oneSeqSize_1;
1772 }
1773 op = op.add(oneSeqSize_1);
1774 nbSeq -= 1;
1775 }
1776 }
1777 if nbSeq != 0 {
1778 return Error::corruption_detected.to_error_code();
1779 }
1780 if !seqState.DStream.is_empty() {
1781 return Error::corruption_detected.to_error_code();
1782 }
1783
1784 for i_0 in 0..ZSTD_REP_NUM {
1785 *(dctx.entropy.rep).as_mut_ptr().offset(i_0 as isize) =
1786 *(seqState.prevOffset).as_mut_ptr().offset(i_0 as isize) as u32;
1787 }
1788 }
1789
1790 if dctx.litBufferLocation == LitLocation::ZSTD_split {
1791 let lastLLSize = litBufferEnd.offset_from(litPtr) as size_t;
1792 if lastLLSize > oend.offset_from(op) as size_t {
1793 return Error::dstSize_tooSmall.to_error_code();
1794 }
1795 if !op.is_null() {
1796 libc::memmove(
1797 op as *mut core::ffi::c_void,
1798 litPtr as *const core::ffi::c_void,
1799 lastLLSize as libc::size_t,
1800 );
1801 op = op.add(lastLLSize);
1802 }
1803 litPtr = (dctx.litExtraBuffer).as_mut_ptr();
1804 litBufferEnd = dctx.litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE..].as_mut_ptr();
1805 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
1806 }
1807
1808 let lastLLSize_0 = litBufferEnd.offset_from(litPtr) as size_t;
1809 if lastLLSize_0 > oend.offset_from(op) as size_t {
1810 return Error::dstSize_tooSmall.to_error_code();
1811 }
1812
1813 if !op.is_null() {
1814 libc::memcpy(
1815 op as *mut core::ffi::c_void,
1816 litPtr as *const core::ffi::c_void,
1817 lastLLSize_0 as libc::size_t,
1818 );
1819 op = op.add(lastLLSize_0);
1820 }
1821 op.offset_from(ostart) as size_t
1822}
1823
1824#[inline(always)]
1825unsafe fn ZSTD_decompressSequences_body(
1826 dctx: &mut ZSTD_DCtx,
1827 dst: *mut core::ffi::c_void,
1828 maxDstSize: size_t,
1829 seq: &[u8],
1830 nbSeq: core::ffi::c_int,
1831 offset: Offset,
1832) -> size_t {
1833 let ostart = dst as *mut u8;
1834 let oend = if dctx.litBufferLocation == LitLocation::ZSTD_not_in_dst {
1835 ZSTD_maybeNullPtrAdd(ostart as *mut core::ffi::c_void, maxDstSize as ptrdiff_t) as *mut u8
1836 } else {
1837 dctx.litBuffer
1838 };
1839 let mut op = ostart;
1840 let mut litPtr = dctx.litPtr;
1841 let litEnd = litPtr.add(dctx.litSize);
1842 let prefixStart = dctx.prefixStart as *const u8;
1843 let vBase = dctx.virtualStart as *const u8;
1844 let dictEnd = dctx.dictEnd as *const u8;
1845 if nbSeq != 0 {
1846 let mut seqState = seqState_t {
1847 DStream: BIT_DStream_t {
1848 bitContainer: 0,
1849 bitsConsumed: 0,
1850 ptr: core::ptr::null::<core::ffi::c_char>(),
1851 start: core::ptr::null::<core::ffi::c_char>(),
1852 limitPtr: core::ptr::null::<core::ffi::c_char>(),
1853 },
1854 stateLL: ZSTD_fseState {
1855 state: 0,
1856 table: core::ptr::null::<ZSTD_seqSymbol>(),
1857 },
1858 stateOffb: ZSTD_fseState {
1859 state: 0,
1860 table: core::ptr::null::<ZSTD_seqSymbol>(),
1861 },
1862 stateML: ZSTD_fseState {
1863 state: 0,
1864 table: core::ptr::null::<ZSTD_seqSymbol>(),
1865 },
1866 prevOffset: [0; 3],
1867 };
1868 dctx.fseEntropy = 1;
1869 seqState.prevOffset = dctx.entropy.rep.map(|v| v as usize);
1870 seqState.DStream = match BIT_DStream_t::new(seq) {
1871 Ok(v) => v,
1872 Err(_) => return Error::corruption_detected.to_error_code(),
1873 };
1874
1875 ZSTD_initFseState(&mut seqState.stateLL, &mut seqState.DStream, dctx.LLTptr);
1876 ZSTD_initFseState(&mut seqState.stateOffb, &mut seqState.DStream, dctx.OFTptr);
1877 ZSTD_initFseState(&mut seqState.stateML, &mut seqState.DStream, dctx.MLTptr);
1878
1879 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1880 if !cfg!(miri) {
1881 asm!(".p2align 6", options(preserves_flags, att_syntax));
1882 asm!("nop", options(preserves_flags, att_syntax));
1883 asm!(".p2align 4", options(preserves_flags, att_syntax));
1884 asm!("nop", options(preserves_flags, att_syntax));
1885 asm!(".p2align 3", options(preserves_flags, att_syntax));
1886 }
1887
1888 for nbSeq in (1..=nbSeq).rev() {
1889 let sequence = ZSTD_decodeSequence(&mut seqState, offset, nbSeq == 1);
1890 let oneSeqSize = ZSTD_execSequence(
1891 op,
1892 oend,
1893 sequence,
1894 &mut litPtr,
1895 litEnd,
1896 prefixStart,
1897 vBase,
1898 dictEnd,
1899 );
1900
1901 if ERR_isError(oneSeqSize) as core::ffi::c_long != 0 {
1902 return oneSeqSize;
1903 }
1904
1905 op = op.add(oneSeqSize);
1906 }
1907
1908 if !seqState.DStream.is_empty() {
1909 return Error::corruption_detected.to_error_code();
1910 }
1911
1912 dctx.entropy.rep = seqState.prevOffset.map(|v| v as u32);
1913 }
1914
1915 let lastLLSize = litEnd.offset_from(litPtr) as size_t;
1916 if lastLLSize > oend.offset_from(op) as size_t {
1917 return Error::dstSize_tooSmall.to_error_code();
1918 }
1919
1920 if !op.is_null() {
1921 libc::memcpy(
1922 op as *mut core::ffi::c_void,
1923 litPtr as *const core::ffi::c_void,
1924 lastLLSize as libc::size_t,
1925 );
1926 op = op.add(lastLLSize);
1927 }
1928
1929 op.offset_from(ostart) as size_t
1930}
1931
1932unsafe fn ZSTD_decompressSequences_default(
1933 dctx: &mut ZSTD_DCtx,
1934 dst: *mut core::ffi::c_void,
1935 maxDstSize: size_t,
1936 seqStart: &[u8],
1937 nbSeq: core::ffi::c_int,
1938 offset: Offset,
1939) -> size_t {
1940 ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
1941}
1942
1943unsafe fn ZSTD_decompressSequencesSplitLitBuffer_default(
1944 dctx: &mut ZSTD_DCtx,
1945 dst: *mut core::ffi::c_void,
1946 maxDstSize: size_t,
1947 seqStart: &[u8],
1948 nbSeq: core::ffi::c_int,
1949 offset: Offset,
1950) -> size_t {
1951 ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
1952}
1953
1954pub const _PREFETCH_LOCALITY2: i32 = 2;
1955pub const _PREFETCH_LOCALITY3: i32 = 3;
1956
1957#[inline(always)]
1958#[cfg(target_arch = "aarch64")]
1959unsafe fn _prefetch_read<const LOCALITY: i32>(ptr: *const i8) {
1960 core::arch::asm!(
1961 "prfm {op}, [{addr}]",
1962 op = const {
1963 match LOCALITY {
1964 0 => 0b00000, 1 => 0b00001, 2 => 0b00010, 3 => 0b00011, _ => panic!(),
1969 }
1970 },
1971 addr = in(reg) ptr,
1972 options(nostack, preserves_flags)
1973 );
1974}
1975
1976#[inline(always)]
1977fn prefetch_l1<T>(ptr: *const T) {
1978 if cfg!(feature = "no-prefetch") {
1979 return;
1980 }
1981
1982 #[cfg(target_arch = "x86_64")]
1983 {
1984 use core::arch::x86_64;
1985 unsafe { x86_64::_mm_prefetch(ptr as *const i8, x86_64::_MM_HINT_T0) };
1986 return;
1987 }
1988
1989 #[cfg(target_arch = "x86")]
1990 if cfg!(target_feature = "sse") {
1991 use core::arch::x86;
1992 unsafe { x86::_mm_prefetch(ptr as *const i8, x86::_MM_HINT_T0) };
1993 return;
1994 }
1995
1996 #[cfg(target_arch = "aarch64")]
1997 {
1998 unsafe { _prefetch_read::<_PREFETCH_LOCALITY3>(ptr as *const i8) };
2000 return;
2001 }
2002}
2003
2004#[inline(always)]
2005fn prefetch_l2<T>(ptr: *const T) {
2006 if cfg!(feature = "no-prefetch") {
2007 return;
2008 }
2009
2010 #[cfg(target_arch = "x86_64")]
2011 {
2012 use core::arch::x86_64;
2013 unsafe { x86_64::_mm_prefetch(ptr as *const i8, x86_64::_MM_HINT_T1) };
2014 return;
2015 }
2016
2017 #[cfg(target_arch = "x86")]
2018 if cfg!(target_feature = "sse") {
2019 use core::arch::x86;
2020 unsafe { x86::_mm_prefetch(ptr as *const i8, x86::_MM_HINT_T1) };
2021 return;
2022 }
2023
2024 #[cfg(target_arch = "aarch64")]
2025 {
2026 unsafe { _prefetch_read::<_PREFETCH_LOCALITY2>(ptr as *const i8) };
2028 return;
2029 }
2030}
2031
2032#[inline(always)]
2033fn prefetch_area<T>(ptr: *const T, bytes: usize) {
2034 for pos in (0..bytes).step_by(CACHELINE_SIZE as size_t) {
2035 prefetch_l2(ptr.wrapping_byte_add(pos));
2036 }
2037}
2038
2039#[inline(always)]
2040fn prefetch_val<T>(ptr: *const T) {
2041 prefetch_area(ptr, size_of::<T>())
2042}
2043
2044#[inline(always)]
2045unsafe fn ZSTD_prefetchMatch(
2046 prefetchPos: size_t,
2047 sequence: seq_t,
2048 prefixStart: *const u8,
2049 dictEnd: *const u8,
2050) -> size_t {
2051 let matchBase = if sequence.offset > prefetchPos.wrapping_add(sequence.litLength) {
2052 dictEnd
2053 } else {
2054 prefixStart
2055 };
2056
2057 let match_ = matchBase
2058 .wrapping_add(prefetchPos)
2059 .wrapping_sub(sequence.offset);
2060
2061 prefetch_l1(match_);
2062 prefetch_l1(match_.wrapping_add(64));
2063
2064 prefetchPos.wrapping_add(sequence.matchLength)
2065}
2066
2067#[inline(always)]
2068unsafe fn ZSTD_decompressSequencesLong_body(
2069 dctx: &mut ZSTD_DCtx,
2070 mut dst: Writer<'_>,
2071 seq: &[u8],
2072 nbSeq: core::ffi::c_int,
2073 offset: Offset,
2074) -> size_t {
2075 let ostart = dst.as_mut_ptr();
2076 let oend = if dctx.litBufferLocation == LitLocation::ZSTD_in_dst {
2077 dctx.litBuffer
2078 } else {
2079 dst.as_mut_ptr_range().end
2080 };
2081 let mut op = ostart;
2082 let mut litPtr = dctx.litPtr;
2083 let mut litBufferEnd = dctx.litBufferEnd;
2084 let prefixStart = dctx.prefixStart as *const u8;
2085 let dictStart = dctx.virtualStart as *const u8;
2086 let dictEnd = dctx.dictEnd as *const u8;
2087 if nbSeq != 0 {
2088 let seqAdvance = if nbSeq < 8 { nbSeq } else { 8 };
2089 let mut seqState = seqState_t {
2090 DStream: BIT_DStream_t {
2091 bitContainer: 0,
2092 bitsConsumed: 0,
2093 ptr: core::ptr::null::<core::ffi::c_char>(),
2094 start: core::ptr::null::<core::ffi::c_char>(),
2095 limitPtr: core::ptr::null::<core::ffi::c_char>(),
2096 },
2097 stateLL: ZSTD_fseState {
2098 state: 0,
2099 table: core::ptr::null::<ZSTD_seqSymbol>(),
2100 },
2101 stateOffb: ZSTD_fseState {
2102 state: 0,
2103 table: core::ptr::null::<ZSTD_seqSymbol>(),
2104 },
2105 stateML: ZSTD_fseState {
2106 state: 0,
2107 table: core::ptr::null::<ZSTD_seqSymbol>(),
2108 },
2109 prevOffset: [0; 3],
2110 };
2111 dctx.fseEntropy = 1;
2112 seqState.prevOffset = dctx.entropy.rep.map(|v| v as usize);
2113 seqState.DStream = match BIT_DStream_t::new(seq) {
2114 Ok(v) => v,
2115 Err(_) => return Error::corruption_detected.to_error_code(),
2116 };
2117
2118 ZSTD_initFseState(&mut seqState.stateLL, &mut seqState.DStream, dctx.LLTptr);
2119 ZSTD_initFseState(&mut seqState.stateOffb, &mut seqState.DStream, dctx.OFTptr);
2120 ZSTD_initFseState(&mut seqState.stateML, &mut seqState.DStream, dctx.MLTptr);
2121
2122 let mut prefetchPos = op.offset_from(prefixStart) as usize;
2123 let mut sequences: [seq_t; 8] = [seq_t::default(); 8];
2124
2125 for seqNb in 0..seqAdvance {
2126 let sequence = ZSTD_decodeSequence(&mut seqState, offset, seqNb == nbSeq - 1);
2127 prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
2128 sequences[seqNb as usize] = sequence;
2129 }
2130
2131 for seqNb in seqAdvance..nbSeq {
2132 let sequence_0 = ZSTD_decodeSequence(&mut seqState, offset, seqNb == nbSeq - 1);
2133 if dctx.litBufferLocation == LitLocation::ZSTD_split
2134 && litPtr.add(
2135 (sequences[((seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK) as usize]).litLength,
2136 ) > dctx.litBufferEnd
2137 {
2138 let leftoverLit = (dctx.litBufferEnd).offset_from(litPtr) as size_t;
2139 if leftoverLit != 0 {
2140 if leftoverLit > oend.offset_from(op) as size_t {
2141 return Error::dstSize_tooSmall.to_error_code();
2142 }
2143 ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
2144 sequences[((seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK) as usize].litLength += 1;
2145 op = op.add(leftoverLit);
2146 }
2147 litPtr = (dctx.litExtraBuffer).as_mut_ptr();
2148 litBufferEnd = dctx.litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE..].as_mut_ptr();
2149 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
2150 let oneSeqSize = ZSTD_execSequence(
2151 op,
2152 oend,
2153 sequences[((seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK) as usize],
2154 &mut litPtr,
2155 litBufferEnd,
2156 prefixStart,
2157 dictStart,
2158 dictEnd,
2159 );
2160
2161 if ERR_isError(oneSeqSize) {
2162 return oneSeqSize;
2163 }
2164
2165 prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence_0, prefixStart, dictEnd);
2166 sequences[(seqNb & STORED_SEQS_MASK) as usize] = sequence_0;
2167 op = op.add(oneSeqSize);
2168 } else {
2169 let sequence = sequences[((seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK) as usize];
2170 let oneSeqSize_0 = if dctx.litBufferLocation == LitLocation::ZSTD_split {
2171 ZSTD_execSequenceSplitLitBuffer(
2172 op,
2173 oend,
2174 litPtr.add(sequence.litLength).sub(WILDCOPY_OVERLENGTH),
2175 sequences[((seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK) as usize],
2176 &mut litPtr,
2177 litBufferEnd,
2178 prefixStart,
2179 dictStart,
2180 dictEnd,
2181 )
2182 } else {
2183 ZSTD_execSequence(
2184 op,
2185 oend,
2186 sequence,
2187 &mut litPtr,
2188 litBufferEnd,
2189 prefixStart,
2190 dictStart,
2191 dictEnd,
2192 )
2193 };
2194 if ERR_isError(oneSeqSize_0) {
2195 return oneSeqSize_0;
2196 }
2197
2198 prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence_0, prefixStart, dictEnd);
2199 sequences[(seqNb & STORED_SEQS_MASK) as usize] = sequence_0;
2200 op = op.add(oneSeqSize_0);
2201 }
2202 }
2203
2204 if !seqState.DStream.is_empty() {
2205 return Error::corruption_detected.to_error_code();
2206 }
2207
2208 for seqNb in nbSeq - seqAdvance..nbSeq {
2209 let sequence = &mut sequences[(seqNb & STORED_SEQS_MASK) as usize];
2210 if dctx.litBufferLocation == LitLocation::ZSTD_split
2211 && litPtr.add(sequence.litLength) > dctx.litBufferEnd
2212 {
2213 let leftoverLit_0 = (dctx.litBufferEnd).offset_from(litPtr) as size_t;
2214 if leftoverLit_0 != 0 {
2215 if leftoverLit_0 > oend.offset_from(op) as size_t {
2216 return Error::dstSize_tooSmall.to_error_code();
2217 }
2218 ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit_0);
2219 sequence.litLength = (sequence.litLength).wrapping_sub(leftoverLit_0);
2220 op = op.add(leftoverLit_0);
2221 }
2222 litPtr = (dctx.litExtraBuffer).as_mut_ptr();
2223 litBufferEnd = dctx.litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE..].as_mut_ptr();
2224 dctx.litBufferLocation = LitLocation::ZSTD_not_in_dst;
2225 let oneSeqSize_1 = ZSTD_execSequence(
2226 op,
2227 oend,
2228 *sequence,
2229 &mut litPtr,
2230 litBufferEnd,
2231 prefixStart,
2232 dictStart,
2233 dictEnd,
2234 );
2235 if ERR_isError(oneSeqSize_1) {
2236 return oneSeqSize_1;
2237 }
2238 op = op.add(oneSeqSize_1);
2239 } else {
2240 let oneSeqSize_2 = if dctx.litBufferLocation == LitLocation::ZSTD_split {
2241 ZSTD_execSequenceSplitLitBuffer(
2242 op,
2243 oend,
2244 litPtr.add(sequence.litLength).sub(WILDCOPY_OVERLENGTH),
2245 *sequence,
2246 &mut litPtr,
2247 litBufferEnd,
2248 prefixStart,
2249 dictStart,
2250 dictEnd,
2251 )
2252 } else {
2253 ZSTD_execSequence(
2254 op,
2255 oend,
2256 *sequence,
2257 &mut litPtr,
2258 litBufferEnd,
2259 prefixStart,
2260 dictStart,
2261 dictEnd,
2262 )
2263 };
2264 if ERR_isError(oneSeqSize_2) {
2265 return oneSeqSize_2;
2266 }
2267 op = op.add(oneSeqSize_2);
2268 }
2269 }
2270
2271 dctx.entropy.rep = seqState.prevOffset.map(|v| v as u32);
2272 }
2273
2274 if dctx.litBufferLocation == LitLocation::ZSTD_split {
2275 let lastLLSize = litBufferEnd.offset_from(litPtr) as size_t;
2276 if lastLLSize > oend.offset_from(op) as size_t {
2277 return Error::dstSize_tooSmall.to_error_code();
2278 }
2279 if !op.is_null() {
2280 libc::memmove(
2281 op as *mut core::ffi::c_void,
2282 litPtr as *const core::ffi::c_void,
2283 lastLLSize as libc::size_t,
2284 );
2285 op = op.add(lastLLSize);
2286 }
2287 litPtr = (dctx.litExtraBuffer).as_mut_ptr();
2288 litBufferEnd = dctx.litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE..].as_mut_ptr();
2289 }
2290
2291 let lastLLSize_0 = litBufferEnd.offset_from(litPtr) as size_t;
2292 if lastLLSize_0 > oend.offset_from(op) as size_t {
2293 return Error::dstSize_tooSmall.to_error_code();
2294 }
2295
2296 if !op.is_null() {
2297 libc::memmove(
2298 op as *mut core::ffi::c_void,
2299 litPtr as *const core::ffi::c_void,
2300 lastLLSize_0 as libc::size_t,
2301 );
2302 op = op.add(lastLLSize_0);
2303 }
2304
2305 op.offset_from(ostart) as size_t
2306}
2307
2308pub const STORED_SEQS: core::ffi::c_int = 8;
2309pub const STORED_SEQS_MASK: core::ffi::c_int = STORED_SEQS - 1;
2310pub const ADVANCED_SEQS: core::ffi::c_int = STORED_SEQS;
2311unsafe fn ZSTD_decompressSequencesLong_default(
2312 dctx: &mut ZSTD_DCtx,
2313 dst: Writer<'_>,
2314 seqStart: &[u8],
2315 nbSeq: core::ffi::c_int,
2316 offset: Offset,
2317) -> size_t {
2318 ZSTD_decompressSequencesLong_body(dctx, dst, seqStart, nbSeq, offset)
2319}
2320
2321unsafe fn ZSTD_decompressSequences_bmi2(
2322 dctx: &mut ZSTD_DCtx,
2323 dst: *mut core::ffi::c_void,
2324 maxDstSize: size_t,
2325 seqStart: &[u8],
2326 nbSeq: core::ffi::c_int,
2327 offset: Offset,
2328) -> size_t {
2329 ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
2330}
2331
2332unsafe fn ZSTD_decompressSequencesSplitLitBuffer_bmi2(
2333 dctx: &mut ZSTD_DCtx,
2334 dst: *mut core::ffi::c_void,
2335 maxDstSize: size_t,
2336 seqStart: &[u8],
2337 nbSeq: core::ffi::c_int,
2338 offset: Offset,
2339) -> size_t {
2340 ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
2341}
2342
2343unsafe fn ZSTD_decompressSequencesLong_bmi2(
2344 dctx: &mut ZSTD_DCtx,
2345 dst: Writer<'_>,
2346 seqStart: &[u8],
2347 nbSeq: core::ffi::c_int,
2348 offset: Offset,
2349) -> size_t {
2350 ZSTD_decompressSequencesLong_body(dctx, dst, seqStart, nbSeq, offset)
2351}
2352
2353unsafe fn ZSTD_decompressSequences(
2354 dctx: &mut ZSTD_DCtx,
2355 dst: *mut core::ffi::c_void,
2356 maxDstSize: size_t,
2357 seqStart: &[u8],
2358 nbSeq: core::ffi::c_int,
2359 offset: Offset,
2360) -> size_t {
2361 if ZSTD_DCtx_get_bmi2(dctx) != 0 {
2362 ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
2363 } else {
2364 ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
2365 }
2366}
2367
2368unsafe fn ZSTD_decompressSequencesSplitLitBuffer(
2369 dctx: &mut ZSTD_DCtx,
2370 dst: *mut core::ffi::c_void,
2371 maxDstSize: size_t,
2372 seqStart: &[u8],
2373 nbSeq: core::ffi::c_int,
2374 offset: Offset,
2375) -> size_t {
2376 if ZSTD_DCtx_get_bmi2(dctx) != 0 {
2377 ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, nbSeq, offset)
2378 } else {
2379 ZSTD_decompressSequencesSplitLitBuffer_default(
2380 dctx, dst, maxDstSize, seqStart, nbSeq, offset,
2381 )
2382 }
2383}
2384
2385unsafe fn ZSTD_decompressSequencesLong(
2386 dctx: &mut ZSTD_DCtx,
2387 dst: Writer<'_>,
2388 seqStart: &[u8],
2389 nbSeq: core::ffi::c_int,
2390 offset: Offset,
2391) -> size_t {
2392 if ZSTD_DCtx_get_bmi2(dctx) != 0 {
2393 ZSTD_decompressSequencesLong_bmi2(dctx, dst, seqStart, nbSeq, offset)
2394 } else {
2395 ZSTD_decompressSequencesLong_default(dctx, dst, seqStart, nbSeq, offset)
2396 }
2397}
2398
2399unsafe fn ZSTD_getOffsetInfo(
2400 offTable: *const ZSTD_seqSymbol,
2401 nbSeq: core::ffi::c_int,
2402) -> ZSTD_OffsetInfo {
2403 let mut info = {
2404 ZSTD_OffsetInfo {
2405 longOffsetShare: 0,
2406 maxNbAdditionalBits: 0,
2407 }
2408 };
2409 if nbSeq != 0 {
2410 let ptr = offTable as *const core::ffi::c_void;
2411 let tableLog = (*(ptr as *const ZSTD_seqSymbol_header).offset(0)).tableLog;
2412 let table = offTable.offset(1);
2413 for u in 0..1 << tableLog {
2414 info.maxNbAdditionalBits = if info.maxNbAdditionalBits
2415 > (*table.add(u)).nbAdditionalBits as core::ffi::c_uint
2416 {
2417 info.maxNbAdditionalBits
2418 } else {
2419 (*table.add(u)).nbAdditionalBits as core::ffi::c_uint
2420 };
2421 if (*table.add(u)).nbAdditionalBits as core::ffi::c_int > 22 {
2422 info.longOffsetShare = (info.longOffsetShare).wrapping_add(1);
2423 }
2424 }
2425 info.longOffsetShare <<= (OffFSELog as u32).wrapping_sub(tableLog);
2426 }
2427 info
2428}
2429
2430const fn ZSTD_maxShortOffset() -> size_t {
2434 match size_of::<usize>() {
2435 4 => {
2436 let maxOffbase = ((1 as size_t) << (STREAM_ACCUMULATOR_MIN as u32 + 1)).wrapping_sub(1);
2440
2441 maxOffbase.wrapping_sub(ZSTD_REP_NUM as size_t)
2442 }
2443 8 => {
2444 const { assert!(ZSTD_WINDOWLOG_MAX <= 31) }
2447
2448 -(1 as core::ffi::c_int) as size_t
2449 }
2450 _ => unreachable!(),
2451 }
2452}
2453
2454pub unsafe fn ZSTD_decompressBlock_internal(
2455 dctx: *mut ZSTD_DCtx,
2456 dst: *mut core::ffi::c_void,
2457 dstCapacity: size_t,
2458 src: *const core::ffi::c_void,
2459 srcSize: size_t,
2460 streaming: streaming_operation,
2461) -> size_t {
2462 let Some(dctx) = dctx.as_mut() else {
2463 return Error::GENERIC.to_error_code();
2464 };
2465
2466 let Ok(streaming) = StreamingOperation::try_from(streaming) else {
2467 return Error::GENERIC.to_error_code();
2468 };
2469
2470 let src = if src.is_null() {
2471 &[]
2472 } else {
2473 core::slice::from_raw_parts(src.cast::<u8>(), srcSize)
2474 };
2475
2476 let dst = Writer::from_raw_parts(dst.cast::<u8>(), dstCapacity);
2478
2479 ZSTD_decompressBlock_internal_help(dctx, dst, src, streaming)
2480}
2481
2482unsafe fn ZSTD_decompressBlock_internal_help(
2483 dctx: &mut ZSTD_DCtx,
2484 mut dst: Writer<'_>,
2485 src: &[u8],
2486 streaming: StreamingOperation,
2487) -> size_t {
2488 if src.len() > dctx.block_size_max() {
2489 return Error::srcSize_wrong.to_error_code();
2490 }
2491
2492 let litCSize = ZSTD_decodeLiteralsBlock(dctx, src, dst.subslice(..), streaming);
2493 if ERR_isError(litCSize) {
2494 return litCSize;
2495 }
2496
2497 let mut ip = &src[litCSize as usize..];
2498
2499 let blockSizeMax = Ord::min(dst.capacity(), dctx.block_size_max());
2500 let totalHistorySize =
2501 dst.as_mut_ptr().wrapping_add(blockSizeMax) as usize - dctx.virtualStart as usize;
2502 let mut offset = if MEM_32bits() != 0 && totalHistorySize > ZSTD_maxShortOffset() {
2503 Offset::Long
2504 } else {
2505 Offset::Regular
2506 };
2507 let mut use_prefetch_decoder = dctx.ddictIsCold != 0;
2508 let mut nbSeq: core::ffi::c_int = 0;
2509 let seqHSize = ZSTD_decodeSeqHeaders(dctx, &mut nbSeq, ip);
2510 if ERR_isError(seqHSize) {
2511 return seqHSize;
2512 }
2513 ip = &ip[seqHSize as usize..];
2514 if dst.is_empty() && nbSeq > 0 {
2515 return Error::dstSize_tooSmall.to_error_code();
2516 }
2517 if MEM_64bits() != 0
2518 && ::core::mem::size_of::<size_t>() == ::core::mem::size_of::<*mut core::ffi::c_void>()
2519 && (usize::MAX - dst.as_mut_ptr() as usize) < (1 << 20)
2520 {
2521 return Error::dstSize_tooSmall.to_error_code();
2522 }
2523 if offset == Offset::Long
2524 || !use_prefetch_decoder && totalHistorySize > ((1) << 24) as size_t && nbSeq > 8
2525 {
2526 let info = ZSTD_getOffsetInfo(dctx.OFTptr, nbSeq);
2527 if offset == Offset::Long && info.maxNbAdditionalBits <= STREAM_ACCUMULATOR_MIN as u32 {
2528 offset = Offset::Regular;
2529 }
2530 if !use_prefetch_decoder {
2531 let minShare = (if MEM_64bits() != 0 { 7 } else { 20 }) as u32;
2532 use_prefetch_decoder = info.longOffsetShare >= minShare;
2533 }
2534 }
2535
2536 dctx.ddictIsCold = 0;
2537
2538 if use_prefetch_decoder {
2539 return ZSTD_decompressSequencesLong(dctx, dst.subslice(..), ip, nbSeq, offset);
2540 }
2541
2542 if dctx.litBufferLocation == LitLocation::ZSTD_split {
2543 ZSTD_decompressSequencesSplitLitBuffer(
2544 dctx,
2545 dst.as_mut_ptr().cast(),
2546 dst.capacity(),
2547 ip,
2548 nbSeq,
2549 offset,
2550 )
2551 } else {
2552 ZSTD_decompressSequences(
2553 dctx,
2554 dst.as_mut_ptr().cast(),
2555 dst.capacity(),
2556 ip,
2557 nbSeq,
2558 offset,
2559 )
2560 }
2561}
2562
2563pub unsafe fn ZSTD_checkContinuity(
2564 dctx: *mut ZSTD_DCtx,
2565 dst: *const core::ffi::c_void,
2566 dstSize: size_t,
2567) {
2568 if dst != (*dctx).previousDstEnd && dstSize > 0 {
2569 (*dctx).dictEnd = (*dctx).previousDstEnd;
2570 (*dctx).virtualStart =
2571 dst.byte_offset(-(((*dctx).previousDstEnd).byte_offset_from((*dctx).prefixStart)));
2572 (*dctx).prefixStart = dst;
2573 (*dctx).previousDstEnd = dst;
2574 }
2575}
2576
2577unsafe fn ZSTD_decompressBlock_deprecated(
2578 dctx: *mut ZSTD_DCtx,
2579 dst: *mut core::ffi::c_void,
2580 dstCapacity: size_t,
2581 src: *const core::ffi::c_void,
2582 srcSize: size_t,
2583) -> size_t {
2584 let mut dSize: size_t = 0;
2585 (*dctx).isFrameDecompression = 0;
2586 ZSTD_checkContinuity(dctx, dst, dstCapacity);
2587 dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, not_streaming);
2588 let err_code = dSize;
2589 if ERR_isError(err_code) {
2590 return err_code;
2591 }
2592 (*dctx).previousDstEnd = dst.byte_add(dSize);
2593 dSize
2594}
2595
2596#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(ZSTD_decompressBlock))]
2597pub unsafe extern "C" fn ZSTD_decompressBlock(
2598 dctx: *mut ZSTD_DCtx,
2599 dst: *mut core::ffi::c_void,
2600 dstCapacity: size_t,
2601 src: *const core::ffi::c_void,
2602 srcSize: size_t,
2603) -> size_t {
2604 ZSTD_decompressBlock_deprecated(dctx, dst, dstCapacity, src, srcSize)
2605}
2606
2607#[cfg(test)]
2608mod test {
2609 use core::ffi::*;
2610
2611 #[test]
2612 fn basic_decompress() {
2613 rs(&[40, 181, 47, 253, 48, 21, 44, 0, 0, 0, 253, 49, 0, 21]);
2614 }
2615
2616 fn rs(compressed: &[u8]) -> (usize, Vec<u8>) {
2617 use crate::lib::decompress::zstd_decompress::*;
2618
2619 let compressed_ptr = compressed.as_ptr() as *const c_void;
2620 let compressed_size = compressed.len();
2621
2622 let decompressed_size =
2624 unsafe { ZSTD_getFrameContentSize(compressed_ptr, compressed_size) };
2625 if decompressed_size == ZSTD_CONTENTSIZE_ERROR {
2626 return (decompressed_size as usize, vec![]);
2627 } else if decompressed_size == ZSTD_CONTENTSIZE_UNKNOWN {
2628 return (decompressed_size as usize, vec![]);
2629 }
2630
2631 let mut decompressed = vec![0u8; Ord::min(decompressed_size as usize, 1 << 20)];
2633 let result = unsafe {
2634 ZSTD_decompress(
2635 decompressed.as_mut_ptr() as *mut c_void,
2636 decompressed.len(),
2637 compressed_ptr,
2638 compressed_size,
2639 )
2640 };
2641
2642 (result as usize, decompressed)
2643 }
2644}