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;
13use alloc::SliceWrapperMut;
14use shared_dictionary;
15use shared_dictionary::{BrotliSharedDictionary, TRANSFORM_LIST_STRIDE, WORD_LIST_STRIDE};
16
17#[allow(dead_code)]
18pub enum WhichTreeGroup {
19 LITERAL,
20 INSERT_COPY,
21 DISTANCE,
22}
23#[repr(C)]
24#[derive(Clone,Copy, Debug)]
25pub enum BrotliDecoderErrorCode{
26 BROTLI_DECODER_NO_ERROR = 0,
27 BROTLI_DECODER_SUCCESS = 1,
29 BROTLI_DECODER_NEEDS_MORE_INPUT = 2,
30 BROTLI_DECODER_NEEDS_MORE_OUTPUT = 3,
31
32 BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE = -1,
34 BROTLI_DECODER_ERROR_FORMAT_RESERVED = -2,
35 BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE = -3,
36 BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET = -4,
37 BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME = -5,
38 BROTLI_DECODER_ERROR_FORMAT_CL_SPACE = -6,
39 BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE = -7,
40 BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT = -8,
41 BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 = -9,
42 BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 = -10,
43 BROTLI_DECODER_ERROR_FORMAT_TRANSFORM = -11,
44 BROTLI_DECODER_ERROR_FORMAT_DICTIONARY = -12,
45 BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS = -13,
46 BROTLI_DECODER_ERROR_FORMAT_PADDING_1 = -14,
47 BROTLI_DECODER_ERROR_FORMAT_PADDING_2 = -15,
48 BROTLI_DECODER_ERROR_FORMAT_DISTANCE = -16,
49
50 BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY = -18,
53 BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET = -19,
54 BROTLI_DECODER_ERROR_INVALID_ARGUMENTS = -20,
55
56 BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES = -21,
58 BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS = -22,
60 BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP = -25,
62 BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 = -26,
63 BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 = -27,
64 BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES = -30,
66
67 BROTLI_DECODER_ERROR_UNREACHABLE = -31,
69}
70
71#[derive(Debug)]
72pub enum BrotliRunningState {
73 BROTLI_STATE_UNINITED,
74 BROTLI_STATE_LARGE_WINDOW_BITS,
75 BROTLI_STATE_INITIALIZE,
76 BROTLI_STATE_METABLOCK_BEGIN,
77 BROTLI_STATE_METABLOCK_HEADER,
78 BROTLI_STATE_METABLOCK_HEADER_2,
79 BROTLI_STATE_CONTEXT_MODES,
80 BROTLI_STATE_COMMAND_BEGIN,
81 BROTLI_STATE_COMMAND_INNER,
82 BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
83 BROTLI_STATE_COMMAND_POST_WRAP_COPY,
84 BROTLI_STATE_UNCOMPRESSED,
85 BROTLI_STATE_METADATA,
86 BROTLI_STATE_COMMAND_INNER_WRITE,
87 BROTLI_STATE_METABLOCK_DONE,
88 BROTLI_STATE_COMMAND_POST_WRITE_1,
89 BROTLI_STATE_COMMAND_POST_WRITE_2,
90 BROTLI_STATE_HUFFMAN_CODE_0,
91 BROTLI_STATE_HUFFMAN_CODE_1,
92 BROTLI_STATE_HUFFMAN_CODE_2,
93 BROTLI_STATE_HUFFMAN_CODE_3,
94 BROTLI_STATE_CONTEXT_MAP_1,
95 BROTLI_STATE_CONTEXT_MAP_2,
96 BROTLI_STATE_TREE_GROUP,
97 BROTLI_STATE_DONE,
98}
99
100pub enum BrotliRunningMetablockHeaderState {
101 BROTLI_STATE_METABLOCK_HEADER_NONE,
102 BROTLI_STATE_METABLOCK_HEADER_EMPTY,
103 BROTLI_STATE_METABLOCK_HEADER_NIBBLES,
104 BROTLI_STATE_METABLOCK_HEADER_SIZE,
105 BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,
106 BROTLI_STATE_METABLOCK_HEADER_RESERVED,
107 BROTLI_STATE_METABLOCK_HEADER_BYTES,
108 BROTLI_STATE_METABLOCK_HEADER_METADATA,
109}
110pub enum BrotliRunningUncompressedState {
111 BROTLI_STATE_UNCOMPRESSED_NONE,
112 BROTLI_STATE_UNCOMPRESSED_WRITE,
113}
114
115pub enum BrotliRunningTreeGroupState {
116 BROTLI_STATE_TREE_GROUP_NONE,
117 BROTLI_STATE_TREE_GROUP_LOOP,
118}
119
120pub enum BrotliRunningContextMapState {
121 BROTLI_STATE_CONTEXT_MAP_NONE,
122 BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
123 BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
124 BROTLI_STATE_CONTEXT_MAP_DECODE,
125 BROTLI_STATE_CONTEXT_MAP_TRANSFORM,
126}
127
128pub enum BrotliRunningHuffmanState {
129 BROTLI_STATE_HUFFMAN_NONE,
130 BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
131 BROTLI_STATE_HUFFMAN_SIMPLE_READ,
132 BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
133 BROTLI_STATE_HUFFMAN_COMPLEX,
134 BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS,
135}
136
137pub enum BrotliRunningDecodeUint8State {
138 BROTLI_STATE_DECODE_UINT8_NONE,
139 BROTLI_STATE_DECODE_UINT8_SHORT,
140 BROTLI_STATE_DECODE_UINT8_LONG,
141}
142
143pub enum BrotliRunningReadBlockLengthState {
144 BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
145 BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX,
146}
147
148pub const kLiteralContextBits: usize = 6;
149
150pub const SHARED_BROTLI_MAX_COMPOUND_DICTS: usize = 15;
154#[cfg(target_pointer_width = "64")]
157pub const SHARED_BROTLI_MAX_RAW_DICT_SIZE: usize = 1usize << 31;
158#[cfg(not(target_pointer_width = "64"))]
159pub const SHARED_BROTLI_MAX_RAW_DICT_SIZE: usize = 1usize << 27;
160
161#[allow(dead_code)]
172pub enum MaybeOwnedSlice<AllocU8: alloc::Allocator<u8>> {
173 Owned(AllocU8::AllocatedMemory),
174 Borrowed(&'static [u8]),
179}
180
181impl<AllocU8: alloc::Allocator<u8>> Default for MaybeOwnedSlice<AllocU8> {
182 fn default() -> Self {
183 MaybeOwnedSlice::Owned(AllocU8::AllocatedMemory::default())
184 }
185}
186
187impl<AllocU8: alloc::Allocator<u8>> alloc::SliceWrapper<u8> for MaybeOwnedSlice<AllocU8> {
188 fn slice(&self) -> &[u8] {
189 match *self {
190 MaybeOwnedSlice::Owned(ref mem) => mem.slice(),
191 MaybeOwnedSlice::Borrowed(data) => data,
192 }
193 }
194}
195
196pub const COMPOUND_DICTIONARY_BLOCK_MAP_UNINITIALIZED: u32 = 255;
203
204pub struct BrotliDecoderCompoundDictionary<AllocU8: alloc::Allocator<u8>> {
210 pub num_chunks: usize,
211 pub total_size: usize,
212 pub block_bits: u32,
216 pub block_map: [u8; 256],
217 pub chunk_offsets: [u32; SHARED_BROTLI_MAX_COMPOUND_DICTS + 1],
220 pub chunks: [MaybeOwnedSlice<AllocU8>; SHARED_BROTLI_MAX_COMPOUND_DICTS],
221 pub br_index: usize,
224 pub br_offset: usize,
225 pub br_length: usize,
226 pub br_copied: usize,
227}
228
229impl<AllocU8: alloc::Allocator<u8>> Default for BrotliDecoderCompoundDictionary<AllocU8> {
230 fn default() -> Self {
231 BrotliDecoderCompoundDictionary::<AllocU8> {
232 num_chunks: 0,
233 total_size: 0,
234 block_bits: COMPOUND_DICTIONARY_BLOCK_MAP_UNINITIALIZED,
235 block_map: [0; 256],
236 chunk_offsets: [0; SHARED_BROTLI_MAX_COMPOUND_DICTS + 1],
237 chunks: Default::default(),
238 br_index: 0,
239 br_offset: 0,
240 br_length: 0,
241 br_copied: 0,
242 }
243 }
244}
245
246pub struct BlockTypeAndLengthState<AllocHC: alloc::Allocator<HuffmanCode>> {
247 pub substate_read_block_length: BrotliRunningReadBlockLengthState,
248 pub num_block_types: [u32; 3],
249 pub block_length_index: u32,
250 pub block_length: [u32; 3],
251 pub block_type_trees: AllocHC::AllocatedMemory,
252 pub block_len_trees: AllocHC::AllocatedMemory,
253 pub block_type_rb: [u32; 6],
254}
255
256pub struct BrotliState<AllocU8: alloc::Allocator<u8>,
257 AllocU32: alloc::Allocator<u32>,
258 AllocHC: alloc::Allocator<HuffmanCode>>
259{
260 pub state: BrotliRunningState,
261
262 pub loop_counter: i32,
264 pub br: BrotliBitReader,
265 pub alloc_u8: AllocU8,
266 pub alloc_u32: AllocU32,
267 pub alloc_hc: AllocHC,
268 pub buffer: [u8; 8],
270 pub buffer_length: u32,
271 pub pos: i32,
272 pub max_backward_distance: i32,
273 pub max_distance: i32,
274 pub ringbuffer_size: i32,
275 pub ringbuffer_mask: i32,
276 pub dist_rb_idx: i32,
277 pub dist_rb: [i32; 4],
278 pub ringbuffer: AllocU8::AllocatedMemory,
279 pub htree_command_index: u16,
281 pub context_lookup: &'static [u8;512],
282 pub context_map_slice_index: usize,
283 pub dist_context_map_slice_index: usize,
284
285 pub sub_loop_counter: u32,
286
287 pub literal_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
290 pub insert_copy_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
291 pub distance_hgroup: HuffmanTreeGroup<AllocU32, AllocHC>,
292 pub trivial_literal_context: i32,
295 pub distance_context: i32,
298 pub meta_block_remaining_len: i32,
299 pub block_type_length_state: BlockTypeAndLengthState<AllocHC>,
300 pub distance_postfix_bits: u32,
301 pub num_direct_distance_codes: u32,
302 pub distance_postfix_mask: i32,
303 pub num_dist_htrees: u32,
304 pub dist_context_map: AllocU8::AllocatedMemory,
305 pub literal_htree_index: u8,
307 pub dist_htree_index: u8,
308 pub large_window: bool,
309 pub(crate) canny_ringbuffer_allocation: bool,
310 pub should_wrap_ringbuffer: bool,
311 pub error_code: BrotliDecoderErrorCode,
312 pub repeat_code_len: u32,
313 pub prev_code_len: u32,
314
315 pub copy_length: i32,
316 pub distance_code: i32,
317
318 pub rb_roundtrips: u64, pub partial_pos_out: u64, pub symbol: u32,
326 pub repeat: u32,
327 pub space: u32,
328
329 pub table: [HuffmanCode; 32],
330 pub symbol_lists_index: usize, pub symbols_lists_array: [u16; BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
334 BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
335 pub next_symbol: [i32; 32],
337 pub code_length_code_lengths: [u8; 18],
338 pub code_length_histo: [u16; 16],
340
341 pub htree_index: i32,
343 pub htree_next_offset: u32,
344
345 pub context_index: u32,
347 pub max_run_length_prefix: u32,
348 pub code: u32,
349 pub context_map_table: AllocHC::AllocatedMemory,
351
352 pub mtf_upper_bound: u32,
354 pub mtf_or_error_string: Result<[u8; 256], [u8; 256]>,
355
356 pub custom_dict: AllocU8::AllocatedMemory,
358 pub compound_dictionary: BrotliDecoderCompoundDictionary<AllocU8>,
359 pub dictionary: BrotliSharedDictionary<AllocU8, AllocU32>,
362 pub substate_metablock_header: BrotliRunningMetablockHeaderState,
365 pub substate_tree_group: BrotliRunningTreeGroupState,
366 pub substate_context_map: BrotliRunningContextMapState,
367 pub substate_uncompressed: BrotliRunningUncompressedState,
368 pub substate_huffman: BrotliRunningHuffmanState,
369 pub substate_decode_uint8: BrotliRunningDecodeUint8State,
370
371 pub is_last_metablock: u8,
372 pub is_uncompressed: u8,
373 pub is_metadata: u8,
374 pub size_nibbles: u8,
375 pub window_bits: u32,
376
377 pub num_literal_htrees: u32,
378 pub context_map: AllocU8::AllocatedMemory,
379 pub context_modes: AllocU8::AllocatedMemory,
380 pub trivial_literal_contexts: [u32; 8],
381}
382macro_rules! make_brotli_state {
383 ($alloc_u8 : expr, $alloc_u32 : expr, $alloc_hc : expr, $custom_dict : expr) => (BrotliState::<AllocU8, AllocU32, AllocHC>{
384 state : BrotliRunningState::BROTLI_STATE_UNINITED,
385 loop_counter : 0,
386 br : BrotliBitReader::default(),
387 alloc_u8 : $alloc_u8,
388 alloc_u32 : $alloc_u32,
389 alloc_hc : $alloc_hc,
390 buffer : [0u8; 8],
391 buffer_length : 0,
392 pos : 0,
393 max_backward_distance : 0,
394 max_distance : 0,
395 ringbuffer_size : 0,
396 ringbuffer_mask: 0,
397 dist_rb_idx : 0,
398 dist_rb : [16, 15, 11, 4],
399 ringbuffer : AllocU8::AllocatedMemory::default(),
400 htree_command_index : 0,
401 context_lookup : &kContextLookup[0],
402 context_map_slice_index : 0,
403 dist_context_map_slice_index : 0,
404 sub_loop_counter : 0,
405
406 literal_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
407 insert_copy_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
408 distance_hgroup : HuffmanTreeGroup::<AllocU32, AllocHC>::default(),
409 trivial_literal_context : 0,
410 distance_context : 0,
411 meta_block_remaining_len : 0,
412 block_type_length_state : BlockTypeAndLengthState::<AllocHC> {
413 block_length_index : 0,
414 block_length : [0; 3],
415 num_block_types : [0;3],
416 block_type_rb: [0;6],
417 substate_read_block_length : BrotliRunningReadBlockLengthState::BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
418 block_type_trees : AllocHC::AllocatedMemory::default(),
419 block_len_trees : AllocHC::AllocatedMemory::default(),
420 },
421 distance_postfix_bits : 0,
422 num_direct_distance_codes : 0,
423 distance_postfix_mask : 0,
424 num_dist_htrees : 0,
425 dist_context_map : AllocU8::AllocatedMemory::default(),
426 literal_htree_index : 0,
428 dist_htree_index : 0,
429 repeat_code_len : 0,
430 prev_code_len : 0,
431 copy_length : 0,
432 distance_code : 0,
433 rb_roundtrips : 0, partial_pos_out : 0, symbol : 0,
436 repeat : 0,
437 space : 0,
438 table : [HuffmanCode::default(); 32],
439 symbol_lists_index : BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1,
441 symbols_lists_array : [0;BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
442 BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE],
443 next_symbol : [0; 32],
444 code_length_code_lengths : [0; 18],
445 code_length_histo : [0; 16],
446 htree_index : 0,
447 htree_next_offset : 0,
448
449 context_index : 0,
451 max_run_length_prefix : 0,
452 code : 0,
453 context_map_table : AllocHC::AllocatedMemory::default(),
454
455 mtf_upper_bound : 255,
457 mtf_or_error_string : Ok([0; 256]),
458
459 custom_dict : $custom_dict,
461 compound_dictionary : BrotliDecoderCompoundDictionary::default(),
462 dictionary : BrotliSharedDictionary::default(),
463 substate_metablock_header : BrotliRunningMetablockHeaderState::BROTLI_STATE_METABLOCK_HEADER_NONE,
466 substate_tree_group : BrotliRunningTreeGroupState::BROTLI_STATE_TREE_GROUP_NONE,
467 substate_context_map : BrotliRunningContextMapState::BROTLI_STATE_CONTEXT_MAP_NONE,
468 substate_uncompressed : BrotliRunningUncompressedState::BROTLI_STATE_UNCOMPRESSED_NONE,
469 substate_huffman : BrotliRunningHuffmanState::BROTLI_STATE_HUFFMAN_NONE,
470 substate_decode_uint8 : BrotliRunningDecodeUint8State::BROTLI_STATE_DECODE_UINT8_NONE,
471
472 is_last_metablock : 0,
473 is_uncompressed : 0,
474 is_metadata : 0,
475 size_nibbles : 0,
476 window_bits : 0,
477 large_window: false,
478 canny_ringbuffer_allocation: true,
479 should_wrap_ringbuffer: false,
480 error_code: BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS,
481 num_literal_htrees : 0,
482 context_map : AllocU8::AllocatedMemory::default(),
483 context_modes : AllocU8::AllocatedMemory::default(),
484 trivial_literal_contexts : [0u32; 8],
485 }
486 );
487}
488impl <'brotli_state,
489 AllocU8 : alloc::Allocator<u8>,
490 AllocU32 : alloc::Allocator<u32>,
491 AllocHC : alloc::Allocator<HuffmanCode> > BrotliState<AllocU8, AllocU32, AllocHC> {
492 pub fn new(alloc_u8 : AllocU8,
493 alloc_u32 : AllocU32,
494 alloc_hc : AllocHC) -> Self{
495 let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default());
496 retval.large_window = true;
497 retval.context_map_table = retval.alloc_hc.alloc_cell(
498 BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
499 BrotliInitBitReader(&mut retval.br);
500 retval
501 }
502 pub fn new_with_custom_dictionary(alloc_u8 : AllocU8,
503 alloc_u32 : AllocU32,
504 alloc_hc : AllocHC,
505 custom_dict: AllocU8::AllocatedMemory) -> Self{
506 let custom_dict_len = custom_dict.slice().len();
507 let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, custom_dict);
508 retval.context_map_table = retval.alloc_hc.alloc_cell(
509 BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
510 retval.large_window = true;
511 BrotliInitBitReader(&mut retval.br);
512 if custom_dict_len != 0 && custom_dict_len <= SHARED_BROTLI_MAX_RAW_DICT_SIZE {
516 let dict = core::mem::replace(&mut retval.custom_dict,
517 AllocU8::AllocatedMemory::default());
518 let attached = retval.attach_compound_dictionary_chunk(MaybeOwnedSlice::Owned(dict));
522 debug_assert!(attached);
523 }
524 retval
525 }
526 pub fn new_strict(alloc_u8 : AllocU8,
527 alloc_u32 : AllocU32,
528 alloc_hc : AllocHC) -> Self{
529 let mut retval = make_brotli_state!(alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default());
530 retval.context_map_table = retval.alloc_hc.alloc_cell(
531 BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize);
532 retval.large_window = false;
533 BrotliInitBitReader(&mut retval.br);
534 retval
535 }
536 pub fn attach_dictionary(self : &mut Self,
543 dict: AllocU8::AllocatedMemory) -> bool {
544 self.attach_dictionary_chunk(MaybeOwnedSlice::Owned(dict))
545 }
546 pub fn attach_dictionary_borrowed(self : &mut Self, dict: &'static [u8]) -> bool {
555 self.attach_dictionary_chunk(MaybeOwnedSlice::Borrowed(dict))
556 }
557 fn attach_dictionary_chunk(self : &mut Self,
558 dict: MaybeOwnedSlice<AllocU8>) -> bool {
559 match self.state {
560 BrotliRunningState::BROTLI_STATE_UNINITED => {},
561 _ => {
562 self.free_chunk(dict);
563 return false;
564 },
565 }
566 self.attach_compound_dictionary_chunk(dict)
567 }
568 pub fn attach_serialized_dictionary(self : &mut Self,
577 dict_data: AllocU8::AllocatedMemory) -> bool {
578 self.attach_serialized_dictionary_chunk(MaybeOwnedSlice::Owned(dict_data))
579 }
580 pub fn attach_serialized_dictionary_borrowed(self : &mut Self,
586 dict_data: &'static [u8]) -> bool {
587 self.attach_serialized_dictionary_chunk(MaybeOwnedSlice::Borrowed(dict_data))
588 }
589 fn attach_serialized_dictionary_chunk(self : &mut Self,
590 dict_data: MaybeOwnedSlice<AllocU8>) -> bool {
591 match self.state {
592 BrotliRunningState::BROTLI_STATE_UNINITED => {},
593 _ => {
594 self.free_chunk(dict_data);
595 return false;
596 },
597 }
598 let summary = match shared_dictionary::dry_parse_serialized_dictionary(
599 dict_data.slice()) {
600 Ok(summary) => summary,
601 Err(()) => {
602 self.free_chunk(dict_data);
603 return false;
604 },
605 };
606 let is_custom = summary.num_word_lists != 0 || summary.num_transform_lists != 0;
607 if is_custom && self.dictionary.is_custom() {
610 self.free_chunk(dict_data);
611 return false;
612 }
613 let borrowed_blob: Option<&'static [u8]> = match dict_data {
617 MaybeOwnedSlice::Borrowed(data) => Some(data),
618 MaybeOwnedSlice::Owned(_) => None,
619 };
620 let mut parsed = BrotliSharedDictionary::<AllocU8, AllocU32>::default();
621 if is_custom {
622 let arena_size = summary.num_word_lists as usize * WORD_LIST_STRIDE +
623 summary.num_transform_lists as usize * TRANSFORM_LIST_STRIDE;
624 parsed.meta = self.alloc_u32.alloc_cell(arena_size);
625 if parsed.meta.slice().len() != arena_size ||
626 shared_dictionary::parse_serialized_dictionary_into(
627 dict_data.slice(), &summary, &mut parsed).is_err() {
628 self.alloc_u32.free_cell(core::mem::replace(&mut parsed.meta,
629 AllocU32::AllocatedMemory::default()));
630 self.free_chunk(dict_data);
631 return false;
632 }
633 }
634 if let Some((prefix_offset, prefix_len)) = summary.prefix {
635 let chunk = match borrowed_blob {
636 Some(blob) => MaybeOwnedSlice::Borrowed(
637 &blob[prefix_offset..prefix_offset + prefix_len]),
638 None => {
643 let mut chunk = self.alloc_u8.alloc_cell(prefix_len);
644 if chunk.slice().len() != prefix_len {
645 self.alloc_u8.free_cell(chunk);
646 self.alloc_u32.free_cell(core::mem::replace(&mut parsed.meta,
647 AllocU32::AllocatedMemory::default()));
648 self.free_chunk(dict_data);
649 return false;
650 }
651 chunk.slice_mut().clone_from_slice(
652 &dict_data.slice()[prefix_offset..prefix_offset + prefix_len]);
653 MaybeOwnedSlice::Owned(chunk)
654 },
655 };
656 if !self.attach_compound_dictionary_chunk(chunk) {
657 self.alloc_u32.free_cell(core::mem::replace(&mut parsed.meta,
658 AllocU32::AllocatedMemory::default()));
659 self.free_chunk(dict_data);
660 return false;
661 }
662 }
663 if is_custom {
664 parsed.blob = dict_data;
665 let old = core::mem::replace(&mut self.dictionary, parsed);
666 self.free_chunk(old.blob);
667 self.alloc_u32.free_cell(old.meta);
668 } else {
669 self.free_chunk(dict_data);
672 }
673 true
674 }
675 pub(crate) fn free_chunk(self : &mut Self, chunk: MaybeOwnedSlice<AllocU8>) {
682 if let MaybeOwnedSlice::Owned(mem) = chunk {
683 self.alloc_u8.free_cell(mem);
684 }
685 }
686 pub(crate) fn attach_compound_dictionary_chunk(self : &mut Self,
687 chunk: MaybeOwnedSlice<AllocU8>) -> bool {
688 let size = chunk.slice().len();
689 if size == 0 {
691 self.free_chunk(chunk);
692 return true;
693 }
694 let addon = &mut self.compound_dictionary;
695 if addon.num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS ||
696 size > SHARED_BROTLI_MAX_RAW_DICT_SIZE - addon.total_size {
697 self.free_chunk(chunk);
698 return false;
699 }
700 addon.chunks[addon.num_chunks] = chunk;
701 addon.num_chunks += 1;
702 addon.total_size += size;
703 addon.chunk_offsets[addon.num_chunks] = addon.total_size as u32;
704 addon.block_bits = COMPOUND_DICTIONARY_BLOCK_MAP_UNINITIALIZED;
706 true
707 }
708 pub fn BrotliStateMetablockBegin(self : &mut Self) {
709 self.meta_block_remaining_len = 0;
710 self.block_type_length_state.block_length[0] = 1u32 << 24;
711 self.block_type_length_state.block_length[1] = 1u32 << 24;
712 self.block_type_length_state.block_length[2] = 1u32 << 24;
713 self.block_type_length_state.num_block_types[0] = 1;
714 self.block_type_length_state.num_block_types[1] = 1;
715 self.block_type_length_state.num_block_types[2] = 1;
716 self.block_type_length_state.block_type_rb[0] = 1;
717 self.block_type_length_state.block_type_rb[1] = 0;
718 self.block_type_length_state.block_type_rb[2] = 1;
719 self.block_type_length_state.block_type_rb[3] = 0;
720 self.block_type_length_state.block_type_rb[4] = 1;
721 self.block_type_length_state.block_type_rb[5] = 0;
722 self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
723 AllocU8::AllocatedMemory::default()));
724 self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
725 AllocU8::AllocatedMemory::default()));
726 self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
727 AllocU8::AllocatedMemory::default()));
728 self.context_map_slice_index = 0;
729 self.literal_htree_index = 0;
730 self.dist_context_map_slice_index = 0;
731 self.dist_htree_index = 0;
732 self.context_lookup = &kContextLookup[0];
733 self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
734 self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
735 self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
736 }
737 pub fn BrotliStateCleanupAfterMetablock(self : &mut Self) {
738 self.alloc_u8.free_cell(core::mem::replace(&mut self.context_map,
739 AllocU8::AllocatedMemory::default()));
740 self.alloc_u8.free_cell(core::mem::replace(&mut self.context_modes,
741 AllocU8::AllocatedMemory::default()));
742 self.alloc_u8.free_cell(core::mem::replace(&mut self.dist_context_map,
743 AllocU8::AllocatedMemory::default()));
744
745
746 self.literal_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
747 self.insert_copy_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
748 self.distance_hgroup.reset(&mut self.alloc_u32, &mut self.alloc_hc);
749 }
750
751 fn BrotliStateCleanup(self : &mut Self) {
752 self.BrotliStateCleanupAfterMetablock();
753 self.alloc_u8.free_cell(core::mem::replace(&mut self.ringbuffer,
754 AllocU8::AllocatedMemory::default()));
755 self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_type_trees,
756 AllocHC::AllocatedMemory::default()));
757 self.alloc_hc.free_cell(core::mem::replace(&mut self.block_type_length_state.block_len_trees,
758 AllocHC::AllocatedMemory::default()));
759 self.alloc_hc.free_cell(core::mem::replace(&mut self.context_map_table,
760 AllocHC::AllocatedMemory::default()));
761 self.alloc_u8.free_cell(core::mem::replace(&mut self.custom_dict,
762 AllocU8::AllocatedMemory::default()));
763 for chunk in self.compound_dictionary.chunks.iter_mut() {
764 if let MaybeOwnedSlice::Owned(mem) =
765 core::mem::replace(chunk, MaybeOwnedSlice::default()) {
766 self.alloc_u8.free_cell(mem);
767 }
768 }
769 self.compound_dictionary = BrotliDecoderCompoundDictionary::default();
770 if let MaybeOwnedSlice::Owned(mem) =
771 core::mem::replace(&mut self.dictionary.blob, MaybeOwnedSlice::default()) {
772 self.alloc_u8.free_cell(mem);
773 }
774 self.alloc_u32.free_cell(core::mem::replace(&mut self.dictionary.meta,
775 AllocU32::AllocatedMemory::default()));
776
777 }
780
781 pub fn BrotliStateIsStreamStart(self : &Self) -> bool {
782 match self.state {
783 BrotliRunningState::BROTLI_STATE_UNINITED =>
784 BrotliGetAvailableBits(&self.br) == 0,
785 _ => false,
786 }
787 }
788
789 pub fn BrotliStateIsStreamEnd(self : &Self) -> bool {
790 match self.state {
791 BrotliRunningState::BROTLI_STATE_DONE => true,
792 _ => false
793 }
794 }
795 pub fn BrotliHuffmanTreeGroupInit(self :&mut Self, group : WhichTreeGroup,
796 alphabet_size : u16, max_symbol: u16, ntrees : u16) {
797 match group {
798 WhichTreeGroup::LITERAL => self.literal_hgroup.init(&mut self.alloc_u32,
799 &mut self.alloc_hc,
800 alphabet_size, max_symbol, ntrees),
801 WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.init(&mut self.alloc_u32,
802 &mut self.alloc_hc,
803 alphabet_size, max_symbol, ntrees),
804 WhichTreeGroup::DISTANCE => self.distance_hgroup.init(&mut self.alloc_u32,
805 &mut self.alloc_hc,
806 alphabet_size, max_symbol, ntrees),
807 }
808 }
809 pub fn BrotliHuffmanTreeGroupRelease(self :&mut Self, group : WhichTreeGroup) {
810 match group {
811 WhichTreeGroup::LITERAL => self.literal_hgroup.reset(&mut self.alloc_u32,
812 &mut self.alloc_hc),
813 WhichTreeGroup::INSERT_COPY => self.insert_copy_hgroup.reset(&mut self.alloc_u32,
814 &mut self.alloc_hc),
815 WhichTreeGroup::DISTANCE => self.distance_hgroup.reset(&mut self.alloc_u32,
816 &mut self.alloc_hc),
817 }
818 }
819}
820
821impl <'brotli_state,
822 AllocU8 : alloc::Allocator<u8>,
823 AllocU32 : alloc::Allocator<u32>,
824 AllocHC : alloc::Allocator<HuffmanCode> > Drop for BrotliState<AllocU8, AllocU32, AllocHC> {
825 fn drop(&mut self) {
826 self.BrotliStateCleanup();
827 }
828}
829
830
831
832pub fn BrotliDecoderErrorStr(c: BrotliDecoderErrorCode) -> &'static str {
833 match c {
834 BrotliDecoderErrorCode::BROTLI_DECODER_NO_ERROR => "NO_ERROR\0",
835 BrotliDecoderErrorCode::BROTLI_DECODER_SUCCESS => "SUCCESS\0",
837 BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_INPUT => "NEEDS_MORE_INPUT\0",
838 BrotliDecoderErrorCode::BROTLI_DECODER_NEEDS_MORE_OUTPUT => "NEEDS_MORE_OUTPUT\0",
839
840 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE => "ERROR_FORMAT_EXUBERANT_NIBBLE\0",
842 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_RESERVED => "ERROR_FORMAT_RESERVED\0",
843 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE => "ERROR_FORMAT_EXUBERANT_META_NIBBLE\0",
844 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET => "ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET\0",
845 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME => "ERROR_FORMAT_SIMPLE_HUFFMAN_SAME\0",
846 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CL_SPACE => "ERROR_FORMAT_FL_SPACE\0",
847 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE => "ERROR_FORMAT_HUFFMAN_SPACE\0",
848 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT => "ERROR_FORMAT_CONTEXT_MAP_REPEAT\0",
849 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1 =>"ERROR_FORMAT_BLOCK_LENGTH_1\0",
850 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2 =>"ERROR_FORMAT_BLOCK_LENGTH_2\0",
851 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_TRANSFORM => "ERROR_FORMAT_TRANSFORM\0",
852 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DICTIONARY =>"ERROR_FORMAT_DICTIONARY\0",
853 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS =>"ERROR_FORMAT_WINDOW_BITS\0",
854 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_1 =>"ERROR_FORMAT_PADDING_1\0",
855 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_PADDING_2 =>"ERROR_FORMAT_PADDING_2\0",
856 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_FORMAT_DISTANCE =>"ERROR_FORMAT_DISTANCE\0",
857
858 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY => "ERROR_COMPOUND_DICTIONARY\0",
861 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET => "ERROR_DICTIONARY_NOT_SET\0",
862 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_INVALID_ARGUMENTS => "ERROR_INVALID_ARGUMENTS\0",
863
864 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES => "ERROR_ALLOC_CONTEXT_MODES\0",
866 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS => "ERROR_ALLOC_TREE_GROUPS\0",
868 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP => "ERROR_ALLOC_CONTEXT_MAP\0",
870 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1 => "ERROR_ALLOC_RING_BUFFER_1\0",
871 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2 => "ERROR_ALLOC_RING_BUFFER_2\0",
872 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES => "ERROR_ALLOC_BLOCK_TYPE_TREES\0",
874
875 BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_UNREACHABLE => "ERROR_UNREACHABLE\0",
877 }
878}