Skip to main content

libzstd_rs_sys/lib/compress/
zstd_fast.rs

1use core::arch::asm;
2#[repr(C)]
3pub struct optState_t {
4    pub litFreq: *mut core::ffi::c_uint,
5    pub litLengthFreq: *mut core::ffi::c_uint,
6    pub matchLengthFreq: *mut core::ffi::c_uint,
7    pub offCodeFreq: *mut core::ffi::c_uint,
8    pub matchTable: *mut ZSTD_match_t,
9    pub priceTable: *mut ZSTD_optimal_t,
10    pub litSum: u32,
11    pub litLengthSum: u32,
12    pub matchLengthSum: u32,
13    pub offCodeSum: u32,
14    pub litSumBasePrice: u32,
15    pub litLengthSumBasePrice: u32,
16    pub matchLengthSumBasePrice: u32,
17    pub offCodeSumBasePrice: u32,
18    pub priceType: ZSTD_OptPrice_e,
19    pub symbolCosts: *const ZSTD_entropyCTables_t,
20    pub literalCompressionMode: ZSTD_ParamSwitch_e,
21}
22#[repr(C)]
23pub struct ZSTD_entropyCTables_t {
24    pub huf: ZSTD_hufCTables_t,
25    pub fse: ZSTD_fseCTables_t,
26}
27#[repr(C)]
28pub struct ZSTD_fseCTables_t {
29    pub offcodeCTable: [FSE_CTable; 193],
30    pub matchlengthCTable: [FSE_CTable; 363],
31    pub litlengthCTable: [FSE_CTable; 329],
32    pub offcode_repeatMode: FSE_repeat,
33    pub matchlength_repeatMode: FSE_repeat,
34    pub litlength_repeatMode: FSE_repeat,
35}
36#[repr(C)]
37pub struct ZSTD_hufCTables_t {
38    pub CTable: [HUF_CElt; 257],
39    pub repeatMode: HUF_repeat,
40}
41
42pub type ZSTD_dictTableLoadMethod_e = core::ffi::c_uint;
43pub const ZSTD_dtlm_full: ZSTD_dictTableLoadMethod_e = 1;
44pub const ZSTD_dtlm_fast: ZSTD_dictTableLoadMethod_e = 0;
45pub type ZSTD_tableFillPurpose_e = core::ffi::c_uint;
46pub const ZSTD_tfp_forCDict: ZSTD_tableFillPurpose_e = 1;
47pub const ZSTD_tfp_forCCtx: ZSTD_tableFillPurpose_e = 0;
48pub type ZSTD_match4Found = Option<unsafe fn(*const u8, *const u8, u32, u32) -> core::ffi::c_int>;
49pub const CACHELINE_SIZE: core::ffi::c_int = 64;
50
51use libc::size_t;
52
53use crate::lib::common::fse::{FSE_CTable, FSE_repeat};
54use crate::lib::common::huf::{HUF_CElt, HUF_repeat};
55use crate::lib::common::mem::MEM_read32;
56use crate::lib::common::zstd_internal::ZSTD_REP_NUM;
57use crate::lib::compress::zstd_compress::{
58    SeqStore_t, ZSTD_MatchState_t, ZSTD_match_t, ZSTD_optimal_t,
59};
60use crate::lib::compress::zstd_compress_internal::{
61    ZSTD_OptPrice_e, ZSTD_count, ZSTD_count_2segments, ZSTD_getLowestMatchIndex,
62    ZSTD_getLowestPrefixIndex, ZSTD_hashPtr, ZSTD_index_overlap_check, ZSTD_storeSeq,
63};
64use crate::lib::zstd::{ZSTD_ParamSwitch_e, ZSTD_compressionParameters};
65pub const kSearchStrength: core::ffi::c_int = 8;
66pub const HASH_READ_SIZE: core::ffi::c_int = 8;
67
68pub const REPCODE1_TO_OFFBASE: core::ffi::c_int = 1;
69
70pub const ZSTD_SHORT_CACHE_TAG_BITS: core::ffi::c_int = 8;
71pub const ZSTD_SHORT_CACHE_TAG_MASK: core::ffi::c_uint =
72    ((1 as core::ffi::c_uint) << ZSTD_SHORT_CACHE_TAG_BITS).wrapping_sub(1);
73#[inline]
74unsafe fn ZSTD_writeTaggedIndex(hashTable: *mut u32, hashAndTag: size_t, index: u32) {
75    let hash = hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;
76    let tag = (hashAndTag & ZSTD_SHORT_CACHE_TAG_MASK as size_t) as u32;
77    *hashTable.add(hash) = index << ZSTD_SHORT_CACHE_TAG_BITS | tag;
78}
79#[inline]
80unsafe fn ZSTD_comparePackedTags(packedTag1: size_t, packedTag2: size_t) -> core::ffi::c_int {
81    let tag1 = (packedTag1 & ZSTD_SHORT_CACHE_TAG_MASK as size_t) as u32;
82    let tag2 = (packedTag2 & ZSTD_SHORT_CACHE_TAG_MASK as size_t) as u32;
83    (tag1 == tag2) as core::ffi::c_int
84}
85unsafe fn ZSTD_fillHashTableForCDict(
86    ms: &mut ZSTD_MatchState_t,
87    end: *const core::ffi::c_void,
88    dtlm: ZSTD_dictTableLoadMethod_e,
89) {
90    let cParams: *const ZSTD_compressionParameters = &mut ms.cParams;
91    let hashTable = ms.hashTable;
92    let hBits = ((*cParams).hashLog).wrapping_add(ZSTD_SHORT_CACHE_TAG_BITS as core::ffi::c_uint);
93    let mls = (*cParams).minMatch;
94    let base = ms.window.base;
95    let mut ip = base.offset(ms.nextToUpdate as isize);
96    let iend = (end as *const u8).offset(-(HASH_READ_SIZE as isize));
97    let fastHashFillStep = 3;
98    while ip.offset(fastHashFillStep as isize) < iend.add(2) {
99        let curr = ip.offset_from(base) as core::ffi::c_long as u32;
100        let hashAndTag = ZSTD_hashPtr(ip as *const core::ffi::c_void, hBits, mls);
101        ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr);
102        if dtlm as core::ffi::c_uint != ZSTD_dtlm_fast as core::ffi::c_int as core::ffi::c_uint {
103            let mut p: u32 = 0;
104            p = 1;
105            while p < fastHashFillStep {
106                let hashAndTag_0 = ZSTD_hashPtr(
107                    ip.offset(p as isize) as *const core::ffi::c_void,
108                    hBits,
109                    mls,
110                );
111                if *hashTable.add(hashAndTag_0 >> ZSTD_SHORT_CACHE_TAG_BITS) == 0 {
112                    ZSTD_writeTaggedIndex(hashTable, hashAndTag_0, curr.wrapping_add(p));
113                }
114                p = p.wrapping_add(1);
115            }
116        }
117        ip = ip.offset(fastHashFillStep as isize);
118    }
119}
120unsafe fn ZSTD_fillHashTableForCCtx(
121    ms: &mut ZSTD_MatchState_t,
122    end: *const core::ffi::c_void,
123    dtlm: ZSTD_dictTableLoadMethod_e,
124) {
125    let cParams: *const ZSTD_compressionParameters = &mut ms.cParams;
126    let hashTable = ms.hashTable;
127    let hBits = (*cParams).hashLog;
128    let mls = (*cParams).minMatch;
129    let base = ms.window.base;
130    let mut ip = base.offset(ms.nextToUpdate as isize);
131    let iend = (end as *const u8).offset(-(HASH_READ_SIZE as isize));
132    let fastHashFillStep = 3;
133    while ip.offset(fastHashFillStep as isize) < iend.add(2) {
134        let curr = ip.offset_from(base) as core::ffi::c_long as u32;
135        let hash0 = ZSTD_hashPtr(ip as *const core::ffi::c_void, hBits, mls);
136        *hashTable.add(hash0) = curr;
137        if dtlm as core::ffi::c_uint != ZSTD_dtlm_fast as core::ffi::c_int as core::ffi::c_uint {
138            let mut p: u32 = 0;
139            p = 1;
140            while p < fastHashFillStep {
141                let hash = ZSTD_hashPtr(
142                    ip.offset(p as isize) as *const core::ffi::c_void,
143                    hBits,
144                    mls,
145                );
146                if *hashTable.add(hash) == 0 {
147                    *hashTable.add(hash) = curr.wrapping_add(p);
148                }
149                p = p.wrapping_add(1);
150            }
151        }
152        ip = ip.offset(fastHashFillStep as isize);
153    }
154}
155pub unsafe fn ZSTD_fillHashTable(
156    ms: &mut ZSTD_MatchState_t,
157    end: *const core::ffi::c_void,
158    dtlm: ZSTD_dictTableLoadMethod_e,
159    tfp: ZSTD_tableFillPurpose_e,
160) {
161    if tfp as core::ffi::c_uint == ZSTD_tfp_forCDict as core::ffi::c_int as core::ffi::c_uint {
162        ZSTD_fillHashTableForCDict(ms, end, dtlm);
163    } else {
164        ZSTD_fillHashTableForCCtx(ms, end, dtlm);
165    }
166}
167
168unsafe fn ZSTD_match4Found_cmov(
169    currentPtr: *const u8,
170    matchAddress: *const u8,
171    matchIdx: u32,
172    idxLowLimit: u32,
173) -> core::ffi::c_int {
174    // Array of ~random data, should have low probability of matching data.
175    // Load from here if the index is invalid.
176    // Used to avoid unpredictable branches.
177    static dummy: [u8; 4] = [0x12, 0x34, 0x56, 0x78];
178
179    // currentIdx >= lowLimit is a (somewhat) unpredictable branch.
180    // However expression below compiles into conditional move.
181    let mvalAddr =
182        core::hint::select_unpredictable(matchIdx >= idxLowLimit, matchAddress, dummy.as_ptr());
183
184    // Note: this used to be written as : return test1 && test2;
185    // Unfortunately, once inlined, these tests become branches,
186    // in which case it becomes critical that they are executed in the right order (test1 then test2).
187    // So we have to write these tests in a specific manner to ensure their ordering.
188    if MEM_read32(currentPtr as *const core::ffi::c_void)
189        != MEM_read32(mvalAddr as *const core::ffi::c_void)
190    {
191        return 0;
192    }
193
194    // force ordering of these tests, which matters once the function is inlined, as they become branches.
195    #[cfg(not(target_family = "wasm"))]
196    asm!("", options(preserves_flags));
197
198    (matchIdx >= idxLowLimit) as core::ffi::c_int
199}
200
201unsafe fn ZSTD_match4Found_branch(
202    currentPtr: *const u8,
203    matchAddress: *const u8,
204    matchIdx: u32,
205    idxLowLimit: u32,
206) -> core::ffi::c_int {
207    let mut mval: u32 = 0;
208    if matchIdx >= idxLowLimit {
209        mval = MEM_read32(matchAddress as *const core::ffi::c_void);
210    } else {
211        mval = MEM_read32(currentPtr as *const core::ffi::c_void) ^ 1;
212    }
213    (MEM_read32(currentPtr as *const core::ffi::c_void) == mval) as core::ffi::c_int
214}
215#[inline(always)]
216unsafe fn ZSTD_compressBlock_fast_noDict_generic(
217    ms: &mut ZSTD_MatchState_t,
218    seqStore: &mut SeqStore_t,
219    rep: *mut u32,
220    src: *const core::ffi::c_void,
221    srcSize: size_t,
222    mls: u32,
223    useCmov: core::ffi::c_int,
224) -> size_t {
225    let mut current_block: u64;
226    let cParams: *const ZSTD_compressionParameters = &mut ms.cParams;
227    let hashTable = ms.hashTable;
228    let hlog = (*cParams).hashLog;
229    let stepSize = ((*cParams).targetLength)
230        .wrapping_add(((*cParams).targetLength == 0) as core::ffi::c_int as core::ffi::c_uint)
231        .wrapping_add(1) as size_t;
232    let base = ms.window.base;
233    let istart = src as *const u8;
234    let endIndex = (istart.offset_from_unsigned(base)).wrapping_add(srcSize) as u32;
235    let prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, (*cParams).windowLog);
236    let prefixStart = base.offset(prefixStartIndex as isize);
237    let iend = istart.add(srcSize);
238    let ilimit = iend.offset(-(HASH_READ_SIZE as isize));
239    let mut anchor = istart;
240    let mut ip0 = istart;
241    let mut ip1 = core::ptr::null::<u8>();
242    let mut ip2 = core::ptr::null::<u8>();
243    let mut ip3 = core::ptr::null::<u8>();
244    let mut current0: u32 = 0;
245    let mut rep_offset1 = *rep;
246    let mut rep_offset2 = *rep.add(1);
247    let mut offsetSaved1 = 0;
248    let mut offsetSaved2 = 0;
249    let mut hash0: size_t = 0;
250    let mut hash1: size_t = 0;
251    let mut matchIdx: u32 = 0;
252    let mut offcode: u32 = 0;
253    let mut match0 = core::ptr::null::<u8>();
254    let mut mLength: size_t = 0;
255    let mut step: size_t = 0;
256    let mut nextStep = core::ptr::null::<u8>();
257    let kStepIncr = ((1) << (kSearchStrength - 1)) as size_t;
258    let matchFound: ZSTD_match4Found = if useCmov != 0 {
259        Some(ZSTD_match4Found_cmov as unsafe fn(*const u8, *const u8, u32, u32) -> core::ffi::c_int)
260    } else {
261        Some(
262            ZSTD_match4Found_branch
263                as unsafe fn(*const u8, *const u8, u32, u32) -> core::ffi::c_int,
264        )
265    };
266    ip0 = ip0.offset((ip0 == prefixStart) as core::ffi::c_int as isize);
267    let curr = ip0.offset_from(base) as core::ffi::c_long as u32;
268    let windowLow = ZSTD_getLowestPrefixIndex(ms, curr, (*cParams).windowLog);
269    let maxRep = curr.wrapping_sub(windowLow);
270    if rep_offset2 > maxRep {
271        offsetSaved2 = rep_offset2;
272        rep_offset2 = 0;
273    }
274    if rep_offset1 > maxRep {
275        offsetSaved1 = rep_offset1;
276        rep_offset1 = 0;
277    }
278    '__start: loop {
279        step = stepSize;
280        nextStep = ip0.add(kStepIncr);
281        ip1 = ip0.add(1);
282        ip2 = ip0.add(step);
283        ip3 = ip2.add(1);
284        if ip3 >= ilimit {
285            break;
286        }
287        hash0 = ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls);
288        hash1 = ZSTD_hashPtr(ip1 as *const core::ffi::c_void, hlog, mls);
289        matchIdx = *hashTable.add(hash0);
290        loop {
291            let rval = MEM_read32(ip2.offset(-(rep_offset1 as isize)) as *const core::ffi::c_void);
292            current0 = ip0.offset_from(base) as core::ffi::c_long as u32;
293            *hashTable.add(hash0) = current0;
294            if (MEM_read32(ip2 as *const core::ffi::c_void) == rval) as core::ffi::c_int
295                & (rep_offset1 > 0) as core::ffi::c_int
296                != 0
297            {
298                ip0 = ip2;
299                match0 = ip0.offset(-(rep_offset1 as isize));
300                mLength = (*ip0.sub(1) as core::ffi::c_int == *match0.sub(1) as core::ffi::c_int)
301                    as core::ffi::c_int as size_t;
302                ip0 = ip0.offset(-(mLength as isize));
303                match0 = match0.offset(-(mLength as isize));
304                offcode = REPCODE1_TO_OFFBASE as u32;
305                mLength = mLength.wrapping_add(4);
306                *hashTable.add(hash1) = ip1.offset_from(base) as core::ffi::c_long as u32;
307                current_block = 4391991184774404966;
308                break;
309            } else if matchFound.unwrap_unchecked()(
310                ip0,
311                base.offset(matchIdx as isize),
312                matchIdx,
313                prefixStartIndex,
314            ) != 0
315            {
316                *hashTable.add(hash1) = ip1.offset_from(base) as core::ffi::c_long as u32;
317                current_block = 11113405673187116881;
318                break;
319            } else {
320                matchIdx = *hashTable.add(hash1);
321                hash0 = hash1;
322                hash1 = ZSTD_hashPtr(ip2 as *const core::ffi::c_void, hlog, mls);
323                ip0 = ip1;
324                ip1 = ip2;
325                ip2 = ip3;
326                current0 = ip0.offset_from(base) as core::ffi::c_long as u32;
327                *hashTable.add(hash0) = current0;
328                if matchFound.unwrap_unchecked()(
329                    ip0,
330                    base.offset(matchIdx as isize),
331                    matchIdx,
332                    prefixStartIndex,
333                ) != 0
334                {
335                    if step <= 4 {
336                        *hashTable.add(hash1) = ip1.offset_from(base) as core::ffi::c_long as u32;
337                    }
338                    current_block = 11113405673187116881;
339                    break;
340                } else {
341                    matchIdx = *hashTable.add(hash1);
342                    hash0 = hash1;
343                    hash1 = ZSTD_hashPtr(ip2 as *const core::ffi::c_void, hlog, mls);
344                    ip0 = ip1;
345                    ip1 = ip2;
346                    ip2 = ip0.add(step);
347                    ip3 = ip1.add(step);
348                    if ip2 >= nextStep {
349                        step = step.wrapping_add(1);
350                        nextStep = nextStep.add(kStepIncr);
351                    }
352                    if ip3 >= ilimit {
353                        break '__start;
354                    }
355                }
356            }
357        }
358        if current_block == 11113405673187116881 {
359            match0 = base.offset(matchIdx as isize);
360            rep_offset2 = rep_offset1;
361            rep_offset1 = ip0.offset_from(match0) as core::ffi::c_long as u32;
362            offcode = rep_offset1.wrapping_add(ZSTD_REP_NUM as u32);
363            mLength = 4;
364            while (ip0 > anchor) as core::ffi::c_int & (match0 > prefixStart) as core::ffi::c_int
365                != 0
366                && *ip0.sub(1) as core::ffi::c_int == *match0.sub(1) as core::ffi::c_int
367            {
368                ip0 = ip0.sub(1);
369                match0 = match0.sub(1);
370                mLength = mLength.wrapping_add(1);
371            }
372        }
373        mLength = mLength.wrapping_add(ZSTD_count(ip0.add(mLength), match0.add(mLength), iend));
374        ZSTD_storeSeq(
375            seqStore,
376            ip0.offset_from_unsigned(anchor),
377            anchor,
378            iend,
379            offcode,
380            mLength,
381        );
382        ip0 = ip0.add(mLength);
383        anchor = ip0;
384        if ip0 <= ilimit {
385            *hashTable.add(ZSTD_hashPtr(
386                base.offset(current0 as isize).add(2) as *const core::ffi::c_void,
387                hlog,
388                mls,
389            )) = current0.wrapping_add(2);
390            *hashTable.add(ZSTD_hashPtr(
391                ip0.sub(2) as *const core::ffi::c_void,
392                hlog,
393                mls,
394            )) = ip0.sub(2).offset_from(base) as core::ffi::c_long as u32;
395            if rep_offset2 > 0 {
396                while ip0 <= ilimit
397                    && MEM_read32(ip0 as *const core::ffi::c_void)
398                        == MEM_read32(
399                            ip0.offset(-(rep_offset2 as isize)) as *const core::ffi::c_void
400                        )
401                {
402                    let rLength =
403                        (ZSTD_count(ip0.add(4), ip0.add(4).offset(-(rep_offset2 as isize)), iend))
404                            .wrapping_add(4);
405                    core::mem::swap(&mut rep_offset2, &mut rep_offset1);
406                    *hashTable.add(ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls)) =
407                        ip0.offset_from(base) as core::ffi::c_long as u32;
408                    ip0 = ip0.add(rLength);
409                    ZSTD_storeSeq(
410                        seqStore,
411                        0,
412                        anchor,
413                        iend,
414                        REPCODE1_TO_OFFBASE as u32,
415                        rLength,
416                    );
417                    anchor = ip0;
418                }
419            }
420        }
421    }
422    offsetSaved2 = if offsetSaved1 != 0 && rep_offset1 != 0 {
423        offsetSaved1
424    } else {
425        offsetSaved2
426    };
427    *rep = if rep_offset1 != 0 {
428        rep_offset1
429    } else {
430        offsetSaved1
431    };
432    *rep.add(1) = if rep_offset2 != 0 {
433        rep_offset2
434    } else {
435        offsetSaved2
436    };
437    iend.offset_from_unsigned(anchor)
438}
439unsafe fn ZSTD_compressBlock_fast_noDict_4_1(
440    ms: &mut ZSTD_MatchState_t,
441    seqStore: &mut SeqStore_t,
442    rep: *mut u32,
443    src: *const core::ffi::c_void,
444    srcSize: size_t,
445) -> size_t {
446    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 4, 1)
447}
448unsafe fn ZSTD_compressBlock_fast_noDict_5_1(
449    ms: &mut ZSTD_MatchState_t,
450    seqStore: &mut SeqStore_t,
451    rep: *mut u32,
452    src: *const core::ffi::c_void,
453    srcSize: size_t,
454) -> size_t {
455    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 5, 1)
456}
457unsafe fn ZSTD_compressBlock_fast_noDict_6_1(
458    ms: &mut ZSTD_MatchState_t,
459    seqStore: &mut SeqStore_t,
460    rep: *mut u32,
461    src: *const core::ffi::c_void,
462    srcSize: size_t,
463) -> size_t {
464    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 6, 1)
465}
466unsafe fn ZSTD_compressBlock_fast_noDict_7_1(
467    ms: &mut ZSTD_MatchState_t,
468    seqStore: &mut SeqStore_t,
469    rep: *mut u32,
470    src: *const core::ffi::c_void,
471    srcSize: size_t,
472) -> size_t {
473    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 7, 1)
474}
475unsafe fn ZSTD_compressBlock_fast_noDict_4_0(
476    ms: &mut ZSTD_MatchState_t,
477    seqStore: &mut SeqStore_t,
478    rep: *mut u32,
479    src: *const core::ffi::c_void,
480    srcSize: size_t,
481) -> size_t {
482    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 4, 0)
483}
484unsafe fn ZSTD_compressBlock_fast_noDict_5_0(
485    ms: &mut ZSTD_MatchState_t,
486    seqStore: &mut SeqStore_t,
487    rep: *mut u32,
488    src: *const core::ffi::c_void,
489    srcSize: size_t,
490) -> size_t {
491    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 5, 0)
492}
493unsafe fn ZSTD_compressBlock_fast_noDict_6_0(
494    ms: &mut ZSTD_MatchState_t,
495    seqStore: &mut SeqStore_t,
496    rep: *mut u32,
497    src: *const core::ffi::c_void,
498    srcSize: size_t,
499) -> size_t {
500    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 6, 0)
501}
502unsafe fn ZSTD_compressBlock_fast_noDict_7_0(
503    ms: &mut ZSTD_MatchState_t,
504    seqStore: &mut SeqStore_t,
505    rep: *mut u32,
506    src: *const core::ffi::c_void,
507    srcSize: size_t,
508) -> size_t {
509    ZSTD_compressBlock_fast_noDict_generic(ms, seqStore, rep, src, srcSize, 7, 0)
510}
511pub unsafe fn ZSTD_compressBlock_fast(
512    ms: &mut ZSTD_MatchState_t,
513    seqStore: &mut SeqStore_t,
514    rep: *mut u32,
515    src: *const core::ffi::c_void,
516    srcSize: size_t,
517) -> size_t {
518    let mml = ms.cParams.minMatch;
519    let useCmov = (ms.cParams.windowLog < 19) as core::ffi::c_int;
520    if useCmov != 0 {
521        match mml {
522            5 => ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize),
523            6 => ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize),
524            7 => ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize),
525            _ => ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize),
526        }
527    } else {
528        match mml {
529            5 => ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize),
530            6 => ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize),
531            7 => ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize),
532            _ => ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize),
533        }
534    }
535}
536#[inline(always)]
537unsafe fn ZSTD_compressBlock_fast_dictMatchState_generic(
538    ms: &mut ZSTD_MatchState_t,
539    seqStore: &mut SeqStore_t,
540    rep: *mut u32,
541    src: *const core::ffi::c_void,
542    srcSize: size_t,
543    mls: u32,
544    hasStep: u32,
545) -> size_t {
546    let cParams: *const ZSTD_compressionParameters = &mut ms.cParams;
547    let hashTable = ms.hashTable;
548    let hlog = (*cParams).hashLog;
549    let stepSize = ((*cParams).targetLength)
550        .wrapping_add(((*cParams).targetLength == 0) as core::ffi::c_int as core::ffi::c_uint);
551    let base = ms.window.base;
552    let istart = src as *const u8;
553    let mut ip0 = istart;
554    let mut ip1 = ip0.offset(stepSize as isize);
555    let mut anchor = istart;
556    let prefixStartIndex = ms.window.dictLimit;
557    let prefixStart = base.offset(prefixStartIndex as isize);
558    let iend = istart.add(srcSize);
559    let ilimit = iend.offset(-(HASH_READ_SIZE as isize));
560    let mut offset_1 = *rep;
561    let mut offset_2 = *rep.add(1);
562    let dms = ms.dictMatchState;
563    let dictCParams: *const ZSTD_compressionParameters = &(*dms).cParams;
564    let dictHashTable: *const u32 = (*dms).hashTable;
565    let dictStartIndex = (*dms).window.dictLimit;
566    let dictBase = (*dms).window.base;
567    let dictStart = dictBase.offset(dictStartIndex as isize);
568    let dictEnd = (*dms).window.nextSrc;
569    let dictIndexDelta =
570        prefixStartIndex.wrapping_sub(dictEnd.offset_from(dictBase) as core::ffi::c_long as u32);
571    let dictAndPrefixLength = dictEnd
572        .offset(istart.offset_from(prefixStart) as core::ffi::c_long as isize)
573        .offset_from(dictStart) as core::ffi::c_long as u32;
574    let dictHBits =
575        ((*dictCParams).hashLog).wrapping_add(ZSTD_SHORT_CACHE_TAG_BITS as core::ffi::c_uint);
576    let maxDistance = (1) << (*cParams).windowLog;
577    let endIndex = (istart.offset_from_unsigned(base)).wrapping_add(srcSize) as u32;
578    assert!(endIndex - prefixStartIndex <= maxDistance);
579
580    let _ = hasStep; /* not currently specialized on whether it's accelerated */
581
582    /* ensure there will be no underflow
583     * when translating a dict index into a local index */
584    assert!(prefixStartIndex as usize >= dictEnd as usize - dictBase as usize);
585
586    if ms.prefetchCDictTables != 0 {
587        let hashTableBytes = ((1 as core::ffi::c_int as size_t) << (*dictCParams).hashLog)
588            .wrapping_mul(::core::mem::size_of::<u32>());
589        let _ptr = dictHashTable as *const core::ffi::c_char;
590        let _size = hashTableBytes;
591        let mut _pos: size_t = 0;
592        _pos = 0;
593        while _pos < _size {
594            _pos = _pos.wrapping_add(CACHELINE_SIZE as size_t);
595        }
596    }
597    ip0 = ip0.offset((dictAndPrefixLength == 0) as core::ffi::c_int as isize);
598    's_135: while ip1 <= ilimit {
599        let mut mLength: size_t = 0;
600        let mut hash0 = ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls);
601        let dictHashAndTag0 = ZSTD_hashPtr(ip0 as *const core::ffi::c_void, dictHBits, mls);
602        let mut dictMatchIndexAndTag =
603            *dictHashTable.add(dictHashAndTag0 >> ZSTD_SHORT_CACHE_TAG_BITS);
604        let mut dictTagsMatch =
605            ZSTD_comparePackedTags(dictMatchIndexAndTag as size_t, dictHashAndTag0);
606        let mut matchIndex = *hashTable.add(hash0);
607        let mut curr = ip0.offset_from(base) as core::ffi::c_long as u32;
608        let mut step = stepSize as size_t;
609        let kStepIncr = ((1) << kSearchStrength) as size_t;
610        let mut nextStep = ip0.add(kStepIncr);
611        loop {
612            let mut match_0 = base.offset(matchIndex as isize);
613            let repIndex = curr.wrapping_add(1).wrapping_sub(offset_1);
614            let repMatch = if repIndex < prefixStartIndex {
615                dictBase.offset(repIndex.wrapping_sub(dictIndexDelta) as isize)
616            } else {
617                base.offset(repIndex as isize)
618            };
619            let hash1 = ZSTD_hashPtr(ip1 as *const core::ffi::c_void, hlog, mls);
620            let dictHashAndTag1 = ZSTD_hashPtr(ip1 as *const core::ffi::c_void, dictHBits, mls);
621            *hashTable.add(hash0) = curr;
622            if ZSTD_index_overlap_check(prefixStartIndex, repIndex) != 0
623                && MEM_read32(repMatch as *const core::ffi::c_void)
624                    == MEM_read32(ip0.add(1) as *const core::ffi::c_void)
625            {
626                let repMatchEnd = if repIndex < prefixStartIndex {
627                    dictEnd
628                } else {
629                    iend
630                };
631                mLength = (ZSTD_count_2segments(
632                    ip0.add(1).add(4),
633                    repMatch.add(4),
634                    iend,
635                    repMatchEnd,
636                    prefixStart,
637                ))
638                .wrapping_add(4);
639                ip0 = ip0.add(1);
640                ZSTD_storeSeq(
641                    seqStore,
642                    ip0.offset_from_unsigned(anchor),
643                    anchor,
644                    iend,
645                    REPCODE1_TO_OFFBASE as u32,
646                    mLength,
647                );
648                break;
649            } else {
650                if dictTagsMatch != 0 {
651                    let dictMatchIndex = dictMatchIndexAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;
652                    let mut dictMatch = dictBase.offset(dictMatchIndex as isize);
653                    if dictMatchIndex > dictStartIndex
654                        && MEM_read32(dictMatch as *const core::ffi::c_void)
655                            == MEM_read32(ip0 as *const core::ffi::c_void)
656                        && matchIndex <= prefixStartIndex
657                    {
658                        let offset = curr
659                            .wrapping_sub(dictMatchIndex)
660                            .wrapping_sub(dictIndexDelta);
661                        mLength = (ZSTD_count_2segments(
662                            ip0.add(4),
663                            dictMatch.add(4),
664                            iend,
665                            dictEnd,
666                            prefixStart,
667                        ))
668                        .wrapping_add(4);
669                        while (ip0 > anchor) as core::ffi::c_int
670                            & (dictMatch > dictStart) as core::ffi::c_int
671                            != 0
672                            && *ip0.sub(1) as core::ffi::c_int
673                                == *dictMatch.sub(1) as core::ffi::c_int
674                        {
675                            ip0 = ip0.sub(1);
676                            dictMatch = dictMatch.sub(1);
677                            mLength = mLength.wrapping_add(1);
678                        }
679                        offset_2 = offset_1;
680                        offset_1 = offset;
681                        ZSTD_storeSeq(
682                            seqStore,
683                            ip0.offset_from_unsigned(anchor),
684                            anchor,
685                            iend,
686                            offset.wrapping_add(ZSTD_REP_NUM as u32),
687                            mLength,
688                        );
689                        break;
690                    }
691                }
692                if ZSTD_match4Found_cmov(ip0, match_0, matchIndex, prefixStartIndex) != 0 {
693                    let offset_0 = ip0.offset_from(match_0) as core::ffi::c_long as u32;
694                    mLength = (ZSTD_count(ip0.add(4), match_0.add(4), iend)).wrapping_add(4);
695                    while (ip0 > anchor) as core::ffi::c_int
696                        & (match_0 > prefixStart) as core::ffi::c_int
697                        != 0
698                        && *ip0.sub(1) as core::ffi::c_int == *match_0.sub(1) as core::ffi::c_int
699                    {
700                        ip0 = ip0.sub(1);
701                        match_0 = match_0.sub(1);
702                        mLength = mLength.wrapping_add(1);
703                    }
704                    offset_2 = offset_1;
705                    offset_1 = offset_0;
706                    ZSTD_storeSeq(
707                        seqStore,
708                        ip0.offset_from_unsigned(anchor),
709                        anchor,
710                        iend,
711                        offset_0.wrapping_add(ZSTD_REP_NUM as u32),
712                        mLength,
713                    );
714                    break;
715                } else {
716                    dictMatchIndexAndTag =
717                        *dictHashTable.add(dictHashAndTag1 >> ZSTD_SHORT_CACHE_TAG_BITS);
718                    dictTagsMatch =
719                        ZSTD_comparePackedTags(dictMatchIndexAndTag as size_t, dictHashAndTag1);
720                    matchIndex = *hashTable.add(hash1);
721                    if ip1 >= nextStep {
722                        step = step.wrapping_add(1);
723                        nextStep = nextStep.add(kStepIncr);
724                    }
725                    ip0 = ip1;
726                    ip1 = ip1.add(step);
727                    if ip1 > ilimit {
728                        break 's_135;
729                    }
730                    curr = ip0.offset_from(base) as core::ffi::c_long as u32;
731                    hash0 = hash1;
732                }
733            }
734        }
735        ip0 = ip0.add(mLength);
736        anchor = ip0;
737        if ip0 <= ilimit {
738            *hashTable.add(ZSTD_hashPtr(
739                base.offset(curr as isize).add(2) as *const core::ffi::c_void,
740                hlog,
741                mls,
742            )) = curr.wrapping_add(2);
743            *hashTable.add(ZSTD_hashPtr(
744                ip0.sub(2) as *const core::ffi::c_void,
745                hlog,
746                mls,
747            )) = ip0.sub(2).offset_from(base) as core::ffi::c_long as u32;
748            while ip0 <= ilimit {
749                let current2 = ip0.offset_from(base) as core::ffi::c_long as u32;
750                let repIndex2 = current2.wrapping_sub(offset_2);
751                let repMatch2 = if repIndex2 < prefixStartIndex {
752                    dictBase
753                        .offset(-(dictIndexDelta as isize))
754                        .offset(repIndex2 as isize)
755                } else {
756                    base.offset(repIndex2 as isize)
757                };
758                if !(ZSTD_index_overlap_check(prefixStartIndex, repIndex2) != 0
759                    && MEM_read32(repMatch2 as *const core::ffi::c_void)
760                        == MEM_read32(ip0 as *const core::ffi::c_void))
761                {
762                    break;
763                }
764                let repEnd2 = if repIndex2 < prefixStartIndex {
765                    dictEnd
766                } else {
767                    iend
768                };
769                let repLength2 = (ZSTD_count_2segments(
770                    ip0.add(4),
771                    repMatch2.add(4),
772                    iend,
773                    repEnd2,
774                    prefixStart,
775                ))
776                .wrapping_add(4);
777                core::mem::swap(&mut offset_2, &mut offset_1);
778                ZSTD_storeSeq(
779                    seqStore,
780                    0,
781                    anchor,
782                    iend,
783                    REPCODE1_TO_OFFBASE as u32,
784                    repLength2,
785                );
786                *hashTable.add(ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls)) = current2;
787                ip0 = ip0.add(repLength2);
788                anchor = ip0;
789            }
790        }
791        ip1 = ip0.offset(stepSize as isize);
792    }
793    *rep = offset_1;
794    *rep.add(1) = offset_2;
795    iend.offset_from_unsigned(anchor)
796}
797unsafe fn ZSTD_compressBlock_fast_dictMatchState_4_0(
798    ms: &mut ZSTD_MatchState_t,
799    seqStore: &mut SeqStore_t,
800    rep: *mut u32,
801    src: *const core::ffi::c_void,
802    srcSize: size_t,
803) -> size_t {
804    ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4, 0)
805}
806unsafe fn ZSTD_compressBlock_fast_dictMatchState_5_0(
807    ms: &mut ZSTD_MatchState_t,
808    seqStore: &mut SeqStore_t,
809    rep: *mut u32,
810    src: *const core::ffi::c_void,
811    srcSize: size_t,
812) -> size_t {
813    ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5, 0)
814}
815unsafe fn ZSTD_compressBlock_fast_dictMatchState_6_0(
816    ms: &mut ZSTD_MatchState_t,
817    seqStore: &mut SeqStore_t,
818    rep: *mut u32,
819    src: *const core::ffi::c_void,
820    srcSize: size_t,
821) -> size_t {
822    ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6, 0)
823}
824unsafe fn ZSTD_compressBlock_fast_dictMatchState_7_0(
825    ms: &mut ZSTD_MatchState_t,
826    seqStore: &mut SeqStore_t,
827    rep: *mut u32,
828    src: *const core::ffi::c_void,
829    srcSize: size_t,
830) -> size_t {
831    ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7, 0)
832}
833pub unsafe fn ZSTD_compressBlock_fast_dictMatchState(
834    ms: &mut ZSTD_MatchState_t,
835    seqStore: &mut SeqStore_t,
836    rep: *mut u32,
837    src: *const core::ffi::c_void,
838    srcSize: size_t,
839) -> size_t {
840    let mls = ms.cParams.minMatch;
841    match mls {
842        5 => ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize),
843        6 => ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize),
844        7 => ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize),
845        _ => ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize),
846    }
847}
848unsafe fn ZSTD_compressBlock_fast_extDict_generic(
849    ms: &mut ZSTD_MatchState_t,
850    seqStore: &mut SeqStore_t,
851    rep: *mut u32,
852    src: *const core::ffi::c_void,
853    srcSize: size_t,
854    mls: u32,
855    hasStep: u32,
856) -> size_t {
857    let mut current_block: u64;
858    let cParams: *const ZSTD_compressionParameters = &mut ms.cParams;
859    let hashTable = ms.hashTable;
860    let hlog = (*cParams).hashLog;
861    let stepSize = ((*cParams).targetLength)
862        .wrapping_add(((*cParams).targetLength == 0) as core::ffi::c_int as core::ffi::c_uint)
863        .wrapping_add(1) as size_t;
864    let base = ms.window.base;
865    let dictBase = ms.window.dictBase;
866    let istart = src as *const u8;
867    let mut anchor = istart;
868    let endIndex = (istart.offset_from_unsigned(base)).wrapping_add(srcSize) as u32;
869    let lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, (*cParams).windowLog);
870    let dictStartIndex = lowLimit;
871    let dictStart = dictBase.offset(dictStartIndex as isize);
872    let dictLimit = ms.window.dictLimit;
873    let prefixStartIndex = if dictLimit < lowLimit {
874        lowLimit
875    } else {
876        dictLimit
877    };
878    let prefixStart = base.offset(prefixStartIndex as isize);
879    let dictEnd = dictBase.offset(prefixStartIndex as isize);
880    let iend = istart.add(srcSize);
881    let ilimit = iend.sub(8);
882    let mut offset_1 = *rep;
883    let mut offset_2 = *rep.add(1);
884    let mut offsetSaved1 = 0;
885    let mut offsetSaved2 = 0;
886    let mut ip0 = istart;
887    let mut ip1 = core::ptr::null::<u8>();
888    let mut ip2 = core::ptr::null::<u8>();
889    let mut ip3 = core::ptr::null::<u8>();
890    let mut current0: u32 = 0;
891    let mut hash0: size_t = 0;
892    let mut hash1: size_t = 0;
893    let mut idx: u32 = 0;
894    let mut idxBase = core::ptr::null::<u8>();
895    let mut offcode: u32 = 0;
896    let mut match0 = core::ptr::null::<u8>();
897    let mut mLength: size_t = 0;
898    let mut matchEnd = core::ptr::null::<u8>();
899    let mut step: size_t = 0;
900    let mut nextStep = core::ptr::null::<u8>();
901    let kStepIncr = ((1) << (kSearchStrength - 1)) as size_t;
902
903    let _ = hasStep; /* not currently specialized on whether it's accelerated */
904
905    if prefixStartIndex == dictStartIndex {
906        return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize);
907    }
908    let curr = ip0.offset_from(base) as core::ffi::c_long as u32;
909    let maxRep = curr.wrapping_sub(dictStartIndex);
910    if offset_2 >= maxRep {
911        offsetSaved2 = offset_2;
912        offset_2 = 0;
913    }
914    if offset_1 >= maxRep {
915        offsetSaved1 = offset_1;
916        offset_1 = 0;
917    }
918    '__start: loop {
919        step = stepSize;
920        nextStep = ip0.add(kStepIncr);
921        ip1 = ip0.add(1);
922        ip2 = ip0.add(step);
923        ip3 = ip2.add(1);
924        if ip3 >= ilimit {
925            break;
926        }
927        hash0 = ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls);
928        hash1 = ZSTD_hashPtr(ip1 as *const core::ffi::c_void, hlog, mls);
929        idx = *hashTable.add(hash0);
930        idxBase = if idx < prefixStartIndex {
931            dictBase
932        } else {
933            base
934        };
935        loop {
936            let current2 = ip2.offset_from(base) as core::ffi::c_long as u32;
937            let repIndex = current2.wrapping_sub(offset_1);
938            let repBase = if repIndex < prefixStartIndex {
939                dictBase
940            } else {
941                base
942            };
943            let mut rval: u32 = 0;
944            if (prefixStartIndex.wrapping_sub(repIndex) >= 4) as core::ffi::c_int
945                & (offset_1 > 0) as core::ffi::c_int
946                != 0
947            {
948                rval = MEM_read32(repBase.offset(repIndex as isize) as *const core::ffi::c_void);
949            } else {
950                rval = MEM_read32(ip2 as *const core::ffi::c_void) ^ 1;
951            }
952            current0 = ip0.offset_from(base) as core::ffi::c_long as u32;
953            *hashTable.add(hash0) = current0;
954            if MEM_read32(ip2 as *const core::ffi::c_void) == rval {
955                ip0 = ip2;
956                match0 = repBase.offset(repIndex as isize);
957                matchEnd = if repIndex < prefixStartIndex {
958                    dictEnd
959                } else {
960                    iend
961                };
962                mLength = (*ip0.sub(1) as core::ffi::c_int == *match0.sub(1) as core::ffi::c_int)
963                    as core::ffi::c_int as size_t;
964                ip0 = ip0.offset(-(mLength as isize));
965                match0 = match0.offset(-(mLength as isize));
966                offcode = REPCODE1_TO_OFFBASE as u32;
967                mLength = mLength.wrapping_add(4);
968                current_block = 1352918242886884122;
969                break;
970            } else {
971                let mval = if idx >= dictStartIndex {
972                    MEM_read32(idxBase.offset(idx as isize) as *const core::ffi::c_void)
973                } else {
974                    MEM_read32(ip0 as *const core::ffi::c_void) ^ 1
975                };
976                if MEM_read32(ip0 as *const core::ffi::c_void) == mval {
977                    current_block = 934346911184053177;
978                    break;
979                } else {
980                    idx = *hashTable.add(hash1);
981                    idxBase = if idx < prefixStartIndex {
982                        dictBase
983                    } else {
984                        base
985                    };
986                    hash0 = hash1;
987                    hash1 = ZSTD_hashPtr(ip2 as *const core::ffi::c_void, hlog, mls);
988                    ip0 = ip1;
989                    ip1 = ip2;
990                    ip2 = ip3;
991                    current0 = ip0.offset_from(base) as core::ffi::c_long as u32;
992                    *hashTable.add(hash0) = current0;
993                    let mval_0 = if idx >= dictStartIndex {
994                        MEM_read32(idxBase.offset(idx as isize) as *const core::ffi::c_void)
995                    } else {
996                        MEM_read32(ip0 as *const core::ffi::c_void) ^ 1
997                    };
998                    if MEM_read32(ip0 as *const core::ffi::c_void) == mval_0 {
999                        current_block = 934346911184053177;
1000                        break;
1001                    }
1002                    idx = *hashTable.add(hash1);
1003                    idxBase = if idx < prefixStartIndex {
1004                        dictBase
1005                    } else {
1006                        base
1007                    };
1008                    hash0 = hash1;
1009                    hash1 = ZSTD_hashPtr(ip2 as *const core::ffi::c_void, hlog, mls);
1010                    ip0 = ip1;
1011                    ip1 = ip2;
1012                    ip2 = ip0.add(step);
1013                    ip3 = ip1.add(step);
1014                    if ip2 >= nextStep {
1015                        step = step.wrapping_add(1);
1016                        nextStep = nextStep.add(kStepIncr);
1017                    }
1018                    if ip3 >= ilimit {
1019                        break '__start;
1020                    }
1021                }
1022            }
1023        }
1024        if current_block == 934346911184053177 {
1025            let offset = current0.wrapping_sub(idx);
1026            let lowMatchPtr = if idx < prefixStartIndex {
1027                dictStart
1028            } else {
1029                prefixStart
1030            };
1031            matchEnd = if idx < prefixStartIndex {
1032                dictEnd
1033            } else {
1034                iend
1035            };
1036            match0 = idxBase.offset(idx as isize);
1037            offset_2 = offset_1;
1038            offset_1 = offset;
1039            offcode = offset.wrapping_add(ZSTD_REP_NUM as u32);
1040            mLength = 4;
1041            while (ip0 > anchor) as core::ffi::c_int & (match0 > lowMatchPtr) as core::ffi::c_int
1042                != 0
1043                && *ip0.sub(1) as core::ffi::c_int == *match0.sub(1) as core::ffi::c_int
1044            {
1045                ip0 = ip0.sub(1);
1046                match0 = match0.sub(1);
1047                mLength = mLength.wrapping_add(1);
1048            }
1049        }
1050        mLength = mLength.wrapping_add(ZSTD_count_2segments(
1051            ip0.add(mLength),
1052            match0.add(mLength),
1053            iend,
1054            matchEnd,
1055            prefixStart,
1056        ));
1057        ZSTD_storeSeq(
1058            seqStore,
1059            ip0.offset_from_unsigned(anchor),
1060            anchor,
1061            iend,
1062            offcode,
1063            mLength,
1064        );
1065        ip0 = ip0.add(mLength);
1066        anchor = ip0;
1067        if ip1 < ip0 {
1068            *hashTable.add(hash1) = ip1.offset_from(base) as core::ffi::c_long as u32;
1069        }
1070        if ip0 <= ilimit {
1071            *hashTable.add(ZSTD_hashPtr(
1072                base.offset(current0 as isize).add(2) as *const core::ffi::c_void,
1073                hlog,
1074                mls,
1075            )) = current0.wrapping_add(2);
1076            *hashTable.add(ZSTD_hashPtr(
1077                ip0.sub(2) as *const core::ffi::c_void,
1078                hlog,
1079                mls,
1080            )) = ip0.sub(2).offset_from(base) as core::ffi::c_long as u32;
1081            while ip0 <= ilimit {
1082                let repIndex2 =
1083                    (ip0.offset_from(base) as core::ffi::c_long as u32).wrapping_sub(offset_2);
1084                let repMatch2 = if repIndex2 < prefixStartIndex {
1085                    dictBase.offset(repIndex2 as isize)
1086                } else {
1087                    base.offset(repIndex2 as isize)
1088                };
1089                if !(ZSTD_index_overlap_check(prefixStartIndex, repIndex2)
1090                    & (offset_2 > 0) as core::ffi::c_int
1091                    != 0
1092                    && MEM_read32(repMatch2 as *const core::ffi::c_void)
1093                        == MEM_read32(ip0 as *const core::ffi::c_void))
1094                {
1095                    break;
1096                }
1097                let repEnd2 = if repIndex2 < prefixStartIndex {
1098                    dictEnd
1099                } else {
1100                    iend
1101                };
1102                let repLength2 = (ZSTD_count_2segments(
1103                    ip0.add(4),
1104                    repMatch2.add(4),
1105                    iend,
1106                    repEnd2,
1107                    prefixStart,
1108                ))
1109                .wrapping_add(4);
1110                core::mem::swap(&mut offset_2, &mut offset_1);
1111                ZSTD_storeSeq(
1112                    seqStore,
1113                    0,
1114                    anchor,
1115                    iend,
1116                    REPCODE1_TO_OFFBASE as u32,
1117                    repLength2,
1118                );
1119                *hashTable.add(ZSTD_hashPtr(ip0 as *const core::ffi::c_void, hlog, mls)) =
1120                    ip0.offset_from(base) as core::ffi::c_long as u32;
1121                ip0 = ip0.add(repLength2);
1122                anchor = ip0;
1123            }
1124        }
1125    }
1126    offsetSaved2 = if offsetSaved1 != 0 && offset_1 != 0 {
1127        offsetSaved1
1128    } else {
1129        offsetSaved2
1130    };
1131    *rep = if offset_1 != 0 {
1132        offset_1
1133    } else {
1134        offsetSaved1
1135    };
1136    *rep.add(1) = if offset_2 != 0 {
1137        offset_2
1138    } else {
1139        offsetSaved2
1140    };
1141    iend.offset_from_unsigned(anchor)
1142}
1143unsafe fn ZSTD_compressBlock_fast_extDict_4_0(
1144    ms: &mut ZSTD_MatchState_t,
1145    seqStore: &mut SeqStore_t,
1146    rep: *mut u32,
1147    src: *const core::ffi::c_void,
1148    srcSize: size_t,
1149) -> size_t {
1150    ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 4, 0)
1151}
1152unsafe fn ZSTD_compressBlock_fast_extDict_5_0(
1153    ms: &mut ZSTD_MatchState_t,
1154    seqStore: &mut SeqStore_t,
1155    rep: *mut u32,
1156    src: *const core::ffi::c_void,
1157    srcSize: size_t,
1158) -> size_t {
1159    ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 5, 0)
1160}
1161unsafe fn ZSTD_compressBlock_fast_extDict_6_0(
1162    ms: &mut ZSTD_MatchState_t,
1163    seqStore: &mut SeqStore_t,
1164    rep: *mut u32,
1165    src: *const core::ffi::c_void,
1166    srcSize: size_t,
1167) -> size_t {
1168    ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 6, 0)
1169}
1170unsafe fn ZSTD_compressBlock_fast_extDict_7_0(
1171    ms: &mut ZSTD_MatchState_t,
1172    seqStore: &mut SeqStore_t,
1173    rep: *mut u32,
1174    src: *const core::ffi::c_void,
1175    srcSize: size_t,
1176) -> size_t {
1177    ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 7, 0)
1178}
1179pub unsafe fn ZSTD_compressBlock_fast_extDict(
1180    ms: &mut ZSTD_MatchState_t,
1181    seqStore: &mut SeqStore_t,
1182    rep: *mut u32,
1183    src: *const core::ffi::c_void,
1184    srcSize: size_t,
1185) -> size_t {
1186    let mls = ms.cParams.minMatch;
1187    match mls {
1188        5 => ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize),
1189        6 => ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize),
1190        7 => ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize),
1191        _ => ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize),
1192    }
1193}