libbz2_rs_sys/
decompress.rs

1#![forbid(unsafe_code)]
2
3use core::ffi::c_int;
4
5use crate::allocator::Allocator;
6use crate::bzlib::{
7    index_into_f, BzStream, DSlice, DState, DecompressMode, ReturnCode, SaveArea, BZ_MAX_SELECTORS,
8    BZ_RAND_UPD_MASK, BZ_RUNA, BZ_RUNB,
9};
10use crate::{debug_log, huffman};
11
12/*-- Constants for the fast MTF decoder. --*/
13
14const MTFA_SIZE: u16 = 4096;
15const MTFL_SIZE: usize = 16;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18#[allow(non_camel_case_types)]
19pub(crate) enum State {
20    BZ_X_IDLE = 1,
21    BZ_X_OUTPUT = 2,
22    BZ_X_MAGIC_1 = 10,
23    BZ_X_MAGIC_2 = 11,
24    BZ_X_MAGIC_3 = 12,
25    BZ_X_MAGIC_4 = 13,
26    BZ_X_BLKHDR_1 = 14,
27    BZ_X_BLKHDR_2 = 15,
28    BZ_X_BLKHDR_3 = 16,
29    BZ_X_BLKHDR_4 = 17,
30    BZ_X_BLKHDR_5 = 18,
31    BZ_X_BLKHDR_6 = 19,
32    BZ_X_BCRC_1 = 20,
33    BZ_X_BCRC_2 = 21,
34    BZ_X_BCRC_3 = 22,
35    BZ_X_BCRC_4 = 23,
36    BZ_X_RANDBIT = 24,
37    BZ_X_ORIGPTR_1 = 25,
38    BZ_X_ORIGPTR_2 = 26,
39    BZ_X_ORIGPTR_3 = 27,
40    BZ_X_MAPPING_1 = 28,
41    BZ_X_MAPPING_2 = 29,
42    BZ_X_SELECTOR_1 = 30,
43    BZ_X_SELECTOR_2 = 31,
44    BZ_X_SELECTOR_3 = 32,
45    BZ_X_CODING_1 = 33,
46    BZ_X_CODING_2 = 34,
47    BZ_X_CODING_3 = 35,
48    BZ_X_MTF_1 = 36,
49    BZ_X_MTF_2 = 37,
50    BZ_X_MTF_3 = 38,
51    BZ_X_MTF_4 = 39,
52    BZ_X_MTF_5 = 40,
53    BZ_X_MTF_6 = 41,
54    BZ_X_ENDHDR_2 = 42,
55    BZ_X_ENDHDR_3 = 43,
56    BZ_X_ENDHDR_4 = 44,
57    BZ_X_ENDHDR_5 = 45,
58    BZ_X_ENDHDR_6 = 46,
59    BZ_X_CCRC_1 = 47,
60    BZ_X_CCRC_2 = 48,
61    BZ_X_CCRC_3 = 49,
62    BZ_X_CCRC_4 = 50,
63}
64
65#[allow(non_camel_case_types)]
66#[derive(Eq, PartialEq)]
67enum Block {
68    BZ_X_MAGIC_2,
69    BZ_X_MAGIC_3,
70    BZ_X_MAGIC_4,
71    BZ_X_BLKHDR_1,
72    BZ_X_BLKHDR_2,
73    BZ_X_BLKHDR_3,
74    BZ_X_BLKHDR_4,
75    BZ_X_BLKHDR_5,
76    BZ_X_BLKHDR_6,
77    BZ_X_BCRC_1,
78    BZ_X_BCRC_2,
79    BZ_X_BCRC_3,
80    BZ_X_BCRC_4,
81    BZ_X_RANDBIT,
82    BZ_X_ORIGPTR_1,
83    BZ_X_ORIGPTR_2,
84    BZ_X_ORIGPTR_3,
85    BZ_X_MAPPING_1,
86    BZ_X_MAPPING_2,
87    BZ_X_SELECTOR_1,
88    BZ_X_SELECTOR_2,
89    BZ_X_SELECTOR_3,
90    BZ_X_CODING_1,
91    BZ_X_CODING_2,
92    BZ_X_CODING_3,
93    BZ_X_MTF_1,
94    BZ_X_MTF_2,
95    BZ_X_MTF_3,
96    BZ_X_MTF_4,
97    BZ_X_MTF_5,
98    BZ_X_MTF_6,
99    BZ_X_ENDHDR_2,
100    BZ_X_ENDHDR_3,
101    BZ_X_ENDHDR_4,
102    BZ_X_ENDHDR_5,
103    BZ_X_ENDHDR_6,
104    BZ_X_CCRC_1,
105    BZ_X_CCRC_2,
106    BZ_X_CCRC_3,
107    BZ_X_CCRC_4,
108    Block1,
109    Block11,
110    Block18,
111    Block24,
112    Block25,
113    Block26,
114    Block28,
115    Block35,
116    Block39,
117    Block40,
118    Block41,
119    Block43,
120    Block45,
121    Block46,
122    Block51,
123    Block52,
124    Block56,
125    Block58,
126}
127use Block::*;
128
129pub(crate) fn decompress(
130    strm: &mut BzStream<DState>,
131    s: &mut DState,
132    allocator: &Allocator,
133) -> ReturnCode {
134    let mut current_block: Block;
135    let mut uc: u8;
136
137    let old_avail_in = strm.avail_in;
138
139    if let State::BZ_X_MAGIC_1 = s.state {
140        /*zero out the save area*/
141        s.save = SaveArea::default();
142    }
143
144    /*restore from the save area*/
145    let SaveArea {
146        mut i,
147        mut j,
148        mut t,
149        mut alphaSize,
150        mut nGroups,
151        mut nSelectors,
152        mut EOB,
153        mut groupNo,
154        mut groupPos,
155        mut nextSym,
156        mut nblockMAX100k,
157        mut nblock,
158        mut es,
159        mut logN,
160        mut curr,
161        mut zn,
162        mut zvec,
163        mut zj,
164        mut gSel,
165        mut gMinlen,
166    } = s.save;
167
168    let ret_val: ReturnCode = 'save_state_and_return: {
169        macro_rules! GET_BYTE {
170            ($strm:expr, $s:expr) => {
171                (GET_BITS!($strm, $s, 8) & 0xFF) as u8
172            };
173        }
174
175        macro_rules! GET_BIT {
176            ($strm:expr, $s:expr) => {
177                GET_BITS!($strm, $s, 1) != 0
178            };
179        }
180
181        macro_rules! GET_BITS {
182            ($strm:expr, $s:expr, $nnn:expr) => {
183                loop {
184                    if $s.bsLive >= $nnn {
185                        let v: u64 = ($s.bsBuff >> ($s.bsLive - $nnn)) & ((1 << $nnn) - 1);
186                        $s.bsLive -= $nnn;
187                        break v;
188                    }
189
190                    // try and read up to 8 bytes, but only if there is no risk of reading past the
191                    // end of the file. This is important in a multistream scenario (where 2 bzip2
192                    // files are stored back-to-back)
193                    //
194                    // Before `State::BZ_X_ENDHDR_2` is reached, at least 9 more bytes are expected
195                    // (in a valid file), so reading 8 bytes will not cross the boundary between two files.
196                    if $s.state < State::BZ_X_ENDHDR_2 {
197                        if let Some((bit_buffer, bits_used)) = strm.pull_u64($s.bsBuff, $s.bsLive) {
198                            $s.bsBuff = bit_buffer;
199                            $s.bsLive = bits_used;
200                            continue;
201                        }
202                    }
203
204                    if let Some((bit_buffer, bits_used)) = strm.pull_u8($s.bsBuff, $s.bsLive) {
205                        $s.bsBuff = bit_buffer;
206                        $s.bsLive = bits_used;
207                    } else {
208                        break 'save_state_and_return ReturnCode::BZ_OK;
209                    }
210                }
211            };
212        }
213
214        macro_rules! update_group_pos {
215            ($s:expr) => {
216                if groupPos == 0 {
217                    groupNo += 1;
218                    gSel = match $s.selector[..usize::from(nSelectors)].get(groupNo as usize) {
219                        Some(&gSel) => gSel,
220                        None => error!(BZ_DATA_ERROR),
221                    };
222                    gMinlen = $s.minLens[usize::from(gSel)];
223                    groupPos = 50;
224                }
225                groupPos -= 1;
226            };
227        }
228
229        macro_rules! error {
230            ($code:ident) => {{
231                break 'save_state_and_return ReturnCode::$code;
232            }};
233        }
234
235        match s.state {
236            State::BZ_X_MAGIC_1 => {
237                s.state = State::BZ_X_MAGIC_1;
238
239                uc = GET_BYTE!(strm, s);
240
241                if uc != b'B' {
242                    error!(BZ_DATA_ERROR_MAGIC);
243                }
244
245                current_block = BZ_X_MAGIC_2;
246            }
247            State::BZ_X_MAGIC_2 => current_block = BZ_X_MAGIC_2,
248            State::BZ_X_MAGIC_3 => current_block = BZ_X_MAGIC_3,
249            State::BZ_X_MAGIC_4 => current_block = BZ_X_MAGIC_4,
250            State::BZ_X_BLKHDR_1 => current_block = BZ_X_BLKHDR_1,
251            State::BZ_X_BLKHDR_2 => current_block = BZ_X_BLKHDR_2,
252            State::BZ_X_BLKHDR_3 => current_block = BZ_X_BLKHDR_3,
253            State::BZ_X_BLKHDR_4 => current_block = BZ_X_BLKHDR_4,
254            State::BZ_X_BLKHDR_5 => current_block = BZ_X_BLKHDR_5,
255            State::BZ_X_BLKHDR_6 => current_block = BZ_X_BLKHDR_6,
256            State::BZ_X_BCRC_1 => current_block = BZ_X_BCRC_1,
257            State::BZ_X_BCRC_2 => current_block = BZ_X_BCRC_2,
258            State::BZ_X_BCRC_3 => current_block = BZ_X_BCRC_3,
259            State::BZ_X_BCRC_4 => current_block = BZ_X_BCRC_4,
260            State::BZ_X_RANDBIT => current_block = BZ_X_RANDBIT,
261            State::BZ_X_ORIGPTR_1 => current_block = BZ_X_ORIGPTR_1,
262            State::BZ_X_ORIGPTR_2 => current_block = BZ_X_ORIGPTR_2,
263            State::BZ_X_ORIGPTR_3 => current_block = BZ_X_ORIGPTR_3,
264            State::BZ_X_MAPPING_1 => current_block = BZ_X_MAPPING_1,
265            State::BZ_X_MAPPING_2 => current_block = BZ_X_MAPPING_2,
266            State::BZ_X_SELECTOR_1 => current_block = BZ_X_SELECTOR_1,
267            State::BZ_X_SELECTOR_2 => current_block = BZ_X_SELECTOR_2,
268            State::BZ_X_SELECTOR_3 => current_block = BZ_X_SELECTOR_3,
269            State::BZ_X_CODING_1 => current_block = BZ_X_CODING_1,
270            State::BZ_X_CODING_2 => current_block = BZ_X_CODING_2,
271            State::BZ_X_CODING_3 => current_block = BZ_X_CODING_3,
272            State::BZ_X_MTF_1 => current_block = BZ_X_MTF_1,
273            State::BZ_X_MTF_2 => current_block = BZ_X_MTF_2,
274            State::BZ_X_MTF_3 => current_block = BZ_X_MTF_3,
275            State::BZ_X_MTF_4 => current_block = BZ_X_MTF_4,
276            State::BZ_X_MTF_5 => current_block = BZ_X_MTF_5,
277            State::BZ_X_MTF_6 => current_block = BZ_X_MTF_6,
278            State::BZ_X_ENDHDR_2 => current_block = BZ_X_ENDHDR_2,
279            State::BZ_X_ENDHDR_3 => current_block = BZ_X_ENDHDR_3,
280            State::BZ_X_ENDHDR_4 => current_block = BZ_X_ENDHDR_4,
281            State::BZ_X_ENDHDR_5 => current_block = BZ_X_ENDHDR_5,
282            State::BZ_X_ENDHDR_6 => current_block = BZ_X_ENDHDR_6,
283            State::BZ_X_CCRC_1 => current_block = BZ_X_CCRC_1,
284            State::BZ_X_CCRC_2 => current_block = BZ_X_CCRC_2,
285            State::BZ_X_CCRC_3 => current_block = BZ_X_CCRC_3,
286            State::BZ_X_CCRC_4 => current_block = BZ_X_CCRC_4,
287            State::BZ_X_IDLE | State::BZ_X_OUTPUT => unreachable!(),
288        }
289        if current_block == BZ_X_MAGIC_2 {
290            s.state = State::BZ_X_MAGIC_2;
291
292            uc = GET_BYTE!(strm, s);
293
294            if uc != b'Z' {
295                error!(BZ_DATA_ERROR_MAGIC);
296            }
297
298            current_block = BZ_X_MAGIC_3;
299        }
300        if current_block == BZ_X_MAGIC_3 {
301            s.state = State::BZ_X_MAGIC_3;
302
303            uc = GET_BYTE!(strm, s);
304
305            if uc != b'h' {
306                error!(BZ_DATA_ERROR_MAGIC);
307            }
308
309            current_block = BZ_X_MAGIC_4;
310        }
311        if current_block == BZ_X_MAGIC_4 {
312            s.state = State::BZ_X_MAGIC_4;
313
314            s.blockSize100k = GET_BYTE!(strm, s);
315
316            if !(b'1'..=b'9').contains(&s.blockSize100k) {
317                error!(BZ_DATA_ERROR_MAGIC);
318            }
319
320            s.blockSize100k -= b'0';
321
322            match s.smallDecompress {
323                DecompressMode::Small => {
324                    // SAFETY: we assume allocation is safe
325                    let ll16_len = usize::from(s.blockSize100k) * 100000;
326                    let Some(ll16) = DSlice::alloc(allocator, ll16_len) else {
327                        error!(BZ_MEM_ERROR);
328                    };
329
330                    // SAFETY: we assume allocation is safe
331                    let ll4_len = (1 + usize::from(s.blockSize100k) * 100000) >> 1;
332                    let Some(ll4) = DSlice::alloc(allocator, ll4_len) else {
333                        error!(BZ_MEM_ERROR);
334                    };
335
336                    s.ll16 = ll16;
337                    s.ll4 = ll4;
338                }
339                DecompressMode::Fast => {
340                    // SAFETY: we assume allocation is safe
341                    let tt_len = usize::from(s.blockSize100k) * 100000;
342                    let Some(tt) = DSlice::alloc(allocator, tt_len) else {
343                        error!(BZ_MEM_ERROR);
344                    };
345
346                    s.tt = tt;
347                }
348            }
349
350            current_block = BZ_X_BLKHDR_1;
351        }
352        if current_block == BZ_X_BLKHDR_1 {
353            s.state = State::BZ_X_BLKHDR_1;
354
355            uc = GET_BYTE!(strm, s);
356
357            match uc {
358                0x17 => current_block = BZ_X_ENDHDR_2,
359                0x31 => current_block = BZ_X_BLKHDR_2,
360                _ => error!(BZ_DATA_ERROR),
361            };
362        }
363        match current_block {
364            BZ_X_ENDHDR_2 => {
365                s.state = State::BZ_X_ENDHDR_2;
366
367                uc = GET_BYTE!(strm, s);
368
369                if uc != 0x72 {
370                    error!(BZ_DATA_ERROR);
371                }
372
373                current_block = BZ_X_ENDHDR_3;
374            }
375            BZ_X_BLKHDR_2 => {
376                s.state = State::BZ_X_BLKHDR_2;
377
378                uc = GET_BYTE!(strm, s);
379
380                if uc != 0x41 {
381                    error!(BZ_DATA_ERROR);
382                }
383                current_block = BZ_X_BLKHDR_3;
384            }
385            _ => {}
386        }
387        match current_block {
388            BZ_X_ENDHDR_3 => {
389                s.state = State::BZ_X_ENDHDR_3;
390
391                uc = GET_BYTE!(strm, s);
392
393                if uc != 0x45 {
394                    error!(BZ_DATA_ERROR);
395                }
396
397                current_block = BZ_X_ENDHDR_4;
398            }
399            BZ_X_BLKHDR_3 => {
400                s.state = State::BZ_X_BLKHDR_3;
401
402                uc = GET_BYTE!(strm, s);
403
404                if uc != 0x59 {
405                    error!(BZ_DATA_ERROR);
406                }
407
408                current_block = BZ_X_BLKHDR_4;
409            }
410            _ => {}
411        }
412        match current_block {
413            BZ_X_ENDHDR_4 => {
414                s.state = State::BZ_X_ENDHDR_4;
415
416                uc = GET_BYTE!(strm, s);
417
418                if uc != 0x38 {
419                    error!(BZ_DATA_ERROR);
420                }
421
422                current_block = BZ_X_ENDHDR_5;
423            }
424            BZ_X_BLKHDR_4 => {
425                s.state = State::BZ_X_BLKHDR_4;
426
427                uc = GET_BYTE!(strm, s);
428
429                if uc != 0x26 {
430                    error!(BZ_DATA_ERROR);
431                }
432
433                current_block = BZ_X_BLKHDR_5;
434            }
435            _ => {}
436        }
437        match current_block {
438            BZ_X_ENDHDR_5 => {
439                s.state = State::BZ_X_ENDHDR_5;
440
441                uc = GET_BYTE!(strm, s);
442
443                if uc != 0x50 {
444                    error!(BZ_DATA_ERROR);
445                }
446
447                current_block = BZ_X_ENDHDR_6;
448            }
449            BZ_X_BLKHDR_5 => {
450                s.state = State::BZ_X_BLKHDR_5;
451
452                uc = GET_BYTE!(strm, s);
453
454                if uc != 0x53 {
455                    error!(BZ_DATA_ERROR);
456                }
457
458                current_block = BZ_X_BLKHDR_6;
459            }
460            _ => {}
461        }
462        match current_block {
463            BZ_X_ENDHDR_6 => {
464                s.state = State::BZ_X_ENDHDR_6;
465
466                uc = GET_BYTE!(strm, s);
467
468                if uc != 0x90 {
469                    error!(BZ_DATA_ERROR);
470                }
471
472                s.storedCombinedCRC = 0_u32;
473                current_block = BZ_X_CCRC_1;
474            }
475            BZ_X_BLKHDR_6 => {
476                s.state = State::BZ_X_BLKHDR_6;
477
478                uc = GET_BYTE!(strm, s);
479
480                if uc != 0x59 {
481                    error!(BZ_DATA_ERROR);
482                }
483
484                s.currBlockNo += 1;
485                if s.verbosity >= 2 {
486                    debug_log!("\n    [{}: huff+mtf ", s.currBlockNo);
487                }
488                s.storedBlockCRC = 0_u32;
489                current_block = BZ_X_BCRC_1;
490            }
491            _ => {}
492        }
493        match current_block {
494            BZ_X_CCRC_1 => {
495                s.state = State::BZ_X_CCRC_1;
496
497                uc = GET_BYTE!(strm, s);
498
499                s.storedCombinedCRC = (s.storedCombinedCRC << 8) | uc as u32;
500                current_block = BZ_X_CCRC_2;
501            }
502            BZ_X_BCRC_1 => {
503                s.state = State::BZ_X_BCRC_1;
504
505                uc = GET_BYTE!(strm, s);
506
507                s.storedBlockCRC = (s.storedBlockCRC << 8) | uc as u32;
508                current_block = BZ_X_BCRC_2;
509            }
510            _ => {}
511        }
512        match current_block {
513            BZ_X_CCRC_2 => {
514                s.state = State::BZ_X_CCRC_2;
515
516                uc = GET_BYTE!(strm, s);
517
518                s.storedCombinedCRC = (s.storedCombinedCRC << 8) | uc as u32;
519                current_block = BZ_X_CCRC_3;
520            }
521            BZ_X_BCRC_2 => {
522                s.state = State::BZ_X_BCRC_2;
523
524                uc = GET_BYTE!(strm, s);
525
526                s.storedBlockCRC = (s.storedBlockCRC << 8) | uc as u32;
527                current_block = BZ_X_BCRC_3;
528            }
529            _ => {}
530        }
531        match current_block {
532            BZ_X_CCRC_3 => {
533                s.state = State::BZ_X_CCRC_3;
534
535                uc = GET_BYTE!(strm, s);
536
537                s.storedCombinedCRC = (s.storedCombinedCRC << 8) | uc as u32;
538                current_block = BZ_X_CCRC_4;
539            }
540            BZ_X_BCRC_3 => {
541                s.state = State::BZ_X_BCRC_3;
542
543                uc = GET_BYTE!(strm, s);
544
545                s.storedBlockCRC = (s.storedBlockCRC << 8) | uc as u32;
546                current_block = BZ_X_BCRC_4;
547            }
548            _ => {}
549        }
550        match current_block {
551            BZ_X_BCRC_4 => {
552                s.state = State::BZ_X_BCRC_4;
553
554                uc = GET_BYTE!(strm, s);
555
556                s.storedBlockCRC = (s.storedBlockCRC << 8) | uc as u32;
557                current_block = BZ_X_RANDBIT;
558            }
559            BZ_X_CCRC_4 => {
560                s.state = State::BZ_X_CCRC_4;
561
562                uc = GET_BYTE!(strm, s);
563
564                s.storedCombinedCRC = (s.storedCombinedCRC << 8) | uc as u32;
565                s.state = State::BZ_X_IDLE;
566                error!(BZ_STREAM_END);
567            }
568            _ => {}
569        }
570        if current_block == BZ_X_RANDBIT {
571            s.state = State::BZ_X_RANDBIT;
572
573            s.blockRandomised = GET_BITS!(strm, s, 1) != 0;
574
575            s.origPtr = 0;
576            current_block = BZ_X_ORIGPTR_1;
577        }
578        if current_block == BZ_X_ORIGPTR_1 {
579            s.state = State::BZ_X_ORIGPTR_1;
580
581            uc = GET_BYTE!(strm, s);
582
583            s.origPtr = (s.origPtr << 8) | i32::from(uc);
584            current_block = BZ_X_ORIGPTR_2;
585        }
586        if current_block == BZ_X_ORIGPTR_2 {
587            s.state = State::BZ_X_ORIGPTR_2;
588
589            uc = GET_BYTE!(strm, s);
590
591            s.origPtr = (s.origPtr << 8) | i32::from(uc);
592            current_block = BZ_X_ORIGPTR_3;
593        }
594        if current_block == BZ_X_ORIGPTR_3 {
595            s.state = State::BZ_X_ORIGPTR_3;
596
597            uc = GET_BYTE!(strm, s);
598
599            s.origPtr = (s.origPtr << 8) | i32::from(uc);
600            if !(0..=10 + 100000 * i32::from(s.blockSize100k)).contains(&s.origPtr) {
601                error!(BZ_DATA_ERROR);
602            }
603
604            i = 0;
605            current_block = Block43;
606        }
607
608        // mutable because they need to be reborrowed
609        let tt = s.tt.as_mut_slice();
610        let ll16 = s.ll16.as_mut_slice();
611        let ll4 = s.ll4.as_mut_slice();
612
613        'state_machine: loop {
614            match current_block {
615                BZ_X_MAPPING_1 => {
616                    s.state = State::BZ_X_MAPPING_1;
617
618                    uc = GET_BIT!(strm, s) as u8;
619
620                    s.inUse16[i as usize] = uc == 1;
621                    i += 1;
622                    current_block = Block43;
623                    continue;
624                }
625                Block43 => {
626                    if i < 16 {
627                        current_block = BZ_X_MAPPING_1;
628                        continue;
629                    }
630                    s.inUse.fill(false);
631                    i = 0;
632                    current_block = Block18;
633                }
634                BZ_X_MAPPING_2 => {
635                    s.state = State::BZ_X_MAPPING_2;
636
637                    uc = GET_BIT!(strm, s) as u8;
638
639                    if uc == 1 {
640                        s.inUse[(i * 16 + j) as usize] = true;
641                    }
642                    j += 1;
643                    current_block = Block28;
644                }
645                BZ_X_SELECTOR_1 => {
646                    s.state = State::BZ_X_SELECTOR_1;
647
648                    nGroups = GET_BITS!(strm, s, 3) as u8;
649
650                    if (2..=6).contains(&nGroups) {
651                        current_block = BZ_X_SELECTOR_2;
652                        continue;
653                    }
654                    error!(BZ_DATA_ERROR);
655                }
656                BZ_X_SELECTOR_2 => {
657                    s.state = State::BZ_X_SELECTOR_2;
658
659                    nSelectors = GET_BITS!(strm, s, 15) as u16;
660
661                    if nSelectors < 1 {
662                        error!(BZ_DATA_ERROR);
663                    } else {
664                        i = 0;
665                    }
666                    current_block = Block39;
667                }
668                BZ_X_SELECTOR_3 => {
669                    s.state = State::BZ_X_SELECTOR_3;
670
671                    uc = GET_BIT!(strm, s) as u8;
672
673                    if uc == 0 {
674                        current_block = Block1;
675                    } else {
676                        j += 1;
677                        if j >= i32::from(nGroups) {
678                            error!(BZ_DATA_ERROR);
679                        } else {
680                            current_block = Block25;
681                        }
682                    }
683                }
684                BZ_X_CODING_1 => {
685                    s.state = State::BZ_X_CODING_1;
686
687                    curr = GET_BITS!(strm, s, 5) as u8;
688
689                    i = 0;
690                    current_block = Block26;
691                }
692                BZ_X_CODING_2 => {
693                    s.state = State::BZ_X_CODING_2;
694
695                    uc = GET_BIT!(strm, s) as u8;
696
697                    if uc != 0 {
698                        current_block = BZ_X_CODING_3;
699                        continue;
700                    }
701                    current_block = Block51;
702                }
703                BZ_X_CODING_3 => {
704                    s.state = State::BZ_X_CODING_3;
705
706                    uc = GET_BIT!(strm, s) as u8;
707
708                    match uc {
709                        0 => curr += 1,
710                        _ => curr -= 1,
711                    }
712
713                    current_block = Block45;
714                }
715                BZ_X_MTF_1 => {
716                    s.state = State::BZ_X_MTF_1;
717
718                    zvec = GET_BITS!(strm, s, zn as i32) as i32;
719
720                    current_block = Block56;
721                }
722                BZ_X_MTF_2 => {
723                    s.state = State::BZ_X_MTF_2;
724
725                    zj = GET_BIT!(strm, s);
726
727                    zvec = (zvec << 1) | zj as i32;
728                    current_block = Block56;
729                }
730                BZ_X_MTF_3 => {
731                    s.state = State::BZ_X_MTF_3;
732
733                    zvec = GET_BITS!(strm, s, zn as i32) as i32;
734
735                    current_block = Block52;
736                }
737                BZ_X_MTF_4 => {
738                    s.state = State::BZ_X_MTF_4;
739
740                    zj = GET_BIT!(strm, s);
741
742                    zvec = (zvec << 1) | zj as i32;
743                    current_block = Block52;
744                }
745                BZ_X_MTF_5 => {
746                    s.state = State::BZ_X_MTF_5;
747
748                    zvec = GET_BITS!(strm, s, zn as i32) as i32;
749
750                    current_block = Block24;
751                }
752                _ => {
753                    s.state = State::BZ_X_MTF_6;
754
755                    zj = GET_BIT!(strm, s);
756
757                    zvec = (zvec << 1) | zj as i32;
758                    current_block = Block24;
759                }
760            }
761
762            macro_rules! get_next_sym {
763                ($next_block:ident) => {
764                    if zn > 20 {
765                        // zn is higher than the longest code, that's invalid input
766                        error!(BZ_DATA_ERROR);
767                    } else if zvec <= s.limit[usize::from(gSel)][zn as usize] {
768                        let index = zvec - s.base[usize::from(gSel)][zn as usize];
769                        match s.perm[usize::from(gSel)].get(index as usize) {
770                            Some(&nextSym) => nextSym,
771                            None => error!(BZ_DATA_ERROR),
772                        }
773                    } else {
774                        zn += 1;
775                        current_block = $next_block;
776                        continue 'state_machine;
777                    }
778                };
779            }
780
781            match current_block {
782                Block24 => {
783                    nextSym = get_next_sym!(BZ_X_MTF_6);
784                    current_block = Block40;
785                }
786                Block52 => {
787                    nextSym = get_next_sym!(BZ_X_MTF_4);
788
789                    if nextSym == BZ_RUNA || nextSym == BZ_RUNB {
790                        current_block = Block46;
791                    } else {
792                        let uc = s.seqToUnseq[usize::from(s.mtfa[usize::from(s.mtfbase[0])])];
793                        s.unzftab[usize::from(uc)] += es;
794                        match s.smallDecompress {
795                            DecompressMode::Small => {
796                                match ll16.get_mut(nblock as usize..(nblock + es) as usize) {
797                                    Some(slice) => slice.fill(u16::from(uc)),
798                                    None => error!(BZ_DATA_ERROR),
799                                };
800                                nblock += es;
801                            }
802                            DecompressMode::Fast => {
803                                match tt.get_mut(nblock as usize..(nblock + es) as usize) {
804                                    Some(slice) => slice.fill(u32::from(uc)),
805                                    None => error!(BZ_DATA_ERROR),
806                                };
807                                nblock += es;
808                            }
809                        }
810                        current_block = Block40;
811                    }
812                }
813                Block56 => {
814                    nextSym = get_next_sym!(BZ_X_MTF_2);
815                    current_block = Block40;
816                }
817                _ => {}
818            }
819            if current_block == Block40 {
820                if nextSym == EOB {
821                    current_block = Block41;
822                } else if nextSym == BZ_RUNA || nextSym == BZ_RUNB {
823                    es = 0;
824                    logN = 0;
825                    current_block = Block46;
826                } else if nblock >= 100000 * u32::from(nblockMAX100k) {
827                    error!(BZ_DATA_ERROR);
828                } else {
829                    let uc = usize::from(initialize_mtfa(&mut s.mtfa, &mut s.mtfbase, nextSym));
830                    let index = s.seqToUnseq[uc];
831                    s.unzftab[usize::from(index)] += 1;
832                    match s.smallDecompress {
833                        DecompressMode::Small => ll16[nblock as usize] = u16::from(index),
834                        DecompressMode::Fast => tt[nblock as usize] = u32::from(index),
835                    }
836                    nblock += 1;
837                    update_group_pos!(s);
838                    zn = gMinlen;
839                    current_block = BZ_X_MTF_5;
840                    continue;
841                }
842                match current_block {
843                    Block46 => {}
844                    _ => {
845                        if s.origPtr < 0 || s.origPtr >= nblock as i32 {
846                            error!(BZ_DATA_ERROR);
847                        } else {
848                            if s.unzftab.iter().any(|e| !(0..=nblock).contains(e)) {
849                                error!(BZ_DATA_ERROR);
850                            }
851                            s.cftab[0] = 0;
852                            s.cftab[1..].copy_from_slice(&s.unzftab);
853                            for i in 1..s.cftab.len() {
854                                s.cftab[i] += s.cftab[i - 1];
855                            }
856                            if s.cftab.iter().any(|e| !(0..=nblock).contains(e)) {
857                                error!(BZ_DATA_ERROR);
858                            }
859                            // FIXME: use https://doc.rust-lang.org/std/primitive.slice.html#method.is_sorted
860                            // when available in our MSRV (requires >= 1.82.0)
861                            if s.cftab.windows(2).any(|w| w[0] > w[1]) {
862                                error!(BZ_DATA_ERROR);
863                            }
864                            s.state_out_len = 0;
865                            s.state_out_ch = 0;
866                            s.calculatedBlockCRC = u32::MAX;
867                            s.state = State::BZ_X_OUTPUT;
868                            if s.verbosity >= 2 {
869                                debug_log!("rt+rld");
870                            }
871                            match s.smallDecompress {
872                                DecompressMode::Small => {
873                                    // Make a copy of cftab, used in generation of T
874                                    s.cftabCopy = s.cftab;
875
876                                    // compute the T vector
877                                    for i in 0..nblock as usize {
878                                        let uc = usize::from(ll16[i]);
879                                        ll16[i] = (s.cftabCopy[uc] & 0xffff) as u16;
880
881                                        // set the lower or higher nibble depending on i
882                                        let (mask, shift) = match i & 0x1 {
883                                            0 => (0xF0, 0),
884                                            _ => (0x0F, 4),
885                                        };
886                                        ll4[i / 2] &= mask;
887                                        ll4[i / 2] |= ((s.cftabCopy[uc] >> 16) << shift) as u8;
888
889                                        s.cftabCopy[uc] += 1;
890                                    }
891
892                                    // Compute T^(-1) by pointer reversal on T
893                                    i = s.origPtr;
894                                    j = (ll16[i as usize] as u32
895                                        | (((ll4[(i >> 1) as usize] as u32 >> ((i << 2) & 0b100))
896                                            & 0xf)
897                                            << 16)) as i32;
898                                    loop {
899                                        let tmp_0: i32 = (ll16[j as usize] as u32
900                                            | (((ll4[(j >> 1) as usize] as u32
901                                                >> ((j << 2) & 0b100))
902                                                & 0xf)
903                                                << 16))
904                                            as i32;
905                                        ll16[j as usize] = (i & 0xffff) as u16;
906                                        if j & 0x1 == 0 {
907                                            ll4[(j >> 1) as usize] = (ll4[(j >> 1) as usize]
908                                                as c_int
909                                                & 0xf0
910                                                | (i >> 16))
911                                                as u8;
912                                        } else {
913                                            ll4[(j >> 1) as usize] =
914                                                (ll4[(j >> 1) as usize] as c_int & 0xf
915                                                    | ((i >> 16) << 4))
916                                                    as u8
917                                        }
918                                        i = j;
919                                        j = tmp_0;
920                                        if i == s.origPtr {
921                                            break;
922                                        }
923                                    }
924
925                                    s.tPos = s.origPtr as u32;
926                                    s.nblock_used = 0;
927
928                                    s.k0 = index_into_f(s.tPos, &s.cftab);
929                                    s.tPos = match ll16.get(s.tPos as usize) {
930                                        None => error!(BZ_DATA_ERROR),
931                                        Some(&low_bits) => {
932                                            let high_bits = (ll4[(s.tPos >> 1) as usize]
933                                                >> ((s.tPos << 2) & 0b100))
934                                                & 0xf;
935                                            u32::from(low_bits) | (u32::from(high_bits) << 16)
936                                        }
937                                    };
938                                    s.nblock_used += 1;
939
940                                    if s.blockRandomised {
941                                        s.rNToGo = 0;
942                                        s.rTPos = 0;
943                                        BZ_RAND_UPD_MASK!(s);
944                                        s.k0 ^= u8::from(s.rNToGo == 1)
945                                    }
946                                }
947                                DecompressMode::Fast => {
948                                    for i in 0..nblock as usize {
949                                        let uc = (tt[i] & 0xff) as usize;
950                                        tt[s.cftab[uc] as usize] |= (i << 8) as u32;
951                                        s.cftab[uc] += 1;
952                                    }
953                                    s.tPos = tt[s.origPtr as usize] >> 8;
954                                    s.nblock_used = 0;
955
956                                    s.tPos = match tt.get(s.tPos as usize) {
957                                        Some(&tPos) => tPos,
958                                        None => error!(BZ_DATA_ERROR),
959                                    };
960                                    s.k0 = (s.tPos & 0xff) as u8;
961                                    s.tPos >>= 8;
962                                    s.nblock_used += 1;
963
964                                    if s.blockRandomised {
965                                        s.rNToGo = 0;
966                                        s.rTPos = 0;
967                                        BZ_RAND_UPD_MASK!(s);
968                                        s.k0 ^= u8::from(s.rNToGo == 1)
969                                    }
970                                }
971                            }
972
973                            break 'save_state_and_return ReturnCode::BZ_OK;
974                        }
975                    }
976                }
977            }
978            if current_block == Block46 {
979                // Check that N doesn't get too big, so that es doesn't
980                // go negative.  The maximum value that can be
981                // RUNA/RUNB encoded is equal to the block size (post
982                // the initial RLE), viz, 900k, so bounding N at 2
983                // million should guard against overflow without
984                // rejecting any legitimate inputs.
985                const LOG_2MB: u8 = 21; // 2 * 1024 * 1024
986
987                if logN >= LOG_2MB {
988                    error!(BZ_DATA_ERROR);
989                } else {
990                    let mul = match nextSym {
991                        BZ_RUNA => 1,
992                        BZ_RUNB => 2,
993                        _ => 0,
994                    };
995                    es += mul * (1 << logN);
996                    logN += 1;
997                    update_group_pos!(s);
998                    zn = gMinlen;
999                    current_block = BZ_X_MTF_3;
1000                    continue;
1001                }
1002            }
1003            loop {
1004                match current_block {
1005                    Block28 => {
1006                        if j < 16 {
1007                            current_block = BZ_X_MAPPING_2;
1008                            continue 'state_machine;
1009                        }
1010                    }
1011                    Block39 => {
1012                        if i < i32::from(nSelectors) {
1013                            j = 0;
1014                            current_block = Block25;
1015                            continue;
1016                        } else {
1017                            // make sure that the constant fits in a u16
1018                            nSelectors = Ord::min(nSelectors, BZ_MAX_SELECTORS);
1019
1020                            let mut pos: [u8; 6] = [0, 1, 2, 3, 4, 5];
1021                            for i in 0..usize::from(nSelectors) {
1022                                rotate_right_1(&mut pos[..=usize::from(s.selectorMtf[i])]);
1023                                s.selector[i] = pos[0];
1024                            }
1025
1026                            // try to read the coding tables in one go if there is sufficient input
1027                            let bits_needed =
1028                                usize::from(nGroups) * (5 + (usize::from(alphaSize) * 2 * 20));
1029                            let bytes_needed = bits_needed.div_ceil(8);
1030
1031                            if strm.avail_in as usize >= bytes_needed {
1032                                for t in 0..usize::from(nGroups) {
1033                                    let mut curr = GET_BITS!(strm, s, 5);
1034                                    for i in 0..usize::from(alphaSize) {
1035                                        loop {
1036                                            if !(1..=20).contains(&curr) {
1037                                                error!(BZ_DATA_ERROR);
1038                                            }
1039                                            if !GET_BIT!(strm, s) {
1040                                                break;
1041                                            };
1042                                            match GET_BIT!(strm, s) {
1043                                                false => curr += 1,
1044                                                true => curr -= 1,
1045                                            }
1046                                        }
1047
1048                                        s.len[t][i] = curr as u8;
1049                                    }
1050                                }
1051
1052                                t = nGroups;
1053                                current_block = Block35;
1054                                break;
1055                            } else {
1056                                t = 0;
1057                                current_block = Block35;
1058                                break;
1059                            }
1060                        }
1061                    }
1062                    Block18 => {
1063                        if let Some(&in_use) = s.inUse16.get(i as usize) {
1064                            if in_use {
1065                                j = 0;
1066                                current_block = Block28;
1067                                continue;
1068                            }
1069                        } else {
1070                            // inlined `make_maps_d`
1071                            s.nInUse = 0;
1072                            for (i, in_use) in s.inUse.iter().enumerate() {
1073                                if *in_use {
1074                                    s.seqToUnseq[usize::from(s.nInUse)] = i as u8;
1075                                    s.nInUse += 1;
1076                                }
1077                            }
1078
1079                            if s.nInUse == 0 {
1080                                current_block = Block11;
1081                                break;
1082                            } else {
1083                                current_block = Block58;
1084                                break;
1085                            }
1086                        }
1087                    }
1088                    Block51 => {
1089                        s.len[t as usize][i as usize] = curr;
1090                        i += 1;
1091                        current_block = Block26;
1092                        continue;
1093                    }
1094                    Block26 => {
1095                        if i < i32::from(alphaSize) {
1096                            current_block = Block45;
1097                            continue;
1098                        }
1099                        t += 1;
1100                        current_block = Block35;
1101                        break;
1102                    }
1103                    Block1 => {
1104                        if i < i32::from(BZ_MAX_SELECTORS) {
1105                            s.selectorMtf[i as usize] = j as u8;
1106                        }
1107                        i += 1;
1108                        current_block = Block39;
1109                        continue;
1110                    }
1111                    Block25 => {
1112                        current_block = BZ_X_SELECTOR_3;
1113                        continue 'state_machine;
1114                    }
1115                    _ => {
1116                        if false {
1117                            current_block = Block51;
1118                            continue;
1119                        }
1120                        if (1..=20).contains(&curr) {
1121                            current_block = BZ_X_CODING_2;
1122                            continue 'state_machine;
1123                        }
1124                        error!(BZ_DATA_ERROR);
1125                    }
1126                }
1127                i += 1;
1128                current_block = Block18;
1129            }
1130            match current_block {
1131                Block58 => {
1132                    alphaSize = s.nInUse + 2;
1133                    current_block = BZ_X_SELECTOR_1;
1134                }
1135                Block11 => {
1136                    error!(BZ_DATA_ERROR);
1137                }
1138                _ => {
1139                    if t < nGroups {
1140                        current_block = BZ_X_CODING_1;
1141                        continue;
1142                    }
1143
1144                    /*--- Create the Huffman decoding tables ---*/
1145                    for t in 0..usize::from(nGroups) {
1146                        // NOTE: s.nInUse <= 256, alphaSize <= 258
1147                        let len = &s.len[t][..usize::from(alphaSize)];
1148
1149                        let mut minLen = 32u8;
1150                        let mut maxLen = 0u8;
1151                        for &current in len {
1152                            maxLen = Ord::max(maxLen, current);
1153                            minLen = Ord::min(minLen, current);
1154                        }
1155                        s.minLens[t] = minLen;
1156
1157                        huffman::create_decode_tables(
1158                            &mut s.limit[t],
1159                            &mut s.base[t],
1160                            &mut s.perm[t],
1161                            len,
1162                            minLen,
1163                            maxLen,
1164                        );
1165                    }
1166
1167                    /*--- Now the MTF values ---*/
1168
1169                    EOB = s.nInUse + 1;
1170                    nblockMAX100k = s.blockSize100k;
1171                    s.unzftab.fill(0);
1172
1173                    /*-- MTF init --*/
1174                    let mut kk: u16 = MTFA_SIZE - 1;
1175                    for ii in (0..256 / MTFL_SIZE).rev() {
1176                        for jj in (0..MTFL_SIZE).rev() {
1177                            s.mtfa[usize::from(kk)] = (ii * MTFL_SIZE + jj) as u8;
1178                            kk -= 1;
1179                        }
1180                        s.mtfbase[ii] = kk + 1;
1181                    }
1182                    /*-- end MTF init --*/
1183
1184                    nblock = 0;
1185                    groupNo = -1;
1186                    groupPos = 0;
1187                    update_group_pos!(s);
1188
1189                    zn = gMinlen;
1190                    current_block = BZ_X_MTF_1;
1191                }
1192            }
1193        }
1194    };
1195
1196    s.save = SaveArea {
1197        i,
1198        j,
1199        t,
1200        alphaSize,
1201        nGroups,
1202        nSelectors,
1203        EOB,
1204        groupNo,
1205        groupPos,
1206        nextSym,
1207        nblockMAX100k,
1208        nblock,
1209        es,
1210        logN,
1211        curr,
1212        zn,
1213        zvec,
1214        zj,
1215        gSel,
1216        gMinlen,
1217    };
1218
1219    // update total_in with how many bytes were read during this call
1220    let bytes_read = old_avail_in - strm.avail_in;
1221    let old_total_in_lo32 = strm.total_in_lo32;
1222    strm.total_in_lo32 = strm.total_in_lo32.wrapping_add(bytes_read);
1223    strm.total_in_hi32 += (strm.total_in_lo32 < old_total_in_lo32) as u32;
1224
1225    ret_val
1226}
1227
1228fn initialize_mtfa(mtfa: &mut [u8; 4096], mtfbase: &mut [u16; 16], nextSym: u16) -> u8 {
1229    let nn = usize::from(nextSym - 1);
1230
1231    if nn < MTFL_SIZE {
1232        // avoid general case expense
1233        let pp = usize::from(mtfbase[0]);
1234        let uc = mtfa[pp + nn];
1235        rotate_right_1(&mut mtfa[pp..][..=nn]);
1236
1237        uc
1238    } else {
1239        // general case
1240        let mut lno = nn.wrapping_div(MTFL_SIZE);
1241        let off = nn.wrapping_rem(MTFL_SIZE);
1242        let base = usize::from(mtfbase[lno]);
1243        let uc = mtfa[base + off];
1244
1245        // shift this range one to the right
1246        mtfa.copy_within(base..base + off, base + 1);
1247
1248        mtfbase[lno] += 1;
1249        while lno > 0 {
1250            mtfbase[lno] -= 1;
1251            mtfa[usize::from(mtfbase[lno])] = mtfa[usize::from(mtfbase[lno - 1] + 16 - 1)];
1252            lno -= 1;
1253        }
1254        mtfbase[0] -= 1;
1255        mtfa[usize::from(mtfbase[0])] = uc;
1256
1257        if mtfbase[0] == 0 {
1258            let mut kk = MTFA_SIZE - 1;
1259            for ii in (0..256 / MTFL_SIZE).rev() {
1260                for jj in (0..MTFL_SIZE).rev() {
1261                    mtfa[usize::from(kk)] = mtfa[usize::from(mtfbase[ii]) + jj];
1262                    kk -= 1;
1263                }
1264                mtfbase[ii] = kk + 1;
1265            }
1266        }
1267
1268        uc
1269    }
1270}
1271
1272fn rotate_right_1(slice: &mut [u8]) {
1273    match slice {
1274        [] | [_] => { /* ignore */ }
1275        [a, b] => {
1276            // The 2-element case is fairly common, and because we already branch on the length,
1277            // the check for `len == 2` is very cheap.
1278            //
1279            // On x86_64 the `rol` instruction is used to swap the bytes with just 1 instruction.
1280            // See https://godbolt.org/z/385K7qs91
1281            core::mem::swap(a, b)
1282        }
1283        [.., last] => {
1284            let last = *last;
1285            slice.copy_within(0..slice.len() - 1, 1);
1286            slice[0] = last;
1287        }
1288    }
1289}