1use core::cmp::max;
9
10#[derive(Clone, Copy, Default)]
11pub struct HuffmanTree {
12 pub total_count_: u32,
13 pub index_left_: i16,
14 pub index_right_or_value_: i16,
15}
16
17impl HuffmanTree {
18 pub fn new(count: u32, left: i16, right: i16) -> Self {
19 Self {
20 total_count_: count,
21 index_left_: left,
22 index_right_or_value_: right,
23 }
24 }
25}
26
27pub fn BrotliSetDepth(p0: i32, pool: &mut [HuffmanTree], depth: &mut [u8], max_depth: i32) -> bool {
28 let mut stack: [i32; 16] = [0; 16];
29 let mut level: i32 = 0i32;
30 let mut p: i32 = p0;
31 stack[0] = -1i32;
32 loop {
33 if (pool[(p as usize)]).index_left_ as i32 >= 0i32 {
34 level += 1;
35 if level > max_depth {
36 return false;
37 }
38 stack[level as usize] = (pool[(p as usize)]).index_right_or_value_ as i32;
39 p = (pool[(p as usize)]).index_left_ as i32;
40 {
41 continue;
42 }
43 } else {
44 let pp = pool[(p as usize)];
45 depth[((pp).index_right_or_value_ as usize)] = level as u8;
46 }
47 while level >= 0i32 && (stack[level as usize] == -1i32) {
48 level -= 1;
49 }
50 if level < 0i32 {
51 return true;
52 }
53 p = stack[level as usize];
54 stack[level as usize] = -1i32;
55 }
56}
57
58pub trait HuffmanComparator {
59 fn Cmp(&self, a: &HuffmanTree, b: &HuffmanTree) -> bool;
60}
61pub struct SortHuffmanTree {}
62impl HuffmanComparator for SortHuffmanTree {
63 fn Cmp(&self, v0: &HuffmanTree, v1: &HuffmanTree) -> bool {
64 if v0.total_count_ != v1.total_count_ {
65 v0.total_count_ < v1.total_count_
66 } else {
67 v0.index_right_or_value_ > v1.index_right_or_value_
68 }
69 }
70}
71pub fn SortHuffmanTreeItems<Comparator: HuffmanComparator>(
72 items: &mut [HuffmanTree],
73 n: usize,
74 comparator: Comparator,
75) {
76 static gaps: [usize; 6] = [132, 57, 23, 10, 4, 1];
77 if n < 13 {
78 for i in 1..n {
79 let mut tmp: HuffmanTree = items[i];
80 let mut k: usize = i;
81 let mut j: usize = i.wrapping_sub(1);
82 while comparator.Cmp(&mut tmp, &mut items[j]) {
83 items[k] = items[j];
84 k = j;
85 if {
86 let _old = j;
87 j = j.wrapping_sub(1);
88 _old
89 } == 0
90 {
91 break;
92 }
93 }
94 items[k] = tmp;
95 }
96 } else {
97 let mut g: i32 = if n < 57usize { 2i32 } else { 0i32 };
98 while g < 6i32 {
99 {
100 let gap: usize = gaps[g as usize];
101 for i in gap..n {
102 let mut j: usize = i;
103 let mut tmp: HuffmanTree = items[i];
104 while j >= gap && (comparator.Cmp(&mut tmp, &mut items[j.wrapping_sub(gap)])) {
105 {
106 items[j] = items[j.wrapping_sub(gap)];
107 }
108 j = j.wrapping_sub(gap);
109 }
110 items[j] = tmp;
111 }
112 }
113 g += 1;
114 }
115 }
116}
117
118pub fn BrotliCreateHuffmanTree(
134 data: &[u32],
135 length: usize,
136 tree_limit: i32,
137 tree: &mut [HuffmanTree],
138 depth: &mut [u8],
139) {
140 let sentinel = HuffmanTree::new(u32::MAX, -1, -1);
141 let mut count_limit = 1u32;
142 'break1: loop {
143 {
144 let mut n: usize = 0usize;
145 let mut i: usize;
146 let mut j: usize;
147 let mut k: usize;
148 i = length;
149 while i != 0usize {
150 i = i.wrapping_sub(1);
151 if data[i] != 0 {
152 let count: u32 = max(data[i], count_limit);
153 tree[n] = HuffmanTree::new(count, -1, i as i16);
154 n = n.wrapping_add(1);
155 }
156 }
157 if n == 1 {
158 depth[((tree[0]).index_right_or_value_ as usize)] = 1u8;
159 {
160 break 'break1;
161 }
162 }
163 SortHuffmanTreeItems(tree, n, SortHuffmanTree {});
164 tree[n] = sentinel;
165 tree[n.wrapping_add(1)] = sentinel;
166 i = 0usize;
167 j = n.wrapping_add(1);
168 k = n.wrapping_sub(1);
169 while k != 0usize {
170 {
171 let left: usize;
172 let right: usize;
173 if (tree[i]).total_count_ <= (tree[j]).total_count_ {
174 left = i;
175 i = i.wrapping_add(1);
176 } else {
177 left = j;
178 j = j.wrapping_add(1);
179 }
180 if (tree[i]).total_count_ <= (tree[j]).total_count_ {
181 right = i;
182 i = i.wrapping_add(1);
183 } else {
184 right = j;
185 j = j.wrapping_add(1);
186 }
187 {
188 let j_end: usize = (2usize).wrapping_mul(n).wrapping_sub(k);
189 (tree[j_end]).total_count_ = (tree[left])
190 .total_count_
191 .wrapping_add((tree[right]).total_count_);
192 (tree[j_end]).index_left_ = left as i16;
193 (tree[j_end]).index_right_or_value_ = right as i16;
194 tree[j_end.wrapping_add(1)] = sentinel;
195 }
196 }
197 k = k.wrapping_sub(1);
198 }
199 if BrotliSetDepth(
200 (2usize).wrapping_mul(n).wrapping_sub(1) as i32,
201 tree,
202 depth,
203 tree_limit,
204 ) {
205 break 'break1;
206 }
207 }
208 count_limit = count_limit.wrapping_mul(2);
209 }
210}
211pub fn BrotliOptimizeHuffmanCountsForRle(
212 mut length: usize,
213 counts: &mut [u32],
214 good_for_rle: &mut [u8],
215) {
216 let mut nonzero_count: usize = 0usize;
217 let mut stride: usize;
218 let mut limit: usize;
219 let mut sum: usize;
220 let streak_limit: usize = 1240usize;
221 for i in 0usize..length {
222 if counts[i] != 0 {
223 nonzero_count = nonzero_count.wrapping_add(1);
224 }
225 }
226 if nonzero_count < 16usize {
227 return;
228 }
229 while length != 0usize && (counts[length.wrapping_sub(1)] == 0u32) {
230 length = length.wrapping_sub(1);
231 }
232 if length == 0usize {
233 return;
234 }
235 {
236 let mut nonzeros: usize = 0usize;
237 let mut smallest_nonzero: u32 = (1i32 << 30) as u32;
238 for i in 0usize..length {
239 if counts[i] != 0u32 {
240 nonzeros = nonzeros.wrapping_add(1);
241 if smallest_nonzero > counts[i] {
242 smallest_nonzero = counts[i];
243 }
244 }
245 }
246 if nonzeros < 5usize {
247 return;
248 }
249 if smallest_nonzero < 4u32 {
250 let zeros: usize = length.wrapping_sub(nonzeros);
251 if zeros < 6 {
252 for i in 1..length.wrapping_sub(1) {
253 if counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0 {
254 counts[i] = 1;
255 }
256 }
257 }
258 }
259 if nonzeros < 28usize {
260 return;
261 }
262 }
263 for rle_item in good_for_rle.iter_mut() {
264 *rle_item = 0;
265 }
266 {
267 let mut symbol: u32 = counts[0];
268 let mut step: usize = 0usize;
269 for i in 0..=length {
270 if i == length || counts[i] != symbol {
271 if symbol == 0u32 && (step >= 5usize) || symbol != 0u32 && (step >= 7usize) {
272 for k in 0usize..step {
273 good_for_rle[i.wrapping_sub(k).wrapping_sub(1)] = 1u8;
274 }
275 }
276 step = 1;
277 if i != length {
278 symbol = counts[i];
279 }
280 } else {
281 step = step.wrapping_add(1);
282 }
283 }
284 }
285 stride = 0usize;
286 limit = (256u32)
287 .wrapping_mul((counts[0]).wrapping_add(counts[1]).wrapping_add(counts[2]))
288 .wrapping_div(3)
289 .wrapping_add(420) as usize;
290 sum = 0usize;
291 for i in 0..=length {
292 if i == length
293 || good_for_rle[i] != 0
294 || i != 0usize && (good_for_rle[i.wrapping_sub(1)] != 0)
295 || ((256u32).wrapping_mul(counts[i]) as usize)
296 .wrapping_sub(limit)
297 .wrapping_add(streak_limit)
298 >= (2usize).wrapping_mul(streak_limit)
299 {
300 if stride >= 4usize || stride >= 3usize && (sum == 0usize) {
301 let mut count: usize = sum
302 .wrapping_add(stride.wrapping_div(2))
303 .wrapping_div(stride);
304 if count == 0usize {
305 count = 1;
306 }
307 if sum == 0usize {
308 count = 0usize;
309 }
310 for k in 0usize..stride {
311 counts[i.wrapping_sub(k).wrapping_sub(1)] = count as u32;
312 }
313 }
314 stride = 0usize;
315 sum = 0usize;
316 if i < length.wrapping_sub(2) {
317 limit = (256u32)
318 .wrapping_mul(
319 (counts[i])
320 .wrapping_add(counts[i.wrapping_add(1)])
321 .wrapping_add(counts[i.wrapping_add(2)]),
322 )
323 .wrapping_div(3)
324 .wrapping_add(420) as usize;
325 } else if i < length {
326 limit = (256u32).wrapping_mul(counts[i]) as usize;
327 } else {
328 limit = 0usize;
329 }
330 }
331 stride = stride.wrapping_add(1);
332 if i != length {
333 sum = sum.wrapping_add(counts[i] as usize);
334 if stride >= 4usize {
335 limit = (256usize)
336 .wrapping_mul(sum)
337 .wrapping_add(stride.wrapping_div(2))
338 .wrapping_div(stride);
339 }
340 if stride == 4usize {
341 limit = limit.wrapping_add(120);
342 }
343 }
344 }
345}
346
347
348pub(crate) fn decide_over_rle_use(depth: &[u8], length: usize) -> (bool, bool) {
349 let mut total_reps_zero: usize = 0usize;
350 let mut total_reps_non_zero: usize = 0usize;
351 let mut count_reps_zero: usize = 1;
352 let mut count_reps_non_zero: usize = 1;
353 let mut i: usize;
354 i = 0usize;
355 while i < length {
356 let value: u8 = depth[i];
357 let mut reps: usize = 1;
358 let mut k: usize;
359 k = i.wrapping_add(1);
360 while k < length && (depth[k] as i32 == value as i32) {
361 {
362 reps = reps.wrapping_add(1);
363 }
364 k = k.wrapping_add(1);
365 }
366 if reps >= 3usize && (value as i32 == 0i32) {
367 total_reps_zero = total_reps_zero.wrapping_add(reps);
368 count_reps_zero = count_reps_zero.wrapping_add(1);
369 }
370 if reps >= 4usize && (value as i32 != 0i32) {
371 total_reps_non_zero = total_reps_non_zero.wrapping_add(reps);
372 count_reps_non_zero = count_reps_non_zero.wrapping_add(1);
373 }
374 i = i.wrapping_add(reps);
375 }
376 let use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero.wrapping_mul(2);
377 let use_rle_for_zero = total_reps_zero > count_reps_zero.wrapping_mul(2);
378
379 (use_rle_for_non_zero, use_rle_for_zero)
380}
381
382fn Reverse(v: &mut [u8], mut start: usize, mut end: usize) {
383 end = end.wrapping_sub(1);
384 while start < end {
385 v.swap(start, end);
386 start = start.wrapping_add(1);
387 end = end.wrapping_sub(1);
388 }
389}
390
391fn BrotliWriteHuffmanTreeRepetitions(
392 previous_value: u8,
393 value: u8,
394 mut repetitions: usize,
395 tree_size: &mut usize,
396 tree: &mut [u8],
397 extra_bits_data: &mut [u8],
398) {
399 if previous_value as i32 != value as i32 {
400 tree[*tree_size] = value;
401 extra_bits_data[*tree_size] = 0u8;
402 *tree_size = tree_size.wrapping_add(1);
403 repetitions = repetitions.wrapping_sub(1);
404 }
405 if repetitions == 7usize {
406 tree[*tree_size] = value;
407 extra_bits_data[*tree_size] = 0u8;
408 *tree_size = tree_size.wrapping_add(1);
409 repetitions = repetitions.wrapping_sub(1);
410 }
411 if repetitions < 3usize {
412 for _i in 0usize..repetitions {
413 tree[*tree_size] = value;
414 extra_bits_data[*tree_size] = 0u8;
415 *tree_size = tree_size.wrapping_add(1);
416 }
417 } else {
418 let start: usize = *tree_size;
419 repetitions = repetitions.wrapping_sub(3);
420 loop {
421 tree[*tree_size] = 16u8;
422 extra_bits_data[*tree_size] = (repetitions & 0x03) as u8;
423 *tree_size = tree_size.wrapping_add(1);
424 repetitions >>= 2i32;
425 if repetitions == 0usize {
426 break;
427 }
428 repetitions = repetitions.wrapping_sub(1);
429 }
430 Reverse(tree, start, *tree_size);
431 Reverse(extra_bits_data, start, *tree_size);
432 }
433}
434
435fn BrotliWriteHuffmanTreeRepetitionsZeros(
436 mut repetitions: usize,
437 tree_size: &mut usize,
438 tree: &mut [u8],
439 extra_bits_data: &mut [u8],
440) {
441 if repetitions == 11 {
442 tree[*tree_size] = 0u8;
443 extra_bits_data[*tree_size] = 0u8;
444 *tree_size = tree_size.wrapping_add(1);
445 repetitions = repetitions.wrapping_sub(1);
446 }
447 if repetitions < 3usize {
448 for _i in 0usize..repetitions {
449 tree[*tree_size] = 0u8;
450 extra_bits_data[*tree_size] = 0u8;
451 *tree_size = tree_size.wrapping_add(1);
452 }
453 } else {
454 let start: usize = *tree_size;
455 repetitions = repetitions.wrapping_sub(3);
456 loop {
457 tree[*tree_size] = 17u8;
458 extra_bits_data[*tree_size] = (repetitions & 0x7usize) as u8;
459 *tree_size = tree_size.wrapping_add(1);
460 repetitions >>= 3i32;
461 if repetitions == 0usize {
462 break;
463 }
464 repetitions = repetitions.wrapping_sub(1);
465 }
466 Reverse(tree, start, *tree_size);
467 Reverse(extra_bits_data, start, *tree_size);
468 }
469}
470
471pub fn BrotliWriteHuffmanTree(
472 depth: &[u8],
473 length: usize,
474 tree_size: &mut usize,
475 tree: &mut [u8],
476 extra_bits_data: &mut [u8],
477) {
478 let mut previous_value: u8 = 8u8;
479 let mut i: usize;
480 let mut use_rle_for_non_zero = false;
481 let mut use_rle_for_zero = false;
482 let mut new_length: usize = length;
483 i = 0usize;
484 'break27: while i < length {
485 {
486 if depth[length.wrapping_sub(i).wrapping_sub(1)] as i32 == 0i32 {
487 new_length = new_length.wrapping_sub(1);
488 } else {
489 break 'break27;
490 }
491 }
492 i = i.wrapping_add(1);
493 }
494 if length > 50 {
495 (use_rle_for_non_zero, use_rle_for_zero) = decide_over_rle_use(depth, new_length);
496 }
497 i = 0usize;
498 while i < new_length {
499 let value: u8 = depth[i];
500 let mut reps: usize = 1;
501 if value != 0 && use_rle_for_non_zero || value == 0 && use_rle_for_zero {
502 let mut k: usize;
503 k = i.wrapping_add(1);
504 while k < new_length && (depth[k] as i32 == value as i32) {
505 {
506 reps = reps.wrapping_add(1);
507 }
508 k = k.wrapping_add(1);
509 }
510 }
511 if value as i32 == 0i32 {
512 BrotliWriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data);
513 } else {
514 BrotliWriteHuffmanTreeRepetitions(
515 previous_value,
516 value,
517 reps,
518 tree_size,
519 tree,
520 extra_bits_data,
521 );
522 previous_value = value;
523 }
524 i = i.wrapping_add(reps);
525 }
526}
527
528fn BrotliReverseBits(num_bits: usize, mut bits: u16) -> u16 {
529 static kLut: [usize; 16] = [
530 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
531 ];
532 let mut retval: usize = kLut[(bits as i32 & 0xfi32) as usize];
533 let mut i: usize;
534 i = 4usize;
535 while i < num_bits {
536 {
537 retval <<= 4i32;
538 bits = (bits as i32 >> 4) as u16;
539 retval |= kLut[(bits as i32 & 0xfi32) as usize];
540 }
541 i = i.wrapping_add(4);
542 }
543 retval >>= (0usize.wrapping_sub(num_bits) & 0x3usize);
544 retval as u16
545}
546const MAX_HUFFMAN_BITS: usize = 16;
547pub fn BrotliConvertBitDepthsToSymbols(depth: &[u8], len: usize, bits: &mut [u16]) {
548 let mut bl_count: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
552 let mut next_code: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
553 let mut code: i32 = 0i32;
554 for i in 0usize..len {
555 let _rhs = 1;
556 let _lhs = &mut bl_count[depth[i] as usize];
557 *_lhs = (*_lhs as i32 + _rhs) as u16;
558 }
559 bl_count[0] = 0u16;
560 next_code[0] = 0u16;
561 for i in 1..MAX_HUFFMAN_BITS {
562 code = (code + bl_count[i - 1] as i32) << 1;
563 next_code[i] = code as u16;
564 }
565 for i in 0usize..len {
566 if depth[i] != 0 {
567 bits[i] = BrotliReverseBits(depth[i] as usize, {
568 let _rhs = 1;
569 let _lhs = &mut next_code[depth[i] as usize];
570 let _old = *_lhs;
571 *_lhs = (*_lhs as i32 + _rhs) as u16;
572 _old
573 });
574 }
575 }
576}