export class TypedArrayManager {
  constructor(options = {}) {
    this._pool = [];
    this.opts = {
      overAlloc: 2,
      poolSize: 100
    };
    this.setOptions(options);
  }

  setOptions(options) {
    Object.assign(this.opts, options);
  }

  allocate(typedArray, count, {
    size = 1,
    type,
    padding = 0,
    copy = false,
    initialize = false,
    maxCount
  }) {
    const Type = type || typedArray && typedArray.constructor || Float32Array;
    const newSize = count * size + padding;

    if (ArrayBuffer.isView(typedArray)) {
      if (newSize <= typedArray.length) {
        return typedArray;
      }

      if (newSize * typedArray.BYTES_PER_ELEMENT <= typedArray.buffer.byteLength) {
        return new Type(typedArray.buffer, 0, newSize);
      }
    }

    let maxSize = Infinity;

    if (maxCount) {
      maxSize = maxCount * size + padding;
    }

    const newArray = this._allocate(Type, newSize, initialize, maxSize);

    if (typedArray && copy) {
      newArray.set(typedArray);
    } else if (!initialize) {
      newArray.fill(0, 0, 4);
    }

    this._release(typedArray);

    return newArray;
  }

  release(typedArray) {
    this._release(typedArray);
  }

  _allocate(Type, size, initialize, maxSize) {
    let sizeToAllocate = Math.max(Math.ceil(size * this.opts.overAlloc), 1);

    if (sizeToAllocate > maxSize) {
      sizeToAllocate = maxSize;
    }

    const pool = this._pool;
    const byteLength = Type.BYTES_PER_ELEMENT * sizeToAllocate;
    const i = pool.findIndex(b => b.byteLength >= byteLength);

    if (i >= 0) {
      const array = new Type(pool.splice(i, 1)[0], 0, sizeToAllocate);

      if (initialize) {
        array.fill(0);
      }

      return array;
    }

    return new Type(sizeToAllocate);
  }

  _release(typedArray) {
    if (!ArrayBuffer.isView(typedArray)) {
      return;
    }

    const pool = this._pool;
    const {
      buffer
    } = typedArray;
    const {
      byteLength
    } = buffer;
    const i = pool.findIndex(b => b.byteLength >= byteLength);

    if (i < 0) {
      pool.push(buffer);
    } else if (i > 0 || pool.length < this.opts.poolSize) {
      pool.splice(i, 0, buffer);
    }

    if (pool.length > this.opts.poolSize) {
      pool.shift();
    }
  }

}
export default new TypedArrayManager();
//# sourceMappingURL=typed-array-manager.js.map