///|
/// Largest positive Int value, used to clamp capacity math before allocation
fn max_int_val() -> Int {
((-1).reinterpret_as_uint() >> 1).reinterpret_as_int()
}
///|
/// Saturating add for internal non-negative buffer sizing math.
/// Panics on negative inputs so invariant violations fail fast.
fn sat_add(a : Int, b : Int) -> Int {
guard a >= 0 && b >= 0
let max_i = max_int_val()
if a > max_i - b {
max_i
} else {
a + b
}
}
///|
/// Saturating multiply for internal non-negative sizing math.
/// Panics on negative inputs so invariant violations fail fast.
fn sat_mul(a : Int, b : Int) -> Int {
guard a >= 0 && b >= 0
let max_i = max_int_val()
if a == 0 || b == 0 {
0
} else if a > max_i / b {
max_i
} else {
a * b
}
}
///|
/// Compute required output capacity without letting intermediate sums wrap
fn out_capacity_need(pre : Int, pos : Int, bl : Int, post : Int) -> Int {
let with_pre = sat_add(pre, shft(pos))
let with_block = sat_add(with_pre, bl)
let with_header = sat_add(with_block, 8)
sat_add(with_header, post)
}
///|
/// Grow output capacity without overflowing the doubling step
fn grown_out_capacity(cur : Int, need : Int) -> Int {
let max_i = max_int_val()
let safe_need = if need < 0 { max_i } else { need }
let doubled = if cur > 0 && cur <= max_i / 2 { cur * 2 } else { max_i }
if doubled > safe_need {
doubled
} else {
safe_need
}
}
///|
let small_fixed_block_threshold : Int = 1024
///|
let periodic_dynamic_block_limit : Int = 4096
///|
let periodic_non_overlap_distance : Int = 258
///|
/// Write a stored (uncompressed) block
/// Returns new bit position
fn wfblk(
out : FixedArray[Byte],
pos : Int,
dat : FixedArray[Byte],
dat_start : Int,
dat_len : Int,
) -> Int {
let o = shft(pos + 2)
out[o] = (dat_len & 255).to_byte()
out[o + 1] = (dat_len >> 8).to_byte()
out[o + 2] = (out[o].to_int() ^ 255).to_byte()
out[o + 3] = (out[o + 1].to_int() ^ 255).to_byte()
dat.blit_to(out, len=dat_len, src_offset=dat_start, dst_offset=o + 4)
(o + 4 + dat_len) * 8
}
///|
/// Write symbols with given encoding tables
fn write_syms(
out : FixedArray[Byte],
lm_enc : FixedArray[Int],
ll : FixedArray[Byte],
dm_enc : FixedArray[Int],
dl : FixedArray[Byte],
syms : FixedArray[Int],
li : Int,
p : Int,
) -> Int {
let mut p = p
for i in 0.. 255 {
let len = (sym >> 18) & 31
wbits16(out, p, lm_enc[len + 257])
p += ll[len + 257].to_int()
if len > 7 {
wbits(out, p, (sym >> 23) & 31)
p += fleb[len].to_int()
}
let dst = sym & 31
wbits16(out, p, dm_enc[dst])
p += dl[dst].to_int()
if dst > 3 {
wbits16(out, p, (sym >> 5) & 8191)
p += fdeb[dst].to_int()
}
} else {
wbits16(out, p, lm_enc[sym])
p += ll[sym].to_int()
}
}
wbits16(out, p, lm_enc[256])
p + ll[256].to_int()
}
///|
/// Write a compressed block
fn wblk(
dat : FixedArray[Byte],
out : FixedArray[Byte],
final_ : Int,
syms : FixedArray[Int],
lf : FixedArray[Int],
df : FixedArray[Int],
eb : Int,
li : Int,
bs : Int,
bl : Int,
p : Int,
) -> Int {
let mut p = p
wbits(out, p, final_)
p += 1
lf[256] = lf[256] + 1
if bl <= small_fixed_block_threshold {
let flen = (bl + 5) << 3
let ftlen = clen(lf, flt) + clen(df, fdt) + eb
if bs >= 0 && flen <= ftlen {
return wfblk(out, p, dat, bs, bl)
}
wbits(out, p, 1) // fixed
p += 2
return write_syms(out, flm, flt, fdm, fdt, syms, li, p)
}
let (dlt, mlb) = h_tree(lf, 15)
let (ddt, mdb) = h_tree(df, 15)
let (lclt, nlc) = lc_gen(dlt)
let (lcdt, ndc) = lc_gen(ddt)
let lcfreq : FixedArray[Int] = FixedArray::make(19, 0)
for i in 0.. 4 {
let ci = clim[nlcc - 1].to_int()
if ci < lct_len && lct[ci].to_int() == 0 {
nlcc -= 1
} else if ci >= lct_len {
// Code index beyond lct is effectively zero-length
nlcc -= 1
} else {
break
}
}
let flen = (bl + 5) << 3
let ftlen = clen(lf, flt) + clen(df, fdt) + eb
let dtlen = clen(lf, dlt) +
clen(df, ddt) +
eb +
14 +
3 * nlcc +
clen(lcfreq, lct) +
2 * lcfreq[16] +
3 * lcfreq[17] +
7 * lcfreq[18]
if bs >= 0 && flen <= ftlen && flen <= dtlen {
return wfblk(out, p, dat, bs, bl)
}
if dtlen < ftlen {
wbits(out, p, 2) // dynamic
p += 2
let lm_enc = h_map(dlt, mlb, 0)
let ll = dlt
let dm_enc = h_map(ddt, mdb, 0)
let dl = ddt
let llm = h_map(lct, mlcb, 0)
wbits(out, p, nlc - 257)
wbits(out, p + 5, ndc - 1)
wbits(out, p + 10, nlcc - 4)
p += 14
for i in 0.. 15 {
wbits(out, p, (clct[i] >> 5) & 127)
p += clct[i] >> 12
}
}
}
write_syms(out, lm_enc, ll, dm_enc, dl, syms, li, p)
} else {
wbits(out, p, 1) // fixed
p += 2
write_syms(out, flm, flt, fdm, fdt, syms, li, p)
}
}
///|
/// Internal deflate state for streaming
priv struct DeflateState {
mut head : FixedArray[Int]? // hash head
mut prev : FixedArray[Int]? // hash chain prev
mut i : Int // current index
z : Int // end index
mut w : Int // wait index
mut r : Int // remainder byte info
l : Int // last chunk flag
}
///|
/// Compute memory level for compression
fn compute_mem_level(len : Int) -> Int {
// Aggressive memory strategy for small data to reduce hash table overhead
if len < small_data_mem_threshold {
return 10 // head array = 2^10 = 1KB (vs 128KB before)
}
if len < full_scan_threshold {
return 12 // head array = 2^12 = 4KB
}
let mut log_val = 8
let mut v = len
while v > 256 {
v = v >> 1
log_val += 1
if log_val >= 10 {
break
}
}
if log_val < 8 {
log_val = 8
}
(log_val * 3 + 1) / 2
}
///|
/// Fast compressibility detection via sampling
fn is_compressible(dat : FixedArray[Byte], start : Int, len : Int) -> Bool {
if len < min_compressibility_check_len {
return true
}
// For data < 8192, full scan is cheap and accurate
if len < full_scan_threshold {
// First pass: lightweight unique count with boolean array (256 bytes)
let seen : FixedArray[Bool] = FixedArray::make(256, false)
let mut unique_count = 0
for i in 0.. high_entropy_unique_threshold {
// Second pass: frequency analysis (only for high-entropy candidates)
let freq : FixedArray[Int] = FixedArray::make(256, 0)
for i in 0.. max_freq {
max_freq = freq[i]
}
}
if max_freq > len >> freq_skew_shift {
return true
}
// Near-uniform: check periodicity before declaring incompressible
let dists : FixedArray[Int] = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
for di in 0.. check_count {
return true
}
}
}
return false
}
return true
}
// Sampling for large data
let sample_size = len / sampling_stride
let mut unique_count = 0
let seen : FixedArray[Bool] = FixedArray::make(256, false)
let mut match_count = 0
for i in 0..= 3 &&
(
dat[pos] == dat[pos - 1] ||
(dat[pos] == dat[pos - 2] && dat[pos - 1] == dat[pos - 3])
) {
match_count += 1
}
}
let entropy_high = unique_count > sampling_entropy_threshold
let match_rate_low = match_count * 10 < sample_size
!(entropy_high && match_rate_low)
}
///|
fn is_all_same(dat : FixedArray[Byte], len : Int) -> Bool {
if len <= 1 {
return true
}
let first = dat[0]
for i in 1.. (FixedArray[Byte], Int) {
let s = if st.z != 0 { st.z } else { dat.length() }
let o_size = sat_add(sat_add(pre, s), sat_add(16, post))
let mut o = FixedArray::make(o_size, b'\x00')
let syms_size = s / 258 + 4
let syms : FixedArray[Int] = FixedArray::make(syms_size, 0)
let lf : FixedArray[Int] = FixedArray::make(288, 0)
let df : FixedArray[Int] = FixedArray::make(32, 0)
let mut li = 0
let b = dat[0].to_int()
syms[li] = b
li += 1
lf[b] += 1
let mut rem = s - 1
while rem >= 3 {
let l = if rem > 258 { 258 } else { rem }
let lc = revfl[l]
let dc = revfd[1]
syms[li] = 268435456 | (lc << 18) | dc
li += 1
lf[257 + (lc & 31)] += 1
df[dc & 31] += 1
rem -= l
}
while rem > 0 {
syms[li] = b
li += 1
lf[b] += 1
rem -= 1
}
o = ensure_out(o, out_capacity_need(pre, 0, s, post))
let pos = wblk(dat, o, st.l, syms, lf, df, 0, li, 0, s, pre * 8) - pre * 8
match crc_state {
Some(cs) => cs.push_range(dat, 0, s)
None => ()
}
match adler_state {
Some(a_s) => a_s.push_range(dat, 0, s)
None => ()
}
st.i = s
(o, pre + shft(pos) + post)
}
///|
fn is_periodic(dat : FixedArray[Byte], len : Int, period : Int) -> Bool {
if period <= 0 || period >= len {
return false
}
for i in period.. Int {
let periods : FixedArray[Int] = [2, 4, 8, 16, 32, 64, 128, 256, 512]
for i in 0.. (FixedArray[Byte], Int) {
let s = if st.z != 0 { st.z } else { dat.length() }
let use_fixed = s > periodic_dynamic_block_limit
let main_dist = if !use_fixed {
period
} else if period >= periodic_non_overlap_distance {
period
} else {
let rem = periodic_non_overlap_distance % period
if rem == 0 {
periodic_non_overlap_distance
} else {
periodic_non_overlap_distance + period - rem
}
}
let o_size = sat_add(sat_add(pre, s), sat_add(16, post))
let mut o = FixedArray::make(o_size, b'\x00')
o = ensure_out(o, out_capacity_need(pre, 0, s, post))
let pos = if use_fixed {
// Two-block split for large periodic data.
//
// Block A (the dictionary seed) emits the first `main_dist` output bytes as
// literals plus one period-distance run. It is <= the small-block threshold,
// so `wblk` keeps it on the fixed/stored path — the ~`period` *unique* seed
// literals never enter a dynamic Huffman tree.
//
// Block B emits the bulk back-references at distance `main_dist`. Its
// alphabet is tiny (1-2 length symbols + 1 distance symbol), so its dynamic
// tree assigns ~1-bit codes (small output) AND the decoder builds a tiny
// decode table over few symbols (fast inflate). Keeping the seed literals
// out of this tree is what makes both the encoding small and the table
// cheap — a single combined dynamic block would pay a ~`period`-symbol tree
// on both sides. `main_dist >= 258` keeps every block-B copy non-overlapping.
let literal_seed = if period < 3 { main_dist } else { period }
let seed_match_cap = if period < 3 {
0
} else {
(main_dist - literal_seed + period - 1) / period
}
let syms_a : FixedArray[Int] = FixedArray::make(
literal_seed + seed_match_cap + 2,
0,
)
let lf_a : FixedArray[Int] = FixedArray::make(288, 0)
let df_a : FixedArray[Int] = FixedArray::make(32, 0)
let mut li_a = 0
for i in 0..= 3 {
let period_dc = revfd[period]
let mut produced = literal_seed
while produced < main_dist {
let rem_seed = main_dist - produced
let l = if rem_seed > period { period } else { rem_seed }
let lc = revfl[l]
syms_a[li_a] = 268435456 | (lc << 18) | period_dc
li_a += 1
lf_a[257 + (lc & 31)] += 1
df_a[period_dc & 31] += 1
produced += l
}
}
let dc = revfd[main_dist]
let syms_b : FixedArray[Int] = FixedArray::make(
(s - main_dist + 257) / 258 + 4,
0,
)
let lf_b : FixedArray[Int] = FixedArray::make(288, 0)
let df_b : FixedArray[Int] = FixedArray::make(32, 0)
let mut li_b = 0
let mut rem = s - main_dist
while rem >= 3 {
let l = if rem > 258 { 258 } else { rem }
let lc = revfl[l]
syms_b[li_b] = 268435456 | (lc << 18) | dc
li_b += 1
lf_b[257 + (lc & 31)] += 1
df_b[dc & 31] += 1
rem -= l
}
let mut tail = s - rem
while rem > 0 {
let b = dat[tail].to_int()
syms_b[li_b] = b
li_b += 1
lf_b[b] += 1
tail += 1
rem -= 1
}
// Block A is non-final; block B carries the stream's final flag.
let pos_a = wblk(
dat,
o,
0,
syms_a,
lf_a,
df_a,
0,
li_a,
0,
main_dist,
pre * 8,
)
let pos_b = wblk(
dat,
o,
st.l,
syms_b,
lf_b,
df_b,
0,
li_b,
main_dist,
s - main_dist,
pos_a,
)
pos_b - pre * 8
} else {
// Small periodic data: one block, distance == period (the few literal seed
// symbols barely affect the tree, so splitting would only add overhead).
let syms : FixedArray[Int] = FixedArray::make(
period + (s - main_dist + 257) / 258 + 4,
0,
)
let lf : FixedArray[Int] = FixedArray::make(288, 0)
let df : FixedArray[Int] = FixedArray::make(32, 0)
let mut li = 0
for i in 0..= 3 {
let l = if rem > 258 { 258 } else { rem }
let lc = revfl[l]
syms[li] = 268435456 | (lc << 18) | dc
li += 1
lf[257 + (lc & 31)] += 1
df[dc & 31] += 1
rem -= l
}
let mut tail = s - rem
while rem > 0 {
let b = dat[tail].to_int()
syms[li] = b
li += 1
lf[b] += 1
tail += 1
rem -= 1
}
let block_pos = wblk(dat, o, st.l, syms, lf, df, 0, li, 0, s, pre * 8)
block_pos - pre * 8
}
match crc_state {
Some(cs) => cs.push_range(dat, 0, s)
None => ()
}
match adler_state {
Some(a_s) => a_s.push_range(dat, 0, s)
None => ()
}
st.i = s
(o, pre + shft(pos) + post)
}
///|
/// Ensure output buffer has enough capacity, growing if needed
fn ensure_out(o : FixedArray[Byte], need : Int) -> FixedArray[Byte] {
let need = if need < 0 { max_int_val() } else { need }
if need <= o.length() {
return o
}
let new_size = grown_out_capacity(o.length(), need)
let n = FixedArray::make(new_size, b'\x00')
o.blit_to(n, len=o.length(), src_offset=0, dst_offset=0)
n
}
///|
let dflt_head_pool : Array[FixedArray[Int]] = []
///|
let dflt_prev_pool : Array[FixedArray[Int]] = []
///|
let dflt_syms_pool : Array[FixedArray[Int]] = []
///|
let dflt_lf_pool : Array[FixedArray[Int]] = []
///|
let dflt_df_pool : Array[FixedArray[Int]] = []
///|
/// Core DEFLATE compression function
fn dflt(
dat : FixedArray[Byte],
lvl : Int,
plvl : Int,
pre : Int,
post : Int,
st : DeflateState,
crc_state? : CRC32State? = None,
adler_state? : AdlerState? = None,
) -> (FixedArray[Byte], Int) {
let s = if st.z != 0 { st.z } else { dat.length() }
let block_count = if s == 0 { 1 } else { 1 + (s - 1) / 7000 }
let block_overhead = sat_mul(block_count, 5)
let base_size = if lvl > 0 && s > 512 { sat_add(s >> 1, 128) } else { s }
let o_size = sat_add(sat_add(pre, base_size), sat_add(block_overhead, post))
let mut o = FixedArray::make(o_size, b'\x00')
let w_start = pre
let lst = st.l
let mut pos = st.r & 7
if lvl > 0 {
if s >= 3 && st.w == 0 && st.i == 0 && st.r == 0 && is_all_same(dat, s) {
return dflt_rle_block(dat, pre, post, st, crc_state~, adler_state~)
}
// Fast incompressible data detection (方案 1)
if !is_compressible(dat, 0, s) {
return dflt(dat, 0, plvl, pre, post, st, crc_state~, adler_state~)
}
if s >= 1024 && st.w == 0 && st.i == 0 && st.r == 0 {
let period = detect_period(dat, s)
if period != 0 {
return dflt_periodic_block(
dat,
period,
pre,
post,
st,
crc_state~,
adler_state~,
)
}
}
if pos != 0 {
o[w_start] = (st.r >> 3).to_byte()
}
let opt = deo[lvl - 1]
let n = opt >> 13
let c = opt & 8191
let msk = (1 << plvl) - 1
let window_size = if s < 32768 { s } else { 32768 }
let my_prev_from_pool = st.prev is None
let prev = match st.prev {
Some(p) => p
None =>
match dflt_prev_pool.pop() {
Some(p) =>
if p.length() >= window_size {
for j in 0.. FixedArray::make(window_size, 0)
}
}
let my_head_from_pool = st.head is None
let head = match st.head {
Some(h) => h
None =>
match dflt_head_pool.pop() {
Some(h) =>
if h.length() >= msk + 1 {
for j in 0..<=msk {
h[j] = 0
}
h
} else {
FixedArray::make(msk + 1, 0)
}
None => FixedArray::make(msk + 1, 0)
}
}
let bs1 = (plvl + 2) / 3
let bs2 = 2 * bs1
let syms_size = if s < 512 {
512
} else if s < 4096 {
s
} else if s < 16384 {
s + s / 4
} else {
25000
}
// Optimized buffer allocation
let syms = match dflt_syms_pool.pop() {
Some(s) =>
if s.length() >= syms_size {
s
} else {
FixedArray::make(syms_size, 0)
}
None => FixedArray::make(syms_size, 0)
}
let lf = match dflt_lf_pool.pop() {
Some(a) => {
for j in 0..<288 {
a[j] = 0
}
a
}
None => FixedArray::make(288, 0)
}
let df = match dflt_df_pool.pop() {
Some(a) => {
for j in 0..<32 {
a[j] = 0
}
a
}
None => FixedArray::make(32, 0)
}
let mut lc = 0
let mut eb = 0
let mut i = if st.i != 0 { st.i } else { 0 }
let mut li = 0
let mut wi = if st.w != 0 { st.w } else { 0 }
let mut bs = 0
// Dynamic search tracking (方案 2)
let mut successful_matches = 0
let mut total_searches = 0
let mut cksum_i = wi
while i + 2 < s {
let hv = (
dat[i].to_int() ^
(dat[i + 1].to_int() << bs1) ^
(dat[i + 2].to_int() << bs2)
) &
msk
let imod = i & 32767
let mut pimod = head[hv]
prev[imod] = pimod
head[hv] = imod
if wi <= i {
let rem = s - i
if (lc > 7000 || li > 24576) && (rem > 423 || lst == 0) {
let bl = i - bs
o = ensure_out(o, out_capacity_need(pre, pos, bl, post))
pos = wblk(dat, o, 0, syms, lf, df, eb, li, bs, bl, pos + w_start * 8) -
w_start * 8
li = 0
lc = 0
eb = 0
bs = i
for j in 0..<286 {
lf[j] = 0
}
for j in 0..<30 {
df[j] = 0
}
if i > cksum_i {
match crc_state {
Some(cs) => cs.push_range(dat, cksum_i, i - cksum_i)
None => ()
}
match adler_state {
Some(a_s) => a_s.push_range(dat, cksum_i, i - cksum_i)
None => ()
}
cksum_i = i
}
}
let mut l = 2
let mut d = 0
let mut ch = c
let mut dif = (imod - pimod) & 32767
if rem > 2 &&
hv ==
(
(
dat[i - dif].to_int() ^
(dat[i - dif + 1].to_int() << bs1) ^
(dat[i - dif + 2].to_int() << bs2)
) &
msk
) {
let maxn_val = (if n < rem { n } else { rem }) - 1
let maxd = if 32767 < i { 32767 } else { i }
let ml = if 258 < rem { 258 } else { rem }
let good_match_len = {
let g = n / 4
if g < 4 {
4
} else if g > 64 {
64
} else {
g
}
}
let min_improvement = if rem < 1024 { 2 } else { 4 }
total_searches += 1
// Adaptive chain depth based on success rate
let max_chain = if total_searches < 100 {
c
} else {
let success_100 = successful_matches * 100
if success_100 < total_searches * 5 {
let reduced = c / 4
if reduced < 4 {
4
} else if reduced > 64 {
64
} else {
reduced
}
} else if success_100 < total_searches * 20 {
let reduced = c / 2
if reduced < 4 {
4
} else {
reduced
}
} else {
c
}
}
let mut chain_count = 0
while dif <= maxd &&
ch > 0 &&
imod != pimod &&
chain_count < max_chain {
chain_count += 1
// Early exit 1: found good enough match
if l >= good_match_len {
break
}
ch -= 1
if dat[i + l] == dat[i + l - dif] {
let mut nl = 0
while nl + 3 < ml &&
dat[i + nl] == dat[i + nl - dif] &&
dat[i + nl + 1] == dat[i + nl - dif + 1] &&
dat[i + nl + 2] == dat[i + nl - dif + 2] &&
dat[i + nl + 3] == dat[i + nl - dif + 3] {
nl += 4
}
while nl < ml && dat[i + nl] == dat[i + nl - dif] {
nl += 1
}
// Early exit 2: only update if significant improvement
if nl > l + min_improvement {
l = nl
d = dif
if nl > maxn_val {
break
}
let mmd = if dif < nl - 2 { dif } else { nl - 2 }
let mut md = 0
for j in 0.. md {
md = cd
pimod = ti
}
}
} else if nl > l {
// Small improvement: still update but consider stopping
l = nl
d = dif
if nl > maxn_val {
break
}
} else {
// Early exit 3: match quality degrading
break
}
}
let old_imod = pimod
pimod = prev[old_imod]
dif += (old_imod - pimod) & 32767
}
}
if d != 0 {
successful_matches += 1
syms[li] = 268435456 | (revfl[l] << 18) | revfd[d]
li += 1
let lin = revfl[l] & 31
let din = revfd[d] & 31
eb += fleb[lin].to_int() + fdeb[din].to_int()
lf[257 + lin] += 1
df[din] += 1
wi = i + l
lc += 1
if l > 16 && rem > 500 {
i += l - 1
}
} else {
syms[li] = dat[i].to_int()
li += 1
lf[dat[i].to_int()] += 1
}
}
i += 1
}
let start = if i > wi { i } else { wi }
let mut j = start
while j < s {
syms[li] = dat[j].to_int()
li += 1
lf[dat[j].to_int()] += 1
j += 1
}
let bl = j - bs
o = ensure_out(o, out_capacity_need(pre, pos, bl, post))
pos = wblk(dat, o, lst, syms, lf, df, eb, li, bs, bl, pos + w_start * 8) -
w_start * 8
if s > cksum_i {
match crc_state {
Some(cs) => cs.push_range(dat, cksum_i, s - cksum_i)
None => ()
}
match adler_state {
Some(a_s) => a_s.push_range(dat, cksum_i, s - cksum_i)
None => ()
}
}
if lst == 0 {
st.r = (pos & 7) | (o[w_start + pos / 8].to_int() << 3)
pos -= 7
st.head = Some(head)
st.prev = Some(prev)
st.i = j
st.w = wi
} else {
if my_head_from_pool {
dflt_head_pool.push(head)
}
if my_prev_from_pool {
dflt_prev_pool.push(prev)
}
}
dflt_syms_pool.push(syms)
dflt_lf_pool.push(lf)
dflt_df_pool.push(df)
} else {
let cksum_off = if st.w != 0 { st.w } else { 0 }
if s > cksum_off {
match crc_state {
Some(cs) => cs.push_range(dat, cksum_off, s - cksum_off)
None => ()
}
match adler_state {
Some(a_s) => a_s.push_range(dat, cksum_off, s - cksum_off)
None => ()
}
}
let mut i2 = if st.w != 0 { st.w } else { 0 }
while i2 < s + lst {
let mut e = i2 + 65535
if e >= s {
o[w_start + pos / 8] = lst.to_byte()
e = s
}
pos = wfblk(o, pos + w_start * 8 + 1, dat, i2, e - i2) - w_start * 8
i2 += 65535
}
st.i = s
}
(o, pre + shft(pos) + post)
}
///|
/// Deflate with options
fn dopt(
dat : FixedArray[Byte],
opt : DeflateOptions,
pre : Int,
post : Int,
st : DeflateState?,
crc_state? : CRC32State? = None,
adler_state? : AdlerState? = None,
) -> (FixedArray[Byte], Int) {
let (dat, st) = match st {
Some(s) => (dat, s)
None => {
let s : DeflateState = {
head: None,
prev: None,
i: 0,
z: 0,
w: 0,
r: 0,
l: 1,
}
match opt.dictionary {
Some(dict) => {
let dict_slice = if dict.length() > 32768 {
slc(dict, dict.length() - 32768)
} else {
dict
}
let new_dat = FixedArray::make(
dict_slice.length() + dat.length(),
b'\x00',
)
fa_set(new_dat, dict_slice)
fa_set(new_dat, dat, offset=dict_slice.length())
s.w = dict_slice.length()
(new_dat, s)
}
None => (dat, s)
}
}
}
let level = opt.level
let mem = if opt.mem != 0 {
12 + opt.mem
} else if st.l != 0 {
compute_mem_level(dat.length())
} else {
20
}
dflt(dat, level, mem, pre, post, st, crc_state~, adler_state~)
}
///|
/// Compress data as a raw DEFLATE stream.
///
/// Raw DEFLATE contains only compressed blocks, with no GZIP or Zlib wrapper
/// and no checksum footer. Use this when another protocol supplies its own
/// framing, or when you need the exact DEFLATE payload for ZIP entries.
pub fn deflate_sync(
data : FixedArray[Byte],
opts? : DeflateOptions = DeflateOptions::default(),
) -> FixedArray[Byte] {
let (buf, len) = dopt(data, opts, 0, 0, None)
trim_buf(buf, len)
}