const constants = require('./lib/constants') const ascii = require('./lib/ascii') const base64 = require('./lib/base64') const base64url = require('./lib/base64url') const hex = require('./lib/hex') const utf8 = require('./lib/utf8') const utf16le = require('./lib/utf16le') const latin1 = require('./lib/latin1') const binding = require('./binding') const checked = require('./lib/checked') const kind = Symbol.for('bare.buffer.kind') const SWAP_MIN_LENGTH = 128 let poolSize = 65536 let pool = null let poolLength = 0 let poolOffset = 0 class Buffer extends Uint8Array { static get [kind]() { return 0 // Compatibility version } static get poolSize() { return poolSize } static set poolSize(value) { assertSize(value, 'Pool size') poolSize = value } constructor(arrayBuffer, offset, length, opts = {}) { if (typeof arrayBuffer === 'number') { opts = offset || {} const { uninitialized = false } = opts offset = 0 length = arrayBuffer if (Number.isInteger(length) === false || length < 0 || length > constants.MAX_LENGTH) { throw new RangeError( `Buffer length must be an integer between 0 and ${constants.MAX_LENGTH}` ) } arrayBuffer = uninitialized ? binding.allocUnsafe(length) : binding.alloc(length) } else { if (typeof offset === 'number') assertInteger(offset, 'Offset') if (typeof length === 'number') assertInteger(length, 'Length') if (length > constants.MAX_LENGTH) { throw new RangeError(`Buffer length must be at most ${constants.MAX_LENGTH}`) } if (typeof offset === 'object' && offset !== null) { opts = offset offset = 0 length = arrayBuffer.byteLength } else if (typeof length === 'object' && length !== null) { opts = length length = arrayBuffer.byteLength - offset } } super(arrayBuffer, offset, length) } get [kind]() { return Buffer[kind] } copy(target, targetStart = 0, sourceStart = 0, sourceEnd = this.byteLength) { const source = this assertView(target, 'Target') assertSize(targetStart, 'Target start') assertSize(sourceStart, 'Source start') assertSize(sourceEnd, 'Source end') if (target.BYTES_PER_ELEMENT !== 1) { target = new Uint8Array(target.buffer, target.byteOffset, target.byteLength) } const sourceLength = source.byteLength const targetLength = target.byteLength if (sourceStart > sourceLength) { throw new RangeError(`Source start must be at most ${sourceLength}`) } if (targetStart >= targetLength) return 0 if (sourceEnd > sourceLength) sourceEnd = sourceLength if (sourceEnd <= sourceStart) return 0 const room = targetLength - targetStart if (sourceEnd - sourceStart > room) sourceEnd = sourceStart + room const length = sourceEnd - sourceStart if (source === target) { target.copyWithin(targetStart, sourceStart, sourceEnd) } else if (sourceStart === 0 && sourceEnd === sourceLength) { target.set(source, targetStart) } else { target.set( new Uint8Array(source.buffer, source.byteOffset + sourceStart, length), targetStart ) } return length } equals(target) { const source = this if (source === target) return true assertView(target, 'Target') const sourceLength = source.byteLength const targetLength = target.byteLength if (sourceLength !== targetLength) return false return ( checked( binding.compare( source.buffer, source.byteOffset, sourceLength, target.buffer, target.byteOffset, targetLength ) ) === 0 ) } compare( target, targetStart = 0, targetEnd = target.byteLength, sourceStart = 0, sourceEnd = this.byteLength ) { const source = this if (source === target) return 0 assertView(target, 'Target') const sourceLength = source.byteLength const targetLength = target.byteLength if (arguments.length === 1) { targetStart = 0 targetEnd = targetLength sourceStart = 0 sourceEnd = sourceLength } else { assertInteger(targetStart, 'Target start') assertInteger(targetEnd, 'Target end') assertInteger(sourceStart, 'Source start') assertInteger(sourceEnd, 'Source end') if (targetStart < 0) targetStart = 0 if (targetStart > targetLength) targetStart = targetLength if (targetEnd < targetStart) targetEnd = targetStart if (targetEnd > targetLength) targetEnd = targetLength if (sourceStart < 0) sourceStart = 0 if (sourceStart > sourceLength) sourceStart = sourceLength if (sourceEnd < sourceStart) sourceEnd = sourceStart if (sourceEnd > sourceLength) sourceEnd = sourceLength } return checked( binding.compare( source.buffer, source.byteOffset + sourceStart, sourceEnd - sourceStart, target.buffer, target.byteOffset + targetStart, targetEnd - targetStart ) ) } fill(value, offset = 0, end = this.byteLength, encoding = 'utf8') { if (typeof value === 'string') { if (typeof offset === 'string') { // fill(string, encoding) encoding = offset offset = 0 end = this.byteLength } else if (typeof end === 'string') { // fill(string, offset, encoding) encoding = end end = this.byteLength } } else if (typeof value === 'number') { value = value & 0xff } else if (typeof value === 'boolean') { value = +value } else if (ArrayBuffer.isView(value)) { if (value.BYTES_PER_ELEMENT !== 1) { value = new Uint8Array(value.buffer, value.byteOffset, value.byteLength) } } else { throw new TypeError( `Fill value must be a number, a string or a view, received type ${typeof value}` ) } assertInteger(offset, 'Offset') assertInteger(end, 'End') const byteLength = this.byteLength if (offset < 0) offset = 0 if (offset >= byteLength) return this if (end <= offset) return this if (end > byteLength) end = byteLength if (typeof value === 'number') return super.fill(value, offset, end) if (typeof value === 'string') value = exports.from(value, encoding) const length = value.byteLength if (length === 0) return super.fill(0, offset, end) if (length === 1) return super.fill(value[0], offset, end) return fillPattern(this, value, length, offset, end) } includes(value, offset, encoding) { return this.indexOf(value, offset, encoding) !== -1 } indexOf(value, offset = 0, encoding) { if (typeof offset === 'number') assertInteger(offset, 'Offset') if (typeof value === 'boolean') value = +value if (typeof value === 'number') { return super.indexOf(value & 0xff, offset) } return bidirectionalIndexOf(this, value, offset, encoding, true /* first */) } lastIndexOf(value, offset = this.byteLength - 1, encoding) { if (typeof offset === 'number') assertInteger(offset, 'Offset') if (typeof value === 'boolean') value = +value if (typeof value === 'number') { return super.lastIndexOf(value & 0xff, offset) } return bidirectionalIndexOf(this, value, offset, encoding, false /* last */) } swap16() { const length = this.byteLength if (length % 2 !== 0) { throw new RangeError('Buffer size must be a multiple of 16-bits') } if (length < SWAP_MIN_LENGTH) { for (let i = 0; i < length; i += 2) swap(this, i, i + 1) } else { checked(binding.swap16(this.buffer, this.byteOffset, length)) } return this } swap32() { const length = this.byteLength if (length % 4 !== 0) { throw new RangeError('Buffer size must be a multiple of 32-bits') } if (length < SWAP_MIN_LENGTH) { for (let i = 0; i < length; i += 4) { swap(this, i, i + 3) swap(this, i + 1, i + 2) } } else { checked(binding.swap32(this.buffer, this.byteOffset, length)) } return this } swap64() { const length = this.byteLength if (length % 8 !== 0) { throw new RangeError('Buffer size must be a multiple of 64-bits') } if (length < SWAP_MIN_LENGTH) { for (let i = 0; i < length; i += 8) { swap(this, i, i + 7) swap(this, i + 1, i + 6) swap(this, i + 2, i + 5) swap(this, i + 3, i + 4) } } else { checked(binding.swap64(this.buffer, this.byteOffset, length)) } return this } toString(encoding = 'utf8', start = 0, end = this.byteLength) { // toString() if (arguments.length === 0) return utf8.toString(this) // toString(encoding) if (arguments.length === 1) return codecFor(encoding).toString(this) assertInteger(start, 'Start') assertInteger(end, 'End') const length = this.byteLength if (start < 0) start = 0 if (start >= length) return '' if (end <= start) return '' if (end > length) end = length return codecFor(encoding).toString(this, start, end) } toJSON() { const length = this.byteLength const data = new Array(length) for (let i = 0; i < length; i++) data[i] = this[i] return data } write(string, offset = 0, length = this.byteLength - offset, encoding = 'utf8') { assertString(string, 'String') // write(string) if (arguments.length === 1) return utf8.write(this, string) if (typeof offset === 'string') { // write(string, encoding) encoding = offset offset = 0 length = this.byteLength } else if (typeof length === 'string') { // write(string, offset, encoding) encoding = length length = this.byteLength - offset } assertInteger(offset, 'Offset') assertInteger(length, 'Length') length = Math.min(length, exports.byteLength(string, encoding)) const byteLength = this.byteLength let start = offset if (start < 0) start = 0 if (start >= byteLength) return 0 let end = offset + length if (end <= start) return 0 if (end > byteLength) end = byteLength return codecFor(encoding).write(this, string, start, end) } readBigInt64BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getBigInt64(offset, false) } readBigInt64LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getBigInt64(offset, true) } readBigUint64BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getBigUint64(offset, false) } readBigUint64LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getBigUint64(offset, true) } readDoubleBE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getFloat64(offset, false) } readDoubleLE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getFloat64(offset, true) } readFloatBE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getFloat32(offset, false) } readFloatLE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) return viewOf(this).getFloat32(offset, true) } readInt8(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const value = this[offset] if (value === undefined) boundsError() return (value << 24) >> 24 } readInt16BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 1] if (first === undefined || last === undefined) boundsError() return (((first << 8) | last) << 16) >> 16 } readInt16LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 1] if (first === undefined || last === undefined) boundsError() return (((last << 8) | first) << 16) >> 16 } readInt32BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 3] if (first === undefined || last === undefined) boundsError() return (first << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | last } readInt32LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 3] if (first === undefined || last === undefined) boundsError() return first | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (last << 24) } readIntBE(offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return readInt48BE(this, offset) if (byteLength === 5) return readInt40BE(this, offset) if (byteLength === 3) return readInt24BE(this, offset) if (byteLength === 4) return this.readInt32BE(offset) if (byteLength === 2) return this.readInt16BE(offset) if (byteLength === 1) return this.readInt8(offset) throw new RangeError(`Byte length must be between 1 and 6`) } readIntLE(offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return readInt48LE(this, offset) if (byteLength === 5) return readInt40LE(this, offset) if (byteLength === 3) return readInt24LE(this, offset) if (byteLength === 4) return this.readInt32LE(offset) if (byteLength === 2) return this.readInt16LE(offset) if (byteLength === 1) return this.readInt8(offset) throw new RangeError(`Byte length must be between 1 and 6`) } readUint8(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const value = this[offset] if (value === undefined) boundsError() return value } readUint16BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 1] if (first === undefined || last === undefined) boundsError() return (first << 8) | last } readUint16LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 1] if (first === undefined || last === undefined) boundsError() return (last << 8) | first } readUint32BE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 3] if (first === undefined || last === undefined) boundsError() return first * 0x1000000 + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | last) } readUint32LE(offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) const first = this[offset] const last = this[offset + 3] if (first === undefined || last === undefined) boundsError() return last * 0x1000000 + ((this[offset + 2] << 16) | (this[offset + 1] << 8) | first) } readUintBE(offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return readUint48BE(this, offset) if (byteLength === 5) return readUint40BE(this, offset) if (byteLength === 3) return readUint24BE(this, offset) if (byteLength === 4) return this.readUint32BE(offset) if (byteLength === 2) return this.readUint16BE(offset) if (byteLength === 1) return this.readUint8(offset) throw new RangeError(`Byte length must be between 1 and 6`) } readUintLE(offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return readUint48LE(this, offset) if (byteLength === 5) return readUint40LE(this, offset) if (byteLength === 3) return readUint24LE(this, offset) if (byteLength === 4) return this.readUint32LE(offset) if (byteLength === 2) return this.readUint16LE(offset) if (byteLength === 1) return this.readUint8(offset) throw new RangeError(`Byte length must be between 1 and 6`) } writeBigInt64BE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setBigInt64(offset, value, false) return offset + 8 } writeBigInt64LE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setBigInt64(offset, value, true) return offset + 8 } writeBigUint64BE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setBigUint64(offset, value, false) return offset + 8 } writeBigUint64LE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setBigUint64(offset, value, true) return offset + 8 } writeDoubleBE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setFloat64(offset, value, false) return offset + 8 } writeDoubleLE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setFloat64(offset, value, true) return offset + 8 } writeFloatBE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setFloat32(offset, value, false) return offset + 4 } writeFloatLE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) viewOf(this).setFloat32(offset, value, true) return offset + 4 } writeInt8(value, offset = 0) { return this.writeUint8(value, offset) } writeInt16BE(value, offset = 0) { return this.writeUint16BE(value, offset) } writeInt16LE(value, offset = 0) { return this.writeUint16LE(value, offset) } writeInt32BE(value, offset = 0) { return this.writeUint32BE(value, offset) } writeInt32LE(value, offset = 0) { return this.writeUint32LE(value, offset) } writeIntBE(value, offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return writeInt48BE(this, value, offset) if (byteLength === 5) return writeInt40BE(this, value, offset) if (byteLength === 3) return writeInt24BE(this, value, offset) if (byteLength === 4) return this.writeInt32BE(value, offset) if (byteLength === 2) return this.writeInt16BE(value, offset) if (byteLength === 1) return this.writeInt8(value, offset) throw new RangeError(`Byte length must be between 1 and 6`) } writeIntLE(value, offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return writeInt48LE(this, value, offset) if (byteLength === 5) return writeInt40LE(this, value, offset) if (byteLength === 3) return writeInt24LE(this, value, offset) if (byteLength === 4) return this.writeInt32LE(value, offset) if (byteLength === 2) return this.writeInt16LE(value, offset) if (byteLength === 1) return this.writeInt8(value, offset) throw new RangeError(`Byte length must be between 1 and 6`) } writeUint8(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) if (this[offset] === undefined) boundsError() this[offset] = value return offset + 1 } writeUint16BE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) if (this[offset] === undefined || this[offset + 1] === undefined) boundsError() this[offset] = value >>> 8 this[offset + 1] = value return offset + 2 } writeUint16LE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) if (this[offset] === undefined || this[offset + 1] === undefined) boundsError() this[offset] = value this[offset + 1] = value >>> 8 return offset + 2 } writeUint32LE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) if (this[offset] === undefined || this[offset + 3] === undefined) boundsError() this[offset] = value this[offset + 1] = value >>> 8 this[offset + 2] = value >>> 16 this[offset + 3] = value >>> 24 return offset + 4 } writeUint32BE(value, offset = 0) { if (!Number.isInteger(offset)) offsetError(offset) if (this[offset] === undefined || this[offset + 3] === undefined) boundsError() this[offset] = value >>> 24 this[offset + 1] = value >>> 16 this[offset + 2] = value >>> 8 this[offset + 3] = value return offset + 4 } writeUintBE(value, offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return writeUint48BE(this, value, offset) if (byteLength === 5) return writeUint40BE(this, value, offset) if (byteLength === 3) return writeUint24BE(this, value, offset) if (byteLength === 4) return this.writeUint32BE(value, offset) if (byteLength === 2) return this.writeUint16BE(value, offset) if (byteLength === 1) return this.writeUint8(value, offset) throw new RangeError(`Byte length must be between 1 and 6`) } writeUintLE(value, offset, byteLength) { if (!Number.isInteger(offset)) offsetError(offset) if (byteLength === 6) return writeUint48LE(this, value, offset) if (byteLength === 5) return writeUint40LE(this, value, offset) if (byteLength === 3) return writeUint24LE(this, value, offset) if (byteLength === 4) return this.writeUint32LE(value, offset) if (byteLength === 2) return this.writeUint16LE(value, offset) if (byteLength === 1) return this.writeUint8(value, offset) throw new RangeError(`Byte length must be between 1 and 6`) } } for (const [alias, name] of [ ['readBigUInt64BE', 'readBigUint64BE'], ['readBigUInt64LE', 'readBigUint64LE'], ['readUInt8', 'readUint8'], ['readUInt16BE', 'readUint16BE'], ['readUInt16LE', 'readUint16LE'], ['readUInt32BE', 'readUint32BE'], ['readUInt32LE', 'readUint32LE'], ['readUIntBE', 'readUintBE'], ['readUIntLE', 'readUintLE'], ['writeBigUInt64BE', 'writeBigUint64BE'], ['writeBigUInt64LE', 'writeBigUint64LE'], ['writeUInt8', 'writeUint8'], ['writeUInt16BE', 'writeUint16BE'], ['writeUInt16LE', 'writeUint16LE'], ['writeUInt32BE', 'writeUint32BE'], ['writeUInt32LE', 'writeUint32LE'], ['writeUIntBE', 'writeUintBE'], ['writeUIntLE', 'writeUintLE'] ]) { Object.defineProperty(Buffer.prototype, alias, { value: Buffer.prototype[name], writable: true, configurable: true }) } module.exports = exports = Buffer exports.Buffer = Buffer // For Node.js compatibility exports.constants = constants const codecs = Object.create(null) codecs.ascii = ascii codecs.base64 = base64 codecs.base64url = base64url codecs.hex = hex codecs.utf8 = codecs['utf-8'] = utf8 codecs.utf16le = codecs.ucs2 = codecs['utf-16le'] = codecs['ucs-2'] = utf16le codecs.latin1 = codecs.binary = latin1 function codecFor(encoding) { if (encoding === undefined) return utf8 let codec = codecs[encoding] if (codec !== undefined) return codec if (typeof encoding !== 'string') { throw new TypeError(`Encoding must be a string, received type ${typeof encoding}`) } codec = codecs[encoding.toLowerCase()] if (codec !== undefined) return codec throw new Error(`Unknown encoding '${encoding}'`) } const views = new WeakMap() function viewOf(buffer) { let view = views.get(buffer) if (view === undefined) { const store = buffer.buffer view = new DataView(store, buffer.byteOffset, buffer.byteLength) // A view of a store that can still change size covers the wrong range as // soon as it does, or falls out of bounds entirely, so it is only worth // remembering one of a store that cannot. if (store.resizable !== true && store.growable !== true) { views.set(buffer, view) } } return view } exports.isBuffer = function isBuffer(value) { if (value instanceof Buffer) return true return typeof value === 'object' && value !== null && value[kind] === Buffer[kind] } exports.isEncoding = function isEncoding(encoding) { try { codecFor(encoding) return true } catch { return false } } exports.isASCII = function isASCII(buffer) { return ascii.validate(buffer) } // for Node.js compatibily exports.isAscii = exports.isASCII exports.isUTF8 = function isUTF8(buffer) { return utf8.validate(buffer) } // for Node.js compatibility exports.isUtf8 = exports.isUTF8 exports.alloc = function alloc(size, fill, encoding) { assertSize(size, 'Size') if (fill !== undefined && fill !== 0) { const buffer = new Buffer(size, { uninitialized: true }) return buffer.fill(fill, 0, buffer.byteLength, encoding) } return new Buffer(size) } exports.allocUnsafe = function allocUnsafe(size) { assertSize(size, 'Size') return allocate(size) } exports.allocUnsafeSlow = function allocUnsafeSlow(size) { assertSize(size, 'Size') return new Buffer(size, { uninitialized: true }) } function assertInteger(value, name) { if (typeof value !== 'number') { throw new TypeError(`${name} must be a number, received type ${typeof value}`) } if (Number.isInteger(value) === false) { throw new RangeError(`${name} must be an integer`) } } function assertString(value, name) { if (typeof value !== 'string') { throw new TypeError(`${name} must be a string, received type ${typeof value}`) } } function assertView(value, name) { if (ArrayBuffer.isView(value) === false) { throw new TypeError(`${name} must be a view, received type ${typeof value}`) } } function assertSize(size, name) { if (typeof size !== 'number') { throw new TypeError(`${name} must be a number, received type ${typeof size}`) } if (Number.isInteger(size) === false || size < 0 || size > constants.MAX_LENGTH) { throw new RangeError(`${name} must be an integer between 0 and ${constants.MAX_LENGTH}`) } } exports.byteLength = function byteLength(string, encoding) { if (typeof string === 'string') { return codecFor(encoding).byteLength(string) } return string.byteLength } exports.compare = function compare(a, b) { assertView(a, 'First buffer') assertView(b, 'Second buffer') return checked( binding.compare(a.buffer, a.byteOffset, a.byteLength, b.buffer, b.byteOffset, b.byteLength) ) } exports.concat = function concat(buffers, length) { const n = buffers.length for (let i = 0; i < n; i++) { const buffer = buffers[i] if (ArrayBuffer.isView(buffer) === false || buffer.BYTES_PER_ELEMENT !== 1) { throw new TypeError(`buffers[${i}] must be a view of single bytes`) } } if (length === undefined) { length = 0 for (let i = 0; i < n; i++) length += buffers[i].byteLength } else { assertSize(length, 'Length') } const result = allocate(length) let offset = 0 for (let i = 0; i < n; i++) { const buffer = buffers[i] const buffered = buffer.byteLength if (offset + buffered > length) { const remaining = length - offset result.set(new Uint8Array(buffer.buffer, buffer.byteOffset, remaining), offset) offset = length break } result.set(buffer, offset) offset += buffered } // Only the bytes the inputs did not reach need initializing. if (offset < length) result.fill(0, offset, length) return result } exports.coerce = function coerce(buffer) { if (exports.isBuffer(buffer)) return buffer return new Buffer(buffer.buffer, buffer.byteOffset, buffer.byteLength) } exports.copyBytesFrom = function copyBytesFrom(view, offset = 0, length = view.length - offset) { assertSize(offset, 'Offset') assertSize(length, 'Length') if (offset + length > view.length) { throw new RangeError('View length is out of range') } if (offset !== 0 || length !== view.length) { view = view.subarray(offset, offset + length) } return new Buffer(view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength)) } exports.from = function from(value, encodingOrOffset, length) { // from(string, encoding) if (typeof value === 'string') return fromString(value, encodingOrOffset) // from(array) if (Array.isArray(value)) return fromArray(value) // from(buffer) if (ArrayBuffer.isView(value)) return fromBuffer(value) // from(arrayBuffer[, offset[, length]]) return fromArrayBuffer(value, encodingOrOffset, length) } function fromString(string, encoding) { const codec = codecFor(encoding) const length = codec.byteLength(string) const buffer = allocate(length) const written = codec.write(buffer, string, 0, length) // Some codecs only know an upper bound before encoding, and the remainder is // uninitialized rather than zeroed. if (written < length) return buffer.subarray(0, written) return buffer } function fromArray(array) { const buffer = allocate(array.length) buffer.set(array) return buffer } function fromBuffer(buffer) { // A view is copied element wise, each element truncated to a byte, so the // copy is sized by element count and not by byte length. A view that is not // array like, such as a DataView, reports no length and has nothing to copy. const length = typeof buffer.length === 'number' ? buffer.length : 0 const copy = allocate(length) copy.set(buffer) return copy } function fromArrayBuffer(arrayBuffer, offset, length) { if (offset !== undefined) assertInteger(offset, 'Offset') if (length !== undefined) assertInteger(length, 'Length') return new Buffer(arrayBuffer, offset, length) } function bidirectionalIndexOf(buffer, value, offset, encoding, first) { if (typeof value !== 'string') assertView(value, 'Value') const length = buffer.byteLength if (length === 0) return -1 if (typeof offset === 'string') { encoding = offset offset = 0 } else if (offset === undefined) { offset = first ? 0 : length - 1 } else if (offset < 0) { offset += length } if (offset >= length) { if (first) return -1 else offset = length - 1 } else if (offset < 0) { if (first) offset = 0 else return -1 } if (typeof value === 'string') value = exports.from(value, encoding) const needleLength = value.byteLength if (needleLength === 0) return -1 const last = length - needleLength if (first) { if (offset > last) return -1 } else { if (offset > last) offset = last if (offset < 0) return -1 } // Confirming a match at the position the search starts from costs a handful // of comparisons, and keeps prefix checks off the native path entirely. let j = 0 while (j < needleLength && buffer[offset + j] === value[j]) j++ if (j === needleLength) return offset if (first) { if (offset === last) return -1 return checked( binding.indexOf( buffer.buffer, buffer.byteOffset, length, value.buffer, value.byteOffset, needleLength, offset + 1 ) ) } if (offset === 0) return -1 return checked( binding.lastIndexOf( buffer.buffer, buffer.byteOffset, length, value.buffer, value.byteOffset, needleLength, offset - 1 ) ) } // Writes the pattern once and then repeatedly doubles it in place, so the byte // wise work is proportional to the pattern rather than to the range. Each block // copied is a whole number of periods, which keeps the pattern aligned. function fillPattern(buffer, value, length, offset, end) { const n = end - offset // Below this the copies cost more than they save. if (n < 64) { for (let i = 0; i < n; i++) buffer[offset + i] = value[i % length] return buffer } let filled = length < n ? length : n for (let i = 0; i < filled; i++) buffer[offset + i] = value[i] while (filled < n) { const copy = filled < n - filled ? filled : n - filled buffer.copyWithin(offset + filled, offset, offset + copy) filled += copy } return buffer } function allocate(size) { if (Number.isNaN(size) || size <= 0 || size >= poolSize / 2) { return new Buffer(size, { uninitialized: true }) } if (pool === null || poolLength !== poolSize || poolLength - poolOffset < size) { pool = binding.allocUnsafe(poolSize) poolLength = poolSize poolOffset = 0 } const buffer = new Buffer(pool, poolOffset, size) // Keep the next buffer 8 byte aligned so the wider accessors are not needlessly // reading across word boundaries. poolOffset = (poolOffset + size + 7) & ~7 return buffer } function swap(buffer, n, m) { const i = buffer[n] buffer[n] = buffer[m] buffer[m] = i } exports.atob = function atob(data) { return Buffer.from(data, 'base64').toString('latin1') } exports.btoa = function btoa(data) { if (typeof data !== 'string') data = String(data) return Buffer.from(data, 'latin1').toString('base64') } exports.transcode = function transcode(buffer, from, to) { return Buffer.from(buffer.toString(from), to) } function boundsError() { throw new RangeError('Offset is outside the bounds of the buffer') } function offsetError(offset) { if (typeof offset !== 'number') { throw new TypeError(`Offset must be a number, received type ${typeof offset}`) } throw new RangeError('Offset must be an integer') } function readInt48BE(buffer, offset) { const value = readUint48BE(buffer, offset) return value >= 0x800000000000 ? value - 0x1000000000000 : value } function readInt48LE(buffer, offset) { const value = readUint48LE(buffer, offset) return value >= 0x800000000000 ? value - 0x1000000000000 : value } function readInt40BE(buffer, offset) { const value = readUint40BE(buffer, offset) return value >= 0x8000000000 ? value - 0x10000000000 : value } function readInt40LE(buffer, offset) { const value = readUint40LE(buffer, offset) return value >= 0x8000000000 ? value - 0x10000000000 : value } function readInt24BE(buffer, offset) { const value = readUint24BE(buffer, offset) return value & 0x800000 ? value - 0x1000000 : value } function readInt24LE(buffer, offset) { const value = readUint24LE(buffer, offset) return value & 0x800000 ? value - 0x1000000 : value } function readUint48BE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 5] if (first === undefined || last === undefined) boundsError() return ( (first * 0x100 + buffer[offset + 1]) * 0x100000000 + ((buffer[offset + 2] << 24) >>> 0) + (buffer[offset + 3] << 16) + (buffer[offset + 4] << 8) + last ) } function readUint48LE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 5] if (first === undefined || last === undefined) boundsError() return ( (buffer[offset + 4] + last * 0x100) * 0x100000000 + ((buffer[offset + 3] << 24) >>> 0) + (buffer[offset + 2] << 16) + (buffer[offset + 1] << 8) + first ) } function readUint40BE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 4] if (first === undefined || last === undefined) boundsError() return ( first * 0x100000000 + ((buffer[offset + 1] << 24) >>> 0) + (buffer[offset + 2] << 16) + (buffer[offset + 3] << 8) + last ) } function readUint40LE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 4] if (first === undefined || last === undefined) boundsError() return ( last * 0x100000000 + ((buffer[offset + 3] << 24) >>> 0) + (buffer[offset + 2] << 16) + (buffer[offset + 1] << 8) + first ) } function readUint24BE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 2] if (first === undefined || last === undefined) boundsError() return (first << 16) | (buffer[offset + 1] << 8) | last } function readUint24LE(buffer, offset) { const first = buffer[offset] const last = buffer[offset + 2] if (first === undefined || last === undefined) boundsError() return (last << 16) | (buffer[offset + 1] << 8) | first } function writeInt48BE(buffer, value, offset) { if (value < 0) value += 0x1000000000000 return writeUint48BE(buffer, value, offset) } function writeInt48LE(buffer, value, offset) { if (value < 0) value += 0x1000000000000 return writeUint48LE(buffer, value, offset) } function writeInt40BE(buffer, value, offset) { if (value < 0) value += 0x10000000000 return writeUint40BE(buffer, value, offset) } function writeInt40LE(buffer, value, offset) { if (value < 0) value += 0x10000000000 return writeUint40LE(buffer, value, offset) } function writeInt24BE(buffer, value, offset) { if (value < 0) value += 0x1000000 return writeUint24BE(buffer, value, offset) } function writeInt24LE(buffer, value, offset) { if (value < 0) value += 0x1000000 return writeUint24LE(buffer, value, offset) } function writeUint48BE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 5] === undefined) boundsError() const hi = Math.floor(value / 0x100000000) const lo = value >>> 0 buffer[offset] = hi >>> 8 buffer[offset + 1] = hi buffer[offset + 2] = lo >>> 24 buffer[offset + 3] = lo >>> 16 buffer[offset + 4] = lo >>> 8 buffer[offset + 5] = lo return offset + 6 } function writeUint48LE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 5] === undefined) boundsError() const hi = Math.floor(value / 0x100000000) const lo = value >>> 0 buffer[offset] = lo buffer[offset + 1] = lo >>> 8 buffer[offset + 2] = lo >>> 16 buffer[offset + 3] = lo >>> 24 buffer[offset + 4] = hi buffer[offset + 5] = hi >>> 8 return offset + 6 } function writeUint40BE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 4] === undefined) boundsError() const lo = value >>> 0 buffer[offset] = Math.floor(value / 0x100000000) buffer[offset + 1] = lo >>> 24 buffer[offset + 2] = lo >>> 16 buffer[offset + 3] = lo >>> 8 buffer[offset + 4] = lo return offset + 5 } function writeUint40LE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 4] === undefined) boundsError() const lo = value >>> 0 buffer[offset] = lo buffer[offset + 1] = lo >>> 8 buffer[offset + 2] = lo >>> 16 buffer[offset + 3] = lo >>> 24 buffer[offset + 4] = Math.floor(value / 0x100000000) return offset + 5 } function writeUint24BE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 2] === undefined) boundsError() buffer[offset] = value >>> 16 buffer[offset + 1] = value >>> 8 buffer[offset + 2] = value return offset + 3 } function writeUint24LE(buffer, value, offset) { if (buffer[offset] === undefined || buffer[offset + 2] === undefined) boundsError() buffer[offset] = value buffer[offset + 1] = value >>> 8 buffer[offset + 2] = value >>> 16 return offset + 3 }