// 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.
fn BitWriter::write_bits(self : BitWriter, value : Int, n : Int) -> Unit {
  for i in 0..> i) & 1)
  }
}

///|
/// Write an `n`-bit Huffman code, MSB-first.
fn BitWriter::write_code(self : BitWriter, code : Int, n : Int) -> Unit {
  for i = n - 1; i >= 0; i = i - 1 {
    self.write_bit((code >> i) & 1)
  }
}

///|
/// 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, it is only valid 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
  }
}