1#![forbid(unsafe_code)]
22#![warn(missing_docs)]
23
24mod compress;
25mod decompress;
26mod huffman;
27mod tables;
28
29pub use compress::{compress_to_vec, Compressor, StoredOnlyCompressor};
30pub use decompress::{
31 decompress_to_vec, decompress_to_vec_bounded, BoundedDecompressionError, DecompressionError,
32 Decompressor,
33};
34
35#[doc(hidden)]
39pub fn compute_code_lengths(
40 freqs: &[u64],
41 min_limit: &[u8],
42 max_limit: &[u8],
43 calculated_nbits: &mut [u8],
44) {
45 debug_assert_eq!(freqs.len(), min_limit.len());
46 debug_assert_eq!(freqs.len(), max_limit.len());
47 debug_assert_eq!(freqs.len(), calculated_nbits.len());
48 let len = freqs.len();
49
50 for i in 0..len {
51 debug_assert!(min_limit[i] >= 1);
52 debug_assert!(min_limit[i] <= max_limit[i]);
53 }
54
55 let precision = *max_limit.iter().max().unwrap();
56 let num_patterns = 1 << precision;
57
58 let mut dynp = vec![u64::MAX; (num_patterns + 1) * (len + 1)];
59 let index = |sym: usize, off: usize| sym * (num_patterns + 1) + off;
60
61 dynp[index(0, 0)] = 0;
62 for sym in 0..len {
63 for bits in min_limit[sym]..=max_limit[sym] {
64 let off_delta = 1 << (precision - bits);
65 for off in 0..=num_patterns.saturating_sub(off_delta) {
66 dynp[index(sym + 1, off + off_delta)] = dynp[index(sym, off)]
67 .saturating_add(freqs[sym] * u64::from(bits))
68 .min(dynp[index(sym + 1, off + off_delta)]);
69 }
70 }
71 }
72
73 let mut sym = len;
74 let mut off = num_patterns;
75
76 while sym > 0 {
77 sym -= 1;
78 assert!(off > 0);
79
80 for bits in min_limit[sym]..=max_limit[sym] {
81 let off_delta = 1 << (precision - bits);
82 if off_delta <= off
83 && dynp[index(sym + 1, off)]
84 == dynp[index(sym, off - off_delta)]
85 .saturating_add(freqs[sym] * u64::from(bits))
86 {
87 off -= off_delta;
88 calculated_nbits[sym] = bits;
89 break;
90 }
91 }
92 }
93
94 for i in 0..len {
95 debug_assert!(calculated_nbits[i] >= min_limit[i]);
96 debug_assert!(calculated_nbits[i] <= max_limit[i]);
97 }
98}
99
100const fn compute_codes<const NSYMS: usize>(lengths: &[u8; NSYMS]) -> Option<[u16; NSYMS]> {
101 let mut codes = [0u16; NSYMS];
102
103 let mut code = 0u32;
104
105 let mut len = 1;
106 while len <= 16 {
107 let mut i = 0;
108 while i < lengths.len() {
109 if lengths[i] == len {
110 codes[i] = (code as u16).reverse_bits() >> (16 - len);
111 code += 1;
112 }
113 i += 1;
114 }
115 code <<= 1;
116 len += 1;
117 }
118
119 if code == 2 << 16 {
120 Some(codes)
121 } else {
122 None
123 }
124}