brotli_no_stdlib/
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 bit_reader::{BrotliBitReader, BrotliGetAvailableBits, BrotliInitBitReader};
9use huffman::{HuffmanCode, HuffmanTreeGroup,
10              BROTLI_HUFFMAN_MAX_CODE_LENGTH, BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE,
11              BROTLI_HUFFMAN_MAX_TABLE_SIZE};
12
13#[allow(dead_code)]
14pub enum WhichTreeGroup {
15    LITERAL,
16    INSERT_COPY,
17    DISTANCE,
18}
19
20pub enum BrotliRunningState {
21  BROTLI_STATE_UNINITED,
22  BROTLI_STATE_METABLOCK_BEGIN,
23  BROTLI_STATE_METABLOCK_HEADER,
24  BROTLI_STATE_METABLOCK_HEADER_2,
25  BROTLI_STATE_CONTEXT_MODES,
26  BROTLI_STATE_COMMAND_BEGIN,
27  BROTLI_STATE_COMMAND_INNER,
28  BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
29  BROTLI_STATE_COMMAND_POST_WRAP_COPY,
30  BROTLI_STATE_UNCOMPRESSED,
31  BROTLI_STATE_METADATA,
32  BROTLI_STATE_COMMAND_INNER_WRITE,
33  BROTLI_STATE_METABLOCK_DONE,
34  BROTLI_STATE_COMMAND_POST_WRITE_1,
35  BROTLI_STATE_COMMAND_POST_WRITE_2,
36  BROTLI_STATE_HUFFMAN_CODE_0,
37  BROTLI_STATE_HUFFMAN_CODE_1,
38  BROTLI_STATE_HUFFMAN_CODE_2,
39  BROTLI_STATE_HUFFMAN_CODE_3,
40  BROTLI_STATE_CONTEXT_MAP_1,
41  BROTLI_STATE_CONTEXT_MAP_2,
42  BROTLI_STATE_TREE_GROUP,
43  BROTLI_STATE_DONE
44}
45
46pub enum  BrotliRunningMetablockHeaderState {
47  BROTLI_STATE_METABLOCK_HEADER_NONE,
48  BROTLI_STATE_METABLOCK_HEADER_EMPTY,
49  BROTLI_STATE_METABLOCK_HEADER_NIBBLES,
50  BROTLI_STATE_METABLOCK_HEADER_SIZE,
51  BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,
52  BROTLI_STATE_METABLOCK_HEADER_RESERVED,
53  BROTLI_STATE_METABLOCK_HEADER_BYTES,
54  BROTLI_STATE_METABLOCK_HEADER_METADATA
55}
56pub enum BrotliRunningUncompressedState {
57  BROTLI_STATE_UNCOMPRESSED_NONE,
58  BROTLI_STATE_UNCOMPRESSED_WRITE
59}
60
61pub enum BrotliRunningTreeGroupState {
62  BROTLI_STATE_TREE_GROUP_NONE,
63  BROTLI_STATE_TREE_GROUP_LOOP
64}
65
66pub enum BrotliRunningContextMapState {
67  BROTLI_STATE_CONTEXT_MAP_NONE,
68  BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
69  BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
70  BROTLI_STATE_CONTEXT_MAP_DECODE,
71  BROTLI_STATE_CONTEXT_MAP_TRANSFORM,
72}
73
74pub enum BrotliRunningHuffmanState {
75  BROTLI_STATE_HUFFMAN_NONE,
76  BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
77  BROTLI_STATE_HUFFMAN_SIMPLE_READ,
78  BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
79  BROTLI_STATE_HUFFMAN_COMPLEX,
80  BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS
81}
82
83pub enum BrotliRunningDecodeUint8State {
84  BROTLI_STATE_DECODE_UINT8_NONE,
85  BROTLI_STATE_DECODE_UINT8_SHORT,
86  BROTLI_STATE_DECODE_UINT8_LONG
87}
88
89pub enum  BrotliRunningReadBlockLengthState {
90  BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
91  BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
92}
93
94pub const kLiteralContextBits : usize = 6;
95
96pub struct BlockTypeAndLengthState<AllocHC : alloc::Allocator<HuffmanCode> > {
97  pub substate_read_block_length : BrotliRunningReadBlockLengthState,
98  pub num_block_types : [u32;3],
99  pub block_length_index : u32,
100  pub block_length : [u32; 3],
101  pub block_type_trees : AllocHC::AllocatedMemory,
102  pub block_len_trees : AllocHC::AllocatedMemory,
103  pub block_type_rb: [u32;6],
104
105}
106
107pub struct BrotliState<AllocU8 : alloc::Allocator<u8>,
108                       AllocU32 : alloc::Allocator<u32>,
109                       AllocHC : alloc::Allocator<HuffmanCode> > {
110  pub state : BrotliRunningState,
111
112  /* This counter is reused for several disjoint loops. */
113  pub loop_counter : i32,
114  pub br : BrotliBitReader,
115  pub alloc_u8 : AllocU8,
116  pub alloc_u32 : AllocU32,
117  pub alloc_hc : AllocHC,
118  //void* memory_manager_opaque,
119  pub buffer : [u8;8],
120  pub buffer_length : u32,
121  pub pos : i32,
122  pub max_backward_distance : i32,
123  pub max_backward_distance_minus_custom_dict_size : i32,
124  pub max_distance : i32,
125  pub ringbuffer_size:  i32,
126  pub ringbuffer_mask: i32,
127  pub dist_rb_idx : i32,
128  pub dist_rb : [i32;4],
129  pub ringbuffer : AllocU8::AllocatedMemory,
130  //pub ringbuffer_end : usize,
131  pub htree_command_index : u16,
132  pub context_lookup1 : &'static [u8],
133  pub context_lookup2 : &'static [u8],
134  pub context_map_slice_index : usize,
135  pub dist_context_map_slice_index : usize,
136
137  pub sub_loop_counter : u32,
138
139  /* This ring buffer holds a few past copy distances that will be used by */
140  /* some special distance codes. */
141  pub literal_hgroup : HuffmanTreeGroup<AllocU32, AllocHC>,
142  pub insert_copy_hgroup : HuffmanTreeGroup<AllocU32, AllocHC>,
143  pub distance_hgroup : HuffmanTreeGroup<AllocU32, AllocHC>,
144  /* This is true if the literal context map histogram type always matches the
145  block type. It is then not needed to keep the context (faster decoding). */
146  pub trivial_literal_context : i32,
147  pub distance_context : i32,
148  pub meta_block_remaining_len : i32,
149  pub block_type_length_state : BlockTypeAndLengthState<AllocHC>,
150  pub distance_postfix_bits : u32,
151  pub num_direct_distance_codes : u32,
152  pub distance_postfix_mask : i32,
153  pub num_dist_htrees : u32,
154  pub dist_context_map : AllocU8::AllocatedMemory,
155  // NOT NEEDED? the index below seems to supersede it pub literal_htree : AllocHC::AllocatedMemory,
156  pub literal_htree_index : u8,
157  pub dist_htree_index : u8,
158  pub repeat_code_len : u32,
159  pub prev_code_len : u32,
160
161
162  pub copy_length : i32,
163  pub distance_code : i32,
164
165  /* For partial write operations */
166  pub rb_roundtrips : usize,  /* How many times we went around the ringbuffer */
167  pub partial_pos_out : usize,  /* How much output to the user in total (<= rb) */
168
169  /* For ReadHuffmanCode */
170  pub symbol : u32,
171  pub repeat : u32,
172  pub space : u32,
173
174  pub table : [HuffmanCode;32],
175  /* List of of symbol chains. */
176  pub symbol_lists_index : usize, // AllocU16::AllocatedMemory,
177  /* Storage from symbol_lists. */
178  pub symbols_lists_array : [u16; BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
179                              BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
180  /* Tails of symbol chains. */
181  pub next_symbol: [i32; 32],
182  pub code_length_code_lengths : [u8;18],
183  /* Population counts for the code lengths */
184  pub code_length_histo : [u16;16],
185
186  /* For HuffmanTreeGroupDecode */
187  pub htree_index : i32,
188  pub htree_next_offset : u32,
189
190  /* For DecodeContextMap */
191  pub context_index : u32,
192  pub max_run_length_prefix : u32,
193  pub code : u32,
194  /* always pre-allocated on state creation*/
195  pub context_map_table : AllocHC::AllocatedMemory,
196
197  /* For InverseMoveToFrontTransform */
198  pub mtf_upper_bound : u32,
199  pub mtf : [u8; 256],
200
201  /* For custom dictionaries */
202  pub custom_dict : AllocU8::AllocatedMemory,
203  pub custom_dict_size : i32,
204  /* less used attributes are in the end of this struct */
205  /* States inside function calls */
206  pub substate_metablock_header : BrotliRunningMetablockHeaderState,
207  pub substate_tree_group : BrotliRunningTreeGroupState,
208  pub substate_context_map : BrotliRunningContextMapState,
209  pub substate_uncompressed : BrotliRunningUncompressedState,
210  pub substate_huffman : BrotliRunningHuffmanState,
211  pub substate_decode_uint8 : BrotliRunningDecodeUint8State,
212
213  pub is_last_metablock : u8,
214  pub is_uncompressed : u8,
215  pub is_metadata : u8,
216  pub size_nibbles : u8,
217  pub window_bits : u32,
218
219  pub num_literal_htrees : u32,
220  pub context_map : AllocU8::AllocatedMemory, //[u8; max_num_block_types << kLiteralContextBits],
221  pub context_modes : AllocU8::AllocatedMemory,// [u8; max_num_block_types], // max number of block types is 255
222
223}
224
225impl <'brotli_state,
226      AllocU8 : alloc::Allocator<u8>,
227      AllocU32 : alloc::Allocator<u32>,
228      AllocHC : alloc::Allocator<HuffmanCode> > BrotliState<AllocU8, AllocU32, AllocHC> {
229    pub fn new(alloc_u8 : AllocU8,
230           alloc_u32 : AllocU32,
231           alloc_hc : AllocHC) -> Self{
232        let mut retval = BrotliState::<AllocU8, AllocU32, AllocHC>{
233            state : BrotliRunningState::BROTLI_STATE_UNINITED,
234            loop_counter : 0,
235            br : BrotliBitReader::default(),
236            alloc_u8 : alloc_u8,
237            alloc_u32 : alloc_u32,
238            alloc_hc : alloc_hc,
239            buffer : [0u8; 8],
240            buffer_length : 0,
241            pos : 0,
242            max_backward_distance : 0,
243            max_backward_distance_minus_custom_dict_size : 0,
244            max_distance : 0,
245            ringbuffer_size : 0,
246            ringbuffer_mask: 0,
247            dist_rb_idx : 0,
248            dist_rb : [16, 15, 11, 4],
249            ringbuffer : AllocU8::AllocatedMemory::default(),
250            htree_command_index : 0,
251            context_lookup1 : &[],
252            context_lookup2 : &[],
253            context_map_slice_index : 0,
254            dist_context_map_slice_index : 0,
255            sub_loop_counter : 0,
256
257            literal_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
258            insert_copy_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
259            distance_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
260            trivial_literal_context : 0,
261            distance_context : 0,
262            meta_block_remaining_len : 0,
263            block_type_length_state : BlockTypeAndLengthState::<AllocHC> {
264              block_length_index : 0,
265              block_length : [0; 3],
266              num_block_types : [0;3],
267              block_type_rb: [0;6],
268              substate_read_block_length : BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
269              block_type_trees : AllocHC::AllocatedMemory::default(),
270              block_len_trees : AllocHC::AllocatedMemory::default(),
271            },
272            distance_postfix_bits : 0,
273            num_direct_distance_codes : 0,
274            distance_postfix_mask : 0,
275            num_dist_htrees : 0,
276            dist_context_map : AllocU8::AllocatedMemory::default(),
277            //// not needed literal_htree : AllocHC::AllocatedMemory::default(),
278            literal_htree_index : 0,
279            dist_htree_index : 0,
280            repeat_code_len : 0,
281            prev_code_len : 0,
282            copy_length : 0,
283            distance_code : 0,
284            rb_roundtrips : 0,  /* How many times we went around the ringbuffer */
285            partial_pos_out : 0,  /* How much output to the user in total (<= rb) */
286            symbol : 0,
287            repeat : 0,
288            space : 0,
289            table : [HuffmanCode::default(); 32],
290            //symbol_lists: AllocU16::AllocatedMemory::default(),
291            symbol_lists_index : BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1,
292            symbols_lists_array : [0;BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
293                              BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
294            next_symbol : [0; 32],
295            code_length_code_lengths : [0; 18],
296            code_length_histo : [0; 16],
297            htree_index : 0,
298            htree_next_offset : 0,
299
300            /* For DecodeContextMap */
301           context_index : 0,
302           max_run_length_prefix : 0,
303           code : 0,
304           context_map_table : AllocHC::AllocatedMemory::default(),
305
306           /* For InverseMoveToFrontTransform */
307           mtf_upper_bound : 255,
308           mtf : [0; 256],
309
310           /* For custom dictionaries */
311           custom_dict : AllocU8::AllocatedMemory::default(),
312           custom_dict_size : 0,
313
314           /* less used attributes are in the end of this struct */
315           /* States inside function calls */
316           substate_metablock_header : BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE,
317           substate_tree_group : BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE,
318           substate_context_map : BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE,
319           substate_uncompressed : BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE,
320           substate_huffman : BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE,
321           substate_decode_uint8 : BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE,
322
323           is_last_metablock : 0,
324           is_uncompressed : 0,
325           is_metadata : 0,
326           size_nibbles : 0,
327           window_bits : 0,
328
329           num_literal_htrees : 0,
330           context_map : AllocU8::AllocatedMemory::default(),//[0; max_num_block_types << kLiteralContextBits],
331           context_modes : AllocU8::AllocatedMemory::default(),//[0; max_num_block_types], // max number of block types is 255
332        };
333        retval.context_map_table = retval.alloc_hc.alloc_cell(BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
334        BrotliInitBitReader(&mut retval.br);
335        return retval;
336    }
337    pub fn BrotliStateMetablockBegin(self : &mut Self) {
338        self.meta_block_remaining_len = 0;
339        self.block_type_length_state.block_length[0] = 1u32 << 28;
340        self.block_type_length_state.block_length[1] = 1u32 << 28;
341        self.block_type_length_state.block_length[2] = 1u32 << 28;
342        self.block_type_length_state.num_block_types[0] = 1;
343        self.block_type_length_state.num_block_types[1] = 1;
344        self.block_type_length_state.num_block_types[2] = 1;
345        self.block_type_length_state.block_type_rb[0] = 1;
346        self.block_type_length_state.block_type_rb[1] = 0;
347        self.block_type_length_state.block_type_rb[2] = 1;
348        self.block_type_length_state.block_type_rb[3] = 0;
349        self.block_type_length_state.block_type_rb[4] = 1;
350        self.block_type_length_state.block_type_rb[5] = 0;
351        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
352                                             AllocU8::AllocatedMemory::default()));
353        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
354                                             AllocU8::AllocatedMemory::default()));
355        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
356                                             AllocU8::AllocatedMemory::default()));
357        self.context_map_slice_index = 0;
358        self.literal_htree_index = 0;
359        self.dist_context_map_slice_index = 0;
360        self.dist_htree_index = 0;
361        self.context_lookup1 = &[];
362        self.context_lookup2 = &[];
363        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
364        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
365        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
366    }
367    pub fn BrotliStateCleanupAfterMetablock(self : &mut Self) {
368        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
369                                             AllocU8::AllocatedMemory::default()));
370        self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
371                                             AllocU8::AllocatedMemory::default()));
372        self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
373                                             AllocU8::AllocatedMemory::default()));
374
375
376        self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
377        self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
378        self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
379    }
380
381   pub fn BrotliStateCleanup(self : &mut Self) {
382      self.BrotliStateCleanupAfterMetablock();
383      self.alloc_u8.free_cell(core::mem::replace(&mut self.ringbuffer,
384                              AllocU8::AllocatedMemory::default()));
385      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_type_trees,
386                              AllocHC::AllocatedMemory::default()));
387      self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_len_trees,
388                              AllocHC::AllocatedMemory::default()));
389      self.alloc_hc.free_cell(core::mem::replace(&mut self.context_map_table,
390                              AllocHC::AllocatedMemory::default()));
391
392      //FIXME??  BROTLI_FREE(s, s->legacy_input_buffer);
393      //FIXME??  BROTLI_FREE(s, s->legacy_output_buffer);
394    }
395
396    pub fn BrotliStateIsStreamStart(self : &Self) -> bool {
397        match self.state {
398            BrotliRunningState::BROTLI_STATE_UNINITED =>
399                return BrotliGetAvailableBits(&self.br) == 0,
400            _ => return false,
401        }
402    }
403
404    pub fn BrotliStateIsStreamEnd(self : &Self) -> bool {
405        match self.state {
406            BrotliRunningState::BROTLI_STATE_DONE => return true,
407            _ => return false,
408        }
409    }
410    pub fn BrotliHuffmanTreeGroupInit(self :&mut Self, group : WhichTreeGroup,
411                                      alphabet_size : u16, ntrees : u16) {
412        match group {
413            WhichTreeGroup::LITERAL => self.literal_hgroup.init(&mut self.alloc_u32,
414                                                                &mut self.alloc_hc,
415                                                                alphabet_size, ntrees),
416            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.init(&mut self.alloc_u32,
417                                                                        &mut self.alloc_hc,
418                                                                        alphabet_size, ntrees),
419            WhichTreeGroup::DISTANCE => self.distance_hgroup.init(&mut self.alloc_u32,
420                                                                  &mut self.alloc_hc,
421                                                                  alphabet_size, ntrees),
422        }
423    }
424    pub fn BrotliHuffmanTreeGroupRelease(self :&mut Self, group : WhichTreeGroup) {
425        match group {
426            WhichTreeGroup::LITERAL => self.literal_hgroup.reset(&mut self.alloc_u32,
427                                                                 &mut self.alloc_hc),
428            WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.reset(&mut self.alloc_u32,
429                                                                         &mut self.alloc_hc),
430            WhichTreeGroup::DISTANCE => self.distance_hgroup.reset(&mut self.alloc_u32,
431                                                                   &mut self.alloc_hc),
432        }
433    }
434}