use std::sync::OnceLock;
use crate::deflate::DeflateState;
pub(crate) const LENGTH_CODES: usize = 29; pub(crate) const LITERALS: usize = 256; pub(crate) const L_CODES: usize = LITERALS + 1 + LENGTH_CODES; pub(crate) const D_CODES: usize = 30; pub(crate) const BL_CODES: usize = 19; pub(crate) const HEAP_SIZE: usize = 2 * L_CODES + 1; pub(crate) const MAX_BITS: usize = 15; pub(crate) const MAX_BL_BITS: usize = 7;
pub(crate) const MIN_MATCH: usize = 3;
pub(crate) const MAX_MATCH: usize = 258;
const END_BLOCK: usize = 256; const REP_3_6: usize = 16; const REPZ_3_10: usize = 17; const REPZ_11_138: usize = 18;
const STORED_BLOCK: i32 = 0;
const STATIC_TREES: i32 = 1;
const DYN_TREES: i32 = 2;
const DIST_CODE_LEN: usize = 512;
const SMALLEST: usize = 1;
static EXTRA_LBITS: [i32; LENGTH_CODES] = [
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
];
static EXTRA_DBITS: [i32; D_CODES] = [
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
13,
];
static EXTRA_BLBITS: [i32; BL_CODES] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
const BL_ORDER: [usize; BL_CODES] = [
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
];
#[derive(Clone, Copy, Default)]
pub(crate) struct CtData {
pub(crate) fc: u16,
pub(crate) dl: u16,
}
pub(crate) struct StaticData {
pub(crate) static_ltree: [CtData; L_CODES + 2], pub(crate) static_dtree: [CtData; D_CODES], pub(crate) dist_code: [u8; DIST_CODE_LEN], pub(crate) length_code: [u8; MAX_MATCH - MIN_MATCH + 1], pub(crate) base_length: [i32; LENGTH_CODES],
pub(crate) base_dist: [i32; D_CODES],
}
static STATIC_DATA: OnceLock<StaticData> = OnceLock::new();
pub(crate) fn static_data() -> &'static StaticData {
STATIC_DATA.get_or_init(tr_static_init)
}
fn bi_reverse(mut code: u32, mut len: i32) -> u32 {
let mut res: u32 = 0;
loop {
res |= code & 1;
code >>= 1;
res <<= 1;
len -= 1;
if len <= 0 {
break;
}
}
res >> 1
}
fn gen_codes(tree: &mut [CtData], max_code: i32, bl_count: &[u16]) {
let mut next_code = [0u16; MAX_BITS + 1];
let mut code: u32 = 0;
for bits in 1..=MAX_BITS {
code = (code + bl_count[bits - 1] as u32) << 1;
next_code[bits] = code as u16;
}
for n in 0..=max_code {
let len = tree[n as usize].dl as usize; if len == 0 {
continue;
}
tree[n as usize].fc = bi_reverse(next_code[len] as u32, len as i32) as u16; next_code[len] += 1;
}
}
fn tr_static_init() -> StaticData {
let mut length_code = [0u8; MAX_MATCH - MIN_MATCH + 1];
let mut base_length = [0i32; LENGTH_CODES];
let mut dist_code = [0u8; DIST_CODE_LEN];
let mut base_dist = [0i32; D_CODES];
let mut static_ltree = [CtData::default(); L_CODES + 2];
let mut static_dtree = [CtData::default(); D_CODES];
let mut length = 0i32;
for code in 0..(LENGTH_CODES - 1) {
base_length[code] = length;
for _ in 0..(1 << EXTRA_LBITS[code]) {
length_code[length as usize] = code as u8;
length += 1;
}
}
length_code[(length - 1) as usize] = (LENGTH_CODES - 1) as u8;
let mut dist = 0i32;
for code in 0..16 {
base_dist[code] = dist;
for _ in 0..(1 << EXTRA_DBITS[code]) {
dist_code[dist as usize] = code as u8;
dist += 1;
}
}
dist >>= 7; for code in 16..D_CODES {
base_dist[code] = dist << 7;
for _ in 0..(1 << (EXTRA_DBITS[code] - 7)) {
dist_code[(256 + dist) as usize] = code as u8;
dist += 1;
}
}
let mut bl_count = [0u16; MAX_BITS + 1];
let mut n = 0usize;
while n <= 143 {
static_ltree[n].dl = 8;
bl_count[8] += 1;
n += 1;
}
while n <= 255 {
static_ltree[n].dl = 9;
bl_count[9] += 1;
n += 1;
}
while n <= 279 {
static_ltree[n].dl = 7;
bl_count[7] += 1;
n += 1;
}
while n <= 287 {
static_ltree[n].dl = 8;
bl_count[8] += 1;
n += 1;
}
gen_codes(&mut static_ltree, (L_CODES + 1) as i32, &bl_count);
for (n, e) in static_dtree.iter_mut().enumerate() {
e.dl = 5;
e.fc = bi_reverse(n as u32, 5) as u16;
}
StaticData {
static_ltree,
static_dtree,
dist_code,
length_code,
base_length,
base_dist,
}
}
#[inline]
fn d_code(sd: &StaticData, dist: usize) -> usize {
if dist < 256 {
sd.dist_code[dist] as usize
} else {
sd.dist_code[256 + (dist >> 7)] as usize
}
}
#[derive(Clone, Copy)]
pub(crate) enum TreeKind {
Literal,
Distance,
BitLength,
}
struct Desc {
stree: Option<&'static [CtData]>,
extra: &'static [i32],
extra_base: usize,
elems: usize,
max_length: i32,
}
fn desc_for(kind: TreeKind) -> Desc {
let sd = static_data();
match kind {
TreeKind::Literal => Desc {
stree: Some(&sd.static_ltree[..]),
extra: &EXTRA_LBITS,
extra_base: LITERALS + 1,
elems: L_CODES,
max_length: MAX_BITS as i32,
},
TreeKind::Distance => Desc {
stree: Some(&sd.static_dtree[..]),
extra: &EXTRA_DBITS,
extra_base: 0,
elems: D_CODES,
max_length: MAX_BITS as i32,
},
TreeKind::BitLength => Desc {
stree: None,
extra: &EXTRA_BLBITS,
extra_base: 0,
elems: BL_CODES,
max_length: MAX_BL_BITS as i32,
},
}
}
#[inline]
fn smaller(tree: &[CtData], n: i32, m: i32, depth: &[u8]) -> bool {
let (n, m) = (n as usize, m as usize);
tree[n].fc < tree[m].fc || (tree[n].fc == tree[m].fc && depth[n] <= depth[m])
}
fn scan_tree(tree: &mut [CtData], bltree: &mut [CtData], max_code: i32) {
let mut prevlen: i32 = -1;
let mut nextlen = tree[0].dl as i32;
let mut count = 0i32;
let mut max_count = 7i32;
let mut min_count = 4i32;
if nextlen == 0 {
max_count = 138;
min_count = 3;
}
tree[(max_code + 1) as usize].dl = 0xffff; for n in 0..=max_code {
let curlen = nextlen;
nextlen = tree[(n + 1) as usize].dl as i32;
count += 1;
if count < max_count && curlen == nextlen {
continue;
} else if count < min_count {
bltree[curlen as usize].fc += count as u16;
} else if curlen != 0 {
if curlen != prevlen {
bltree[curlen as usize].fc += 1;
}
bltree[REP_3_6].fc += 1;
} else if count <= 10 {
bltree[REPZ_3_10].fc += 1;
} else {
bltree[REPZ_11_138].fc += 1;
}
count = 0;
prevlen = curlen;
if nextlen == 0 {
max_count = 138;
min_count = 3;
} else if curlen == nextlen {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
impl DeflateState<'_> {
pub(crate) fn init_block(&mut self) {
for n in 0..L_CODES {
self.dyn_ltree[n].fc = 0;
}
for n in 0..D_CODES {
self.dyn_dtree[n].fc = 0;
}
for n in 0..BL_CODES {
self.bl_tree[n].fc = 0;
}
self.dyn_ltree[END_BLOCK].fc = 1;
self.opt_len = 0;
self.static_len = 0;
self.sym_next = 0;
}
pub(crate) fn tr_init(&mut self) {
self.bw.bi_buf = 0;
self.bw.bi_valid = 0;
self.init_block();
}
pub(crate) fn tr_tally(&mut self, dist: usize, lc: usize) -> bool {
self.sym_buf[self.sym_next] = (dist & 0xff) as u8;
self.sym_buf[self.sym_next + 1] = (dist >> 8) as u8;
self.sym_buf[self.sym_next + 2] = lc as u8;
self.sym_next += 3;
if dist == 0 {
self.dyn_ltree[lc].fc += 1; } else {
let d = dist - 1; let sd = static_data();
self.dyn_ltree[sd.length_code[lc] as usize + LITERALS + 1].fc += 1;
self.dyn_dtree[d_code(sd, d)].fc += 1;
}
self.sym_next == self.sym_end
}
fn pqdownheap(&mut self, tree: &[CtData], k0: usize) {
let v = self.heap[k0];
let mut k = k0;
let mut j = k << 1; while j <= self.heap_len {
if j < self.heap_len && smaller(tree, self.heap[j + 1], self.heap[j], &self.depth) {
j += 1;
}
if smaller(tree, v, self.heap[j], &self.depth) {
break;
}
self.heap[k] = self.heap[j];
k = j;
j <<= 1;
}
self.heap[k] = v;
}
fn gen_bitlen(&mut self, tree: &mut [CtData], kind: TreeKind, max_code: i32) {
let d = desc_for(kind);
let stree = d.stree;
let extra = d.extra;
let base = d.extra_base;
let max_length = d.max_length;
let mut overflow = 0i32;
for bits in 0..=MAX_BITS {
self.bl_count[bits] = 0;
}
tree[self.heap[self.heap_max] as usize].dl = 0;
for h in (self.heap_max + 1)..HEAP_SIZE {
let n = self.heap[h] as usize;
let mut bits = tree[tree[n].dl as usize].dl as i32 + 1; if bits > max_length {
bits = max_length;
overflow += 1;
}
tree[n].dl = bits as u16;
if (n as i32) > max_code {
continue; }
self.bl_count[bits as usize] += 1;
let mut xbits = 0i32;
if n >= base {
xbits = extra[n - base];
}
let f = tree[n].fc as u32; self.opt_len = self
.opt_len
.wrapping_add(f.wrapping_mul((bits + xbits) as u32));
if let Some(st) = stree {
self.static_len = self
.static_len
.wrapping_add(f.wrapping_mul((st[n].dl as i32 + xbits) as u32));
}
}
if overflow == 0 {
return;
}
loop {
let mut bits = max_length - 1;
while self.bl_count[bits as usize] == 0 {
bits -= 1;
}
self.bl_count[bits as usize] -= 1; self.bl_count[(bits + 1) as usize] += 2; self.bl_count[max_length as usize] -= 1;
overflow -= 2;
if overflow <= 0 {
break;
}
}
let mut h = HEAP_SIZE;
for bits in (1..=max_length).rev() {
let mut n = self.bl_count[bits as usize];
while n != 0 {
h -= 1;
let m = self.heap[h] as usize;
if (m as i32) > max_code {
continue;
}
if tree[m].dl as i32 != bits {
self.opt_len = self.opt_len.wrapping_add(
(bits as u32)
.wrapping_sub(tree[m].dl as u32)
.wrapping_mul(tree[m].fc as u32),
);
tree[m].dl = bits as u16;
}
n -= 1;
}
}
}
fn build_tree(&mut self, tree: &mut [CtData], kind: TreeKind) -> i32 {
let d = desc_for(kind);
let stree = d.stree;
let elems = d.elems;
let mut max_code: i32 = -1;
self.heap_len = 0;
self.heap_max = HEAP_SIZE;
for (n, t) in tree.iter_mut().enumerate().take(elems) {
if t.fc != 0 {
self.heap_len += 1;
self.heap[self.heap_len] = n as i32;
max_code = n as i32;
self.depth[n] = 0;
} else {
t.dl = 0;
}
}
while self.heap_len < 2 {
let node = if max_code < 2 {
max_code += 1;
max_code
} else {
0
};
self.heap_len += 1;
self.heap[self.heap_len] = node;
tree[node as usize].fc = 1;
self.depth[node as usize] = 0;
self.opt_len = self.opt_len.wrapping_sub(1);
if let Some(st) = stree {
self.static_len = self.static_len.wrapping_sub(st[node as usize].dl as u32);
}
}
for n in (1..=self.heap_len / 2).rev() {
self.pqdownheap(tree, n);
}
let mut node = elems;
loop {
let n = self.heap[SMALLEST];
self.heap[SMALLEST] = self.heap[self.heap_len];
self.heap_len -= 1;
self.pqdownheap(tree, SMALLEST);
let m = self.heap[SMALLEST];
self.heap_max -= 1;
self.heap[self.heap_max] = n; self.heap_max -= 1;
self.heap[self.heap_max] = m;
tree[node].fc = tree[n as usize].fc + tree[m as usize].fc;
self.depth[node] = self.depth[n as usize].max(self.depth[m as usize]) + 1;
tree[n as usize].dl = node as u16; tree[m as usize].dl = node as u16;
self.heap[SMALLEST] = node as i32;
node += 1;
self.pqdownheap(tree, SMALLEST);
if self.heap_len < 2 {
break;
}
}
self.heap_max -= 1;
self.heap[self.heap_max] = self.heap[SMALLEST];
self.gen_bitlen(tree, kind, max_code);
gen_codes(tree, max_code, &self.bl_count);
max_code
}
fn build_bl_tree(
&mut self,
ltree: &mut [CtData],
dtree: &mut [CtData],
bltree: &mut [CtData],
) -> i32 {
scan_tree(ltree, bltree, self.l_max_code);
scan_tree(dtree, bltree, self.d_max_code);
self.build_tree(bltree, TreeKind::BitLength);
let mut max_blindex = (BL_CODES - 1) as i32;
while max_blindex >= 3 {
if bltree[BL_ORDER[max_blindex as usize]].dl != 0 {
break;
}
max_blindex -= 1;
}
self.opt_len = self
.opt_len
.wrapping_add(3 * (max_blindex as u32 + 1) + 5 + 5 + 4);
max_blindex
}
#[inline]
fn send_code(&mut self, c: usize, tree: &[CtData]) {
self.bw.send_bits(tree[c].fc as i32, tree[c].dl as i32);
}
fn send_tree(&mut self, tree: &[CtData], bltree: &[CtData], max_code: i32) {
let mut prevlen: i32 = -1;
let mut nextlen = tree[0].dl as i32;
let mut count = 0i32;
let mut max_count = 7i32;
let mut min_count = 4i32;
if nextlen == 0 {
max_count = 138;
min_count = 3;
}
for n in 0..=max_code {
let curlen = nextlen;
nextlen = tree[(n + 1) as usize].dl as i32;
count += 1;
if count < max_count && curlen == nextlen {
continue;
} else if count < min_count {
loop {
self.send_code(curlen as usize, bltree);
count -= 1;
if count == 0 {
break;
}
}
} else if curlen != 0 {
if curlen != prevlen {
self.send_code(curlen as usize, bltree);
count -= 1;
}
self.send_code(REP_3_6, bltree);
self.bw.send_bits(count - 3, 2);
} else if count <= 10 {
self.send_code(REPZ_3_10, bltree);
self.bw.send_bits(count - 3, 3);
} else {
self.send_code(REPZ_11_138, bltree);
self.bw.send_bits(count - 11, 7);
}
count = 0;
prevlen = curlen;
if nextlen == 0 {
max_count = 138;
min_count = 3;
} else if curlen == nextlen {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
fn send_all_trees(
&mut self,
lcodes: i32,
dcodes: i32,
blcodes: i32,
ltree: &[CtData],
dtree: &[CtData],
bltree: &[CtData],
) {
self.bw.send_bits(lcodes - 257, 5);
self.bw.send_bits(dcodes - 1, 5);
self.bw.send_bits(blcodes - 4, 4);
for rank in 0..blcodes {
self.bw
.send_bits(bltree[BL_ORDER[rank as usize]].dl as i32, 3);
}
self.send_tree(ltree, bltree, lcodes - 1);
self.send_tree(dtree, bltree, dcodes - 1);
}
fn compress_block(&mut self, ltree: &[CtData], dtree: &[CtData]) {
let sd = static_data();
let mut sx = 0usize;
if self.sym_next != 0 {
loop {
let dist = (self.sym_buf[sx] as usize) | ((self.sym_buf[sx + 1] as usize) << 8);
let lc = self.sym_buf[sx + 2] as usize;
sx += 3;
if dist == 0 {
self.send_code(lc, ltree); } else {
let code = sd.length_code[lc] as usize;
self.send_code(code + LITERALS + 1, ltree); let extra = EXTRA_LBITS[code];
if extra != 0 {
let lc2 = lc - sd.base_length[code] as usize;
self.bw.send_bits(lc2 as i32, extra);
}
let mut d = dist - 1; let dc = d_code(sd, d);
self.send_code(dc, dtree); let extra = EXTRA_DBITS[dc];
if extra != 0 {
d -= sd.base_dist[dc] as usize;
self.bw.send_bits(d as i32, extra);
}
}
if sx >= self.sym_next {
break;
}
}
}
self.send_code(END_BLOCK, ltree);
}
fn tr_stored_block(&mut self, buf: Option<usize>, stored_len: usize, last: bool) {
self.bw.send_bits((STORED_BLOCK << 1) + last as i32, 3); self.bw.bi_windup(); self.bw.put_short(stored_len as u16);
self.bw.put_short(!(stored_len as u16));
if let Some(off) = buf {
self.bw
.out
.extend_from_slice(&self.window[off..off + stored_len]);
}
}
pub(crate) fn tr_flush_block(&mut self, buf: Option<usize>, stored_len: usize, last: bool) {
let mut opt_lenb: u32;
let static_lenb: u32;
let mut max_blindex = 0i32;
let mut ltree = std::mem::take(&mut self.dyn_ltree);
let mut dtree = std::mem::take(&mut self.dyn_dtree);
let mut bltree = std::mem::take(&mut self.bl_tree);
if self.level > 0 {
self.l_max_code = self.build_tree(&mut ltree, TreeKind::Literal);
self.d_max_code = self.build_tree(&mut dtree, TreeKind::Distance);
max_blindex = self.build_bl_tree(&mut ltree, &mut dtree, &mut bltree);
opt_lenb = (self.opt_len.wrapping_add(3 + 7)) >> 3;
static_lenb = (self.static_len.wrapping_add(3 + 7)) >> 3;
if static_lenb <= opt_lenb {
opt_lenb = static_lenb;
}
} else {
opt_lenb = (stored_len + 5) as u32;
static_lenb = opt_lenb;
}
if (stored_len + 4) as u32 <= opt_lenb && buf.is_some() {
self.tr_stored_block(buf, stored_len, last);
} else if static_lenb == opt_lenb {
self.bw.send_bits((STATIC_TREES << 1) + last as i32, 3);
let sd = static_data();
self.compress_block(&sd.static_ltree, &sd.static_dtree);
} else {
self.bw.send_bits((DYN_TREES << 1) + last as i32, 3);
self.send_all_trees(
self.l_max_code + 1,
self.d_max_code + 1,
max_blindex + 1,
<ree,
&dtree,
&bltree,
);
self.compress_block(<ree, &dtree);
}
self.dyn_ltree = ltree;
self.dyn_dtree = dtree;
self.bl_tree = bltree;
self.init_block();
if last {
self.bw.bi_windup();
}
}
}