function readBitPacked(reader, header, bitWidth, output, seen) {
  let count = header >> 1 << 3 // values to read
  const mask = (1 << bitWidth) - 1

  let data = 0
  if (reader.offset < reader.view.byteLength) {
    data = reader.view.getUint8(reader.offset++)
  } else if (mask) {
    // sometimes out-of-bounds reads are masked out
    throw new Error(`parquet bitpack offset ${reader.offset} out of range`)
  }
  let left = 8
  let right = 0

  // read values
  while (count) {
    // if we have crossed a byte boundary, shift the data
    if (right > 8) {
      right -= 8
      left -= 8
      data >>>= 8
    } else if (left - right < bitWidth) {
      // if we don't have bitWidth number of bits to read, read next byte
      data |= reader.view.getUint8(reader.offset) << left
      reader.offset++
      left += 8
    } else {
      if (seen < output.length) {
        // emit value
        output[seen++] = data >> right & mask
      }
      count--
      right += bitWidth
    }
  }

  return seen
}
Read a bit-packed run of the rle/bitpack hybrid.
Supports width > 8 (crossing bytes).

@param {DataReader} reader
@param {number} header - bit-pack header
@param {number} bitWidth
@param {DecodedArray} output
@param {number} seen
@returns {number} total output values so far