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: i32,
257  // less used attributes are in the end of this struct */
258  // States inside function calls
259  pub substate_metablock_header: BrotliRunningMetablockHeaderState,
260  pub substate_tree_group: BrotliRunningTreeGroupState,
261  pub substate_context_map: BrotliRunningContextMapState,
262  pub substate_uncompressed: BrotliRunningUncompressedState,
263  pub substate_huffman: BrotliRunningHuffmanState,
264  pub substate_decode_uint8: BrotliRunningDecodeUint8State,
265
266  pub is_last_metablock: u8,
267  pub is_uncompressed: u8,
268  pub is_metadata: u8,
269  pub size_nibbles: u8,
270  pub window_bits: u32,
271
272  pub num_literal_htrees: u32,
273  pub context_map: AllocU8::AllocatedMemory,
274  pub context_modes: AllocU8::AllocatedMemory,
275  pub trivial_literal_contexts: [u32; 8],
276}
277macro_rules! make_brotli_state {
278 ($alloc_u8 : expr, $alloc_u32 : expr, $alloc_hc : expr, $custom_dict : expr, $custom_dict_len: expr) => (BrotliState::<AllocU8, AllocU32, AllocHC>{
279            state : BrotliRunningState::BROTLI_STATE_UNINITED,
280            loop_counter : 0,
281            br : BrotliBitReader::default(),
282            alloc_u8 : $alloc_u8,
283            alloc_u32 : $alloc_u32,
284            alloc_hc : $alloc_hc,
285            buffer : [0u8; 8],
286            buffer_length : 0,
287            pos : 0,
288            max_backward_distance : 0,
289            max_backward_distance_minus_custom_dict_size : 0,
290            max_distance : 0,
291            ringbuffer_size : 0,
292            ringbuffer_mask: 0,
293            dist_rb_idx : 0,
294            dist_rb : [16, 15, 11, 4],
295            ringbuffer : AllocU8::AllocatedMemory::default(),
296            htree_command_index : 0,
297            context_lookup : &kContextLookup[0],
298            context_map_slice_index : 0,
299            dist_context_map_slice_index : 0,
300            sub_loop_counter : 0,
301
302            literal_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
303            insert_copy_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
304            distance_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
305            trivial_literal_context : 0,
306            distance_context : 0,
307            meta_block_remaining_len : 0,
308            block_type_length_state : BlockTypeAndLengthState::<AllocHC> {
309              block_length_index : 0,
310              block_length : [0; 3],
311              num_block_types : [0;3],
312              block_type_rb: [0;6],
313              substate_read_block_length : BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
314              block_type_trees : AllocHC::AllocatedMemory::default(),
315              block_len_trees : AllocHC::AllocatedMemory::default(),
316            },
317            distance_postfix_bits : 0,
318            num_direct_distance_codes : 0,
319            distance_postfix_mask : 0,
320            num_dist_htrees : 0,
321            dist_context_map : AllocU8::AllocatedMemory::default(),
322            //// not needed literal_htree : AllocHC::AllocatedMemory::default(),
323            literal_htree_index : 0,
324            dist_htree_index : 0,
325            repeat_code_len : 0,
326            prev_code_len : 0,
327            copy_length : 0,
328            distance_code : 0,
329            rb_roundtrips : 0,  /* How many times we went around the ringbuffer */
330            partial_pos_out : 0,  /* How much output to the user in total (<= rb) */
331            symbol : 0,
332            repeat : 0,
333            space : 0,
334            table : [HuffmanCode::default(); 32],
335            //symbol_lists: AllocU16::AllocatedMemory::default(),
336            symbol_lists_index : BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1,
337            symbols_lists_array : [0;BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
338                              BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
339            next_symbol : [0; 32],
340            code_length_code_lengths : [0; 18],
341            code_length_histo : [0; 16],
342            htree_index : 0,
343            htree_next_offset : 0,
344
345            /* For DecodeContextMap */
346           context_index : 0,
347           max_run_length_prefix : 0,
348           code : 0,
349           context_map_table : AllocHC::AllocatedMemory::default(),
350
351           /* For InverseMoveToFrontTransform */
352           mtf_upper_bound : 255,
353           mtf_or_error_string : Ok([0; 256]),
354
355           /* For custom dictionaries */
356           custom_dict : $custom_dict,
357           custom_dict_size : $custom_dict_len as i32,
358
359           /* less used attributes are in the end of this struct */
360           /* States inside function calls */
361           substate_metablock_header : BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE,
362           substate_tree_group : BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE,
363           substate_context_map : BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE,
364           substate_uncompressed : BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE,
365           substate_huffman : BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE,
366           substate_decode_uint8 : BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE,
367
368           is_last_metablock : 0,
369           is_uncompressed : 0,
370           is_metadata : 0,
371           size_nibbles : 0,
372           window_bits : 0,
373           large_window: false,
374           should_wrap_ringbuffer: false,
375           error_code: BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS,
376           num_literal_htrees : 0,
377           context_map : AllocU8::AllocatedMemory::default(),
378           context_modes : AllocU8::AllocatedMemory::default(),
379           trivial_literal_contexts : [0u32; 8],
380        }
381    );
382}
383impl <'brotli_state,
384      AllocU8 : alloc::Allocator<u8>,
385      AllocU32 : alloc::Allocator<u32>,
386      AllocHC : alloc::Allocator<HuffmanCode> > BrotliState<AllocU8, AllocU32, AllocHC> {
387    pub fn new(alloc_u8 : AllocU8,
388           alloc_u32 : AllocU32,
389           alloc_hc : AllocHC) -> Self{
390        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), 0);
391        retval.large_window = true;
392        retval.context_map_table = retval.alloc_hc.alloc_cell(
393          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
394        BrotliInitBitReader(&mut retval.br);
395        retval
396    }
397    pub fn new_with_custom_dictionary(alloc_u8 : AllocU8,
398           alloc_u32 : AllocU32,
399           alloc_hc : AllocHC,
400           custom_dict: AllocU8::AllocatedMemory) -> Self{
401        let custom_dict_len = custom_dict.slice().len();
402        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, custom_dict, custom_dict_len);
403        retval.context_map_table = retval.alloc_hc.alloc_cell(
404          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
405        retval.large_window =  true;
406        BrotliInitBitReader(&mut retval.br);
407        retval
408    }
409    pub fn new_strict(alloc_u8 : AllocU8,
410           alloc_u32 : AllocU32,
411           alloc_hc : AllocHC) -> Self{
412        let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), 0);
413        retval.context_map_table = retval.alloc_hc.alloc_cell(
414          BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
415        retval.large_window =  false;
416        BrotliInitBitReader(&mut retval.br);
417        retval
418    }
419    pub fn BrotliStateMetablockBegin(self : &mut Self) {
420        self.meta_block_remaining_len = 0;
421        self.block_type_length_state.block_length[0] = 1u32 << 24;
422        self.block_type_length_state.block_length[1] = 1u32 << 24;
423        self.block_type_length_state.block_length[2] = 1u32 << 24;
424        self.block_type_length_state.num_block_types[0] = 1;
425        self.block_type_length_state.num_block_types[1] = 1;
426        self.block_type_length_state.num_block_types[2] = 1;
427        self.block_type_length_state.block_type_rb[0] = 1;
428        self.block_type_length_state.block_type_rb[1] = 0;
429        self.block_type_length_state.block_type_rb[2] = 1;
430        self.block_type_length_state.block_type_rb[3] = 0;
431        self.block_type_length_state.block_type_rb[4] = 1;
432        self.block_type_length_state.block_type_rb[5] = 0;
433        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
434                                             AllocU8::AllocatedMemory::default()));
435        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
436                                             AllocU8::AllocatedMemory::default()));
437        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
438                                             AllocU8::AllocatedMemory::default()));
439        self.context_map_slice_index = 0;
440        self.literal_htree_index = 0;
441        self.dist_context_map_slice_index = 0;
442        self.dist_htree_index = 0;
443        self.context_lookup = &kContextLookup[0];
444        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
445        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
446        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
447    }
448    pub fn BrotliStateCleanupAfterMetablock(self : &mut Self) {
449        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
450                                             AllocU8::AllocatedMemory::default()));
451        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
452                                             AllocU8::AllocatedMemory::default()));
453        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
454                                             AllocU8::AllocatedMemory::default()));
455
456
457        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
458        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
459        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
460    }
461
462   fn BrotliStateCleanup(self : &mut Self) {
463      self.BrotliStateCleanupAfterMetablock();
464      self.alloc_u8.free_cell(core::mem::replace(&mut self.ringbuffer,
465                              AllocU8::AllocatedMemory::default()));
466      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_type_trees,
467                              AllocHC::AllocatedMemory::default()));
468      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_len_trees,
469                              AllocHC::AllocatedMemory::default()));
470      self.alloc_hc.free_cell(core::mem::replace(&mut self.context_map_table,
471                              AllocHC::AllocatedMemory::default()));
472      self.alloc_u8.free_cell(core::mem::replace(&mut self.custom_dict,
473                              AllocU8::AllocatedMemory::default()));
474
475      //FIXME??  BROTLI_FREE(s, s->legacy_input_buffer);
476      //FIXME??  BROTLI_FREE(s, s->legacy_output_buffer);
477    }
478
479    pub fn BrotliStateIsStreamStart(self : &Self) -> bool {
480        match self.state {
481            BrotliRunningState::BROTLI_STATE_UNINITED =>
482                BrotliGetAvailableBits(&self.br) == 0,
483            _ => false,
484        }
485    }
486
487    pub fn BrotliStateIsStreamEnd(self : &Self) -> bool {
488        match self.state {
489            BrotliRunningState::BROTLI_STATE_DONE => true,
490            _ => false
491        }
492    }
493    pub fn BrotliHuffmanTreeGroupInit(self :&mut Self, group : WhichTreeGroup,
494                                      alphabet_size : u16, max_symbol: u16, ntrees : u16) {
495        match group {
496            WhichTreeGroup::LITERAL => self.literal_hgroup.init(&mut self.alloc_u32,
497                                                                &mut self.alloc_hc,
498                                                                alphabet_size, max_symbol, ntrees),
499            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.init(&mut self.alloc_u32,
500                                                                        &mut self.alloc_hc,
501                                                                        alphabet_size, max_symbol, ntrees),
502            WhichTreeGroup::DISTANCE => self.distance_hgroup.init(&mut self.alloc_u32,
503                                                                  &mut self.alloc_hc,
504                                                                  alphabet_size, max_symbol, ntrees),
505        }
506    }
507    pub fn BrotliHuffmanTreeGroupRelease(self :&mut Self, group : WhichTreeGroup) {
508        match group {
509            WhichTreeGroup::LITERAL => self.literal_hgroup.reset(&mut self.alloc_u32,
510                                                                 &mut self.alloc_hc),
511            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.reset(&mut self.alloc_u32,
512                                                                         &mut self.alloc_hc),
513            WhichTreeGroup::DISTANCE => self.distance_hgroup.reset(&mut self.alloc_u32,
514                                                                   &mut self.alloc_hc),
515        }
516    }
517}
518
519impl <'brotli_state,
520      AllocU8 : alloc::Allocator<u8>,
521      AllocU32 : alloc::Allocator<u32>,
522      AllocHC : alloc::Allocator<HuffmanCode> > Drop for BrotliState<AllocU8, AllocU32, AllocHC> {
523    fn drop(&mut self) {
524        self.BrotliStateCleanup();
525    }
526}
527
528
529
530pub fn BrotliDecoderErrorStr(c: BrotliDecoderErrorCode) -> &'static str {
531  match c {
532  BrotliDecoderErrorCode::BROTLI_DECODER_NO_ERROR => "NO_ERROR\0",
533  /* Same as BrotliDecoderResult values */
534  BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS => "SUCCESS\0",
535  BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_INPUT => "NEEDS_MORE_INPUT\0",
536  BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_OUTPUT => "NEEDS_MORE_OUTPUT\0",
537
538  /* Errors caused by invalid input */
539  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE => "ERROR_FORMAT_EXUBERANT_NIBBLE\0",
540  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_RESERVED => "ERROR_FORMAT_RESERVED\0",
541  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE => "ERROR_FORMAT_EXUBERANT_META_NIBBLE\0",
542  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET => "ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET\0",
543  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME => "ERROR_FORMAT_SIMPLE_HUFFMAN_SAME\0",
544  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CL_SPACE => "ERROR_FORMAT_FL_SPACE\0",
545  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE => "ERROR_FORMAT_HUFFMAN_SPACE\0",
546  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT => "ERROR_FORMAT_CONTEXT_MAP_REPEAT\0",
547  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 =>"ERROR_FORMAT_BLOCK_LENGTH_1\0",
548  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 =>"ERROR_FORMAT_BLOCK_LENGTH_2\0",
549  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_TRANSFORM => "ERROR_FORMAT_TRANSFORM\0",
550  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DICTIONARY =>"ERROR_FORMAT_DICTIONARY\0",
551  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS =>"ERROR_FORMAT_WINDOW_BITS\0",
552  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_1 =>"ERROR_FORMAT_PADDING_1\0",
553  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_2 =>"ERROR_FORMAT_PADDING_2\0",
554  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DISTANCE =>"ERROR_FORMAT_DISTANCE\0",
555
556  /* -17..-18 codes are reserved */
557
558  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET => "ERROR_DICTIONARY_NOT_SET\0",
559  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_INVALID_ARGUMENTS => "ERROR_INVALID_ARGUMENTS\0",
560
561  /* Memory allocation problems */
562  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES => "ERROR_ALLOC_CONTEXT_MODES\0",
563  /* Literal => insert and distance trees together */
564  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS => "ERROR_ALLOC_TREE_GROUPS\0",
565  /* -23..-24 codes are reserved for distinct tree groups */
566  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP => "ERROR_ALLOC_CONTEXT_MAP\0",
567  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 => "ERROR_ALLOC_RING_BUFFER_1\0",
568  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 => "ERROR_ALLOC_RING_BUFFER_2\0",
569  /* -28..-29 codes are reserved for dynamic ring-buffer allocation */
570  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES => "ERROR_ALLOC_BLOCK_TYPE_TREES\0",
571
572  /* "Impossible" states */
573  BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_UNREACHABLE => "ERROR_UNREACHABLE\0",
574  }
575}