// LSB-first bit sink for the encode pipeline. DEFLATE packs bits LSB-first
// into bytes, but Huffman codes are written MSB-first.
///|
priv struct BitWriter {
out : Array[Byte]
mut bitbuf : Int
mut bit_count : Int // bits currently held in `bitbuf`, not yet flushed to a byte
}
///|
fn BitWriter::new() -> BitWriter {
{ out: [], bitbuf: 0, bit_count: 0, }
}
///|
fn BitWriter::write_bit(self : BitWriter, bit : Int) -> Unit {
self.bitbuf = self.bitbuf | (bit << self.bit_count)
self.bit_count = self.bit_count + 1
if self.bit_count == 8 {
self.out.push((self.bitbuf & 0xFF).to_byte())
self.bitbuf = 0
self.bit_count = 0
}
}
///|
/// Write the low `n` bits of `value`, LSB-first. Batched: the bits are shifted
/// into the accumulator in one step and complete bytes flushed whole, instead
/// of looping one bit at a time.
fn BitWriter::write_bits(self : BitWriter, value : Int, n : Int) -> Unit {
self.bitbuf = self.bitbuf | ((value & ((1 << n) - 1)) << self.bit_count)
self.bit_count = self.bit_count + n
while self.bit_count >= 8 {
self.out.push((self.bitbuf & 0xFF).to_byte())
self.bitbuf = self.bitbuf >> 8
self.bit_count = self.bit_count - 8
}
}
///|
/// Write an `n`-bit Huffman code, MSB-first.
fn BitWriter::write_code(self : BitWriter, code : Int, n : Int) -> Unit {
self.write_bits(
reverse_bits(code.reinterpret_as_uint(), n).reinterpret_as_int(),
n,
)
}
///|
/// Write an already-bit-reversed Huffman code, LSB-first.
fn BitWriter::write_rcode(self : BitWriter, code : UInt, n : Int) -> Unit {
self.write_bits(code.reinterpret_as_int(), n)
}
///|
/// Pad any sub-byte remainder in `bitbuf` out to a whole byte (zero-filling the
/// high bits) and emit it. Required before a byte-aligned stored block and at
/// the very end of a stream
fn BitWriter::flush(self : BitWriter) -> Unit {
if self.bit_count > 0 {
self.out.push((self.bitbuf & 0xFF).to_byte())
self.bitbuf = 0
self.bit_count = 0
}
}