// The encoder's view of the fixed tables of RFC 7932: from lengths and
// distances to codes, built from the decoder's tables in `tables.mbt`.
///|
/// Lengths below this have their insert length code in a table.
const INSERT_TABLE_SIZE : Int32 = 2114
///|
/// Lengths below this have their copy length code in a table.
const COPY_TABLE_SIZE : Int32 = 2118
///|
/// `table[v]` is the code whose range holds `v`, for `v < size`.
fn length_code_table(
base : FixedArray[Int32],
size : Int32,
) -> FixedArray[Byte] {
let table = FixedArray::make(size, b'\x00')
for code in 0.. Int32 {
for code = base.length() - 1; code > 0; code = code - 1 {
if base[code] <= v {
return code
}
}
0
}
///|
/// The insert length code of `len` (section 5).
fn insert_code(len : Int32) -> Int32 {
if len < INSERT_TABLE_SIZE {
insert_code_table[len].to_int()
} else {
length_code_above(insert_length_base, len)
}
}
///|
/// The copy length code of `len`, at least 2 (section 5).
fn copy_code(len : Int32) -> Int32 {
if len < COPY_TABLE_SIZE {
copy_code_table[len].to_int()
} else {
length_code_above(copy_length_base, len)
}
}
///|
/// The cell of the insert-and-copy alphabet that holds insert codes from
/// `8 * i` and copy codes from `8 * c`, with an explicit distance, at
/// `3 * i + c`.
let explicit_cells : FixedArray[Int32] = {
let cells = FixedArray::make(9, 0)
for cell in 2..> 3) * 3 + (cell_copy_base[cell] >> 3)] = cell
}
cells
}
///|
/// The insert-and-copy symbol of insert code `ic` and copy code `cc`. With
/// `last_distance`, the command reuses the last distance, implicitly when a
/// cell allows it (symbols below 128).
fn command_symbol(ic : Int32, cc : Int32, last_distance : Bool) -> Int32 {
let cell = if last_distance && ic < 8 && cc < 16 {
cc >> 3
} else {
explicit_cells[(ic >> 3) * 3 + (cc >> 3)]
}
(cell << 6) | ((ic & 7) << 3) | (cc & 7)
}
///|
/// The distance symbol of distance `dist` (at least 1), with NPOSTFIX and
/// NDIRECT 0 (section 4): `16 + 2 * (bits - 1) + hi` with `bits` extra bits.
fn distance_symbol(dist : Int32) -> Int32 {
let x = dist + 3
let bits = 30 - x.clz()
let hi = (x >> bits) & 1
16 + 2 * (bits - 1) + hi
}
///|
/// The extra bits of distance `dist` under `distance_symbol(dist)`.
fn distance_extra(dist : Int32) -> Int32 {
let x = dist + 3
let bits = 30 - x.clz()
x - ((2 + ((x >> bits) & 1)) << bits)
}
///|
/// How many extra bits distance symbol `sym` (at least 16) takes.
fn distance_extra_bits(sym : Int32) -> Int32 {
1 + ((sym - 16) >> 1)
}
///|
/// The fixed code of code length code lengths (section 3.5), inverted: for
/// each length 0..5, its code (bits in writing order) and its bit count.
let code_length_code : FixedArray[Int32] = {
let codes = FixedArray::make(6, 0)
for ix in 0..<16 {
let bits = code_length_prefix_bits[ix]
codes[code_length_prefix_value[ix]] = ix & ((1 << bits) - 1)
}
codes
}
///|
let code_length_code_bits : FixedArray[Int32] = {
let bits = FixedArray::make(6, 0)
for ix in 0..<16 {
bits[code_length_prefix_value[ix]] = code_length_prefix_bits[ix]
}
bits
}