function buildHuffmanTable(tableGroup, tableIdx, rootBits, codeLengths, codeLengthsSize) {
    let /** @type{number} */ tableOffset = tableGroup[tableIdx];
    let /** @type{number} */ key;
    let /** @type{!Int32Array} */ sorted = new Int32Array(codeLengthsSize);
    let /** @type{!Int32Array} */ count = new Int32Array(16);
    let /** @type{!Int32Array} */ offset = new Int32Array(16);
    let /** @type{number} */ symbol;
    for (symbol = 0; symbol < codeLengthsSize; symbol++) {
      count[codeLengths[symbol]]++;
    }
    offset[1] = 0;
    for (let /** @type{number} */ len = 1; len < 15; len++) {
      offset[len + 1] = offset[len] + count[len];
    }
    for (symbol = 0; symbol < codeLengthsSize; symbol++) {
      if (codeLengths[symbol] != 0) {
        sorted[offset[codeLengths[symbol]]++] = symbol;
      }
    }
    let /** @type{number} */ tableBits = rootBits;
    let /** @type{number} */ tableSize = 1 << tableBits;
    let /** @type{number} */ totalSize = tableSize;
    if (offset[15] == 1) {
      for (key = 0; key < totalSize; key++) {
        tableGroup[tableOffset + key] = sorted[0];
      }
      return totalSize;
    }
    key = 0;
    symbol = 0;
    for (let /** @type{number} */ len = 1, step = 2; len <= rootBits; len++, step <<= 1) {
      for (; count[len] > 0; count[len]--) {
        replicateValue(tableGroup, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);
        key = getNextKey(key, len);
      }
    }
    let /** @type{number} */ mask = totalSize - 1;
    let /** @type{number} */ low = -1;
    let /** @type{number} */ currentOffset = tableOffset;
    for (let /** @type{number} */ len = rootBits + 1, step = 2; len <= 15; len++, step <<= 1) {
      for (; count[len] > 0; count[len]--) {
        if ((key & mask) != low) {
          currentOffset += tableSize;
          tableBits = nextTableBitSize(count, len, rootBits);
          tableSize = 1 << tableBits;
          totalSize += tableSize;
          low = key & mask;
          tableGroup[tableOffset + low] = (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);
        }
        replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize, (len - rootBits) << 16 | sorted[symbol++]);
        key = getNextKey(key, len);
      }
    }
    return totalSize;
  }
@param {!Int32Array} tableGroup
@param {number} tableIdx
@param {number} rootBits
@param {!Int32Array} codeLengths
@param {number} codeLengthsSize
@return {number}