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#[deprecated(note = "Use decide_over_rle_use instead")]
348pub fn DecideOverRleUse(
349 depth: &[u8],
350 length: usize,
351 use_rle_for_non_zero: &mut i32,
352 use_rle_for_zero: &mut i32,
353) {
354 let (non_zero, zero) = decide_over_rle_use(depth, length);
355 *use_rle_for_non_zero = non_zero.into();
356 *use_rle_for_zero = zero.into();
357}
358
359pub(crate) fn decide_over_rle_use(depth: &[u8], length: usize) -> (bool, bool) {
360 let mut total_reps_zero: usize = 0usize;
361 let mut total_reps_non_zero: usize = 0usize;
362 let mut count_reps_zero: usize = 1;
363 let mut count_reps_non_zero: usize = 1;
364 let mut i: usize;
365 i = 0usize;
366 while i < length {
367 let value: u8 = depth[i];
368 let mut reps: usize = 1;
369 let mut k: usize;
370 k = i.wrapping_add(1);
371 while k < length && (depth[k] as i32 == value as i32) {
372 {
373 reps = reps.wrapping_add(1);
374 }
375 k = k.wrapping_add(1);
376 }
377 if reps >= 3usize && (value as i32 == 0i32) {
378 total_reps_zero = total_reps_zero.wrapping_add(reps);
379 count_reps_zero = count_reps_zero.wrapping_add(1);
380 }
381 if reps >= 4usize && (value as i32 != 0i32) {
382 total_reps_non_zero = total_reps_non_zero.wrapping_add(reps);
383 count_reps_non_zero = count_reps_non_zero.wrapping_add(1);
384 }
385 i = i.wrapping_add(reps);
386 }
387 let use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero.wrapping_mul(2);
388 let use_rle_for_zero = total_reps_zero > count_reps_zero.wrapping_mul(2);
389
390 (use_rle_for_non_zero, use_rle_for_zero)
391}
392
393fn Reverse(v: &mut [u8], mut start: usize, mut end: usize) {
394 end = end.wrapping_sub(1);
395 while start < end {
396 v.swap(start, end);
397 start = start.wrapping_add(1);
398 end = end.wrapping_sub(1);
399 }
400}
401
402fn BrotliWriteHuffmanTreeRepetitions(
403 previous_value: u8,
404 value: u8,
405 mut repetitions: usize,
406 tree_size: &mut usize,
407 tree: &mut [u8],
408 extra_bits_data: &mut [u8],
409) {
410 if previous_value as i32 != value as i32 {
411 tree[*tree_size] = value;
412 extra_bits_data[*tree_size] = 0u8;
413 *tree_size = tree_size.wrapping_add(1);
414 repetitions = repetitions.wrapping_sub(1);
415 }
416 if repetitions == 7usize {
417 tree[*tree_size] = value;
418 extra_bits_data[*tree_size] = 0u8;
419 *tree_size = tree_size.wrapping_add(1);
420 repetitions = repetitions.wrapping_sub(1);
421 }
422 if repetitions < 3usize {
423 for _i in 0usize..repetitions {
424 tree[*tree_size] = value;
425 extra_bits_data[*tree_size] = 0u8;
426 *tree_size = tree_size.wrapping_add(1);
427 }
428 } else {
429 let start: usize = *tree_size;
430 repetitions = repetitions.wrapping_sub(3);
431 loop {
432 tree[*tree_size] = 16u8;
433 extra_bits_data[*tree_size] = (repetitions & 0x03) as u8;
434 *tree_size = tree_size.wrapping_add(1);
435 repetitions >>= 2i32;
436 if repetitions == 0usize {
437 break;
438 }
439 repetitions = repetitions.wrapping_sub(1);
440 }
441 Reverse(tree, start, *tree_size);
442 Reverse(extra_bits_data, start, *tree_size);
443 }
444}
445
446fn BrotliWriteHuffmanTreeRepetitionsZeros(
447 mut repetitions: usize,
448 tree_size: &mut usize,
449 tree: &mut [u8],
450 extra_bits_data: &mut [u8],
451) {
452 if repetitions == 11 {
453 tree[*tree_size] = 0u8;
454 extra_bits_data[*tree_size] = 0u8;
455 *tree_size = tree_size.wrapping_add(1);
456 repetitions = repetitions.wrapping_sub(1);
457 }
458 if repetitions < 3usize {
459 for _i in 0usize..repetitions {
460 tree[*tree_size] = 0u8;
461 extra_bits_data[*tree_size] = 0u8;
462 *tree_size = tree_size.wrapping_add(1);
463 }
464 } else {
465 let start: usize = *tree_size;
466 repetitions = repetitions.wrapping_sub(3);
467 loop {
468 tree[*tree_size] = 17u8;
469 extra_bits_data[*tree_size] = (repetitions & 0x7usize) as u8;
470 *tree_size = tree_size.wrapping_add(1);
471 repetitions >>= 3i32;
472 if repetitions == 0usize {
473 break;
474 }
475 repetitions = repetitions.wrapping_sub(1);
476 }
477 Reverse(tree, start, *tree_size);
478 Reverse(extra_bits_data, start, *tree_size);
479 }
480}
481
482pub fn BrotliWriteHuffmanTree(
483 depth: &[u8],
484 length: usize,
485 tree_size: &mut usize,
486 tree: &mut [u8],
487 extra_bits_data: &mut [u8],
488) {
489 let mut previous_value: u8 = 8u8;
490 let mut i: usize;
491 let mut use_rle_for_non_zero = false;
492 let mut use_rle_for_zero = false;
493 let mut new_length: usize = length;
494 i = 0usize;
495 'break27: while i < length {
496 {
497 if depth[length.wrapping_sub(i).wrapping_sub(1)] as i32 == 0i32 {
498 new_length = new_length.wrapping_sub(1);
499 } else {
500 break 'break27;
501 }
502 }
503 i = i.wrapping_add(1);
504 }
505 if length > 50 {
506 (use_rle_for_non_zero, use_rle_for_zero) = decide_over_rle_use(depth, new_length);
507 }
508 i = 0usize;
509 while i < new_length {
510 let value: u8 = depth[i];
511 let mut reps: usize = 1;
512 if value != 0 && use_rle_for_non_zero || value == 0 && use_rle_for_zero {
513 let mut k: usize;
514 k = i.wrapping_add(1);
515 while k < new_length && (depth[k] as i32 == value as i32) {
516 {
517 reps = reps.wrapping_add(1);
518 }
519 k = k.wrapping_add(1);
520 }
521 }
522 if value as i32 == 0i32 {
523 BrotliWriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data);
524 } else {
525 BrotliWriteHuffmanTreeRepetitions(
526 previous_value,
527 value,
528 reps,
529 tree_size,
530 tree,
531 extra_bits_data,
532 );
533 previous_value = value;
534 }
535 i = i.wrapping_add(reps);
536 }
537}
538
539fn BrotliReverseBits(num_bits: usize, mut bits: u16) -> u16 {
540 static kLut: [usize; 16] = [
541 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
542 ];
543 let mut retval: usize = kLut[(bits as i32 & 0xfi32) as usize];
544 let mut i: usize;
545 i = 4usize;
546 while i < num_bits {
547 {
548 retval <<= 4i32;
549 bits = (bits as i32 >> 4) as u16;
550 retval |= kLut[(bits as i32 & 0xfi32) as usize];
551 }
552 i = i.wrapping_add(4);
553 }
554 retval >>= (0usize.wrapping_sub(num_bits) & 0x3usize);
555 retval as u16
556}
557const MAX_HUFFMAN_BITS: usize = 16;
558pub fn BrotliConvertBitDepthsToSymbols(depth: &[u8], len: usize, bits: &mut [u16]) {
559 let mut bl_count: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
563 let mut next_code: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
564 let mut code: i32 = 0i32;
565 for i in 0usize..len {
566 let _rhs = 1;
567 let _lhs = &mut bl_count[depth[i] as usize];
568 *_lhs = (*_lhs as i32 + _rhs) as u16;
569 }
570 bl_count[0] = 0u16;
571 next_code[0] = 0u16;
572 for i in 1..MAX_HUFFMAN_BITS {
573 code = (code + bl_count[i - 1] as i32) << 1;
574 next_code[i] = code as u16;
575 }
576 for i in 0usize..len {
577 if depth[i] != 0 {
578 bits[i] = BrotliReverseBits(depth[i] as usize, {
579 let _rhs = 1;
580 let _lhs = &mut next_code[depth[i] as usize];
581 let _old = *_lhs;
582 *_lhs = (*_lhs as i32 + _rhs) as u16;
583 _old
584 });
585 }
586 }
587}