1use core::ptr::NonNull;
2use libc::size_t;
3
4use crate::lib::common::xxhash::XXH64_state_t;
5
6use crate::lib::common::zstd_internal::WILDCOPY_OVERLENGTH;
7use crate::lib::common::zstd_trace::ZSTD_TraceCtx;
8use crate::lib::decompress::huf_decompress::DTable;
9use crate::lib::decompress::zstd_ddict::{MultipleDDicts, ZSTD_DDict, ZSTD_DDictHashSet};
10use crate::lib::decompress::zstd_decompress_block::{FseWorkspace, ZSTD_LITBUFFEREXTRASIZE};
11use crate::lib::zstd::{BufferMode, ForceIgnoreChecksum, Format, ZSTD_customMem, ZSTD_outBuffer};
12
13pub mod huf_decompress;
14pub mod zstd_ddict;
15pub mod zstd_decompress;
16pub mod zstd_decompress_block;
17
18#[cfg(doc)]
19use crate::{ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_FRAMEHEADERSIZE_MAX};
20
21static LL_base: [u32; 36] = [
22 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 28, 32, 40, 48, 64,
23 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000,
24];
25static OF_base: [u32; 32] = [
26 0, 1, 1, 5, 0xd, 0x1d, 0x3d, 0x7d, 0xfd, 0x1fd, 0x3fd, 0x7fd, 0xffd, 0x1ffd, 0x3ffd, 0x7ffd,
27 0xfffd, 0x1fffd, 0x3fffd, 0x7fffd, 0xffffd, 0x1ffffd, 0x3ffffd, 0x7ffffd, 0xfffffd, 0x1fffffd,
28 0x3fffffd, 0x7fffffd, 0xffffffd, 0x1ffffffd, 0x3ffffffd, 0x7ffffffd,
29];
30static OF_bits: [u8; 32] = [
31 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
32 26, 27, 28, 29, 30, 31,
33];
34static ML_base: [u32; 53] = [
35 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
36 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203,
37 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003,
38];
39
40#[derive(Copy, Clone)]
41#[repr(C)]
42pub struct ZSTD_seqSymbol_header {
43 pub fastMode: u32,
44 pub tableLog: u32,
45}
46
47#[derive(Copy, Clone)]
48#[repr(C)]
49pub struct ZSTD_seqSymbol {
50 pub nextState: u16,
51 pub nbAdditionalBits: u8,
52 pub nbBits: u8,
53 pub baseValue: u32,
54}
55
56#[derive(Copy, Clone)]
57#[repr(C)]
58pub struct ZSTD_entropyDTables_t {
59 pub LLTable: SymbolTable<512>,
60 pub OFTable: SymbolTable<256>,
61 pub MLTable: SymbolTable<512>,
62 pub hufTable: DTable,
63 pub rep: [u32; 3],
64 pub workspace: FseWorkspace,
65}
66
67#[derive(Copy, Clone)]
68#[repr(C)]
69pub struct SymbolTable<const N: usize> {
70 header: ZSTD_seqSymbol_header,
71 symbols: [ZSTD_seqSymbol; N],
72}
73
74pub type ZSTD_dStage = core::ffi::c_uint;
75
76#[repr(u32)]
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub enum DecompressStage {
79 GetFrameHeaderSize = 0,
80 DecodeFrameHeader = 1,
81 DecodeBlockHeader = 2,
82 DecompressBlock = 3,
83 DecompressLastBlock = 4,
84 CheckChecksum = 5,
85 DecodeSkippableHeader = 6,
86 SkipFrame = 7,
87}
88
89impl DecompressStage {
90 pub const fn to_next_input_type(self) -> NextInputType {
91 match self {
92 Self::DecodeBlockHeader => NextInputType::BlockHeader,
93 Self::DecompressBlock => NextInputType::Block,
94 Self::DecompressLastBlock => NextInputType::LastBlock,
95 Self::CheckChecksum => NextInputType::Checksum,
96 Self::DecodeSkippableHeader | Self::SkipFrame => NextInputType::SkippableFrame,
97 Self::GetFrameHeaderSize | Self::DecodeFrameHeader => NextInputType::FrameHeader,
98 }
99 }
100}
101
102#[repr(u32)]
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum NextInputType {
106 FrameHeader = zstd_decompress::ZSTDnit_frameHeader,
107 BlockHeader = zstd_decompress::ZSTDnit_blockHeader,
108 Block = zstd_decompress::ZSTDnit_block,
109 LastBlock = zstd_decompress::ZSTDnit_lastBlock,
110 Checksum = zstd_decompress::ZSTDnit_checksum,
111 SkippableFrame = zstd_decompress::ZSTDnit_skippableFrame,
112}
113
114#[repr(u32)]
115#[derive(Debug, Clone, Copy, PartialEq, Eq)]
116pub enum StreamStage {
117 Init,
118 LoadHeader,
119 Read,
120 Load,
121 Flush,
122}
123
124#[repr(i32)]
125enum DictUses {
126 ZSTD_use_once = 1,
127 ZSTD_dont_use = 0,
128 ZSTD_use_indefinitely = -1,
129}
130
131#[repr(u32)]
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum LitLocation {
134 ZSTD_split = 2,
136 ZSTD_in_dst = 1,
138 ZSTD_not_in_dst = 0,
140}
141
142pub type ZSTD_FrameType_e = core::ffi::c_uint;
143pub const ZSTD_skippableFrame: ZSTD_FrameType_e = 1;
144pub const ZSTD_frame: ZSTD_FrameType_e = 0;
145
146#[derive(Copy, Clone, Default)]
147#[repr(C)]
148pub(crate) struct blockProperties_t {
149 pub blockType: BlockType,
150 pub lastBlock: bool,
151 pub origSize: u32,
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
155pub(crate) enum BlockType {
156 #[default]
157 Raw = 0,
158 Rle = 1,
159 Compressed = 2,
160 Reserved = 3,
161}
162
163impl From<u32> for BlockType {
164 fn from(value: u32) -> Self {
165 match value {
166 0 => Self::Raw,
167 1 => Self::Rle,
168 2 => Self::Compressed,
169 3 => Self::Reserved,
170 _ => panic!("invalid `BlockType`: {value}"),
171 }
172 }
173}
174
175#[derive(Default)]
176#[repr(C)]
177pub struct ZSTD_FrameHeader {
178 pub frameContentSize: core::ffi::c_ulonglong,
180 pub windowSize: core::ffi::c_ulonglong,
182 pub blockSizeMax: core::ffi::c_uint,
183 pub frameType: ZSTD_FrameType_e,
185 pub headerSize: core::ffi::c_uint,
186 pub dictID: core::ffi::c_uint,
188 pub checksumFlag: core::ffi::c_uint,
189 pub _reserved1: core::ffi::c_uint,
190 pub _reserved2: core::ffi::c_uint,
191}
192
193#[repr(C)]
194pub struct Workspace {
195 data: [u32; 640],
196}
197
198impl Default for Workspace {
199 fn default() -> Self {
200 Self { data: [0; 640] }
201 }
202}
203
204impl Workspace {
205 fn as_x1_mut(&mut self) -> &mut huf_decompress::HUF_ReadDTableX1_Workspace {
206 const { assert!(size_of::<Self>() >= size_of::<huf_decompress::HUF_ReadDTableX1_Workspace>()) }
207 const { assert!(align_of::<Self>() >= align_of::<huf_decompress::HUF_ReadDTableX1_Workspace>()) }
208
209 unsafe { core::mem::transmute(&mut self.data) }
210 }
211
212 fn as_x2_mut(&mut self) -> &mut huf_decompress::HUF_ReadDTableX2_Workspace {
213 const { assert!(size_of::<Self>() >= size_of::<huf_decompress::HUF_ReadDTableX2_Workspace>()) }
214 const { assert!(align_of::<Self>() >= align_of::<huf_decompress::HUF_ReadDTableX2_Workspace>()) }
215
216 unsafe { core::mem::transmute(&mut self.data) }
217 }
218
219 fn as_fse_workspace(&mut self) -> &mut FseWorkspace {
220 const { assert!(size_of::<Self>() >= size_of::<FseWorkspace>()) }
221 const { assert!(align_of::<Self>() >= align_of::<FseWorkspace>()) }
222 unsafe { core::mem::transmute(&mut self.data) }
223 }
224}
225
226pub type ZSTD_DCtx = ZSTD_DCtx_s;
227
228#[repr(C)]
239pub struct ZSTD_DCtx_s {
240 LLTptr: Option<NonNull<SymbolTable<512>>>,
241 MLTptr: Option<NonNull<SymbolTable<512>>>,
242 OFTptr: Option<NonNull<SymbolTable<256>>>,
243 HUFptr: Option<NonNull<DTable>>, entropy: ZSTD_entropyDTables_t,
245 workspace: Workspace,
246 previousDstEnd: *const core::ffi::c_void,
247 prefixStart: *const core::ffi::c_void,
248 virtualStart: *const core::ffi::c_void,
249 dictEnd: *const core::ffi::c_void,
250 expected: size_t,
251 fParams: ZSTD_FrameHeader,
252 processedCSize: u64,
253 decodedSize: u64,
254 bType: BlockType,
255 stage: DecompressStage,
256 litEntropy: bool,
257 _padding0: [u8; 3],
258 fseEntropy: bool,
259 _padding1: [u8; 3],
260 xxhState: XXH64_state_t,
261 headerSize: size_t,
262 format: Format,
263 forceIgnoreChecksum: ForceIgnoreChecksum,
264 _padding5: [u8; 3],
265 validateChecksum: bool,
266 _padding4: [u8; 3],
267 litPtr: *const u8,
268 customMem: ZSTD_customMem,
269 litSize: size_t,
270 rleSize: size_t,
271 staticSize: size_t,
272 isFrameDecompression: bool,
273 _padding7: [u8; 3],
274 bmi2: bool,
275 _padding2: [u8; 3],
276 ddictLocal: *mut ZSTD_DDict,
277 ddict: *const ZSTD_DDict,
278 dictID: u32,
279 ddictIsCold: bool,
280 _padding3: [u8; 3],
281 dictUses: DictUses,
282 ddictSet: *mut ZSTD_DDictHashSet,
283 refMultipleDDicts: MultipleDDicts,
284 disableHufAsm: bool,
285 _padding6: [u8; 3],
286 maxBlockSizeParam: core::ffi::c_int,
287 streamStage: StreamStage,
288
289 inBuff: *mut u8,
291 inBuffSize: size_t,
292 inPos: size_t,
293 maxWindowSize: size_t,
294 outBuff: *mut u8,
295 outBuffSize: size_t,
296 outStart: size_t,
297 outEnd: size_t,
298 lhSize: size_t,
299 legacyContext: *mut core::ffi::c_void,
300 previousLegacyVersion: u32,
301 legacyVersion: u32,
302 hostageByte: u32,
303 noForwardProgress: core::ffi::c_int,
304 outBufferMode: BufferMode,
305 expectedOutBuffer: ZSTD_outBuffer,
306 litBuffer: *mut u8,
307 litBufferEnd: *const u8,
308 litBufferLocation: LitLocation,
309 litExtraBuffer: [u8; ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH],
311 headerBuffer: [u8; 18],
312 oversizedDuration: size_t,
313 traceCtx: ZSTD_TraceCtx,
314}