brotli_decompressor/
state.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4
5
6use alloc;
7use core;
8use context::kContextLookup;
9use bit_reader::{BrotliBitReader, BrotliGetAvailableBits, BrotliInitBitReader};
10use huffman::{BROTLI_HUFFMAN_MAX_CODE_LENGTH, BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE,
11              BROTLI_HUFFMAN_MAX_TABLE_SIZE, HuffmanCode, HuffmanTreeGroup};
12use alloc::SliceWrapper;
13
14#[allow(dead_code)]
15pub enum WhichTreeGroup {
16  LITERAL,
17  INSERT_COPY,
18  DISTANCE,
19}
20#[repr(C)]
21#[derive(Clone,Copy, Debug)]
22pub enum BrotliDecoderErrorCode{
23  BROTLI_DECODER_NO_ERROR = 0,
24  /* Same as BrotliDecoderResult values */
25  BROTLI_DECODER_SUCCESS = 1,
26  BROTLI_DECODER_NEEDS_MORE_INPUT = 2,
27  BROTLI_DECODER_NEEDS_MORE_OUTPUT = 3,
28
29  /* Errors caused by invalid input */
30  BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE = -1,
31  BROTLI_DECODER_ERROR_FORMAT_RESERVED = -2,
32  BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE = -3,
33  BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET = -4,
34  BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME = -5,
35  BROTLI_DECODER_ERROR_FORMAT_CL_SPACE = -6,
36  BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE = -7,
37  BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT = -8,
38  BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 = -9,
39  BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 = -10,
40  BROTLI_DECODER_ERROR_FORMAT_TRANSFORM = -11,
41  BROTLI_DECODER_ERROR_FORMAT_DICTIONARY = -12,
42  BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS = -13,
43  BROTLI_DECODER_ERROR_FORMAT_PADDING_1 = -14,
44  BROTLI_DECODER_ERROR_FORMAT_PADDING_2 = -15,
45  BROTLI_DECODER_ERROR_FORMAT_DISTANCE = -16,
46
47  /* -17..-18 codes are reserved */
48
49  BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET = -19,
50  BROTLI_DECODER_ERROR_INVALID_ARGUMENTS = -20,
51
52  /* Memory allocation problems */
53  BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES = -21,
54  /* Literal = insert and distance trees together */
55  BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS = -22,
56  /* -23..-24 codes are reserved for distinct tree groups */
57  BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP = -25,
58  BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 = -26,
59  BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 = -27,
60  /* -28..-29 codes are reserved for dynamic ring-buffer allocation */
61  BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES = -30,
62
63  /* "Impossible" states */
64  BROTLI_DECODER_ERROR_UNREACHABLE = -31,
65}
66
67#[derive(Debug)]
68pub enum BrotliRunningState {
69  BROTLI_STATE_UNINITED,
70  BROTLI_STATE_LARGE_WINDOW_BITS,
71  BROTLI_STATE_INITIALIZE,
72  BROTLI_STATE_METABLOCK_BEGIN,
73  BROTLI_STATE_METABLOCK_HEADER,
74  BROTLI_STATE_METABLOCK_HEADER_2,
75  BROTLI_STATE_CONTEXT_MODES,
76  BROTLI_STATE_COMMAND_BEGIN,
77  BROTLI_STATE_COMMAND_INNER,
78  BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
79  BROTLI_STATE_COMMAND_POST_WRAP_COPY,
80  BROTLI_STATE_UNCOMPRESSED,
81  BROTLI_STATE_METADATA,
82  BROTLI_STATE_COMMAND_INNER_WRITE,
83  BROTLI_STATE_METABLOCK_DONE,
84  BROTLI_STATE_COMMAND_POST_WRITE_1,
85  BROTLI_STATE_COMMAND_POST_WRITE_2,
86  BROTLI_STATE_HUFFMAN_CODE_0,
87  BROTLI_STATE_HUFFMAN_CODE_1,
88  BROTLI_STATE_HUFFMAN_CODE_2,
89  BROTLI_STATE_HUFFMAN_CODE_3,
90  BROTLI_STATE_CONTEXT_MAP_1,
91  BROTLI_STATE_CONTEXT_MAP_2,
92  BROTLI_STATE_TREE_GROUP,
93  BROTLI_STATE_DONE,
94}
95
96pub enum BrotliRunningMetablockHeaderState {
97  BROTLI_STATE_METABLOCK_HEADER_NONE,
98  BROTLI_STATE_METABLOCK_HEADER_EMPTY,
99  BROTLI_STATE_METABLOCK_HEADER_NIBBLES,
100  BROTLI_STATE_METABLOCK_HEADER_SIZE,
101  BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,
102  BROTLI_STATE_METABLOCK_HEADER_RESERVED,
103  BROTLI_STATE_METABLOCK_HEADER_BYTES,
104  BROTLI_STATE_METABLOCK_HEADER_METADATA,
105}
106pub enum BrotliRunningUncompressedState {
107  BROTLI_STATE_UNCOMPRESSED_NONE,
108  BROTLI_STATE_UNCOMPRESSED_WRITE,
109}
110
111pub enum BrotliRunningTreeGroupState {
112  BROTLI_STATE_TREE_GROUP_NONE,
113  BROTLI_STATE_TREE_GROUP_LOOP,
114}
115
116pub enum BrotliRunningContextMapState {
117  BROTLI_STATE_CONTEXT_MAP_NONE,
118  BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
119  BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
120  BROTLI_STATE_CONTEXT_MAP_DECODE,
121  BROTLI_STATE_CONTEXT_MAP_TRANSFORM,
122}
123
124pub enum BrotliRunningHuffmanState {
125  BROTLI_STATE_HUFFMAN_NONE,
126  BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
127  BROTLI_STATE_HUFFMAN_SIMPLE_READ,
128  BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
129  BROTLI_STATE_HUFFMAN_COMPLEX,
130  BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS,
131}
132
133pub enum BrotliRunningDecodeUint8State {
134  BROTLI_STATE_DECODE_UINT8_NONE,
135  BROTLI_STATE_DECODE_UINT8_SHORT,
136  BROTLI_STATE_DECODE_UINT8_LONG,
137}
138
139pub enum BrotliRunningReadBlockLengthState {
140  BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
141  BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX,
142}
143
144pub const kLiteralContextBits: usize = 6;
145
146pub struct BlockTypeAndLengthState<AllocHC: alloc::Allocator<HuffmanCode>> {
147  pub substate_read_block_length: BrotliRunningReadBlockLengthState,
148  pub num_block_types: [u32; 3],
149  pub block_length_index: u32,
150  pub block_length: [u32; 3],
151  pub block_type_trees: AllocHC::AllocatedMemory,
152  pub block_len_trees: AllocHC::AllocatedMemory,
153  pub block_type_rb: [u32; 6],
154}
155
156pub struct BrotliState<AllocU8: alloc::Allocator<u8>,
157                       AllocU32: alloc::Allocator<u32>,
158                       AllocHC: alloc::Allocator<HuffmanCode>>
159{
160  pub state: BrotliRunningState,
161
162  // This counter is reused for several disjoint loops.
163  pub loop_counter: i32,
164  pub br: BrotliBitReader,
165  pub alloc_u8: AllocU8,
166  pub alloc_u32: AllocU32,
167  pub alloc_hc: AllocHC,
168  // void* memory_manager_opaque,
169  pub buffer: [u8; 8],
170  pub buffer_length: u32,
171  pub pos: i32,
172  pub max_backward_distance: i32,
173  pub max_backward_distance_minus_custom_dict_size: i32,
174  pub max_distance: i32,
175  pub ringbuffer_size: i32,
176  pub ringbuffer_mask: i32,
177  pub dist_rb_idx: i32,
178  pub dist_rb: [i32; 4],
179  pub ringbuffer: AllocU8::AllocatedMemory,
180  // pub ringbuffer_end : usize,
181  pub htree_command_index: u16,
182  pub context_lookup: &'static [u8;512],
183  pub context_map_slice_index: usize,
184  pub dist_context_map_slice_index: usize,
185
186  pub sub_loop_counter: u32,
187
188  // This ring buffer holds a few past copy distances that will be used by */
189  // some special distance codes.
190  pub literal_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
191  pub insert_copy_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
192  pub distance_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
193  // This is true if the literal context map histogram type always matches the
194  // block type. It is then not needed to keep the context (faster decoding).
195  pub trivial_literal_context: i32,
196  // Distance context is actual after command is decoded and before distance
197  // is computed. After distance computation it is used as a temporary variable
198  pub distance_context: i32,
199  pub meta_block_remaining_len: i32,
200  pub block_type_length_state: BlockTypeAndLengthState<AllocHC>,
201  pub distance_postfix_bits: u32,
202  pub num_direct_distance_codes: u32,
203  pub distance_postfix_mask: i32,
204  pub num_dist_htrees: u32,
205  pub dist_context_map: AllocU8::AllocatedMemory,
206  // NOT NEEDED? the index below seems to supersede it pub literal_htree : AllocHC::AllocatedMemory,
207  pub literal_htree_index: u8,
208  pub dist_htree_index: u8,
209  pub large_window: bool,
210  pub should_wrap_ringbuffer: bool,
211  pub error_code: BrotliDecoderErrorCode,
212  pub repeat_code_len: u32,
213  pub prev_code_len: u32,
214
215  pub copy_length: i32,
216  pub distance_code: i32,
217
218  // For partial write operations
219  pub rb_roundtrips: usize, // How many times we went around the ringbuffer
220  pub partial_pos_out: usize, // How much output to the user in total (<= rb)
221
222  // For ReadHuffmanCode
223  pub symbol: u32,
224  pub repeat: u32,
225  pub space: u32,
226
227  pub table: [HuffmanCode; 32],
228  // List of of symbol chains.
229  pub symbol_lists_index: usize, // AllocU16::AllocatedMemory,
230  // Storage from symbol_lists.
231  pub symbols_lists_array: [u16; BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
232                                 BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
233  // Tails of symbol chains.
234  pub next_symbol: [i32; 32],
235  pub code_length_code_lengths: [u8; 18],
236  // Population counts for the code lengths
237  pub code_length_histo: [u16; 16],
238
239  // For HuffmanTreeGroupDecode
240  pub htree_index: i32,
241  pub htree_next_offset: u32,
242
243  // For DecodeContextMap
244  pub context_index: u32,
245  pub max_run_length_prefix: u32,
246  pub code: u32,
247  // always pre-allocated on state creation
248  pub context_map_table: AllocHC::AllocatedMemory,
249
250  // For InverseMoveToFrontTransform
251  pub mtf_upper_bound: u32,
252  pub mtf_or_error_string: Result<[u8; 256], [u8; 256]>,
253
254  // For custom dictionaries
255  pub custom_dict: AllocU8::AllocatedMemory,
256  pub custom_dict_size: isize,
257  pub custom_dict_avoid_context_seed: bool,
258  // less used attributes are in the end of this struct */
259  // States inside function calls
260  pub substate_metablock_header: BrotliRunningMetablockHeaderState,
261  pub substate_tree_group: BrotliRunningTreeGroupState,
262  pub substate_context_map: BrotliRunningContextMapState,
263  pub substate_uncompressed: BrotliRunningUncompressedState,
264  pub substate_huffman: BrotliRunningHuffmanState,
265  pub substate_decode_uint8: BrotliRunningDecodeUint8State,
266
267  pub is_last_metablock: u8,
268  pub is_uncompressed: u8,
269  pub is_metadata: u8,
270  pub size_nibbles: u8,
271  pub window_bits: u32,
272
273  pub num_literal_htrees: u32,
274  pub context_map: AllocU8::AllocatedMemory,
275  pub context_modes: AllocU8::AllocatedMemory,
276  pub trivial_literal_contexts: [u32; 8],
277}
278macro_rules! make_brotli_state {
279 ($alloc_u8 : expr, $alloc_u32 : expr, $alloc_hc : expr, $custom_dict : expr, $custom_dict_len: expr) => (BrotliState::<AllocU8, AllocU32, AllocHC>{
280            state : BrotliRunningState::BROTLI_STATE_UNINITED,
281            loop_counter : 0,
282            br : BrotliBitReader::default(),
283            alloc_u8 : $alloc_u8,
284            alloc_u32 : $alloc_u32,
285            alloc_hc : $alloc_hc,
286            buffer : [0u8; 8],
287            buffer_length : 0,
288            pos : 0,
289            max_backward_distance : 0,
290            max_backward_distance_minus_custom_dict_size : 0,
291            max_distance : 0,
292            ringbuffer_size : 0,
293            ringbuffer_mask: 0,
294            dist_rb_idx : 0,
295            dist_rb : [16, 15, 11, 4],
296            ringbuffer : AllocU8::AllocatedMemory::default(),
297            htree_command_index : 0,
298            context_lookup : &kContextLookup[0],
299            context_map_slice_index : 0,
300            dist_context_map_slice_index : 0,
301            sub_loop_counter : 0,
302
303            literal_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
304            insert_copy_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
305            distance_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
306            trivial_literal_context : 0,
307            distance_context : 0,
308            meta_block_remaining_len : 0,
309            block_type_length_state : BlockTypeAndLengthState::<AllocHC> {
310              block_length_index : 0,
311              block_length : [0; 3],
312              num_block_types : [0;3],
313              block_type_rb: [0;6],
314              substate_read_block_length : BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
315              block_type_trees : AllocHC::AllocatedMemory::default(),
316              block_len_trees : AllocHC::AllocatedMemory::default(),
317            },
318            distance_postfix_bits : 0,
319            num_direct_distance_codes : 0,
320            distance_postfix_mask : 0,
321            num_dist_htrees : 0,
322            dist_context_map : AllocU8::AllocatedMemory::default(),
323            //// not needed literal_htree : AllocHC::AllocatedMemory::default(),
324            literal_htree_index : 0,
325            dist_htree_index : 0,
326            repeat_code_len : 0,
327            prev_code_len : 0,
328            copy_length : 0,
329            distance_code : 0,
330            rb_roundtrips : 0,  /* How many times we went around the ringbuffer */
331            partial_pos_out : 0,  /* How much output to the user in total (<= rb) */
332            symbol : 0,
333            repeat : 0,
334            space : 0,
335            table : [HuffmanCode::default(); 32],
336            //symbol_lists: AllocU16::AllocatedMemory::default(),
337            symbol_lists_index : BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1,
338            symbols_lists_array : [0;BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
339                              BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
340            next_symbol : [0; 32],
341            code_length_code_lengths : [0; 18],
342            code_length_histo : [0; 16],
343            htree_index : 0,
344            htree_next_offset : 0,
345
346            /* For DecodeContextMap */
347           context_index : 0,
348           max_run_length_prefix : 0,
349           code : 0,
350           context_map_table : AllocHC::AllocatedMemory::default(),
351
352           /* For InverseMoveToFrontTransform */
353           mtf_upper_bound : 255,
354           mtf_or_error_string : Ok([0; 256]),
355
356           /* For custom dictionaries */
357           custom_dict : $custom_dict,
358           custom_dict_size : $custom_dict_len as isize,
359           custom_dict_avoid_context_seed: $custom_dict_len != 0,
360           /* less used attributes are in the end of this struct */
361           /* States inside function calls */
362           substate_metablock_header : BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE,
363           substate_tree_group : BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE,
364           substate_context_map : BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE,
365           substate_uncompressed : BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE,
366           substate_huffman : BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE,
367           substate_decode_uint8 : BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE,
368
369           is_last_metablock : 0,
370           is_uncompressed : 0,
371           is_metadata : 0,
372           size_nibbles : 0,
373           window_bits : 0,
374           large_window: false,
375           should_wrap_ringbuffer: false,
376           error_code: BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS,
377           num_literal_htrees : 0,
378           context_map : AllocU8::AllocatedMemory::default(),
379           context_modes : AllocU8::AllocatedMemory::default(),
380           trivial_literal_contexts : [0u32; 8],
381        }
382    );
383}
384impl <'brotli_state,
385      AllocU8 : alloc::Allocator<u8>,
386      AllocU32 : alloc::Allocator<u32>,
387      AllocHC : alloc::Allocator<HuffmanCode> > BrotliState<AllocU8, AllocU32, AllocHC> {
388    pub fn new(alloc_u8 : AllocU8,
389           alloc_u32 : AllocU32,
390           alloc_hc : AllocHC) -> Self{
391        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), 0);
392        retval.large_window = true;
393        retval.context_map_table = retval.alloc_hc.alloc_cell(
394          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
395        BrotliInitBitReader(&mut retval.br);
396        retval
397    }
398    pub fn new_with_custom_dictionary(alloc_u8 : AllocU8,
399           alloc_u32 : AllocU32,
400           alloc_hc : AllocHC,
401           custom_dict: AllocU8::AllocatedMemory) -> Self{
402        let custom_dict_len = custom_dict.slice().len();
403        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, custom_dict, custom_dict_len);
404        retval.context_map_table = retval.alloc_hc.alloc_cell(
405          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
406        retval.large_window =  true;
407        BrotliInitBitReader(&mut retval.br);
408        retval
409    }
410    pub fn new_strict(alloc_u8 : AllocU8,
411           alloc_u32 : AllocU32,
412           alloc_hc : AllocHC) -> Self{
413        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), 0);
414        retval.context_map_table = retval.alloc_hc.alloc_cell(
415          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
416        retval.large_window =  false;
417        BrotliInitBitReader(&mut retval.br);
418        retval
419    }
420    pub fn BrotliStateMetablockBegin(self : &mut Self) {
421        self.meta_block_remaining_len = 0;
422        self.block_type_length_state.block_length[0] = 1u32 << 24;
423        self.block_type_length_state.block_length[1] = 1u32 << 24;
424        self.block_type_length_state.block_length[2] = 1u32 << 24;
425        self.block_type_length_state.num_block_types[0] = 1;
426        self.block_type_length_state.num_block_types[1] = 1;
427        self.block_type_length_state.num_block_types[2] = 1;
428        self.block_type_length_state.block_type_rb[0] = 1;
429        self.block_type_length_state.block_type_rb[1] = 0;
430        self.block_type_length_state.block_type_rb[2] = 1;
431        self.block_type_length_state.block_type_rb[3] = 0;
432        self.block_type_length_state.block_type_rb[4] = 1;
433        self.block_type_length_state.block_type_rb[5] = 0;
434        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
435                                             AllocU8::AllocatedMemory::default()));
436        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
437                                             AllocU8::AllocatedMemory::default()));
438        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
439                                             AllocU8::AllocatedMemory::default()));
440        self.context_map_slice_index = 0;
441        self.literal_htree_index = 0;
442        self.dist_context_map_slice_index = 0;
443        self.dist_htree_index = 0;
444        self.context_lookup = &kContextLookup[0];
445        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
446        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
447        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
448    }
449    pub fn BrotliStateCleanupAfterMetablock(self : &mut Self) {
450        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
451                                             AllocU8::AllocatedMemory::default()));
452        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
453                                             AllocU8::AllocatedMemory::default()));
454        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
455                                             AllocU8::AllocatedMemory::default()));
456
457
458        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
459        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
460        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
461    }
462
463   fn BrotliStateCleanup(self : &mut Self) {
464      self.BrotliStateCleanupAfterMetablock();
465      self.alloc_u8.free_cell(core::mem::replace(&mut self.ringbuffer,
466                              AllocU8::AllocatedMemory::default()));
467      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_type_trees,
468                              AllocHC::AllocatedMemory::default()));
469      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_len_trees,
470                              AllocHC::AllocatedMemory::default()));
471      self.alloc_hc.free_cell(core::mem::replace(&mut self.context_map_table,
472                              AllocHC::AllocatedMemory::default()));
473      self.alloc_u8.free_cell(core::mem::replace(&mut self.custom_dict,
474                              AllocU8::AllocatedMemory::default()));
475
476      //FIXME??  BROTLI_FREE(s, s->legacy_input_buffer);
477      //FIXME??  BROTLI_FREE(s, s->legacy_output_buffer);
478    }
479
480    pub fn BrotliStateIsStreamStart(self : &Self) -> bool {
481        match self.state {
482            BrotliRunningState::BROTLI_STATE_UNINITED =>
483                BrotliGetAvailableBits(&self.br) == 0,
484            _ => false,
485        }
486    }
487
488    pub fn BrotliStateIsStreamEnd(self : &Self) -> bool {
489        match self.state {
490            BrotliRunningState::BROTLI_STATE_DONE => true,
491            _ => false
492        }
493    }
494    pub fn BrotliHuffmanTreeGroupInit(self :&mut Self, group : WhichTreeGroup,
495                                      alphabet_size : u16, max_symbol: u16, ntrees : u16) {
496        match group {
497            WhichTreeGroup::LITERAL => self.literal_hgroup.init(&mut self.alloc_u32,
498                                                                &mut self.alloc_hc,
499                                                                alphabet_size, max_symbol, ntrees),
500            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.init(&mut self.alloc_u32,
501                                                                        &mut self.alloc_hc,
502                                                                        alphabet_size, max_symbol, ntrees),
503            WhichTreeGroup::DISTANCE => self.distance_hgroup.init(&mut self.alloc_u32,
504                                                                  &mut self.alloc_hc,
505                                                                  alphabet_size, max_symbol, ntrees),
506        }
507    }
508    pub fn BrotliHuffmanTreeGroupRelease(self :&mut Self, group : WhichTreeGroup) {
509        match group {
510            WhichTreeGroup::LITERAL => self.literal_hgroup.reset(&mut self.alloc_u32,
511                                                                 &mut self.alloc_hc),
512            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.reset(&mut self.alloc_u32,
513                                                                         &mut self.alloc_hc),
514            WhichTreeGroup::DISTANCE => self.distance_hgroup.reset(&mut self.alloc_u32,
515                                                                   &mut self.alloc_hc),
516        }
517    }
518}
519
520impl <'brotli_state,
521      AllocU8 : alloc::Allocator<u8>,
522      AllocU32 : alloc::Allocator<u32>,
523      AllocHC : alloc::Allocator<HuffmanCode> > Drop for BrotliState<AllocU8, AllocU32, AllocHC> {
524    fn drop(&mut self) {
525        self.BrotliStateCleanup();
526    }
527}
528
529
530
531pub fn BrotliDecoderErrorStr(c: BrotliDecoderErrorCode) -> &'static str {
532  match c {
533  BrotliDecoderErrorCode::BROTLI_DECODER_NO_ERROR => "NO_ERROR\0",
534  /* Same as BrotliDecoderResult values */
535  BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS => "SUCCESS\0",
536  BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_INPUT => "NEEDS_MORE_INPUT\0",
537  BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_OUTPUT => "NEEDS_MORE_OUTPUT\0",
538
539  /* Errors caused by invalid input */
540  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE => "ERROR_FORMAT_EXUBERANT_NIBBLE\0",
541  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_RESERVED => "ERROR_FORMAT_RESERVED\0",
542  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE => "ERROR_FORMAT_EXUBERANT_META_NIBBLE\0",
543  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET => "ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET\0",
544  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME => "ERROR_FORMAT_SIMPLE_HUFFMAN_SAME\0",
545  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CL_SPACE => "ERROR_FORMAT_FL_SPACE\0",
546  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE => "ERROR_FORMAT_HUFFMAN_SPACE\0",
547  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT => "ERROR_FORMAT_CONTEXT_MAP_REPEAT\0",
548  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 =>"ERROR_FORMAT_BLOCK_LENGTH_1\0",
549  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 =>"ERROR_FORMAT_BLOCK_LENGTH_2\0",
550  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_TRANSFORM => "ERROR_FORMAT_TRANSFORM\0",
551  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DICTIONARY =>"ERROR_FORMAT_DICTIONARY\0",
552  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS =>"ERROR_FORMAT_WINDOW_BITS\0",
553  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_1 =>"ERROR_FORMAT_PADDING_1\0",
554  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_2 =>"ERROR_FORMAT_PADDING_2\0",
555  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DISTANCE =>"ERROR_FORMAT_DISTANCE\0",
556
557  /* -17..-18 codes are reserved */
558
559  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET => "ERROR_DICTIONARY_NOT_SET\0",
560  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_INVALID_ARGUMENTS => "ERROR_INVALID_ARGUMENTS\0",
561
562  /* Memory allocation problems */
563  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES => "ERROR_ALLOC_CONTEXT_MODES\0",
564  /* Literal => insert and distance trees together */
565  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS => "ERROR_ALLOC_TREE_GROUPS\0",
566  /* -23..-24 codes are reserved for distinct tree groups */
567  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP => "ERROR_ALLOC_CONTEXT_MAP\0",
568  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 => "ERROR_ALLOC_RING_BUFFER_1\0",
569  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 => "ERROR_ALLOC_RING_BUFFER_2\0",
570  /* -28..-29 codes are reserved for dynamic ring-buffer allocation */
571  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES => "ERROR_ALLOC_BLOCK_TYPE_TREES\0",
572
573  /* "Impossible" states */
574  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_UNREACHABLE => "ERROR_UNREACHABLE\0",
575  }
576}