“use strict”; const idlUtils = require(“../generated/utils”); const conversions = require(“webidl-conversions”); const Blob = require(“../generated/Blob”);

exports.implementation = class BlobImpl {

constructor(args) {
  const parts = args[0];
  const properties = args[1];

  const buffers = [];

  if (parts !== undefined) {
    if (parts === null || typeof parts !== "object" || typeof parts[Symbol.iterator] !== "function") {
      throw new TypeError("parts must be an iterable object");
    }

    const arr = [];
    for (const part of parts) {
      if (part instanceof ArrayBuffer || ArrayBuffer.isView(part) || Blob.is(part)) {
        arr.push(idlUtils.tryImplForWrapper(part));
      } else {
        arr.push(conversions.USVString(part));
      }
    }

    for (const part of arr) {
      let buffer;
      if (part instanceof ArrayBuffer) {
        buffer = new Buffer(new Uint8Array(part));
      } else if (ArrayBuffer.isView(part)) {
        buffer = new Buffer(new Uint8Array(part.buffer, part.byteOffset, part.byteLength));
      } else if (Blob.isImpl(part)) {
        buffer = part._buffer;
      } else {
        buffer = new Buffer(part);
      }
      buffers.push(buffer);
    }
  }

  this._buffer = Buffer.concat(buffers);

  this.type = properties.type;
  if (/[^\u0020-\u007E]/.test(this.type)) {
    this.type = "";
  } else {
    this.type = this.type.toLowerCase();
  }

  this.isClosed = false;
}

get size() {
  return this.isClosed ? 0 : this._buffer.length;
}

slice(start, end, contentType) {
  const size = this.size;

  let relativeStart;
  let relativeEnd;
  let relativeContentType;

  if (start === undefined) {
    relativeStart = 0;
  } else if (start < 0) {
    relativeStart = Math.max(size + start, 0);
  } else {
    relativeStart = Math.min(start, size);
  }
  if (end === undefined) {
    relativeEnd = size;
  } else if (end < 0) {
    relativeEnd = Math.max(size + end, 0);
  } else {
    relativeEnd = Math.min(end, size);
  }

  if (contentType === undefined) {
    relativeContentType = "";
  } else {
    // sanitization (lower case and invalid char check) is done in the
    // constructor
    relativeContentType = contentType;
  }

  const span = Math.max(relativeEnd - relativeStart, 0);

  const buffer = this._buffer;
  const slicedBuffer = buffer.slice(
    relativeStart,
    relativeStart + span
  );

  const blob = Blob.createImpl([[], { type: relativeContentType }], {});
  blob.isClosed = this.isClosed;
  blob._buffer = slicedBuffer;
  return blob;
}

close() {
  this.isClosed = true;
}

};