text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.CachedKeyDecoder = void 0;
  const utf8_1 = require("./utils/utf8");
  const DEFAULT_MAX_KEY_LENGTH = 16;
  const DEFAULT_MAX_LENGTH_PER_KEY = 16;
  class CachedKeyDecoder {
      constructor(maxKeyLength = DEFAULT_MAX_KEY_LENGTH, maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY) {
          this.maxKeyLength = maxKeyLength;
          this.maxLengthPerKey = maxLengthPerKey;
          this.hit = 0;
          this.miss = 0;
          // avoid `new Array(N)`, which makes a sparse array,
          // because a sparse array is typically slower than a non-sparse array.
          this.caches = [];
          for (let i = 0; i < this.maxKeyLength; i++) {
              this.caches.push([]);
          }
      }
      canBeCached(byteLength) {
          return byteLength > 0 && byteLength <= this.maxKeyLength;
      }
      find(bytes, inputOffset, byteLength) {
          const records = this.caches[byteLength - 1];
          FIND_CHUNK: for (const record of records) {
              const recordBytes = record.bytes;
              for (let j = 0; j < byteLength; j++) {
                  if (recordBytes[j] !== bytes[inputOffset + j]) {
                      continue FIND_CHUNK;
                  }
              }
              return record.str;
          }
          return null;
      }
      store(bytes, value) {
          const records = this.caches[bytes.length - 1];
          const record = { bytes, str: value };
          if (records.length >= this.maxLengthPerKey) {
              // `records` are full!
              // Set `record` to an arbitrary position.
              records[(Math.random() * records.length) | 0] = record;
          }
          else {
              records.push(record);
          }
      }
      decode(bytes, inputOffset, byteLength) {
          const cachedValue = this.find(bytes, inputOffset, byteLength);
          if (cachedValue != null) {
              this.hit++;
              return cachedValue;
          }
          this.miss++;
          const str = (0, utf8_1.utf8DecodeJs)(bytes, inputOffset, byteLength);
          // Ensure to copy a slice of bytes because the byte may be NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.
          const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength);
          this.store(slicedCopyOfBytes, str);
          return str;
      }
  }
  exports.CachedKeyDecoder = CachedKeyDecoder;
  //# sourceMappingURL=CachedKeyDecoder.js.map