Skip to main content

NODE_BUFFER_JS

Constant NODE_BUFFER_JS 

Source
pub const NODE_BUFFER_JS: &str = r#"
// ─── Encoding helpers ────────────────────────────────────────────────────────

function utf8Encode(str) {
  return new TextEncoder().encode(str);
}

function utf8Decode(bytes, start, end) {
  return new TextDecoder().decode(bytes.subarray(start, end));
}

function hexEncode(bytes) {
  let out = '';
  for (let i = 0; i < bytes.length; i++) {
    out += bytes[i].toString(16).padStart(2, '0');
  }
  return out;
}

function hexDecode(str) {
  const len = str.length >>> 1;
  const bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = parseInt(str.slice(i * 2, i * 2 + 2), 16);
  }
  return bytes;
}

function base64Encode(bytes) {
  let binary = '';
  for (let i = 0; i < bytes.length; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return globalThis.btoa(binary);
}

function base64Decode(str) {
  const binary = globalThis.atob(str);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return bytes;
}

function latin1Encode(str) {
  const bytes = new Uint8Array(str.length);
  for (let i = 0; i < str.length; i++) {
    bytes[i] = str.charCodeAt(i) & 0xFF;
  }
  return bytes;
}

function latin1Decode(bytes, start, end) {
  let out = '';
  for (let i = start; i < end; i++) {
    out += String.fromCharCode(bytes[i]);
  }
  return out;
}

function normalizeEncoding(enc) {
  if (!enc || enc === 'utf8' || enc === 'utf-8') return 'utf8';
  const lower = enc.toLowerCase();
  if (lower === 'utf8' || lower === 'utf-8') return 'utf8';
  if (lower === 'hex') return 'hex';
  if (lower === 'base64') return 'base64';
  if (lower === 'ascii' || lower === 'binary' || lower === 'latin1') return 'latin1';
  return 'utf8';
}

function encodeString(str, encoding) {
  switch (normalizeEncoding(encoding)) {
    case 'hex': return hexDecode(str);
    case 'base64': return base64Decode(str);
    case 'latin1': return latin1Encode(str);
    default: return utf8Encode(str);
  }
}

function decodeBytes(bytes, encoding, start, end) {
  start = start || 0;
  end = end != null ? end : bytes.length;
  switch (normalizeEncoding(encoding)) {
    case 'hex': return hexEncode(bytes.subarray(start, end));
    case 'base64': return base64Encode(bytes.subarray(start, end));
    case 'latin1': return latin1Decode(bytes, start, end);
    default: return utf8Decode(bytes, start, end);
  }
}

// ─── Buffer class ────────────────────────────────────────────────────────────

class Buffer extends Uint8Array {
  // ── Static factory methods ─────────────────────────────────────────────
  static from(input, encodingOrOffset, length) {
    if (typeof input === 'string') {
      const bytes = encodeString(input, encodingOrOffset);
      const buf = new Buffer(bytes.length);
      buf.set(bytes);
      return buf;
    }
    if (input instanceof ArrayBuffer || input instanceof SharedArrayBuffer) {
      const offset = encodingOrOffset || 0;
      const len = length != null ? length : input.byteLength - offset;
      return new Buffer(input, offset, len);
    }
    if (ArrayBuffer.isView(input)) {
      const buf = new Buffer(input.length);
      buf.set(input);
      return buf;
    }
    if (Array.isArray(input)) {
      const buf = new Buffer(input.length);
      buf.set(input);
      return buf;
    }
    if (input && typeof input === 'object' && typeof input.length === 'number') {
      const buf = new Buffer(input.length);
      for (let i = 0; i < input.length; i++) buf[i] = input[i] & 0xFF;
      return buf;
    }
    throw new TypeError('The first argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.');
  }

  static alloc(size, fill, encoding) {
    const buf = new Buffer(size);
    if (fill !== undefined && fill !== 0) {
      buf.fill(fill, 0, size, encoding);
    }
    return buf;
  }

  static allocUnsafe(size) {
    return new Buffer(size);
  }

  static allocUnsafeSlow(size) {
    return new Buffer(size);
  }

  static isBuffer(obj) {
    return obj instanceof Buffer;
  }

  static isEncoding(encoding) {
    return ['utf8', 'utf-8', 'hex', 'base64', 'ascii', 'binary', 'latin1']
      .includes((encoding || '').toLowerCase());
  }

  static byteLength(string, encoding) {
    if (typeof string !== 'string') {
      if (ArrayBuffer.isView(string)) return string.byteLength;
      if (string instanceof ArrayBuffer) return string.byteLength;
      throw new TypeError('The "string" argument must be a string, Buffer, or ArrayBuffer');
    }
    return encodeString(string, encoding).length;
  }

  static concat(list, totalLength) {
    if (!Array.isArray(list)) throw new TypeError('"list" argument must be an Array of Buffers');
    if (list.length === 0) return Buffer.alloc(0);
    const total = totalLength != null
      ? totalLength
      : list.reduce((acc, b) => acc + b.length, 0);
    const result = Buffer.alloc(total);
    let offset = 0;
    for (const buf of list) {
      const src = buf instanceof Uint8Array ? buf : Buffer.from(buf);
      const copyLen = Math.min(src.length, total - offset);
      result.set(src.subarray(0, copyLen), offset);
      offset += copyLen;
      if (offset >= total) break;
    }
    return result;
  }

  static compare(a, b) {
    if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) {
      throw new TypeError('Arguments must be Buffers');
    }
    const len = Math.min(a.length, b.length);
    for (let i = 0; i < len; i++) {
      if (a[i] < b[i]) return -1;
      if (a[i] > b[i]) return 1;
    }
    if (a.length < b.length) return -1;
    if (a.length > b.length) return 1;
    return 0;
  }

  // ── Instance methods ───────────────────────────────────────────────────
  toString(encoding, start, end) {
    return decodeBytes(this, encoding, start, end);
  }

  write(string, offset, length, encoding) {
    if (typeof offset === 'string') { encoding = offset; offset = 0; length = this.length; }
    else if (typeof length === 'string') { encoding = length; length = this.length - (offset || 0); }
    offset = offset || 0;
    length = length != null ? length : this.length - offset;
    const bytes = encodeString(string, encoding);
    const writeLen = Math.min(bytes.length, length, this.length - offset);
    this.set(bytes.subarray(0, writeLen), offset);
    return writeLen;
  }

  toJSON() {
    return { type: 'Buffer', data: Array.from(this) };
  }

  equals(other) {
    if (!(other instanceof Uint8Array)) throw new TypeError('Argument must be a Buffer');
    return Buffer.compare(this, other) === 0;
  }

  compare(other, targetStart, targetEnd, sourceStart, sourceEnd) {
    if (!(other instanceof Uint8Array)) throw new TypeError('Argument must be a Buffer');
    targetStart = targetStart || 0;
    targetEnd = targetEnd != null ? targetEnd : other.length;
    sourceStart = sourceStart || 0;
    sourceEnd = sourceEnd != null ? sourceEnd : this.length;
    return Buffer.compare(
      this.subarray(sourceStart, sourceEnd),
      other.subarray(targetStart, targetEnd)
    );
  }

  copy(target, targetStart, sourceStart, sourceEnd) {
    targetStart = targetStart || 0;
    sourceStart = sourceStart || 0;
    sourceEnd = sourceEnd != null ? sourceEnd : this.length;
    const len = Math.min(sourceEnd - sourceStart, target.length - targetStart);
    target.set(this.subarray(sourceStart, sourceStart + len), targetStart);
    return len;
  }

  indexOf(value, byteOffset, encoding) {
    if (typeof value === 'number') {
      byteOffset = byteOffset || 0;
      for (let i = byteOffset; i < this.length; i++) {
        if (this[i] === (value & 0xFF)) return i;
      }
      return -1;
    }
    if (typeof value === 'string') {
      value = Buffer.from(value, encoding);
    }
    if (value instanceof Uint8Array) {
      byteOffset = byteOffset || 0;
      if (value.length === 0) return byteOffset <= this.length ? byteOffset : -1;
      outer: for (let i = byteOffset; i <= this.length - value.length; i++) {
        for (let j = 0; j < value.length; j++) {
          if (this[i + j] !== value[j]) continue outer;
        }
        return i;
      }
    }
    return -1;
  }

  includes(value, byteOffset, encoding) {
    return this.indexOf(value, byteOffset, encoding) !== -1;
  }

  fill(value, offset, end, encoding) {
    offset = offset || 0;
    end = end != null ? end : this.length;
    if (typeof value === 'number') {
      for (let i = offset; i < end; i++) this[i] = value & 0xFF;
    } else if (typeof value === 'string') {
      const bytes = encodeString(value, encoding);
      if (bytes.length === 0) return this;
      for (let i = offset; i < end; i++) {
        this[i] = bytes[(i - offset) % bytes.length];
      }
    }
    return this;
  }

  slice(start, end) {
    const sliced = super.slice(start, end);
    const buf = new Buffer(sliced.length);
    buf.set(sliced);
    return buf;
  }

  subarray(start, end) {
    // Override to return a Buffer, not a plain Uint8Array
    const sub = super.subarray(start, end);
    Object.setPrototypeOf(sub, Buffer.prototype);
    return sub;
  }

  swap16() {
    if (this.length % 2 !== 0) throw new RangeError('Buffer size must be a multiple of 16-bits');
    for (let i = 0; i < this.length; i += 2) {
      const t = this[i]; this[i] = this[i + 1]; this[i + 1] = t;
    }
    return this;
  }

  swap32() {
    if (this.length % 4 !== 0) throw new RangeError('Buffer size must be a multiple of 32-bits');
    for (let i = 0; i < this.length; i += 4) {
      const t0 = this[i], t1 = this[i + 1];
      this[i] = this[i + 3]; this[i + 1] = this[i + 2];
      this[i + 2] = t1; this[i + 3] = t0;
    }
    return this;
  }

  // Read/write integers (LE/BE) — commonly used by extensions
  readUInt8(offset) {
    offset = offset >>> 0;
    if (offset >= this.length) throw new RangeError('Index out of range');
    return this[offset];
  }

  readUInt16LE(offset) {
    offset = offset >>> 0;
    if (offset + 2 > this.length) throw new RangeError('Index out of range');
    return this[offset] | (this[offset + 1] << 8);
  }

  readUInt16BE(offset) {
    offset = offset >>> 0;
    if (offset + 2 > this.length) throw new RangeError('Index out of range');
    return (this[offset] << 8) | this[offset + 1];
  }

  readUInt32LE(offset) {
    offset = offset >>> 0;
    if (offset + 4 > this.length) throw new RangeError('Index out of range');
    return (this[offset] | (this[offset+1] << 8) | (this[offset+2] << 16)) + (this[offset+3] * 0x1000000);
  }

  readUInt32BE(offset) {
    offset = offset >>> 0;
    if (offset + 4 > this.length) throw new RangeError('Index out of range');
    return (this[offset] * 0x1000000) + ((this[offset+1] << 16) | (this[offset+2] << 8) | this[offset+3]);
  }

  readInt8(offset) {
    offset = offset >>> 0;
    if (offset >= this.length) throw new RangeError('Index out of range');
    const v = this[offset];
    return v > 127 ? v - 256 : v;
  }

  writeUInt8(value, offset) {
    offset = offset >>> 0;
    if (offset >= this.length) throw new RangeError('Index out of range');
    this[offset] = value & 0xFF;
    return offset + 1;
  }

  writeUInt16LE(value, offset) {
    offset = offset >>> 0;
    if (offset + 2 > this.length) throw new RangeError('Index out of range');
    this[offset] = value & 0xFF;
    this[offset + 1] = (value >>> 8) & 0xFF;
    return offset + 2;
  }

  writeUInt16BE(value, offset) {
    offset = offset >>> 0;
    if (offset + 2 > this.length) throw new RangeError('Index out of range');
    this[offset] = (value >>> 8) & 0xFF;
    this[offset + 1] = value & 0xFF;
    return offset + 2;
  }

  writeUInt32LE(value, offset) {
    offset = offset >>> 0;
    if (offset + 4 > this.length) throw new RangeError('Index out of range');
    this[offset] = value & 0xFF;
    this[offset+1] = (value >>> 8) & 0xFF;
    this[offset+2] = (value >>> 16) & 0xFF;
    this[offset+3] = (value >>> 24) & 0xFF;
    return offset + 4;
  }

  writeUInt32BE(value, offset) {
    offset = offset >>> 0;
    if (offset + 4 > this.length) throw new RangeError('Index out of range');
    this[offset] = (value >>> 24) & 0xFF;
    this[offset+1] = (value >>> 16) & 0xFF;
    this[offset+2] = (value >>> 8) & 0xFF;
    this[offset+3] = value & 0xFF;
    return offset + 4;
  }
}

// Make Buffer available globally (Node.js compatibility)
globalThis.Buffer = Buffer;

export { Buffer };
export default { Buffer };
"#;
Expand description

The JS source for the node:buffer virtual module.