brotli_no_stdlib/
lib.rs

1#![no_std]
2#![allow(non_snake_case)]
3#![allow(unused_parens)]
4#![allow(non_camel_case_types)]
5#![allow(non_snake_case)]
6#![allow(non_upper_case_globals)]
7
8//#[macro_use] //<-- for debugging, remove xprintln from bit_reader and replace with println
9//extern crate std;
10
11#[macro_use]
12extern crate alloc_no_stdlib as alloc;
13pub use alloc::{Allocator, SliceWrapperMut, SliceWrapper, StackAllocator, AllocatedStackMemory};
14
15use core::mem;
16mod dictionary;
17#[macro_use]
18mod bit_reader;
19mod huffman;
20mod state;
21mod prefix;
22mod context;
23mod transform;
24mod test;
25use transform::{TransformDictionaryWord, kNumTransforms};
26use state::{BlockTypeAndLengthState,
27            BrotliRunningState, BrotliRunningContextMapState, BrotliRunningTreeGroupState,
28            BrotliRunningUncompressedState, BrotliRunningDecodeUint8State,
29            BrotliRunningMetablockHeaderState, BrotliRunningHuffmanState,
30            BrotliRunningReadBlockLengthState, kLiteralContextBits};
31use context:: {kContextLookup, kContextLookupOffsets};
32use ::dictionary::{
33    kBrotliDictionaryOffsetsByLength,
34    kBrotliDictionarySizeBitsByLength,
35    kBrotliMinDictionaryWordLength,
36    kBrotliMaxDictionaryWordLength,
37    kBrotliDictionary };
38pub use huffman::{HuffmanCode, HuffmanTreeGroup};
39pub enum BrotliResult {
40    ResultSuccess,
41    NeedsMoreInput,
42    NeedsMoreOutput,
43    ResultFailure,
44}
45
46const kDefaultCodeLength : u32 = 8;
47const kCodeLengthRepeatCode : u32 = 16;
48const kNumLiteralCodes : u16 = 256;
49const kNumInsertAndCopyCodes : u16 = 704;
50const kNumBlockLengthCodes : u32 = 26;
51const kDistanceContextBits : i32 = 2;
52const HUFFMAN_TABLE_BITS : u32 = 8;
53const HUFFMAN_TABLE_MASK : u32 = 0xff;
54const CODE_LENGTH_CODES : usize = 18;
55const kCodeLengthCodeOrder : [u8;CODE_LENGTH_CODES] = [
56  1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
57];
58
59/* Static prefix code for the complex code length code lengths. */
60const kCodeLengthPrefixLength : [u8; 16] = [
61  2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4,
62];
63
64const kCodeLengthPrefixValue : [u8;16] = [
65  0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,
66];
67
68
69macro_rules! BROTLI_LOG_UINT (
70    ($num : expr) => {
71       xprintln!("{:?} = {:?}", stringify!($num),  $num)
72    };
73);
74
75macro_rules! BROTLI_LOG (
76    ($str : expr, $num : expr) => {xprintln!("{:?} {:?}", $str, $num);};
77    ($str : expr, $num0 : expr, $num1 : expr) => {xprintln!("{:?} {:?} {:?}", $str, $num0, $num1);};
78    ($str : expr, $num0 : expr, $num1 : expr, $num2 : expr) => {xprintln!("{:?} {:?} {:?} {:?}", $str, $num0, $num1, $num2);};
79    ($str : expr, $num0 : expr, $num1 : expr, $num2 : expr, $num3 : expr) => {xprintln!("{:?} {:?} {:?} {:?} {:?}", $str, $num0, $num1, $num2, $num3);};
80);
81
82#[allow(non_snake_case)]
83fn BROTLI_FAILURE() -> BrotliResult {
84    return BrotliResult::ResultFailure;
85}
86macro_rules! BROTLI_LOG_ARRAY_INDEX (
87    ($array : expr, $index : expr) => {
88       xprintln!("{:?}[{:?}] = {:?}", stringify!($array), $index,  $array[$index as usize])
89    };
90);
91
92
93const NUM_DISTANCE_SHORT_CODES : u32 = 16;
94
95/*
96pub struct BrotliState {
97    total_written : usize,
98}
99*/
100pub use state::BrotliState;
101/*
102impl BrotliState {
103    pub fn new() -> BrotliState {
104        return BrotliState {total_written: 0 };
105    }
106}*/
107
108fn DecodeWindowBits(mut br : &mut bit_reader::BrotliBitReader) -> u32 {
109  let mut n : u32 = 0;
110  bit_reader::BrotliTakeBits(&mut br, 1, &mut n);
111  if (n == 0) {
112    return 16;
113  }
114  bit_reader::BrotliTakeBits(&mut br, 3, &mut n);
115  if (n != 0) {
116    return 17 + n;
117  }
118  bit_reader::BrotliTakeBits(&mut br, 3, &mut n);
119  if (n != 0) {
120    return 8 + n;
121  }
122  return 17;
123}
124
125#[cold]
126fn mark_unlikely() {
127}
128
129fn DecodeVarLenUint8(substate_decode_uint8 : &mut state::BrotliRunningDecodeUint8State,
130                     mut br : &mut bit_reader::BrotliBitReader,
131                     mut value : &mut u32,
132                     input : &[u8]) -> BrotliResult {
133  let mut bits : u32 = 0;
134  loop {
135    match *substate_decode_uint8 {
136      BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE => {
137        if !bit_reader::BrotliSafeReadBits(&mut br, 1, &mut bits, input) {
138          mark_unlikely();
139          return BrotliResult::NeedsMoreInput;
140        }
141        if (bits == 0) {
142          *value = 0;
143          return BrotliResult::ResultSuccess;
144        }
145        *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_SHORT;
146        /* No break, transit to the next state. */
147      },
148      BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_SHORT => {
149        if !bit_reader::BrotliSafeReadBits(&mut br, 3, &mut bits, input) {
150          mark_unlikely();
151          *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_SHORT;
152          return BrotliResult::NeedsMoreInput;
153        }
154        if (bits == 0) {
155          *value = 1;
156          *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE;
157          return BrotliResult::ResultSuccess;
158        }
159        /* Use output value as a temporary storage. It MUST be persisted. */
160        *value = bits;
161        /* No break, transit to the next state. */
162        *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_LONG;
163      },
164      BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_LONG => {
165        if !bit_reader::BrotliSafeReadBits(&mut br, *value, &mut bits, input) {
166          mark_unlikely();
167          *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_LONG;
168          return BrotliResult::NeedsMoreInput;
169        }
170        *value = (1u32 << *value) + bits;
171        *substate_decode_uint8 = BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE;
172        return BrotliResult::ResultSuccess;
173      },
174    }
175  }
176}
177
178fn DecodeMetaBlockLength<
179    'a, AllocU8 : alloc::Allocator<u8>,
180    AllocU32 : alloc::Allocator<u32>,
181    AllocHC : alloc::Allocator<HuffmanCode> > (s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> BrotliResult {
182  let mut bits : u32 = 0;
183  loop {
184    match s.substate_metablock_header {
185      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE => {
186        if !bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input) {
187          return BrotliResult::NeedsMoreInput;
188        }
189        s.is_last_metablock = bits as u8;
190        s.meta_block_remaining_len = 0;
191        s.is_uncompressed = 0;
192        s.is_metadata = 0;
193        if (s.is_last_metablock == 0) {
194          s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
195          continue;
196        }
197        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_EMPTY;
198        /* No break, transit to the next state. */
199      },
200      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_EMPTY => {
201        if !bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input) {
202          return BrotliResult::NeedsMoreInput;
203        }
204        if bits != 0 {
205          s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE;
206          return BrotliResult::ResultSuccess;
207        }
208        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
209        /* No break, transit to the next state. */
210      },
211      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NIBBLES => {
212        if !bit_reader::BrotliSafeReadBits(&mut s.br, 2, &mut bits, input) {
213          return BrotliResult::NeedsMoreInput;
214        }
215        s.size_nibbles = (bits + 4) as u8;
216        s.loop_counter = 0;
217        if (bits == 3) {
218          s.is_metadata = 1;
219          s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_RESERVED;
220          continue;
221        }
222        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_SIZE;
223        /* No break, transit to the next state. */
224
225      },
226      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_SIZE => {
227        let mut i = s.loop_counter;
228        while i < s.size_nibbles as i32 {
229          if !bit_reader::BrotliSafeReadBits(&mut s.br, 4, &mut bits, input) {
230            s.loop_counter = i;
231            return BrotliResult::NeedsMoreInput;
232          }
233          if (i + 1 == s.size_nibbles as i32 && s.size_nibbles > 4 && bits == 0) {
234            return BROTLI_FAILURE();
235          }
236          s.meta_block_remaining_len |= (bits << (i * 4)) as i32;
237          i += 1;
238        }
239        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
240        /* No break, transit to the next state. */
241      },
242      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED => {
243        if (s.is_last_metablock == 0 && s.is_metadata == 0) {
244          if !bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input) {
245            return BrotliResult::NeedsMoreInput;
246          }
247          s.is_uncompressed = bits as u8;
248        }
249        s.meta_block_remaining_len += 1;
250        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE;
251        return BrotliResult::ResultSuccess;
252      },
253      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_RESERVED => {
254        if !bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input) {
255          return BrotliResult::NeedsMoreInput;
256        }
257        if (bits != 0) {
258          return BROTLI_FAILURE();
259        }
260        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_BYTES;
261        /* No break, transit to the next state. */
262      },
263      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_BYTES => {
264        if !bit_reader::BrotliSafeReadBits(&mut s.br, 2, &mut bits, input) {
265          return BrotliResult::NeedsMoreInput;
266        }
267        if (bits == 0) {
268          s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE;
269          return BrotliResult::ResultSuccess;
270        }
271        s.size_nibbles = bits as u8;
272        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_METADATA;
273        /* No break, transit to the next state. */
274      },
275      BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_METADATA => {
276        let mut i = s.loop_counter;
277        while i < s.size_nibbles as i32 {
278          if !bit_reader::BrotliSafeReadBits(&mut s.br, 8, &mut bits, input) {
279            s.loop_counter = i;
280            return BrotliResult::NeedsMoreInput;
281          }
282          if (i + 1 == s.size_nibbles as i32 && s.size_nibbles > 1 && bits == 0) {
283            return BROTLI_FAILURE();
284          }
285          s.meta_block_remaining_len |= (bits << (i * 8)) as i32;
286          i += 1;
287        }
288        s.substate_metablock_header = BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
289        continue;
290      },
291    }
292  }
293}
294/* Decodes the Huffman code.
295   This method doesn't read data from the bit reader, BUT drops the amount of
296   bits that correspond to the decoded symbol.
297   bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */
298fn DecodeSymbol(bits : u32,
299                table : &[HuffmanCode],
300                br : &mut bit_reader::BrotliBitReader) -> u32 {
301  let mut table_index = bits & HUFFMAN_TABLE_MASK;
302  let mut table_element = table[table_index as usize];
303  if table_element.bits > HUFFMAN_TABLE_BITS as u8{
304    let nbits = table_element.bits - HUFFMAN_TABLE_BITS as u8;
305    bit_reader::BrotliDropBits(br, HUFFMAN_TABLE_BITS);
306    table_index += table_element.value as u32;
307    table_element = table[(table_index
308                           + ((bits >> HUFFMAN_TABLE_BITS) & bit_reader::BitMask(nbits as u32))) as usize];
309  }
310  bit_reader::BrotliDropBits(br, table_element.bits as u32);
311  return table_element.value as u32;
312}
313
314/* Reads and decodes the next Huffman code from bit-stream.
315   This method peeks 16 bits of input and drops 0 - 15 of them. */
316fn ReadSymbol(table : &[HuffmanCode],
317              br : &mut bit_reader::BrotliBitReader,
318              input : &[u8]) -> u32{
319  return DecodeSymbol(bit_reader::BrotliGet16BitsUnmasked(br, input), &table, br);
320}
321
322/* Same as DecodeSymbol, but it is known that there is less than 15 bits of
323   input are currently available. */
324fn SafeDecodeSymbol(table : &[HuffmanCode],
325                    mut br : &mut bit_reader::BrotliBitReader,
326                    result : &mut u32) -> bool {
327  let mut available_bits = bit_reader::BrotliGetAvailableBits(&mut br);
328  if (available_bits == 0) {
329    if (table[0].bits == 0) {
330      *result = table[0].value as u32;
331      return true;
332    }
333    return false; /* No valid bits at all. */
334  }
335  let mut val = bit_reader::BrotliGetBitsUnmasked(&br) as u32;
336  let table_index = (val & HUFFMAN_TABLE_MASK) as usize;
337  let table_element = table[table_index];
338  if (table_element.bits <= HUFFMAN_TABLE_BITS as u8) {
339    if (table_element.bits as u32 <= available_bits) {
340      bit_reader::BrotliDropBits(&mut br, table_element.bits as u32);
341      *result = table_element.value as u32;
342      return true;
343    } else {
344      return false; /* Not enough bits for the first level. */
345    }
346  }
347  if (available_bits <= HUFFMAN_TABLE_BITS) {
348    return false; /* Not enough bits to move to the second level. */
349  }
350
351  /* Speculatively drop HUFFMAN_TABLE_BITS. */
352  val = (val & bit_reader::BitMask(table_element.bits as u32)) >> HUFFMAN_TABLE_BITS;
353  available_bits -= HUFFMAN_TABLE_BITS;
354  let table_sub_element = table[table_index + table_element.value as usize + val as usize];
355  if (available_bits < table_sub_element.bits as u32) {
356    return false; /* Not enough bits for the second level. */
357  }
358
359  bit_reader::BrotliDropBits(&mut br, HUFFMAN_TABLE_BITS + table_sub_element.bits as u32);
360  *result = table_sub_element.value as u32;
361  return true;
362}
363
364fn SafeReadSymbol (table : &[HuffmanCode],
365                   br : &mut bit_reader::BrotliBitReader,
366                   result : &mut u32,
367                   input : &[u8]) -> bool {
368  let mut val : u32 = 0;
369  if (bit_reader::BrotliSafeGetBits(br, 15, &mut val, input)) {
370    *result = DecodeSymbol(val, &table, br);
371    return true;
372  } else {
373     mark_unlikely();
374  }
375  return SafeDecodeSymbol(&table, br, result);
376}
377
378/* Makes a look-up in first level Huffman table. Peeks 8 bits. */
379fn PreloadSymbol(safe : bool,
380                 table : &[HuffmanCode],
381                 br : &mut bit_reader::BrotliBitReader,
382                 bits : &mut u32,
383                 value : &mut u32,
384                 input : &[u8]) {
385  if (safe) {
386    return;
387  }
388  let table_element = table[bit_reader::BrotliGetBits(br, HUFFMAN_TABLE_BITS, input) as usize];
389  *bits = table_element.bits as u32;
390  *value = table_element.value as u32;
391}
392
393/* Decodes the next Huffman code using data prepared by PreloadSymbol.
394   Reads 0 - 15 bits. Also peeks 8 following bits. */
395fn ReadPreloadedSymbol(table : &[HuffmanCode],
396                       br : &mut bit_reader::BrotliBitReader,
397                       bits : &mut u32,
398                       value : &mut u32,
399                       input : &[u8]) -> u32 {
400  let mut result = *value;
401  if *bits > HUFFMAN_TABLE_BITS {
402    mark_unlikely();
403    let val = bit_reader::BrotliGet16BitsUnmasked(br, input);
404    let mut ext_index = (val & HUFFMAN_TABLE_MASK) + *value;
405    let mask = bit_reader::BitMask((*bits - HUFFMAN_TABLE_BITS));
406    bit_reader::BrotliDropBits(br, HUFFMAN_TABLE_BITS);
407    ext_index += (val >> HUFFMAN_TABLE_BITS) & mask;
408    let ext = table[ext_index as usize];
409    bit_reader::BrotliDropBits(br, ext.bits as u32);
410    result = ext.value as u32;
411  } else {
412    bit_reader::BrotliDropBits(br, *bits);
413  }
414  PreloadSymbol(false, table, br, bits, value, input);
415  return result;
416}
417
418fn Log2Floor(mut x : u32) -> u32{
419  let mut result : u32 = 0;
420  while x != 0 {
421    x >>= 1;
422    result += 1;
423  }
424  return result;
425}
426
427
428/* Reads (s->symbol + 1) symbols.
429   Totally 1..4 symbols are read, 1..10 bits each.
430   The list of symbols MUST NOT contain duplicates.
431 */
432fn ReadSimpleHuffmanSymbols<
433    'a, AllocU8 : alloc::Allocator<u8>,
434    AllocU32 : alloc::Allocator<u32>,
435    AllocHC : alloc::Allocator<HuffmanCode> >(alphabet_size : u32,
436                                              s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
437                                              input : &[u8])
438  -> BrotliResult {
439
440  /* max_bits == 1..10; symbol == 0..3; 1..40 bits will be read. */
441  let max_bits = Log2Floor(alphabet_size - 1);
442  let mut i = s.sub_loop_counter;
443  let num_symbols = s.symbol;
444  for symbols_lists_item in s.symbols_lists_array[s.sub_loop_counter as usize ..
445                                                  num_symbols as usize + 1].iter_mut() {
446    let mut v : u32 = 0;
447    if !bit_reader::BrotliSafeReadBits(&mut s.br, max_bits, &mut v, input) {
448      mark_unlikely();
449      s.sub_loop_counter = i;
450      s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_READ;
451      return BrotliResult::NeedsMoreInput;
452    }
453    if (v >= alphabet_size) {
454      return BROTLI_FAILURE();
455    }
456    *symbols_lists_item = v as u16;
457    BROTLI_LOG_UINT!(v);
458    i += 1;
459  }
460  i = 0;
461  for symbols_list_item in s.symbols_lists_array[.. num_symbols as usize].iter() {
462    for other_item in s.symbols_lists_array[i as usize + 1 .. num_symbols as usize+ 1].iter() {
463      if (*symbols_list_item == *other_item) {
464        return BROTLI_FAILURE();
465      }
466    }
467    i += 1;
468  }
469
470  return BrotliResult::ResultSuccess;
471}
472
473/* Process single decoded symbol code length:
474    A) reset the repeat variable
475    B) remember code length (if it is not 0)
476    C) extend corredponding index-chain
477    D) reduce the huffman space
478    E) update the histogram
479 */
480fn ProcessSingleCodeLength(code_len : u32,
481    symbol : &mut u32, repeat : &mut u32, space : &mut u32,
482    prev_code_len : &mut u32, symbol_lists : &mut [u16], symbol_list_index_offset : usize,
483    code_length_histo : &mut [u16], next_symbol : &mut [i32]) {
484  *repeat = 0;
485  if (code_len != 0) { /* code_len == 1..15 */
486    // next_symbol may be negative, hence we have to supply offset to function
487    symbol_lists[(symbol_list_index_offset as i32 + next_symbol[code_len as usize]) as usize] = (*symbol) as u16;
488    next_symbol[code_len as usize] = (*symbol) as i32;
489    *prev_code_len = code_len;
490    *space -= 32768 >> code_len;
491    code_length_histo[code_len as usize] += 1;
492    BROTLI_LOG!("[ReadHuffmanCode] code_length[{:}]={:} histo[]={:}\n", *symbol, code_len, code_length_histo[code_len as usize]);
493  }
494  (*symbol) += 1;
495}
496
497/* Process repeated symbol code length.
498    A) Check if it is the extension of previous repeat sequence; if the decoded
499       value is not kCodeLengthRepeatCode, then it is a new symbol-skip
500    B) Update repeat variable
501    C) Check if operation is feasible (fits alphapet)
502    D) For each symbol do the same operations as in ProcessSingleCodeLength
503
504   PRECONDITION: code_len == kCodeLengthRepeatCode or kCodeLengthRepeatCode + 1
505 */
506fn ProcessRepeatedCodeLength(code_len : u32,
507    mut repeat_delta : u32, alphabet_size : u32, symbol : &mut u32,
508    repeat : &mut u32, space : &mut u32, prev_code_len : &mut u32,
509    repeat_code_len : &mut u32, symbol_lists : &mut [u16], symbol_lists_index : usize,
510    code_length_histo : &mut [u16], next_symbol : &mut [i32]) {
511  let old_repeat : u32;
512  let mut new_len : u32 = 0;
513  if (code_len == kCodeLengthRepeatCode) {
514    new_len = *prev_code_len;
515  }
516  if (*repeat_code_len != new_len) {
517    *repeat = 0;
518    *repeat_code_len = new_len;
519  }
520  old_repeat = *repeat;
521  if (*repeat > 0) {
522    *repeat -= 2;
523    *repeat <<= code_len - 14;
524  }
525  *repeat += repeat_delta + 3;
526  repeat_delta = *repeat - old_repeat;
527  if (*symbol + repeat_delta > alphabet_size) {
528    let _unused = BROTLI_FAILURE();
529    *symbol = alphabet_size;
530    *space = 0xFFFFF;
531    return;
532  }
533  BROTLI_LOG!("[ReadHuffmanCode] code_length[{:}..{:}] = {:}\n",
534              *symbol, *symbol + repeat_delta - 1, *repeat_code_len);
535  if (*repeat_code_len != 0) {
536    let last : u32 = *symbol + repeat_delta;
537    let mut next : i32 = next_symbol[*repeat_code_len as usize];
538    loop {
539      symbol_lists[(symbol_lists_index as i32 + next) as usize] = (*symbol) as u16;
540      next = (*symbol) as i32;
541      (*symbol) += 1;
542      if *symbol == last {
543        break;
544      }
545    }
546    next_symbol[*repeat_code_len as usize] = next;
547    *space -= repeat_delta << (15 - *repeat_code_len);
548    code_length_histo[*repeat_code_len as usize] =
549        (code_length_histo[*repeat_code_len as usize] as u32 + repeat_delta) as u16;
550  } else {
551    *symbol += repeat_delta;
552  }
553}
554
555/* Reads and decodes symbol codelengths. */
556fn ReadSymbolCodeLengths<
557    'a, AllocU8 : alloc::Allocator<u8>,
558    AllocU32 : alloc::Allocator<u32>,
559    AllocHC : alloc::Allocator<HuffmanCode> >(alphabet_size : u32,
560                                              s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
561                                              input : &[u8])
562    -> BrotliResult {
563
564  let mut symbol = s.symbol;
565  let mut repeat = s.repeat;
566  let mut space = s.space;
567  let mut prev_code_len : u32 = s.prev_code_len;
568  let mut repeat_code_len : u32 = s.repeat_code_len;
569  if (!bit_reader::BrotliWarmupBitReader(&mut s.br, input)) {
570    return BrotliResult::NeedsMoreInput;
571  }
572  while (symbol < alphabet_size && space > 0) {
573    let mut p_index = 0;
574    let code_len : u32;
575    if (!bit_reader::BrotliCheckInputAmount(&s.br, bit_reader::BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
576      s.symbol = symbol;
577      s.repeat = repeat;
578      s.prev_code_len = prev_code_len;
579      s.repeat_code_len = repeat_code_len;
580      s.space = space;
581      return BrotliResult::NeedsMoreInput;
582    }
583    bit_reader::BrotliFillBitWindow16(&mut s.br, input);
584    p_index += bit_reader::BrotliGetBitsUnmasked(& s.br) &
585        bit_reader::BitMask(huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH as u32) as u64;
586    let p = s.table[p_index as usize];
587    bit_reader::BrotliDropBits(&mut s.br, p.bits as u32); /* Use 1..5 bits */
588    code_len = p.value as u32; /* code_len == 0..17 */
589    if (code_len < kCodeLengthRepeatCode) {
590      ProcessSingleCodeLength(code_len, &mut symbol, &mut repeat, &mut space,
591          &mut prev_code_len, &mut s.symbols_lists_array, s.symbol_lists_index as usize,
592          &mut s.code_length_histo[..], &mut s.next_symbol[..]);
593    } else { /* code_len == 16..17, extra_bits == 2..3 */
594      let repeat_delta : u32 =
595          bit_reader::BrotliGetBitsUnmasked(&s.br) as u32 & bit_reader::BitMask(code_len - 14);
596      bit_reader::BrotliDropBits(&mut s.br, code_len - 14);
597      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
598          &mut symbol, &mut repeat, &mut space, &mut prev_code_len, &mut repeat_code_len,
599          &mut s.symbols_lists_array, s.symbol_lists_index as usize,
600          &mut s.code_length_histo[..], &mut s.next_symbol[..]);
601    }
602  }
603  s.space = space;
604  return BrotliResult::ResultSuccess;
605}
606
607fn SafeReadSymbolCodeLengths<
608    'a, AllocU8 : alloc::Allocator<u8>,
609    AllocU32 : alloc::Allocator<u32>,
610    AllocHC : alloc::Allocator<HuffmanCode> >(alphabet_size : u32,
611                                              s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
612                                              input : &[u8])
613    -> BrotliResult {
614  while (s.symbol < alphabet_size && s.space > 0) {
615    let mut p_index = 0;
616    let code_len : u32;
617    let mut bits : u32 = 0;
618    let available_bits : u32 = bit_reader::BrotliGetAvailableBits(&s.br);
619    if (available_bits != 0) {
620      bits = bit_reader::BrotliGetBitsUnmasked(&s.br) as u32;
621    }
622    p_index += bits & bit_reader::BitMask(huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH as u32);
623    let p = s.table[p_index as usize];
624    if (p.bits as u32> available_bits) {
625      // pullMoreInput;
626      if (!bit_reader::BrotliPullByte(&mut s.br, input)) {
627        return BrotliResult::NeedsMoreInput;
628      }
629      continue;
630    }
631    code_len = p.value as u32; /* code_len == 0..17 */
632    if (code_len < kCodeLengthRepeatCode) {
633      bit_reader::BrotliDropBits(&mut s.br, p.bits as u32);
634      ProcessSingleCodeLength(code_len, &mut s.symbol, &mut s.repeat, &mut s.space,
635          &mut s.prev_code_len,
636          &mut s.symbols_lists_array, s.symbol_lists_index as usize,
637          &mut s.code_length_histo[..], &mut s.next_symbol[..]);
638    } else { /* code_len == 16..17, extra_bits == 2..3 */
639      let extra_bits : u32 = code_len - 14;
640      let repeat_delta : u32 = (bits >> p.bits) & bit_reader::BitMask(extra_bits);
641      if (available_bits < p.bits as u32 + extra_bits) {
642        // pullMoreInput;
643        if (!bit_reader::BrotliPullByte(&mut s.br, input)) {
644          return BrotliResult::NeedsMoreInput;
645        }
646        continue;
647      }
648      bit_reader::BrotliDropBits(&mut s.br, p.bits as u32 + extra_bits);
649      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
650          &mut s.symbol, &mut s.repeat, &mut s.space, &mut s.prev_code_len,
651          &mut s.repeat_code_len,
652          &mut s.symbols_lists_array, s.symbol_lists_index as usize,
653          &mut s.code_length_histo[..], &mut s.next_symbol[..]);
654    }
655  }
656  return BrotliResult::ResultSuccess;
657}
658
659/* Reads and decodes 15..18 codes using static prefix code.
660   Each code is 2..4 bits long. In total 30..72 bits are used. */
661fn ReadCodeLengthCodeLengths<
662    'a, AllocU8 : alloc::Allocator<u8>,
663    AllocU32 : alloc::Allocator<u32>,
664    AllocHC : alloc::Allocator<HuffmanCode> >(s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
665                                              input : &[u8])
666    -> BrotliResult {
667
668  let mut num_codes : u32 = s.repeat;
669  let mut space : u32 = s.space;
670  let mut i = s.sub_loop_counter;
671  for code_length_code_order in kCodeLengthCodeOrder[s.sub_loop_counter as usize.. CODE_LENGTH_CODES as usize].iter() {
672    let code_len_idx = *code_length_code_order;
673    let mut ix : u32 = 0;
674
675    if !bit_reader::BrotliSafeGetBits(&mut s.br, 4, &mut ix, input) {
676      mark_unlikely();
677      let available_bits : u32 = bit_reader::BrotliGetAvailableBits(&s.br);
678      if (available_bits != 0) {
679        ix = bit_reader::BrotliGetBitsUnmasked(&s.br) as u32 & 0xF;
680      } else {
681        ix = 0;
682      }
683      if (kCodeLengthPrefixLength[ix as usize] as u32 > available_bits) {
684        s.sub_loop_counter = i;
685        s.repeat = num_codes;
686        s.space = space;
687        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_COMPLEX;
688        return BrotliResult::NeedsMoreInput;
689      }
690    }
691    BROTLI_LOG_UINT!(ix);
692    let v : u32 = kCodeLengthPrefixValue[ix as usize] as u32;
693    bit_reader::BrotliDropBits(&mut s.br, kCodeLengthPrefixLength[ix as usize] as u32);
694    s.code_length_code_lengths[code_len_idx as usize] = v as u8;
695    BROTLI_LOG_ARRAY_INDEX!(s.code_length_code_lengths, code_len_idx);
696    if v != 0 {
697      space = space - (32 >> v);
698      num_codes += 1;
699      s.code_length_histo[v as usize] += 1;
700      if space.wrapping_sub(1) >= 32 {
701        /* space is 0 or wrapped around */
702        break;
703      }
704    }
705    i += 1;
706  }
707  if (!(num_codes == 1 || space == 0)) {
708    return BROTLI_FAILURE();
709  }
710  return BrotliResult::ResultSuccess;
711}
712
713
714/* Decodes the Huffman tables.
715   There are 2 scenarios:
716    A) Huffman code contains only few symbols (1..4). Those symbols are read
717       directly; their code lengths are defined by the number of symbols.
718       For this scenario 4 - 45 bits will be read.
719
720    B) 2-phase decoding:
721    B.1) Small Huffman table is decoded; it is specified with code lengths
722         encoded with predefined entropy code. 32 - 74 bits are used.
723    B.2) Decoded table is used to decode code lengths of symbols in resulting
724         Huffman table. In worst case 3520 bits are read.
725*/
726fn ReadHuffmanCode<
727    'a, AllocU8 : alloc::Allocator<u8>,
728    AllocU32 : alloc::Allocator<u32>,
729    AllocHC : alloc::Allocator<HuffmanCode> > (
730        mut alphabet_size : u32,
731        table :&mut [HuffmanCode],
732        offset : usize,
733        opt_table_size : Option<&mut u32>,
734        s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
735        input : &[u8]) -> BrotliResult {
736  /* Unnecessary masking, but might be good for safety. */
737  alphabet_size &= 0x3ff;
738  /* State machine */
739  loop {
740    match s.substate_huffman {
741      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE => {
742        if !bit_reader::BrotliSafeReadBits(&mut s.br, 2, &mut s.sub_loop_counter, input) {
743          return BrotliResult::NeedsMoreInput;
744        }
745
746        BROTLI_LOG_UINT!(s.sub_loop_counter);
747        /* The value is used as follows:
748           1 for simple code;
749           0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
750        if (s.sub_loop_counter != 1) {
751          s.space = 32;
752          s.repeat = 0; /* num_codes */
753          for code_length_histo in s.code_length_histo[..huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH as usize + 1].iter_mut() {
754            *code_length_histo = 0; // memset
755          }
756          for code_length_code_length in s.code_length_code_lengths[..].iter_mut() {
757            *code_length_code_length = 0;
758          }
759          s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_COMPLEX;
760          //goto Complex;
761          continue;
762        }
763        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
764        /* No break, transit to the next state. */
765      },
766      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_SIZE => {
767        /* Read symbols, codes & code lengths directly. */
768        if (!bit_reader::BrotliSafeReadBits(&mut s.br, 2, &mut s.symbol, input)) { /* num_symbols */
769          s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
770          return BrotliResult::NeedsMoreInput;
771        }
772        s.sub_loop_counter = 0;
773        /* No break, transit to the next state. */
774        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_READ;
775      },
776      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_READ => {
777        let result = ReadSimpleHuffmanSymbols(alphabet_size, s, input);
778        match result {
779          BrotliResult::ResultSuccess => {},
780          _ => return result,
781        }
782        /* No break, transit to the next state. */
783        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
784      },
785      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_BUILD => {
786        let table_size : u32;
787        if (s.symbol == 3) {
788          let mut bits : u32 = 0;
789          if (!bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input)) {
790            s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
791            return BrotliResult::NeedsMoreInput;
792          }
793          s.symbol += bits;
794        }
795        BROTLI_LOG_UINT!(s.symbol);
796        table_size = huffman::BrotliBuildSimpleHuffmanTable(
797            &mut table[offset..], HUFFMAN_TABLE_BITS as i32, &s.symbols_lists_array[..], s.symbol);
798        match opt_table_size {
799          Some(opt_table_size_ref) => *opt_table_size_ref = table_size,
800          None => {},
801        }
802        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE;
803        return BrotliResult::ResultSuccess;
804      },
805  
806      /* Decode Huffman-coded code lengths. */
807      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_COMPLEX => {
808
809        let result = ReadCodeLengthCodeLengths(s, input);
810        match result {
811          BrotliResult::ResultSuccess => {},
812          _ => return result,
813        }
814        huffman::BrotliBuildCodeLengthsHuffmanTable(&mut s.table,
815                                                    &mut s.code_length_code_lengths,
816                                                    &mut s.code_length_histo);
817        for code_length_histo in s.code_length_histo[..].iter_mut() {
818          *code_length_histo = 0; // memset
819        }
820
821        let mut i : u32 = 0;
822        for next_symbol_mut in s.next_symbol[..huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH as usize + 1].iter_mut() {
823          *next_symbol_mut = i as i32 - (huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH as i32 + 1);
824          s.symbols_lists_array[(s.symbol_lists_index as i32
825                                 + i as i32
826                                 - (huffman::BROTLI_HUFFMAN_MAX_CODE_LENGTH as i32 + 1)) as usize] = 0xFFFF;
827          i += 1;
828        }
829  
830        s.symbol = 0;
831        s.prev_code_len = kDefaultCodeLength;
832        s.repeat = 0;
833        s.repeat_code_len = 0;
834        s.space = 32768;
835        /* No break, transit to the next state. */
836        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
837      },
838      BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS => {
839        let table_size : u32;
840        let mut result = ReadSymbolCodeLengths(alphabet_size, s, input);
841        match result {
842          BrotliResult::NeedsMoreInput => result = SafeReadSymbolCodeLengths(alphabet_size, s, input),
843          _ => {},
844        }
845        match result {
846          BrotliResult::ResultSuccess => {},
847          _ => return result,
848        }
849  
850        if (s.space != 0) {
851          BROTLI_LOG!("[ReadHuffmanCode] space = %d\n", s.space);
852          return BROTLI_FAILURE();
853        }
854        table_size = huffman::BrotliBuildHuffmanTable(&mut table[offset..], HUFFMAN_TABLE_BITS as i32,
855            &s.symbols_lists_array[..], s.symbol_lists_index, &mut s.code_length_histo);
856        match opt_table_size {
857          Some(opt_table_size_ref) => *opt_table_size_ref = table_size,
858          None => {},
859        }
860        s.substate_huffman = BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE;
861        return BrotliResult::ResultSuccess;
862      },
863    }
864  }
865}
866
867/* Decodes a block length by reading 3..39 bits. */
868fn ReadBlockLength(table : &[HuffmanCode],
869                   br : &mut bit_reader::BrotliBitReader,
870                   input : &[u8]) -> u32 {
871  let code : u32;
872  let nbits : u32;
873  code = ReadSymbol(table, br, input);
874  nbits = prefix::kBlockLengthPrefixCode[code as usize].nbits as u32; /* nbits == 2..24 */
875  return prefix::kBlockLengthPrefixCode[code as usize].offset as u32
876      + bit_reader::BrotliReadBits(br, nbits, input);
877}
878
879
880/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
881   reading can't be continued with ReadBlockLength. */
882fn SafeReadBlockLengthIndex(substate_read_block_length : &state::BrotliRunningReadBlockLengthState,
883                            block_length_index : u32,
884                            table : &[HuffmanCode],
885                            mut br : &mut bit_reader::BrotliBitReader,
886                            input : &[u8]) -> (bool, u32) {
887  match *substate_read_block_length {
888    state::BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE => {
889      let mut index : u32 = 0;
890      if (!SafeReadSymbol(&table, &mut br, &mut index, input)) {
891        return (false, 0);
892      }
893      return (true, index);
894    },
895    _ => return (true, block_length_index),
896  }
897}
898fn SafeReadBlockLengthFromIndex<
899    AllocHC : alloc::Allocator<HuffmanCode> >(s : &mut BlockTypeAndLengthState<AllocHC>,
900                                              br : &mut bit_reader::BrotliBitReader,
901                                              result : &mut u32,
902                                              res_index : (bool, u32),
903                                              input : &[u8]) -> bool{
904    let (res, index) = res_index;
905    if !res {
906        return false;
907    }
908    let mut bits : u32 = 0;
909    let nbits = prefix::kBlockLengthPrefixCode[index as usize].nbits; /* nbits == 2..24 */
910    if (!bit_reader::BrotliSafeReadBits(br, nbits as u32, &mut bits, input)) {
911      s.block_length_index = index;
912      s.substate_read_block_length
913          = state::BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
914      return false;
915    }
916    *result = prefix::kBlockLengthPrefixCode[index as usize].offset as u32 + bits;
917    s.substate_read_block_length
918        = state::BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
919    return true;
920}
921macro_rules! SafeReadBlockLength (
922   ($state : expr, $result : expr , $table : expr) => {
923       SafeReadBlockLengthFromIndex(&mut $state, &mut $result,
924                                    SafeReadBlockLengthIndex($state.substate_read_block_length,
925                                                             $state.block_length_index,
926                                                             $table,
927                                                             &mut $state.br))
928   };
929);
930
931/* Transform:
932    1) initialize list L with values 0, 1,... 255
933    2) For each input element X:
934    2.1) let Y = L[X]
935    2.2) remove X-th element from L
936    2.3) prepend Y to L
937    2.4) append Y to output
938
939   In most cases max(Y) <= 7, so most of L remains intact.
940   To reduce the cost of initialization, we reuse L, remember the upper bound
941   of Y values, and reinitialize only first elements in L.
942
943   Most of input values are 0 and 1. To reduce number of branches, we replace
944   inner for loop with do-while.
945 */
946fn InverseMoveToFrontTransform(v : &mut [u8], v_len : u32, mtf : &mut [u8], mtf_upper_bound :&mut u32) {
947  /* Reinitialize elements that could have been changed. */
948  let mut i : u32 = 0;
949  let mut upper_bound : u32 = *mtf_upper_bound;
950  for item in mtf[0..(upper_bound as usize + 1usize)].iter_mut() {
951      *item = i as u8;
952      i += 1;
953  }
954
955  /* Transform the input. */
956  upper_bound = 0;
957  for v_i in v[0usize .. (v_len as usize)].iter_mut() {
958    let mut index = (*v_i) as i32;
959    let value = mtf[index as usize];
960    upper_bound |= (*v_i) as u32;
961    *v_i = value;
962    if index <= 0 {
963      mtf[0] = 0;
964    } else {
965      loop {
966        index-=1;
967        mtf[(index + 1) as usize] = mtf[index as usize];
968        if index <= 0 {
969           break;
970        }
971      }
972    }
973    mtf[0] = value;
974  }
975  /* Remember amount of elements to be reinitialized. */
976  *mtf_upper_bound = upper_bound;
977}
978/* Decodes a series of Huffman table using ReadHuffmanCode function. */
979fn HuffmanTreeGroupDecode<
980  'a,
981  AllocU8 : alloc::Allocator<u8>,
982  AllocU32 : alloc::Allocator<u32>,
983  AllocHC : alloc::Allocator<HuffmanCode>>(group_index : i32,
984                                            mut s : &mut BrotliState<AllocU8,
985                                                                     AllocU32,
986                                                                     AllocHC>,
987                                            input : &[u8]) -> BrotliResult {
988  let mut hcodes : AllocHC::AllocatedMemory;
989  let mut htrees : AllocU32::AllocatedMemory;
990  let alphabet_size : u16;
991  let group_num_htrees : u16;
992  if group_index == 0 {
993    hcodes = mem::replace(&mut s.literal_hgroup.codes, AllocHC::AllocatedMemory::default());
994    htrees = mem::replace(&mut s.literal_hgroup.htrees, AllocU32::AllocatedMemory::default());
995    group_num_htrees = s.literal_hgroup.num_htrees;
996    alphabet_size = s.literal_hgroup.alphabet_size;
997  } else if group_index == 1 {
998    hcodes = mem::replace(&mut s.insert_copy_hgroup.codes, AllocHC::AllocatedMemory::default());
999    htrees = mem::replace(&mut s.insert_copy_hgroup.htrees, AllocU32::AllocatedMemory::default());
1000    group_num_htrees = s.insert_copy_hgroup.num_htrees;
1001    alphabet_size = s.insert_copy_hgroup.alphabet_size;
1002  } else {
1003    assert_eq!(group_index, 2);
1004    hcodes = mem::replace(&mut s.distance_hgroup.codes, AllocHC::AllocatedMemory::default());
1005    htrees = mem::replace(&mut s.distance_hgroup.htrees, AllocU32::AllocatedMemory::default());
1006    group_num_htrees = s.distance_hgroup.num_htrees;
1007    alphabet_size = s.distance_hgroup.alphabet_size;
1008  }
1009  match s.substate_tree_group {
1010    BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE => {
1011      s.htree_next_offset = 0;
1012      s.htree_index = 0;
1013      s.substate_tree_group = BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_LOOP;
1014    },
1015    BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_LOOP => {},
1016  }
1017  let mut result : BrotliResult = BrotliResult::ResultSuccess;
1018  for mut htree_iter in htrees.slice_mut()[s.htree_index as usize .. (group_num_htrees as usize)].iter_mut() {
1019    let mut table_size : u32 = 0;
1020    result = ReadHuffmanCode(alphabet_size as u32,
1021                             hcodes.slice_mut(),
1022                             s.htree_next_offset as usize,
1023                             Some(&mut table_size),
1024                             &mut s,
1025                             input);
1026    match result {
1027       BrotliResult::ResultSuccess => {},
1028       _ => break, // break and return the result code
1029    }
1030    *htree_iter = s.htree_next_offset;
1031    s.htree_next_offset += table_size;
1032    s.htree_index += 1;
1033  }
1034  if group_index == 0 {
1035    mem::replace(&mut s.literal_hgroup.codes,
1036                 mem::replace(&mut hcodes,
1037                              AllocHC::AllocatedMemory::default()));
1038    mem::replace(&mut s.literal_hgroup.htrees,
1039                 mem::replace(&mut htrees,
1040                              AllocU32::AllocatedMemory::default()));
1041  } else if group_index == 1 {
1042    mem::replace(&mut s.insert_copy_hgroup.codes,
1043                 mem::replace(&mut hcodes,
1044                              AllocHC::AllocatedMemory::default()));
1045    mem::replace(&mut s.insert_copy_hgroup.htrees,
1046                 mem::replace(&mut htrees,
1047                              AllocU32::AllocatedMemory::default()));
1048  } else {
1049    mem::replace(&mut s.distance_hgroup.codes,
1050                 mem::replace(&mut hcodes,
1051                              AllocHC::AllocatedMemory::default()));
1052    mem::replace(&mut s.distance_hgroup.htrees,
1053                 mem::replace(&mut htrees,
1054                              AllocU32::AllocatedMemory::default()));
1055  }
1056  match result {
1057    BrotliResult::ResultSuccess => s.substate_tree_group = BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE,
1058    _ => {},
1059  }
1060  return result;
1061}
1062
1063
1064fn bzero(data : &mut [u8]) {
1065  for iter in data.iter_mut() {
1066    *iter = 0;
1067  }
1068}
1069
1070
1071/* Decodes a context map.
1072   Decoding is done in 4 phases:
1073    1) Read auxiliary information (6..16 bits) and allocate memory.
1074       In case of trivial context map, decoding is finished at this phase.
1075    2) Decode Huffman table using ReadHuffmanCode function.
1076       This table will be used for reading context map items.
1077    3) Read context map items; "0" values could be run-length encoded.
1078    4) Optionally, apply InverseMoveToFront transform to the resulting map.
1079 */
1080fn DecodeContextMapInner<
1081  'a,
1082  AllocU8 : alloc::Allocator<u8>,
1083  AllocU32 : alloc::Allocator<u32>,
1084  AllocHC : alloc::Allocator<HuffmanCode>> (context_map_size : u32,
1085                                            num_htrees : &mut u32,
1086                                            context_map_arg : &mut AllocU8::AllocatedMemory,
1087                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1088                                            input : &[u8])
1089  -> BrotliResult {
1090
1091  let mut result : BrotliResult;
1092  loop {
1093    match s.substate_context_map {
1094      BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE => {
1095        result = DecodeVarLenUint8(&mut s.substate_decode_uint8, &mut s.br, num_htrees, input);
1096        match result {
1097          BrotliResult::ResultSuccess => {},
1098          _ => return result,
1099        }
1100        (*num_htrees) += 1;
1101        s.context_index = 0;
1102        BROTLI_LOG_UINT!(context_map_size);
1103        BROTLI_LOG_UINT!(*num_htrees);
1104        *context_map_arg = s.alloc_u8.alloc_cell(context_map_size as usize);
1105        if (context_map_arg.slice().len() < context_map_size as usize) {
1106          return BROTLI_FAILURE();
1107        }
1108        if (*num_htrees <= 1) {
1109          bzero(context_map_arg.slice_mut()); // This happens automatically but we do it to retain C++ similarity
1110          return BrotliResult::ResultSuccess;
1111        }
1112        s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
1113        /* No break, continue to next state. */
1114      },
1115      BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_READ_PREFIX => {
1116        let mut bits : u32 = 0;
1117         /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
1118           to peek 4 bits ahead. */
1119        if (!bit_reader::BrotliSafeGetBits(&mut s.br, 5, &mut bits, input)) {
1120          return BrotliResult::NeedsMoreInput;
1121        }
1122        if ((bits & 1) != 0) { /* Use RLE for zeroes. */
1123          s.max_run_length_prefix = (bits >> 1) + 1;
1124          bit_reader::BrotliDropBits(&mut s.br, 5);
1125        } else {
1126          s.max_run_length_prefix = 0;
1127          bit_reader::BrotliDropBits(&mut s.br, 1);
1128        }
1129        BROTLI_LOG_UINT!(s.max_run_length_prefix);
1130        s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
1131        /* No break, continue to next state. */
1132      }
1133      BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_HUFFMAN => {
1134
1135        let mut local_context_map_table = mem::replace(&mut s.context_map_table,
1136                                                       AllocHC::AllocatedMemory::default());
1137        result = ReadHuffmanCode(*num_htrees + s.max_run_length_prefix,
1138                                 &mut local_context_map_table.slice_mut(), 0, None, &mut s, input);
1139        mem::replace(&mut s.context_map_table, mem::replace(&mut local_context_map_table,
1140                                                            AllocHC::AllocatedMemory::default()));
1141        match result {
1142         BrotliResult::ResultSuccess => {},
1143         _ => return result,
1144        }
1145        s.code = 0xFFFF;
1146        s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_DECODE;
1147      /* No break, continue to next state. */
1148      },
1149      BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_DECODE => {
1150        let mut context_index : u32 = s.context_index;
1151        let max_run_length_prefix : u32 = s.max_run_length_prefix;
1152        let mut context_map = &mut context_map_arg.slice_mut();
1153        let mut code : u32 = s.code;
1154        let mut rleCodeGoto : bool = false;
1155        if (code != 0xFFFF) {
1156            rleCodeGoto = true;
1157        }
1158        while (rleCodeGoto || context_index < context_map_size) {
1159          if !rleCodeGoto {
1160            if (!SafeReadSymbol(s.context_map_table.slice(), &mut s.br, &mut code, input)) {
1161              s.code = 0xFFFF;
1162              s.context_index = context_index;
1163              return BrotliResult::NeedsMoreInput;
1164            }
1165            BROTLI_LOG_UINT!(code);
1166
1167            if code == 0 {
1168              context_map[context_index as usize] = 0;
1169              BROTLI_LOG_ARRAY_INDEX!(context_map, context_index as usize);
1170              context_index += 1;
1171              continue;
1172            }
1173            if code > max_run_length_prefix {
1174              context_map[context_index as usize] =
1175                  (code - max_run_length_prefix) as u8;
1176              BROTLI_LOG_ARRAY_INDEX!(context_map, context_index as usize);
1177              context_index += 1;
1178              continue;
1179            }
1180          }
1181          rleCodeGoto = false; // <-- this was a goto beforehand... now we have reached label
1182          // we are treated like everyday citizens from this point forth
1183          {
1184            let mut reps : u32 = 0;
1185            if (!bit_reader::BrotliSafeReadBits(&mut s.br, code, &mut reps, input)) {
1186              s.code = code;
1187              s.context_index = context_index;
1188              return BrotliResult::NeedsMoreInput;
1189            }
1190            reps += 1u32 << code;
1191            BROTLI_LOG_UINT!(reps);
1192            if (context_index + reps > context_map_size) {
1193              return BROTLI_FAILURE();
1194            }
1195            loop {
1196              context_map[context_index as usize] = 0;
1197              BROTLI_LOG_ARRAY_INDEX!(context_map, context_index as usize);
1198              context_index += 1;
1199              reps -= 1;
1200              if reps == 0 {
1201                 break;
1202              }
1203            }
1204          }
1205        }
1206        /* No break, continue to next state. */
1207        s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
1208      },
1209      BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_TRANSFORM => {
1210        let mut bits : u32 = 0;
1211        if (!bit_reader::BrotliSafeReadBits(&mut s.br, 1, &mut bits, input)) {
1212          s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
1213          return BrotliResult::NeedsMoreInput;
1214        }
1215        if (bits != 0) {
1216          InverseMoveToFrontTransform(context_map_arg.slice_mut(),
1217                                      context_map_size,
1218                                      &mut s.mtf,
1219                                      &mut s.mtf_upper_bound);
1220        }
1221        s.substate_context_map = BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE;
1222        return BrotliResult::ResultSuccess;
1223      },
1224    }
1225  }
1226  // unreachable!(); (compiler will error if it's reachable due to the unit return type)
1227}
1228
1229fn DecodeContextMap<
1230  'a, AllocU8 : alloc::Allocator<u8>,
1231  AllocU32 : alloc::Allocator<u32>,
1232  AllocHC : alloc::Allocator<HuffmanCode>> (context_map_size : usize,
1233                                            is_dist_context_map : bool,
1234                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1235                                            input : &[u8])
1236  -> BrotliResult {
1237
1238  match s.state {
1239    BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_1 => assert_eq!(is_dist_context_map, false),
1240    BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_2 => assert_eq!(is_dist_context_map, true),
1241    _ => unreachable!(),
1242  }
1243  let mut num_htrees : u32;
1244  let mut context_map_arg : AllocU8::AllocatedMemory;
1245  if is_dist_context_map {
1246    num_htrees = s.num_dist_htrees;
1247    context_map_arg = mem::replace(&mut s.dist_context_map,
1248                                   AllocU8::AllocatedMemory::default());
1249  } else {
1250    num_htrees = s.num_literal_htrees;
1251    context_map_arg = mem::replace(&mut s.context_map,
1252                                   AllocU8::AllocatedMemory::default());
1253  }
1254
1255  let retval = DecodeContextMapInner(context_map_size as u32, &mut num_htrees, &mut context_map_arg, &mut s, input);
1256  if is_dist_context_map {
1257    s.num_dist_htrees = num_htrees;
1258    mem::replace(&mut s.dist_context_map, mem::replace(&mut context_map_arg,
1259                                                       AllocU8::AllocatedMemory::default()));
1260  } else {
1261    s.num_literal_htrees = num_htrees;
1262    mem::replace(&mut s.context_map, mem::replace(&mut context_map_arg,
1263                                                  AllocU8::AllocatedMemory::default()));
1264  }
1265  return retval;
1266}
1267/* Decodes a command or literal and updates block type ringbuffer.
1268   Reads 3..54 bits. */
1269fn DecodeBlockTypeAndLength<
1270  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1271                                            mut s : &mut BlockTypeAndLengthState<AllocHC>,
1272                                            mut br : &mut bit_reader::BrotliBitReader,
1273                                            tree_type : i32,
1274                                            input : &[u8]) -> bool {
1275  let max_block_type = s.num_block_types[tree_type as usize];
1276  let tree_offset = tree_type as usize * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize;
1277
1278  let mut block_type : u32 = 0;
1279
1280  /* Read 0..15 + 3..39 bits */
1281  if (!safe) {
1282    block_type = ReadSymbol(&s.block_type_trees.slice()[tree_offset..], br, input);
1283    s.block_length[tree_type as usize] = ReadBlockLength(&s.block_len_trees.slice()[tree_offset..],
1284                                                         br,
1285                                                         input);
1286  } else {
1287    let memento = bit_reader::BrotliBitReaderSaveState(br);
1288    if (!SafeReadSymbol(&s.block_type_trees.slice()[tree_offset..], br, &mut block_type, input)) {
1289        return false;
1290    }
1291    let mut block_length_out : u32 = 0;
1292
1293    let index_ret = SafeReadBlockLengthIndex(&s.substate_read_block_length,
1294                                              s.block_length_index,
1295                                              &s.block_len_trees.slice()[tree_offset..],
1296                                              br,
1297                                              input);
1298    if !SafeReadBlockLengthFromIndex(s,
1299                                     br,
1300                                     &mut block_length_out, index_ret, input) {
1301      s.substate_read_block_length
1302          = BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
1303      bit_reader::BrotliBitReaderRestoreState(br, &memento);
1304      return false;
1305    }
1306    s.block_length[tree_type as usize] = block_length_out;
1307  }
1308  let ringbuffer : &mut [u32]= &mut s.block_type_rb[tree_type as usize * 2 ..];
1309  if (block_type == 1) {
1310    block_type = ringbuffer[1] + 1;
1311  } else if (block_type == 0) {
1312    block_type = ringbuffer[0];
1313  } else {
1314    block_type -= 2;
1315  }
1316  if (block_type >= max_block_type) {
1317    block_type -= max_block_type;
1318  }
1319  ringbuffer[0] = ringbuffer[1];
1320  ringbuffer[1] = block_type;
1321  return true;
1322
1323}
1324pub const FILE_BUFFER_SIZE : usize = 65536;
1325/* Decodes the block ty
1326pe and updates the state for literal context.
1327   Reads 3..54 bits. */
1328fn DecodeLiteralBlockSwitchInternal<
1329  AllocU8 : alloc::Allocator<u8>,
1330  AllocU32 : alloc::Allocator<u32>,
1331  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1332                                            mut s : &mut BrotliState<AllocU8,
1333                                                                     AllocU32,
1334                                                                     AllocHC>,
1335                                            input : &[u8]) -> bool {
1336
1337  let context_mode : u8;
1338  let context_offset : u32;
1339  if !DecodeBlockTypeAndLength(safe, &mut s.block_type_length_state, &mut s.br, 0, input) {
1340    return false;
1341  }
1342  context_offset = s.block_type_length_state.block_type_rb[1] << kLiteralContextBits;
1343  s.context_map_slice_index = context_offset as usize;
1344  s.literal_htree_index = s.context_map.slice()[s.context_map_slice_index];
1345  // s.literal_htree = s.literal_hgroup.htrees[s.literal_htree_index]; // redundant
1346  context_mode = s.context_modes.slice()[s.block_type_length_state.block_type_rb[1] as usize];
1347  s.context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode as usize] as usize ..];
1348  s.context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode as usize + 1] as usize..];
1349  return true;
1350}
1351/*
1352fn DecodeLiteralBlockSwitch<
1353  'a,
1354  AllocU8 : alloc::Allocator<u8>,
1355  AllocU32 : alloc::Allocator<u32>,
1356  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1357                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>) {
1358  DecodeLiteralBlockSwitchInternal(false, s);
1359}
1360
1361fn SafeDecodeLiteralBlockSwitch<
1362  'a,
1363  AllocU8 : alloc::Allocator<u8>,
1364  AllocU32 : alloc::Allocator<u32>,
1365  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1366                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>) -> bool {
1367  return DecodeLiteralBlockSwitchInternal(true, s);
1368}
1369*/
1370/* Block switch for insert/copy length.
1371   Reads 3..54 bits. */
1372fn DecodeCommandBlockSwitchInternal<
1373  'a,
1374  AllocU8 : alloc::Allocator<u8>,
1375  AllocU32 : alloc::Allocator<u32>,
1376  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1377                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> bool {
1378  if (!DecodeBlockTypeAndLength(safe, &mut s.block_type_length_state, &mut s.br, 1, input)) {
1379    return false;
1380  }
1381  s.htree_command_index = s.block_type_length_state.block_type_rb[3] as u16;
1382  return true;
1383}
1384
1385#[allow(dead_code)]
1386fn DecodeCommandBlockSwitch<
1387  'a,
1388  AllocU8 : alloc::Allocator<u8>,
1389  AllocU32 : alloc::Allocator<u32>,
1390  AllocHC : alloc::Allocator<HuffmanCode>> (mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) {
1391  DecodeCommandBlockSwitchInternal(false, s, input);
1392}
1393#[allow(dead_code)]
1394fn SafeDecodeCommandBlockSwitch<
1395  'a,
1396  AllocU8 : alloc::Allocator<u8>,
1397  AllocU32 : alloc::Allocator<u32>,
1398  AllocHC : alloc::Allocator<HuffmanCode>> (mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> bool {
1399  return DecodeCommandBlockSwitchInternal(true, s, input);
1400}
1401
1402/* Block switch for distance codes.
1403   Reads 3..54 bits. */
1404fn DecodeDistanceBlockSwitchInternal<
1405  'a,
1406  AllocU8 : alloc::Allocator<u8>,
1407  AllocU32 : alloc::Allocator<u32>,
1408  AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1409                                            mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> bool {
1410  if (!DecodeBlockTypeAndLength(safe, &mut s.block_type_length_state, &mut s.br, 2, input)) {
1411    return false;
1412  }
1413  s.dist_context_map_slice_index = (s.block_type_length_state.block_type_rb[5] << kDistanceContextBits) as usize;
1414  s.dist_htree_index = s.dist_context_map.slice()[s.dist_context_map_slice_index
1415                                                  + s.distance_context as usize];
1416  return true;
1417}
1418
1419#[allow(dead_code)]
1420fn DecodeDistanceBlockSwitch<
1421  'a,
1422  AllocU8 : alloc::Allocator<u8>,
1423  AllocU32 : alloc::Allocator<u32>,
1424  AllocHC : alloc::Allocator<HuffmanCode>> (mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) {
1425  DecodeDistanceBlockSwitchInternal(false, s, input);
1426}
1427
1428#[allow(dead_code)]
1429fn SafeDecodeDistanceBlockSwitch<
1430  'a,
1431  AllocU8 : alloc::Allocator<u8>,
1432  AllocU32 : alloc::Allocator<u32>,
1433  AllocHC : alloc::Allocator<HuffmanCode>> (mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> bool {
1434  return DecodeDistanceBlockSwitchInternal(true, s, input);
1435}
1436
1437fn WriteRingBuffer<'a, AllocU8 : alloc::Allocator<u8>,
1438                   AllocU32 : alloc::Allocator<u32>,
1439                   AllocHC : alloc::Allocator<HuffmanCode> >
1440   (available_out : &mut usize, mut output : &mut [u8], mut output_offset : &mut usize,
1441                   mut total_out : &mut usize, s : &mut BrotliState<AllocU8, AllocU32, AllocHC>) -> BrotliResult {
1442  let pos : usize;
1443  if s.pos > s.ringbuffer_size {
1444    pos = s.ringbuffer_size as usize;
1445  } else {
1446    pos = s.pos as usize;
1447  }
1448  let partial_pos_rb =
1449      (s.rb_roundtrips as usize * s.ringbuffer_size as usize) + pos as usize;
1450  let to_write = (partial_pos_rb - s.partial_pos_out) as usize;
1451  let mut num_written = *available_out as usize;
1452  if (num_written > to_write) {
1453    num_written = to_write;
1454  }
1455  if (s.meta_block_remaining_len < 0) {
1456    return BROTLI_FAILURE();
1457  }
1458  let start_index = (s.partial_pos_out & s.ringbuffer_mask as usize) as usize;
1459  let start = &s.ringbuffer.slice()[start_index .. start_index + num_written as usize];
1460  output[*output_offset .. *output_offset + num_written as usize].clone_from_slice(start);
1461  *output_offset += num_written;
1462  *available_out -= num_written;
1463  BROTLI_LOG_UINT!(to_write);
1464  BROTLI_LOG_UINT!(num_written);
1465  s.partial_pos_out += num_written as usize;
1466  *total_out = s.partial_pos_out;
1467  if (num_written < to_write) {
1468    return BrotliResult::NeedsMoreOutput;
1469  }
1470  return BrotliResult::ResultSuccess;
1471}
1472
1473fn CopyUncompressedBlockToOutput<'a, AllocU8 : alloc::Allocator<u8>,
1474                                                AllocU32 : alloc::Allocator<u32>,
1475                                                AllocHC : alloc::Allocator<HuffmanCode> >
1476   (mut available_out : &mut usize,
1477    mut output : &mut [u8],
1478    mut output_offset : &mut usize,
1479    mut total_out : &mut usize,
1480    mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1481    input : &[u8]) -> BrotliResult {
1482  /* State machine */
1483  loop {
1484    match s.substate_uncompressed {
1485      BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE => {
1486        let mut nbytes = bit_reader::BrotliGetRemainingBytes(&s.br) as i32;
1487        if (nbytes > s.meta_block_remaining_len) {
1488          nbytes = s.meta_block_remaining_len;
1489        }
1490        if (s.pos + nbytes > s.ringbuffer_size) {
1491          nbytes = s.ringbuffer_size - s.pos;
1492        }
1493        /* Copy remaining bytes from s.br.buf_ to ringbuffer. */
1494        bit_reader::BrotliCopyBytes(&mut s.ringbuffer.slice_mut()[s.pos as usize..],
1495                                    &mut s.br,
1496                                    nbytes as u32,
1497                                    input);
1498        s.pos += nbytes;
1499        s.meta_block_remaining_len -= nbytes;
1500        if (s.pos < s.ringbuffer_size) {
1501          if (s.meta_block_remaining_len == 0) {
1502            return BrotliResult::ResultSuccess;
1503          }
1504          return BrotliResult::NeedsMoreInput;
1505        }
1506        s.substate_uncompressed = BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_WRITE;
1507        /*s.partial_pos_rb += (size_t)s.ringbuffer_size;*/
1508        /* No break, continue to next state by going aroudn the loop */
1509      },
1510      BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_WRITE => {
1511        let result = WriteRingBuffer(
1512            &mut available_out, &mut output, &mut output_offset, &mut total_out, &mut s);
1513        match result {
1514          BrotliResult::ResultSuccess => {},
1515          _ => return result,
1516        }
1517        s.pos = 0;
1518        s.rb_roundtrips+=1;
1519        s.max_distance = s.max_backward_distance;
1520        s.substate_uncompressed = BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE;
1521      },
1522    }
1523  }
1524}
1525
1526fn BrotliAllocateRingBuffer<
1527    'a, AllocU8 : alloc::Allocator<u8>,
1528    AllocU32 : alloc::Allocator<u32>,
1529    AllocHC : alloc::Allocator<HuffmanCode> > (s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> bool {
1530  /* We need the slack region for the following reasons:
1531      - doing up to two 16-byte copies for fast backward copying
1532      - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */
1533  const kRingBufferWriteAheadSlack : i32 = 42;
1534  let mut is_last = s.is_last_metablock;
1535  s.ringbuffer_size = 1 << s.window_bits;
1536
1537  if (s.is_uncompressed != 0) {
1538    let next_block_header = bit_reader::BrotliPeekByte(&mut s.br,
1539        s.meta_block_remaining_len as u32,
1540        input);
1541    if (next_block_header != -1) { /* Peek succeeded */
1542      if ((next_block_header & 3) == 3) { /* ISLAST and ISEMPTY */
1543        is_last = 1;
1544      }
1545    }
1546  }
1547
1548  /* We need at least 2 bytes of ring buffer size to get the last two
1549     bytes for context from there */
1550  if (is_last != 0) {
1551    while (s.ringbuffer_size >= s.meta_block_remaining_len * 2
1552        && s.ringbuffer_size > 32) {
1553      s.ringbuffer_size >>= 1;
1554    }
1555  }
1556
1557  /* But make it fit the custom dictionary if there is one. */
1558  while (s.ringbuffer_size < s.custom_dict_size) {
1559    s.ringbuffer_size <<= 1;
1560  }
1561
1562  s.ringbuffer_mask = s.ringbuffer_size - 1;
1563  s.ringbuffer = s.alloc_u8.alloc_cell((s.ringbuffer_size as usize +
1564      kRingBufferWriteAheadSlack as usize + kBrotliMaxDictionaryWordLength as usize));
1565  if (s.ringbuffer.slice().len() == 0) {
1566    return false;
1567  }
1568  s.ringbuffer.slice_mut()[s.ringbuffer_size as usize - 1] = 0;
1569  s.ringbuffer.slice_mut()[s.ringbuffer_size as usize - 2] = 0;
1570  if (s.custom_dict.slice().len() > 0) {
1571    let offset = ((-s.custom_dict_size) & s.ringbuffer_mask) as usize;
1572    let cds = s.custom_dict_size as usize;
1573    s.ringbuffer.slice_mut()[offset .. offset + cds].clone_from_slice(&s.custom_dict.slice()[0..cds]);
1574  }
1575
1576  return true;
1577}
1578
1579/* Reads 1..256 2-bit context modes. */
1580pub fn ReadContextModes<'a, AllocU8 : alloc::Allocator<u8>,
1581           AllocU32 : alloc::Allocator<u32>,
1582           AllocHC : alloc::Allocator<HuffmanCode>> (
1583    s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1584    input : &[u8]) -> BrotliResult {
1585
1586  let mut i : i32 = s.loop_counter;
1587
1588  for context_mode_iter in s.context_modes.slice_mut()[i as usize ..
1589                                                       (s.block_type_length_state.num_block_types[0]
1590                                                        as usize)].iter_mut() {
1591    let mut bits : u32 = 0;
1592    if (!bit_reader::BrotliSafeReadBits(&mut s.br, 2, &mut bits, input)) {
1593      mark_unlikely();
1594      s.loop_counter = i;
1595      return BrotliResult::NeedsMoreInput;
1596    }
1597    *context_mode_iter = (bits << 1) as u8;
1598    BROTLI_LOG_UINT!(i);
1599    BROTLI_LOG_UINT!(*context_mode_iter);
1600    i+=1;
1601  }
1602  return BrotliResult::ResultSuccess;
1603}
1604
1605pub fn TakeDistanceFromRingBuffer<'a, AllocU8 : alloc::Allocator<u8>,
1606           AllocU32 : alloc::Allocator<u32>,
1607           AllocHC : alloc::Allocator<HuffmanCode>> (
1608    s : &mut BrotliState<AllocU8, AllocU32, AllocHC>) {
1609  if (s.distance_code == 0) {
1610    s.dist_rb_idx -= 1;
1611    s.distance_code = s.dist_rb[(s.dist_rb_idx & 3) as usize];
1612  } else {
1613    let distance_code = s.distance_code << 1;
1614    /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: */
1615    /* 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */
1616    const kDistanceShortCodeIndexOffset : u32= 0xaaafff1b;
1617    /* kDistanceShortCodeValueOffset has 2-bit values from LSB: */
1618    /*-0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */
1619    const kDistanceShortCodeValueOffset : u32 = 0xfa5fa500;
1620    let mut v = (s.dist_rb_idx as i32 +
1621        (kDistanceShortCodeIndexOffset as i32 >> distance_code as i32)) as i32 & 0x3;
1622    s.distance_code = s.dist_rb[v as usize];
1623    v = (kDistanceShortCodeValueOffset >> distance_code) as i32 & 0x3;
1624    if ((distance_code & 0x3) != 0) {
1625      s.distance_code += v;
1626    } else {
1627      s.distance_code -= v;
1628      if (s.distance_code <= 0) {
1629        /* A huge distance will cause a BROTLI_FAILURE() soon. */
1630        /* This is a little faster than failing here. */
1631        s.distance_code = 0x0fffffff;
1632      }
1633    }
1634  }
1635}
1636
1637pub fn SafeReadBits(br : &mut bit_reader::BrotliBitReader, n_bits : u32, val : &mut u32, input : &[u8]) -> bool {
1638  if (n_bits != 0) {
1639    return bit_reader::BrotliSafeReadBits(br, n_bits, val, input);
1640  } else {
1641    *val = 0;
1642    return true;
1643  }
1644}
1645
1646/* Precondition: s.distance_code < 0 */
1647pub fn ReadDistanceInternal<'a, AllocU8 : alloc::Allocator<u8>,
1648           AllocU32 : alloc::Allocator<u32>,
1649           AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1650    s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1651    input : &[u8],
1652    distance_hgroup : &[&[HuffmanCode]; 256]) -> bool {
1653  let mut distval : i32;
1654  let mut memento = bit_reader::BrotliBitReaderState::default();
1655  if (!safe) {
1656    s.distance_code
1657        = ReadSymbol(distance_hgroup[s.dist_htree_index as usize],
1658                     &mut s.br,
1659                     input) as i32;
1660  } else {
1661    let mut code : u32 = 0;
1662    memento = bit_reader::BrotliBitReaderSaveState(&s.br);
1663    if !SafeReadSymbol(distance_hgroup[s.dist_htree_index as usize], &mut s.br, &mut code, input) {
1664      return false;
1665    }
1666    s.distance_code = code as i32;
1667  }
1668  /* Convert the distance code to the actual distance by possibly */
1669  /* looking up past distances from the s.ringbuffer. */
1670  if ((s.distance_code as u64 & 0xfffffffffffffff0) == 0) {
1671    TakeDistanceFromRingBuffer(s);
1672    s.block_type_length_state.block_length[2] -= 1;
1673    return true;
1674  }
1675  distval = s.distance_code - s.num_direct_distance_codes as i32;
1676  if (distval >= 0) {
1677    let nbits : u32;
1678    let postfix : i32;
1679    let offset : i32;
1680    if (!safe && (s.distance_postfix_bits == 0)) {
1681      nbits = (distval as u32 >> 1) + 1;
1682      offset = ((2 + (distval & 1)) << nbits) - 4;
1683      s.distance_code = s.num_direct_distance_codes as i32 +
1684          offset + bit_reader::BrotliReadBits(&mut s.br, nbits, input) as i32;
1685    } else {
1686      /* This branch also works well when s.distance_postfix_bits == 0 */
1687      let mut bits : u32 = 0;
1688      postfix = distval & s.distance_postfix_mask;
1689      distval >>= s.distance_postfix_bits;
1690      nbits = (distval as u32 >> 1) + 1;
1691      if (safe) {
1692        if (!SafeReadBits(&mut s.br, nbits, &mut bits, input)) {
1693          s.distance_code = -1; /* Restore precondition. */
1694          bit_reader::BrotliBitReaderRestoreState(&mut s.br, &mut memento);
1695          return false;
1696        }
1697      } else {
1698        bits = bit_reader::BrotliReadBits(&mut s.br, nbits, input);
1699      }
1700      offset = ((2 + (distval & 1)) << nbits) - 4;
1701      s.distance_code = s.num_direct_distance_codes as i32 +
1702          ((offset + bits as i32) << s.distance_postfix_bits) + postfix;
1703    }
1704  }
1705  s.distance_code = s.distance_code - NUM_DISTANCE_SHORT_CODES as i32 + 1;
1706  s.block_type_length_state.block_length[2] -= 1;
1707  return true;
1708}
1709
1710
1711pub fn ReadCommandInternal<'a, AllocU8 : alloc::Allocator<u8>,
1712           AllocU32 : alloc::Allocator<u32>,
1713           AllocHC : alloc::Allocator<HuffmanCode>> (safe : bool,
1714    s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1715    insert_length : &mut i32,
1716    input : &[u8],
1717    insert_copy_hgroup : &[&[HuffmanCode]; 256]) -> bool {
1718  let mut cmd_code : u32 = 0;
1719  let mut insert_len_extra : u32 = 0;
1720  let mut copy_length : u32 = 0;
1721  let v : prefix::CmdLutElement;
1722  let mut memento = bit_reader::BrotliBitReaderState::default();
1723  if (!safe) {
1724    cmd_code = ReadSymbol(insert_copy_hgroup[s.htree_command_index as usize], &mut s.br, input);
1725  } else {
1726    memento = bit_reader::BrotliBitReaderSaveState(&s.br);
1727    if (!SafeReadSymbol(
1728         insert_copy_hgroup[s.htree_command_index as usize],
1729         &mut s.br, &mut cmd_code, input)) {
1730      return false;
1731    }
1732  }
1733  v = prefix::kCmdLut[cmd_code as usize];
1734  s.distance_code = v.distance_code as i32;
1735  s.distance_context = v.context as i32;
1736  s.dist_htree_index = s.dist_context_map.slice()[s.dist_context_map_slice_index
1737                                                  + s.distance_context as usize];
1738  *insert_length = v.insert_len_offset as i32;
1739  if (!safe) {
1740    if v.insert_len_extra_bits != 0 {
1741      mark_unlikely();
1742      insert_len_extra = bit_reader::BrotliReadBits(&mut s.br, v.insert_len_extra_bits as u32, input);
1743    }
1744    copy_length = bit_reader::BrotliReadBits(&mut s.br, v.copy_len_extra_bits as u32, input);
1745  } else {
1746    if (!SafeReadBits(&mut s.br, v.insert_len_extra_bits as u32, &mut insert_len_extra, input)) ||
1747       (!SafeReadBits(&mut s.br, v.copy_len_extra_bits as u32, &mut copy_length, input)) {
1748      bit_reader::BrotliBitReaderRestoreState(&mut s.br, &memento);
1749      return false;
1750    }
1751  }
1752  s.copy_length = copy_length as i32 + v.copy_len_offset as i32;
1753  s.block_type_length_state.block_length[1] -= 1;
1754  *insert_length += insert_len_extra as i32;
1755  return true;
1756}
1757
1758
1759fn WarmupBitReader(safe : bool, br : &mut bit_reader::BrotliBitReader, input : &[u8]) -> bool {
1760  if (safe) {
1761    return true;
1762  }
1763  return bit_reader::BrotliWarmupBitReader(br, input);
1764}
1765
1766fn CheckInputAmount(safe : bool,
1767    br : &bit_reader::BrotliBitReader, num : u32) -> bool {
1768  if (safe) {
1769    return true;
1770  }
1771  return bit_reader::BrotliCheckInputAmount(br, num);
1772}
1773
1774
1775fn memmove16(data : &mut [u8], u32off_dst : u32, u32off_src :u32) {
1776    let off_dst = u32off_dst as usize;
1777    let off_src = u32off_src as usize;
1778/*
1779    data[off_dst + 15] = data[off_src + 15];
1780    data[off_dst + 14] = data[off_src + 14];
1781    data[off_dst + 13] = data[off_src + 13];
1782    data[off_dst + 12] = data[off_src + 12];
1783
1784    data[off_dst + 11] = data[off_src + 11];
1785    data[off_dst + 10] = data[off_src + 10];
1786    data[off_dst + 9] = data[off_src + 9];
1787    data[off_dst + 8] = data[off_src + 8];
1788
1789    data[off_dst + 7] = data[off_src + 7];
1790    data[off_dst + 6] = data[off_src + 6];
1791    data[off_dst + 5] = data[off_src + 5];
1792    data[off_dst + 4] = data[off_src + 4];
1793
1794    data[off_dst + 3] = data[off_src + 3];
1795    data[off_dst + 2] = data[off_src + 2];
1796    data[off_dst + 1] = data[off_src + 1];
1797*/
1798    let mut local_array : [u8; 16] = [0;16];
1799    local_array.clone_from_slice(&mut data[off_src as usize .. off_src as usize + 16]);
1800    data[off_dst as usize .. off_dst as usize + 16].clone_from_slice(&mut local_array);
1801
1802
1803}
1804
1805fn memcpy_within_slice(data : &mut [u8],
1806                       off_dst : usize,
1807                       off_src : usize,
1808                       size : usize) {
1809  if off_dst > off_src {
1810     let (src, dst) = data.split_at_mut(off_dst);
1811     dst[..size].clone_from_slice(&src[off_src .. off_src + size]);
1812  } else {
1813     let (dst, src) = data.split_at_mut(off_src);
1814     dst[off_dst..off_dst + size].clone_from_slice(&src[..size]);
1815  }
1816}
1817
1818fn ProcessCommandsInternal<
1819    AllocU8 : alloc::Allocator<u8>,
1820    AllocU32 : alloc::Allocator<u32>,
1821    AllocHC : alloc::Allocator<HuffmanCode> > (safe : bool,
1822        s : &mut BrotliState<AllocU8, AllocU32, AllocHC>,
1823        input : &[u8]) -> BrotliResult {
1824  if (!CheckInputAmount(safe, &s.br, 28)) || (!WarmupBitReader(safe, &mut s.br, input)) {
1825    mark_unlikely();
1826    return BrotliResult::NeedsMoreInput;
1827  }
1828  let mut pos = s.pos;
1829  let mut i : i32 = s.loop_counter; // important that this is signed
1830  let mut result : BrotliResult = BrotliResult::ResultSuccess;
1831  let mut saved_literal_hgroup = core::mem::replace(&mut s.literal_hgroup,
1832                HuffmanTreeGroup::<AllocU32, AllocHC>::default());
1833  let mut saved_distance_hgroup = core::mem::replace(&mut s.distance_hgroup,
1834                HuffmanTreeGroup::<AllocU32, AllocHC>::default());
1835  let mut saved_insert_copy_hgroup = core::mem::replace(&mut s.insert_copy_hgroup,
1836                HuffmanTreeGroup::<AllocU32, AllocHC>::default());
1837  {
1838
1839    let literal_hgroup = saved_literal_hgroup.build_hgroup_cache();
1840    let distance_hgroup = saved_distance_hgroup.build_hgroup_cache();
1841    let insert_copy_hgroup = saved_insert_copy_hgroup.build_hgroup_cache();
1842
1843    loop {
1844      match s.state {
1845        BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN => {
1846          if (!CheckInputAmount(safe, &s.br, 28)) { /* 156 bits + 7 bytes */
1847            mark_unlikely();
1848            result = BrotliResult::NeedsMoreInput;
1849            break; // return
1850          }
1851          if (s.block_type_length_state.block_length[1] == 0) {
1852            mark_unlikely();
1853            if !DecodeCommandBlockSwitchInternal(safe, s, input) {
1854              result = BrotliResult::NeedsMoreInput;
1855              break; // return
1856            }
1857            s.state = BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN;
1858            continue; // goto CommandBegin;
1859          }
1860          /* Read the insert/copy length in the command */
1861          if (!ReadCommandInternal(safe, s, &mut i, input, &insert_copy_hgroup)) && safe {
1862            result = BrotliResult::NeedsMoreInput;
1863            break; // return
1864          }
1865          BROTLI_LOG!("[ProcessCommandsInternal] pos = %d insert = %d copy = %d distance_code = %d\n",
1866              pos, i, s.copy_length, s.distance_code);
1867          if (i == 0) {
1868            s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
1869            continue; // goto CommandPostDecodeLiterals;
1870          }
1871          s.meta_block_remaining_len -= i;
1872          s.state = BrotliRunningState::BROTLI_STATE_COMMAND_INNER;
1873        },
1874        BrotliRunningState::BROTLI_STATE_COMMAND_INNER => {
1875          /* Read the literals in the command */
1876          if (s.trivial_literal_context != 0) {
1877            let mut bits : u32 = 0;
1878            let mut value : u32 = 0;
1879            let mut literal_htree = &literal_hgroup[s.literal_htree_index as usize];
1880            PreloadSymbol(safe, literal_htree, &mut s.br, &mut bits, &mut value, input);
1881            let mut inner_return : bool = false;
1882            loop {
1883              if (!CheckInputAmount(safe, &s.br, 28)) { /* 162 bits + 7 bytes */
1884                result = BrotliResult::NeedsMoreInput;
1885                inner_return = true;
1886                break;
1887              }
1888              if (s.block_type_length_state.block_length[0] == 0) {
1889                mark_unlikely();
1890                if (!DecodeLiteralBlockSwitchInternal(safe,
1891                                                      s,
1892                                                      input)) && safe { // <-- FIXME PERF if we could make this a macro, we could avoid re-lookuping the literal_hgroup each loop iteration and just keep it borrowed read only up front
1893                  result = BrotliResult::NeedsMoreInput;
1894                  inner_return = true;
1895                  break;
1896                }
1897                literal_htree = &literal_hgroup[s.literal_htree_index as usize];
1898                PreloadSymbol(safe, literal_htree, &mut s.br, &mut bits, &mut value, input);
1899              }
1900              if (!safe) {
1901                s.ringbuffer.slice_mut()[pos as usize] = ReadPreloadedSymbol(
1902                    literal_htree, &mut s.br, &mut bits, &mut value, input) as u8;
1903              } else {
1904                let mut literal : u32 = 0;
1905                if (!SafeReadSymbol(literal_htree, &mut s.br, &mut literal, input)) {
1906                  result = BrotliResult::NeedsMoreInput;
1907                  inner_return = true;
1908                  break;
1909                }
1910                s.ringbuffer.slice_mut()[pos as usize] = literal as u8;
1911              }
1912              s.block_type_length_state.block_length[0] -= 1;
1913              BROTLI_LOG_UINT!(s.literal_htree_index);
1914              BROTLI_LOG_ARRAY_INDEX!(s.ringbuffer.slice(), pos);
1915              pos += 1;
1916              if (pos == s.ringbuffer_size) {
1917                mark_unlikely();
1918                s.state = BrotliRunningState::BROTLI_STATE_COMMAND_INNER_WRITE;
1919                i -= 1;
1920                inner_return = true;
1921                break;
1922              }
1923              i -= 1;
1924              if i == 0 {
1925                break;
1926              }
1927            }
1928            if inner_return {
1929               break; // return
1930            }
1931          } else {
1932            let mut p1 = s.ringbuffer.slice()[((pos - 1) & s.ringbuffer_mask) as usize];
1933            let mut p2 = s.ringbuffer.slice()[((pos - 2) & s.ringbuffer_mask) as usize];
1934            let mut inner_return : bool = false;
1935            loop {
1936              if (!CheckInputAmount(safe, &s.br, 28)) { /* 162 bits + 7 bytes */
1937                s.state = BrotliRunningState::BROTLI_STATE_COMMAND_INNER;
1938                result = BrotliResult::NeedsMoreInput;
1939                inner_return = true;
1940                break;
1941              }
1942              if (s.block_type_length_state.block_length[0] == 0) {
1943                mark_unlikely();
1944                if (!DecodeLiteralBlockSwitchInternal(safe,
1945                                                      s,
1946                                                      input)) && safe {
1947                  result = BrotliResult::NeedsMoreInput;
1948                  inner_return = true;
1949                  break;
1950                }
1951              }
1952              let context = s.context_lookup1[p1 as usize] | s.context_lookup2[p2 as usize];
1953              BROTLI_LOG_UINT!(context);
1954              let hc = &literal_hgroup[s.context_map.slice()[s.context_map_slice_index + context as usize]as usize];
1955              p2 = p1;
1956              if (!safe) {
1957                p1 = ReadSymbol(hc, &mut s.br, input) as u8;
1958              } else {
1959                let mut literal : u32 = 0;
1960                if (!SafeReadSymbol(hc, &mut s.br, &mut literal, input)) {
1961                  result = BrotliResult::NeedsMoreInput;
1962                  inner_return = true;
1963                  break;
1964                }
1965                p1 = literal as u8;
1966              }
1967              s.ringbuffer.slice_mut()[pos as usize] = p1;
1968              s.block_type_length_state.block_length[0] -= 1;
1969              BROTLI_LOG_UINT!(s.context_map.slice()[s.context_map_slice_index as usize + context as usize]);
1970              BROTLI_LOG_ARRAY_INDEX!(s.ringbuffer.slice(), pos & s.ringbuffer_mask);
1971              pos += 1;
1972              if (pos == s.ringbuffer_size) {
1973                mark_unlikely();
1974                s.state = BrotliRunningState::BROTLI_STATE_COMMAND_INNER_WRITE;
1975                i -= 1;
1976                inner_return = true;
1977                break;
1978              }
1979              i -= 1;
1980              if i == 0 {
1981                break;
1982              }
1983            }
1984            if inner_return {
1985              break; // return
1986            }
1987          }
1988          if (s.meta_block_remaining_len <= 0) {
1989            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
1990            break; // return
1991          }
1992          s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
1993        },
1994        BrotliRunningState::BROTLI_STATE_COMMAND_POST_DECODE_LITERALS => {
1995          if s.distance_code >= 0 {
1996             s.dist_rb_idx -= 1;
1997             s.distance_code = s.dist_rb[(s.dist_rb_idx & 3) as usize]
1998             // goto postReadDistance
1999          } else {
2000            if s.block_type_length_state.block_length[2] == 0 {
2001              mark_unlikely();
2002              if (!DecodeDistanceBlockSwitchInternal(safe, s, input)) && safe {
2003                result = BrotliResult::NeedsMoreInput;
2004                break; // return
2005              }
2006            }
2007            if (!ReadDistanceInternal(safe, s, input, &distance_hgroup)) && safe {
2008              result = BrotliResult::NeedsMoreInput;
2009              break; // return
2010            }
2011          }
2012          //postReadDistance:
2013          BROTLI_LOG!("[ProcessCommandsInternal] pos = %d distance = %d\n",
2014                      pos, s.distance_code);
2015
2016          if (s.max_distance != s.max_backward_distance) {
2017            if (pos < s.max_backward_distance_minus_custom_dict_size) {
2018              s.max_distance = pos + s.custom_dict_size;
2019            } else {
2020              s.max_distance = s.max_backward_distance;
2021            }
2022          }
2023          i = s.copy_length;
2024          /* Apply copy of LZ77 back-reference, or static dictionary reference if
2025          the distance is larger than the max LZ77 distance */
2026          if (s.distance_code > s.max_distance) {
2027            if (i >= kBrotliMinDictionaryWordLength as i32 &&
2028                i <= kBrotliMaxDictionaryWordLength as i32) {
2029              let mut offset = kBrotliDictionaryOffsetsByLength[i as usize] as i32;
2030              let word_id = s.distance_code - s.max_distance - 1;
2031              let shift = kBrotliDictionarySizeBitsByLength[i as usize];
2032              let mask = bit_reader::BitMask(shift as u32) as i32;
2033              let word_idx = word_id & mask;
2034              let transform_idx = word_id >> shift;
2035              offset += word_idx * i;
2036              if (transform_idx < kNumTransforms) {
2037                let mut len = i;
2038                let word = &kBrotliDictionary[offset as usize .. (offset + len) as usize];
2039                if (transform_idx == 0) {
2040                  s.ringbuffer.slice_mut()[pos as usize .. ((pos + len) as usize)].clone_from_slice(
2041                      word);
2042                } else {
2043                  len = TransformDictionaryWord(
2044                      &mut s.ringbuffer.slice_mut()[pos as usize..], word, len, transform_idx);
2045                }
2046                pos += len;
2047                s.meta_block_remaining_len -= len;
2048                if (pos >= s.ringbuffer_size) {
2049                  /*s.partial_pos_rb += (size_t)s.ringbuffer_size;*/
2050                  s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_1;
2051                  break; // return return
2052                }
2053              } else {
2054                BROTLI_LOG!("Invalid backward reference. pos: %d distance: %d len: %d bytes left: %d\n",
2055                  pos, s.distance_code, i,
2056                  s.meta_block_remaining_len);
2057                result = BROTLI_FAILURE();
2058                break; // return
2059              }
2060            } else {
2061              BROTLI_LOG!("Invalid backward reference. pos: %d distance: %d len: %d bytes left: %d\n", pos, s.distance_code, i,
2062                     s.meta_block_remaining_len);
2063              result = BROTLI_FAILURE();
2064              break; // return
2065            }
2066          } else {
2067            /* update the recent distances cache */
2068            s.dist_rb[(s.dist_rb_idx & 3) as usize] = s.distance_code;
2069            s.dist_rb_idx += 1;
2070            s.meta_block_remaining_len -= i;
2071            if (s.meta_block_remaining_len < 0) {
2072              mark_unlikely();
2073              BROTLI_LOG!("Invalid backward reference. pos: %d distance: %d len: %d bytes left: %d\n", pos, s.distance_code, i,
2074                     s.meta_block_remaining_len);
2075              result = BROTLI_FAILURE();
2076              break; // return
2077            }
2078            /* There is 128+ bytes of slack in the ringbuffer allocation.
2079               Also, we have 16 short codes, that make these 16 bytes irrelevant
2080               in the ringbuffer. Let's copy over them as a first guess.
2081             */
2082            let src_start = ((pos - s.distance_code) & s.ringbuffer_mask) as u32;
2083            let dst_start = pos as u32;
2084            let dst_end = pos as u32 + i as u32;
2085            let src_end = src_start + i as u32;
2086            memmove16(&mut s.ringbuffer.slice_mut(), dst_start, src_start);
2087            /* Now check if the copy extends over the ringbuffer end,
2088               or if the copy overlaps with itself, if yes, do wrap-copy. */
2089            if (src_end > pos as u32 && dst_end > src_start) {
2090              s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRAP_COPY;
2091              continue; //goto CommandPostWrapCopy;
2092            }
2093            if (dst_end >= s.ringbuffer_size as u32 || src_end >= s.ringbuffer_size as u32) {
2094              s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRAP_COPY;
2095              continue; //goto CommandPostWrapCopy;
2096            }
2097            pos += i;
2098            if (i > 16) {
2099              if (i > 32) {
2100                memcpy_within_slice(s.ringbuffer.slice_mut(),
2101                                    dst_start as usize + 16,
2102                                    src_start as usize + 16,
2103                                    (i - 16) as usize);
2104              } else {
2105                /* This branch covers about 45% cases.
2106                   Fixed size short copy allows more compiler optimizations. */
2107                memmove16(&mut s.ringbuffer.slice_mut(), dst_start + 16, src_start + 16);
2108              }
2109            }
2110          }
2111          if (s.meta_block_remaining_len <= 0) {
2112            /* Next metablock, if any */
2113            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2114            break; // return
2115          } else {
2116            s.state = BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN;
2117            continue; // goto CommandBegin
2118          }
2119        },
2120        BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRAP_COPY => {
2121          let mut wrap_guard = s.ringbuffer_size - pos;
2122          let mut inner_return : bool = false;
2123          while i > 0 {
2124            i -= 1;
2125            s.ringbuffer.slice_mut()[pos as usize] =
2126                s.ringbuffer.slice()[((pos - s.distance_code) & s.ringbuffer_mask) as usize];
2127            pos += 1;
2128            wrap_guard -= 1;
2129            if (wrap_guard == 0) {
2130              mark_unlikely();
2131              /*s.partial_pos_rb += (size_t)s.ringbuffer_size;*/
2132              s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_2;
2133              inner_return = true;
2134              break; //return
2135            }
2136          }
2137          if inner_return {
2138            mark_unlikely();
2139            break;
2140          }
2141          i -= 1;
2142          if (s.meta_block_remaining_len <= 0) {
2143            /* Next metablock, if any */
2144            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2145            break; // return
2146          } else {
2147            s.state = BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN;
2148            continue;
2149          }
2150        },
2151        _ => {
2152          result = BROTLI_FAILURE();
2153          break; // return
2154        },
2155      }
2156    }
2157  }
2158  s.pos = pos;
2159  s.loop_counter = i;
2160
2161  core::mem::replace(&mut s.literal_hgroup,
2162                core::mem::replace(&mut saved_literal_hgroup,
2163                  HuffmanTreeGroup::<AllocU32, AllocHC>::default()));
2164
2165  core::mem::replace(&mut s.distance_hgroup,
2166                core::mem::replace(&mut saved_distance_hgroup,
2167                  HuffmanTreeGroup::<AllocU32, AllocHC>::default()));
2168
2169  core::mem::replace(&mut s.insert_copy_hgroup,
2170                core::mem::replace(&mut saved_insert_copy_hgroup,
2171                  HuffmanTreeGroup::<AllocU32, AllocHC>::default()));
2172
2173  return result;
2174}
2175
2176fn ProcessCommands<
2177    'a, AllocU8 : alloc::Allocator<u8>,
2178    AllocU32 : alloc::Allocator<u32>,
2179    AllocHC : alloc::Allocator<HuffmanCode> > (
2180        s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> BrotliResult {
2181    return ProcessCommandsInternal(false, s, input);
2182}
2183
2184fn SafeProcessCommands<
2185    'a, AllocU8 : alloc::Allocator<u8>,
2186    AllocU32 : alloc::Allocator<u32>,
2187    AllocHC : alloc::Allocator<HuffmanCode> > (
2188        s : &mut BrotliState<AllocU8, AllocU32, AllocHC>, input : &[u8]) -> BrotliResult {
2189    return ProcessCommandsInternal(true, s, input);
2190}
2191
2192
2193
2194
2195pub fn BrotliDecompressStream<'a, AllocU8 : alloc::Allocator<u8>,
2196           AllocU32 : alloc::Allocator<u32>,
2197           AllocHC : alloc::Allocator<HuffmanCode>> (
2198  mut available_in : &mut usize, input_offset : &mut usize, xinput : &[u8], // ugly that we are mutable
2199  mut available_out : &mut usize, mut output_offset : &mut usize, mut output : &mut [u8],
2200  mut total_out : &mut usize, mut s : &mut BrotliState<AllocU8, AllocU32, AllocHC>)
2201  -> BrotliResult {
2202
2203  let mut result : BrotliResult = BrotliResult::ResultSuccess;
2204
2205  let mut saved_buffer : [u8; 8] = s.buffer.clone();
2206  let mut local_input : &[u8];
2207  if *available_in as u64 >= (1u64 << 32) {
2208      return BrotliResult::ResultFailure;
2209  }
2210  if *input_offset as u64 >= (1u64 << 32) {
2211      return BrotliResult::ResultFailure;
2212  }
2213  if s.buffer_length == 0 {
2214    local_input = xinput;
2215    s.br.avail_in = *available_in as u32;
2216    s.br.next_in = *input_offset as u32;
2217  } else {
2218    result = BrotliResult::NeedsMoreInput;
2219    let copy_len = core::cmp::min(saved_buffer.len() - s.buffer_length as usize, *available_in);
2220    if copy_len > 0 {
2221        saved_buffer[s.buffer_length as usize .. (s.buffer_length as usize + copy_len)].
2222            clone_from_slice(&xinput[*input_offset .. copy_len + *input_offset]);
2223        s.buffer[s.buffer_length as usize .. (s.buffer_length as usize + copy_len)].
2224            clone_from_slice(&xinput[*input_offset .. copy_len + *input_offset]);
2225    }
2226    local_input = &saved_buffer[..];
2227    s.br.next_in = 0;
2228    s.br.avail_in = s.buffer_length;
2229  }
2230  loop {
2231    match result {
2232      BrotliResult::ResultSuccess => {},
2233      _ => {
2234        match result {
2235          BrotliResult::NeedsMoreInput => {
2236            if s.ringbuffer.slice().len() != 0 {
2237              let _result = WriteRingBuffer(available_out, &mut output, &mut output_offset,
2238                      &mut total_out, &mut s);
2239            }
2240            if s.buffer_length != 0 { /* Used with internal buffer. */
2241              if s.br.avail_in == 0 { /* Successfully finished read transaction. */
2242              /* Accamulator contains less than 8 bits, because internal buffer
2243                 is expanded byte-by-byte until it is enough to complete read. */
2244                s.buffer_length = 0;
2245                /* Switch to input stream and restart. */
2246                result = BrotliResult::ResultSuccess;
2247                local_input = xinput;
2248                s.br.avail_in = *available_in as u32;
2249                s.br.next_in = *input_offset as u32;
2250                continue;
2251              } else if *available_in != 0 {
2252                 /* Not enough data in buffer, but can take one more byte from
2253                  input stream. */
2254                result = BrotliResult::ResultSuccess;
2255                let new_byte = xinput[*input_offset];
2256                s.buffer[s.buffer_length as usize] = new_byte;
2257                // we did the following copy upfront, so we wouldn't have to do it here
2258                // since saved_buffer[s.buffer_length as usize] = new_byte violates borrow rules
2259                assert_eq!(saved_buffer[s.buffer_length as usize], new_byte);
2260                s.buffer_length += 1;
2261                s.br.avail_in = s.buffer_length;
2262                (*input_offset) += 1;
2263                (*available_in) -= 1;
2264                /* Retry with more data in buffer. */
2265                // we can't re-borrow the saved buffer...so we have to do this recursively
2266                continue;
2267              }
2268              /* Can't finish reading and no more input.*/  
2269              //FIXME :: NOT SURE WHAT THIS MEANT
2270              //saved_buffer = core::mem::replace(
2271              //  &mut s.br.input_,
2272              //  &mut[]); // clear input
2273              break;
2274            } else { /* Input stream doesn't contain enough input. */
2275               /* Copy tail to internal buffer and return. */
2276               *input_offset = s.br.next_in as usize;
2277               *available_in = s.br.avail_in as usize;
2278               while *available_in != 0 {
2279                 s.buffer[s.buffer_length as usize] = xinput[*input_offset];
2280                 s.buffer_length += 1;
2281                 (*input_offset)+=1;
2282                 (*available_in)-=1;
2283               }
2284               break;
2285            }
2286            // unreachable!(); <-- dead code
2287          },
2288          _ => {
2289            /* Fail or needs more output. */
2290            if s.buffer_length != 0 {
2291              /* Just consumed the buffered input and produced some output. Otherwise
2292                it would result in "needs more input". Reset internal buffer.*/
2293              s.buffer_length = 0;
2294            } else {
2295               /* Using input stream in last iteration. When decoder switches to input
2296                stream it has less than 8 bits in accamulator, so it is safe to
2297                return unused accamulator bits there. */
2298               bit_reader::BrotliBitReaderUnload(&mut s.br);
2299               *available_in = s.br.avail_in as usize;
2300               *input_offset = s.br.next_in as usize;
2301            }
2302          },
2303        }
2304        break;
2305      },
2306    }
2307    loop { // this emulates fallthrough behavior
2308      match s.state {
2309        BrotliRunningState::BROTLI_STATE_UNINITED => {
2310          /* Prepare to the first read. */
2311          if (!bit_reader::BrotliWarmupBitReader(&mut s.br, local_input)) {
2312            result = BrotliResult::NeedsMoreInput;
2313            break;
2314          }
2315          /* Decode window size. */
2316          s.window_bits = DecodeWindowBits(&mut s.br); /* Reads 1..7 bits. */
2317          BROTLI_LOG_UINT!(s.window_bits);
2318          if (s.window_bits == 9) {
2319            /* Value 9 is reserved for future use. */
2320            result = BROTLI_FAILURE();
2321            break;
2322          }
2323          s.max_backward_distance = (1 << s.window_bits) - 16;
2324          s.max_backward_distance_minus_custom_dict_size =
2325              s.max_backward_distance - s.custom_dict_size;
2326  
2327          /* (formerly) Allocate memory for both block_type_trees and block_len_trees. */
2328          s.block_type_length_state.block_type_trees
2329            = s.alloc_hc.alloc_cell(3 * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
2330          if (s.block_type_length_state.block_type_trees.slice().len() == 0) {
2331            result = BROTLI_FAILURE();
2332            break;
2333          }
2334          s.block_type_length_state.block_len_trees
2335            = s.alloc_hc.alloc_cell(3 * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
2336  
2337          s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_BEGIN;
2338          /* No break, continue to next state */
2339        },
2340        BrotliRunningState::BROTLI_STATE_METABLOCK_BEGIN => {
2341          s.BrotliStateMetablockBegin();
2342          BROTLI_LOG_UINT!(s.pos);
2343          s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_HEADER;
2344          // No break, continue to next state 
2345        },
2346        BrotliRunningState::BROTLI_STATE_METABLOCK_HEADER => {
2347          result = DecodeMetaBlockLength(&mut s, local_input); // Reads 2 - 31 bits. 
2348          match result {
2349            BrotliResult::ResultSuccess => {},
2350            _ => break,
2351          }
2352          BROTLI_LOG_UINT!(s.is_last_metablock);
2353          BROTLI_LOG_UINT!(s.meta_block_remaining_len);
2354          BROTLI_LOG_UINT!(s.is_metadata);
2355          BROTLI_LOG_UINT!(s.is_uncompressed);
2356          if (s.is_metadata != 0 || s.is_uncompressed != 0) {
2357            if (!bit_reader::BrotliJumpToByteBoundary(&mut s.br)) {
2358              result = BROTLI_FAILURE();
2359              break;
2360            }
2361          }
2362          if (s.is_metadata != 0) {
2363            s.state = BrotliRunningState::BROTLI_STATE_METADATA;
2364            break;
2365          }
2366          if (s.meta_block_remaining_len == 0) {
2367            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2368            break;
2369          }
2370          if (s.ringbuffer.slice().len() == 0) {
2371            if (!BrotliAllocateRingBuffer(&mut s, local_input)) {
2372              result = BROTLI_FAILURE();
2373              break;
2374            }
2375          }
2376          if (s.is_uncompressed != 0) {
2377            s.state = BrotliRunningState::BROTLI_STATE_UNCOMPRESSED;
2378            break;
2379          }
2380          s.loop_counter = 0;
2381          s.state = BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_0;
2382          break;
2383        },
2384        BrotliRunningState::BROTLI_STATE_UNCOMPRESSED => {
2385          let mut _bytes_copied = s.meta_block_remaining_len;
2386          result = CopyUncompressedBlockToOutput(
2387              &mut available_out, &mut output, &mut output_offset, &mut total_out, &mut s, local_input);
2388          _bytes_copied -= s.meta_block_remaining_len;
2389          match result {
2390              BrotliResult::ResultSuccess => {},
2391              _ => break,
2392          }
2393          s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2394          break;
2395        },
2396        BrotliRunningState::BROTLI_STATE_METADATA => {
2397          while s.meta_block_remaining_len > 0 {
2398            let mut bits = 0u32;
2399            // Read one byte and ignore it.
2400            if (!bit_reader::BrotliSafeReadBits(&mut s.br, 8, &mut bits, local_input)) {
2401              result = BrotliResult::NeedsMoreInput;
2402              break;
2403            }
2404            s.meta_block_remaining_len -= 1;
2405          }
2406          match result {
2407            BrotliResult::ResultSuccess => s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE,
2408            _ => {},
2409          }
2410          break;
2411        },
2412        BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_0 => {
2413          if (s.loop_counter >= 3) {
2414            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_HEADER_2;
2415            break;
2416          }
2417          // Reads 1..11 bits. 
2418          result = DecodeVarLenUint8(&mut s.substate_decode_uint8, &mut s.br, &mut s.block_type_length_state.num_block_types[s.loop_counter as usize], local_input);
2419          match result {
2420            BrotliResult::ResultSuccess => {},
2421            _ => break,
2422          }
2423          s.block_type_length_state.num_block_types[s.loop_counter as usize] += 1;
2424          BROTLI_LOG_UINT!(s.block_type_length_state.num_block_types[s.loop_counter as usize]);
2425          if (s.block_type_length_state.num_block_types[s.loop_counter as usize] < 2) {
2426            s.loop_counter+=1;
2427            break;
2428          }
2429          s.state = BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_1;
2430          // No break, continue to next state 
2431        },
2432        BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_1 => {
2433          let tree_offset = s.loop_counter * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as i32;
2434          let mut new_huffman_table = mem::replace(&mut s.block_type_length_state.block_type_trees,
2435                                                   AllocHC::AllocatedMemory::default());
2436          result
2437            = ReadHuffmanCode(s.block_type_length_state.num_block_types[s.loop_counter as usize] +2,
2438                              new_huffman_table.slice_mut(), tree_offset as usize, None, &mut s, local_input);
2439          mem::replace(&mut s.block_type_length_state.block_type_trees,
2440                       new_huffman_table);
2441          match result {
2442            BrotliResult::ResultSuccess => {},
2443            _ => break,
2444          }
2445          s.state = BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_2;
2446          // No break, continue to next state 
2447        },
2448        BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_2 => {
2449          let tree_offset = s.loop_counter * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as i32;
2450          let mut new_huffman_table = mem::replace(&mut s.block_type_length_state.block_len_trees,
2451                                                   AllocHC::AllocatedMemory::default());
2452          result = ReadHuffmanCode(kNumBlockLengthCodes,
2453              new_huffman_table.slice_mut(), tree_offset as usize, None, &mut s, local_input);
2454          mem::replace(&mut s.block_type_length_state.block_len_trees,
2455                       new_huffman_table);
2456          match result {
2457            BrotliResult::ResultSuccess => {},
2458            _ => break,
2459          }
2460          s.state = BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_3;
2461          // No break, continue to next state 
2462        },
2463        BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_3 => {
2464          let tree_offset = s.loop_counter * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as i32;
2465          let mut block_length_out : u32 = 0;
2466          let index_ret = SafeReadBlockLengthIndex(&s.block_type_length_state.substate_read_block_length,
2467                                                   s.block_type_length_state.block_length_index,
2468                                                   &s.block_type_length_state.block_len_trees.slice()[tree_offset as usize ..],
2469                                                   &mut s.br, local_input);
2470
2471          if !SafeReadBlockLengthFromIndex(&mut s.block_type_length_state,
2472                                           &mut s.br, &mut block_length_out, index_ret, local_input) {
2473            result = BrotliResult::NeedsMoreInput;
2474            break;
2475          }
2476          s.block_type_length_state.block_length[s.loop_counter as usize] = block_length_out;
2477          BROTLI_LOG_UINT!(s.block_type_length_state.block_length[s.loop_counter as usize]);
2478          s.loop_counter += 1;
2479          s.state = BrotliRunningState::BROTLI_STATE_HUFFMAN_CODE_0;
2480          break;
2481        }
2482        BrotliRunningState::BROTLI_STATE_METABLOCK_HEADER_2 => {
2483          let mut bits : u32 = 0;
2484          if (!bit_reader::BrotliSafeReadBits(&mut s.br, 6, &mut bits, local_input)) {
2485            result = BrotliResult::NeedsMoreInput;
2486            break;
2487          }
2488          s.distance_postfix_bits = bits & bit_reader::BitMask(2);
2489          bits >>= 2;
2490          s.num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES +
2491              (bits << s.distance_postfix_bits);
2492          BROTLI_LOG_UINT!(s.num_direct_distance_codes);
2493          BROTLI_LOG_UINT!(s.distance_postfix_bits);
2494          s.distance_postfix_mask = bit_reader::BitMask(s.distance_postfix_bits) as i32;
2495          s.context_modes = s.alloc_u8.alloc_cell(s.block_type_length_state.num_block_types[0] as usize);
2496          if (s.context_modes.slice().len() == 0) {
2497            result = BROTLI_FAILURE();
2498            break;
2499          }
2500          s.loop_counter = 0;
2501          s.state = BrotliRunningState::BROTLI_STATE_CONTEXT_MODES;
2502          // No break, continue to next state 
2503        },
2504        BrotliRunningState::BROTLI_STATE_CONTEXT_MODES => {
2505          result = ReadContextModes(&mut s, local_input);
2506          match result {
2507              BrotliResult::ResultSuccess => {},
2508              _ => break,
2509          }
2510          s.state = BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_1;
2511          // No break, continue to next state
2512        },
2513        BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_1 => {
2514          result = DecodeContextMap((s.block_type_length_state.num_block_types[0] as usize) << kLiteralContextBits as usize,
2515                                    false, &mut s, local_input);
2516          match result {
2517              BrotliResult::ResultSuccess => {},
2518              _ => break,
2519          }
2520          let mut is_trivial_context = 1;
2521          let mut j : usize = 0;
2522          for context_map_item in s.context_map.slice()[0 .. (s.block_type_length_state.num_block_types[0] as usize) << (kLiteralContextBits as usize)].iter() {
2523            if (*context_map_item != (j >> kLiteralContextBits) as u8) {
2524              is_trivial_context = 0;
2525              break;
2526            }
2527            j += 1;
2528          }
2529          s.trivial_literal_context = is_trivial_context;
2530          s.state = BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_2;
2531          // No break, continue to next state
2532        },
2533        BrotliRunningState::BROTLI_STATE_CONTEXT_MAP_2 => {
2534          {
2535            let num_distance_codes : u32 =
2536                s.num_direct_distance_codes + (48u32 << s.distance_postfix_bits);
2537            result = DecodeContextMap(
2538                (s.block_type_length_state.num_block_types[2] as usize) << kDistanceContextBits as usize,
2539                true, s, local_input);
2540            match result {
2541              BrotliResult::ResultSuccess => {},
2542              _ => break,
2543            }
2544            s.literal_hgroup.init(&mut s.alloc_u32,
2545                                  &mut s.alloc_hc,
2546                                  kNumLiteralCodes, s.num_literal_htrees as u16);
2547            s.insert_copy_hgroup.init(&mut s.alloc_u32,
2548                                      &mut s.alloc_hc,
2549                                      kNumInsertAndCopyCodes, s.block_type_length_state.num_block_types[1] as u16);
2550            s.distance_hgroup.init(&mut s.alloc_u32,
2551                                   &mut s.alloc_hc,
2552                                   num_distance_codes as u16, s.num_dist_htrees as u16);
2553            if (s.literal_hgroup.codes.slice().len() == 0 ||
2554                s.insert_copy_hgroup.codes.slice().len() == 0 ||
2555                s.distance_hgroup.codes.slice().len() == 0) {
2556              return BROTLI_FAILURE();
2557            }
2558          }
2559          s.loop_counter = 0;
2560          s.state = BrotliRunningState::BROTLI_STATE_TREE_GROUP;
2561          // No break, continue to next state 
2562        },
2563        BrotliRunningState::BROTLI_STATE_TREE_GROUP => {
2564          result = HuffmanTreeGroupDecode(s.loop_counter, &mut s, local_input);
2565          match result {
2566             BrotliResult::ResultSuccess => {},
2567             _ => break,
2568          }
2569          s.loop_counter += 1;
2570          if (s.loop_counter >= 3) {
2571            let context_mode = s.context_modes.slice()[s.block_type_length_state.block_type_rb[1] as usize];
2572            s.context_map_slice_index = 0;
2573            s.dist_context_map_slice_index = 0;
2574            s.context_lookup1 =
2575                &kContextLookup[kContextLookupOffsets[context_mode as usize] as usize ..];
2576            s.context_lookup2 =
2577                &kContextLookup[kContextLookupOffsets[context_mode as usize + 1] as usize ..];
2578            s.htree_command_index = 0;
2579            // look it up each time s.literal_htree =s.literal_hgroup.htrees[s.literal_htree_index];
2580            s.state = BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN;
2581          }
2582          break;
2583        },
2584        BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN
2585        | BrotliRunningState::BROTLI_STATE_COMMAND_INNER
2586        | BrotliRunningState::BROTLI_STATE_COMMAND_POST_DECODE_LITERALS
2587        | BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRAP_COPY => {
2588          result = ProcessCommands(s, local_input);
2589          match result {
2590            BrotliResult::NeedsMoreInput => result = SafeProcessCommands(s, local_input),
2591            _ => {},
2592          }
2593          break;
2594        },
2595        BrotliRunningState::BROTLI_STATE_COMMAND_INNER_WRITE
2596        | BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_1
2597        | BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_2 => {
2598          result = WriteRingBuffer(&mut available_out, &mut output, &mut output_offset, &mut total_out, &mut s);
2599          match result {
2600            BrotliResult::ResultSuccess => {},
2601            _ => break,
2602          }
2603          s.pos -= s.ringbuffer_size;
2604          s.rb_roundtrips += 1;
2605          s.max_distance = s.max_backward_distance;
2606          match s.state {
2607            BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_1 => {
2608            //s.ringbuffer[0 .. pos].clone_from_slice(s.ringbuffer.slice()[s.ringbuffer_size : s.ringbuffer_size + pos]);
2609              /* FIXME
2610              if s.pos > 0 {
2611                let mut pos = s.pos as usize;
2612                // hopefully the following is a hint that the while loop below is safe
2613                let _last_item = s.ringbuffer.slice()[s.ringbuffer_size as usize + pos - 1];
2614                while pos > 0 {
2615                  pos -= 1; // FIXME: this loop is probably super slow.. maybe compiler can bound only once?
2616                  s.ringbuffer.slice_mut()[pos] = s.ringbuffer.slice()[s.ringbuffer_size as usize + pos];
2617                }
2618              } */
2619              memcpy_within_slice(s.ringbuffer.slice_mut(),
2620                                  0,
2621                                  s.ringbuffer_size as usize,
2622                                  s.pos as usize);
2623              //s.ringbuffer memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);
2624              if (s.meta_block_remaining_len <= 0) {
2625                // Next metablock, if any 
2626                s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2627              } else {
2628                s.state = BrotliRunningState::BROTLI_STATE_COMMAND_BEGIN;
2629              }
2630              break;
2631            },
2632            BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRITE_2 => {
2633              s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_WRAP_COPY;
2634            },
2635            _ => {  // BROTLI_STATE_COMMAND_INNER_WRITE 
2636              if (s.loop_counter == 0) {
2637                if (s.meta_block_remaining_len <= 0) {
2638                  s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_DONE;
2639                } else {
2640                  s.state = BrotliRunningState::BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
2641                }
2642                break;
2643              }
2644              s.state = BrotliRunningState::BROTLI_STATE_COMMAND_INNER;
2645            },
2646          }
2647          break;
2648        },
2649        BrotliRunningState::BROTLI_STATE_METABLOCK_DONE => {
2650          s.BrotliStateCleanupAfterMetablock();
2651          if (s.is_last_metablock == 0) {
2652            s.state = BrotliRunningState::BROTLI_STATE_METABLOCK_BEGIN;
2653            break;
2654          }
2655          if (!bit_reader::BrotliJumpToByteBoundary(&mut s.br)) {
2656            result = BROTLI_FAILURE();
2657          }
2658          if (s.buffer_length == 0) {
2659            bit_reader::BrotliBitReaderUnload(&mut s.br);
2660            *available_in = s.br.avail_in as usize;
2661            *input_offset = s.br.next_in as usize;
2662          }
2663          s.state = BrotliRunningState::BROTLI_STATE_DONE;
2664          // No break, continue to next state 
2665        },
2666        BrotliRunningState::BROTLI_STATE_DONE => {
2667          if (s.ringbuffer.slice().len() != 0) {
2668            result = WriteRingBuffer(&mut available_out, &mut output, &mut output_offset, &mut total_out, &mut s);
2669            match result {
2670              BrotliResult::ResultSuccess => {},
2671              _ => break,
2672            }
2673          }
2674          return result;
2675        }
2676      }
2677    }
2678  }
2679
2680  return result;
2681}