Skip to main content
Module

std/node/internal/buffer.mjs

Deno standard library
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.// Copyright Joyent and Node contributors. All rights reserved. MIT license.// Copyright Feross Aboukhadijeh, and other contributors. All rights reserved. MIT license.
import { codes } from "./error_codes.ts";import { encodings } from "../internal_binding/string_decoder.ts";import { indexOfBuffer } from "../internal_binding/buffer.ts";import { asciiToBytes, base64ToBytes, base64UrlToBytes, hexToBytes, utf16leToBytes,} from "../internal_binding/_utils.ts";
const utf8Encoder = new TextEncoder();
// Temporary buffers to convert numbers.const float32Array = new Float32Array(1);const uInt8Float32Array = new Uint8Array(float32Array.buffer);const float64Array = new Float64Array(1);const uInt8Float64Array = new Uint8Array(float64Array.buffer);
// Check endianness.float32Array[0] = -1; // 0xBF800000// Either it is [0, 0, 128, 191] or [191, 128, 0, 0]. It is not possible to// check this with `os.endianness()` because that is determined at compile time.export const bigEndian = uInt8Float32Array[3] === 0;
export function readUInt48LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 5]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 6); }
return first + buf[++offset] * 2 ** 8 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 24 + (buf[++offset] + last * 2 ** 8) * 2 ** 32;}
export function readUInt40LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 4]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 5); }
return first + buf[++offset] * 2 ** 8 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 24 + last * 2 ** 32;}
export function readUInt24LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 3); }
return first + buf[++offset] * 2 ** 8 + last * 2 ** 16;}
export function readUInt48BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 5]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 6); }
return (first * 2 ** 8 + buf[++offset]) * 2 ** 32 + buf[++offset] * 2 ** 24 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 8 + last;}
export function readUInt40BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 4]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 5); }
return first * 2 ** 32 + buf[++offset] * 2 ** 24 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 8 + last;}
export function readUInt24BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 3); }
return first * 2 ** 16 + buf[++offset] * 2 ** 8 + last;}
export function readUInt16BE(offset = 0) { validateNumber(offset, "offset"); const first = this[offset]; const last = this[offset + 1]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 2); }
return first * 2 ** 8 + last;}
export function readUInt32BE(offset = 0) { validateNumber(offset, "offset"); const first = this[offset]; const last = this[offset + 3]; if (first === undefined || last === undefined) { boundsError(offset, this.length - 4); }
return first * 2 ** 24 + this[++offset] * 2 ** 16 + this[++offset] * 2 ** 8 + last;}
export function readDoubleBackwards(buffer, offset = 0) { validateNumber(offset, "offset"); const first = buffer[offset]; const last = buffer[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, buffer.length - 8); }
uInt8Float64Array[7] = first; uInt8Float64Array[6] = buffer[++offset]; uInt8Float64Array[5] = buffer[++offset]; uInt8Float64Array[4] = buffer[++offset]; uInt8Float64Array[3] = buffer[++offset]; uInt8Float64Array[2] = buffer[++offset]; uInt8Float64Array[1] = buffer[++offset]; uInt8Float64Array[0] = last; return float64Array[0];}
export function readDoubleForwards(buffer, offset = 0) { validateNumber(offset, "offset"); const first = buffer[offset]; const last = buffer[offset + 7]; if (first === undefined || last === undefined) { boundsError(offset, buffer.length - 8); }
uInt8Float64Array[0] = first; uInt8Float64Array[1] = buffer[++offset]; uInt8Float64Array[2] = buffer[++offset]; uInt8Float64Array[3] = buffer[++offset]; uInt8Float64Array[4] = buffer[++offset]; uInt8Float64Array[5] = buffer[++offset]; uInt8Float64Array[6] = buffer[++offset]; uInt8Float64Array[7] = last; return float64Array[0];}
export function writeDoubleForwards(buffer, val, offset = 0) { val = +val; checkBounds(buffer, offset, 7);
float64Array[0] = val; buffer[offset++] = uInt8Float64Array[0]; buffer[offset++] = uInt8Float64Array[1]; buffer[offset++] = uInt8Float64Array[2]; buffer[offset++] = uInt8Float64Array[3]; buffer[offset++] = uInt8Float64Array[4]; buffer[offset++] = uInt8Float64Array[5]; buffer[offset++] = uInt8Float64Array[6]; buffer[offset++] = uInt8Float64Array[7]; return offset;}
export function writeDoubleBackwards(buffer, val, offset = 0) { val = +val; checkBounds(buffer, offset, 7);
float64Array[0] = val; buffer[offset++] = uInt8Float64Array[7]; buffer[offset++] = uInt8Float64Array[6]; buffer[offset++] = uInt8Float64Array[5]; buffer[offset++] = uInt8Float64Array[4]; buffer[offset++] = uInt8Float64Array[3]; buffer[offset++] = uInt8Float64Array[2]; buffer[offset++] = uInt8Float64Array[1]; buffer[offset++] = uInt8Float64Array[0]; return offset;}
export function readFloatBackwards(buffer, offset = 0) { validateNumber(offset, "offset"); const first = buffer[offset]; const last = buffer[offset + 3]; if (first === undefined || last === undefined) { boundsError(offset, buffer.length - 4); }
uInt8Float32Array[3] = first; uInt8Float32Array[2] = buffer[++offset]; uInt8Float32Array[1] = buffer[++offset]; uInt8Float32Array[0] = last; return float32Array[0];}
export function readFloatForwards(buffer, offset = 0) { validateNumber(offset, "offset"); const first = buffer[offset]; const last = buffer[offset + 3]; if (first === undefined || last === undefined) { boundsError(offset, buffer.length - 4); }
uInt8Float32Array[0] = first; uInt8Float32Array[1] = buffer[++offset]; uInt8Float32Array[2] = buffer[++offset]; uInt8Float32Array[3] = last; return float32Array[0];}
export function writeFloatForwards(buffer, val, offset = 0) { val = +val; checkBounds(buffer, offset, 3);
float32Array[0] = val; buffer[offset++] = uInt8Float32Array[0]; buffer[offset++] = uInt8Float32Array[1]; buffer[offset++] = uInt8Float32Array[2]; buffer[offset++] = uInt8Float32Array[3]; return offset;}
export function writeFloatBackwards(buffer, val, offset = 0) { val = +val; checkBounds(buffer, offset, 3);
float32Array[0] = val; buffer[offset++] = uInt8Float32Array[3]; buffer[offset++] = uInt8Float32Array[2]; buffer[offset++] = uInt8Float32Array[1]; buffer[offset++] = uInt8Float32Array[0]; return offset;}
export function readInt24LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 3); }
const val = first + buf[++offset] * 2 ** 8 + last * 2 ** 16; return val | (val & 2 ** 23) * 0x1fe;}
export function readInt40LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 4]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 5); }
return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 + first + buf[++offset] * 2 ** 8 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 24;}
export function readInt48LE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 5]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 6); }
const val = buf[offset + 4] + last * 2 ** 8; return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 + first + buf[++offset] * 2 ** 8 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 24;}
export function readInt24BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 2]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 3); }
const val = first * 2 ** 16 + buf[++offset] * 2 ** 8 + last; return val | (val & 2 ** 23) * 0x1fe;}
export function readInt48BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 5]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 6); }
const val = buf[++offset] + first * 2 ** 8; return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 + buf[++offset] * 2 ** 24 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 8 + last;}
export function readInt40BE(buf, offset = 0) { validateNumber(offset, "offset"); const first = buf[offset]; const last = buf[offset + 4]; if (first === undefined || last === undefined) { boundsError(offset, buf.length - 5); }
return (first | (first & 2 ** 7) * 0x1fffffe) * 2 ** 32 + buf[++offset] * 2 ** 24 + buf[++offset] * 2 ** 16 + buf[++offset] * 2 ** 8 + last;}
export function byteLengthUtf8(str) { return utf8Encoder.encode(str).length;}
function base64ByteLength(str, bytes) { // Handle padding if (str.charCodeAt(bytes - 1) === 0x3D) { bytes--; } if (bytes > 1 && str.charCodeAt(bytes - 1) === 0x3D) { bytes--; }
// Base64 ratio: 3/4 return (bytes * 3) >>> 2;}
export const encodingsMap = Object.create(null);for (let i = 0; i < encodings.length; ++i) { encodingsMap[encodings[i]] = i;}
export const encodingOps = { ascii: { byteLength: (string) => string.length, encoding: "ascii", encodingVal: encodingsMap.ascii, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, asciiToBytes(val), byteOffset, encodingsMap.ascii, dir, ), slice: (buf, start, end) => buf.asciiSlice(start, end), write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len), }, base64: { byteLength: (string) => base64ByteLength(string, string.length), encoding: "base64", encodingVal: encodingsMap.base64, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, base64ToBytes(val), byteOffset, encodingsMap.base64, dir, ), slice: (buf, start, end) => buf.base64Slice(start, end), write: (buf, string, offset, len) => buf.base64Write(string, offset, len), }, base64url: { byteLength: (string) => base64ByteLength(string, string.length), encoding: "base64url", encodingVal: encodingsMap.base64url, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, base64UrlToBytes(val), byteOffset, encodingsMap.base64url, dir, ), slice: (buf, start, end) => buf.base64urlSlice(start, end), write: (buf, string, offset, len) => buf.base64urlWrite(string, offset, len), }, hex: { byteLength: (string) => string.length >>> 1, encoding: "hex", encodingVal: encodingsMap.hex, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, hexToBytes(val), byteOffset, encodingsMap.hex, dir, ), slice: (buf, start, end) => buf.hexSlice(start, end), write: (buf, string, offset, len) => buf.hexWrite(string, offset, len), }, latin1: { byteLength: (string) => string.length, encoding: "latin1", encodingVal: encodingsMap.latin1, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, asciiToBytes(val), byteOffset, encodingsMap.latin1, dir, ), slice: (buf, start, end) => buf.latin1Slice(start, end), write: (buf, string, offset, len) => buf.latin1Write(string, offset, len), }, ucs2: { byteLength: (string) => string.length * 2, encoding: "ucs2", encodingVal: encodingsMap.utf16le, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, utf16leToBytes(val), byteOffset, encodingsMap.utf16le, dir, ), slice: (buf, start, end) => buf.ucs2Slice(start, end), write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), }, utf8: { byteLength: byteLengthUtf8, encoding: "utf8", encodingVal: encodingsMap.utf8, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, utf8Encoder.encode(val), byteOffset, encodingsMap.utf8, dir, ), slice: (buf, start, end) => buf.utf8Slice(start, end), write: (buf, string, offset, len) => buf.utf8Write(string, offset, len), }, utf16le: { byteLength: (string) => string.length * 2, encoding: "utf16le", encodingVal: encodingsMap.utf16le, indexOf: (buf, val, byteOffset, dir) => indexOfBuffer( buf, utf16leToBytes(val), byteOffset, encodingsMap.utf16le, dir, ), slice: (buf, start, end) => buf.ucs2Slice(start, end), write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), },};
export function getEncodingOps(encoding) { encoding = String(encoding).toLowerCase(); switch (encoding.length) { case 4: if (encoding === "utf8") return encodingOps.utf8; if (encoding === "ucs2") return encodingOps.ucs2; break; case 5: if (encoding === "utf-8") return encodingOps.utf8; if (encoding === "ascii") return encodingOps.ascii; if (encoding === "ucs-2") return encodingOps.ucs2; break; case 7: if (encoding === "utf16le") { return encodingOps.utf16le; } break; case 8: if (encoding === "utf-16le") { return encodingOps.utf16le; } break; // deno-lint-ignore no-fallthrough case 6: if (encoding === "latin1" || encoding === "binary") { return encodingOps.latin1; } if (encoding === "base64") return encodingOps.base64; case 3: if (encoding === "hex") { return encodingOps.hex; } break; case 9: if (encoding === "base64url") { return encodingOps.base64url; } break; }}
export function _copyActual( source, target, targetStart, sourceStart, sourceEnd,) { if (sourceEnd - sourceStart > target.length - targetStart) { sourceEnd = sourceStart + target.length - targetStart; }
let nb = sourceEnd - sourceStart; const sourceLen = source.length - sourceStart; if (nb > sourceLen) { nb = sourceLen; }
if (sourceStart !== 0 || sourceEnd < source.length) { source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb); }
target.set(source, targetStart);
return nb;}
export function boundsError(value, length, type) { if (Math.floor(value) !== value) { validateNumber(value, type); throw new codes.ERR_OUT_OF_RANGE(type || "offset", "an integer", value); }
if (length < 0) { throw new codes.ERR_BUFFER_OUT_OF_BOUNDS(); }
throw new codes.ERR_OUT_OF_RANGE( type || "offset", `>= ${type ? 1 : 0} and <= ${length}`, value, );}
export function validateNumber(value, name) { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); }}
function checkBounds(buf, offset, byteLength) { validateNumber(offset, "offset"); if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { boundsError(offset, buf.length - (byteLength + 1)); }}
function checkInt(value, min, max, buf, offset, byteLength) { if (value > max || value < min) { const n = typeof min === "bigint" ? "n" : ""; let range; if (byteLength > 3) { if (min === 0 || min === 0n) { range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`; } else { range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and ` + `< 2${n} ** ${(byteLength + 1) * 8 - 1}${n}`; } } else { range = `>= ${min}${n} and <= ${max}${n}`; } throw new codes.ERR_OUT_OF_RANGE("value", range, value); } checkBounds(buf, offset, byteLength);}
export function toInteger(n, defaultVal) { n = +n; if ( !Number.isNaN(n) && n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER ) { return ((n % 1) === 0 ? n : Math.floor(n)); } return defaultVal;}
// deno-lint-ignore camelcaseexport function writeU_Int8(buf, value, offset, min, max) { value = +value; validateNumber(offset, "offset"); if (value > max || value < min) { throw new codes.ERR_OUT_OF_RANGE("value", `>= ${min} and <= ${max}`, value); } if (buf[offset] === undefined) { boundsError(offset, buf.length - 1); }
buf[offset] = value; return offset + 1;}
// deno-lint-ignore camelcaseexport function writeU_Int16BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 1);
buf[offset++] = value >>> 8; buf[offset++] = value; return offset;}
export function _writeUInt32LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3);
buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; return offset;}
// deno-lint-ignore camelcaseexport function writeU_Int16LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 1);
buf[offset++] = value; buf[offset++] = value >>> 8; return offset;}
export function _writeUInt32BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3);
buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4;}
// deno-lint-ignore camelcaseexport function writeU_Int48BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 5);
const newVal = Math.floor(value * 2 ** -32); buf[offset++] = newVal >>> 8; buf[offset++] = newVal; buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4;}
// deno-lint-ignore camelcaseexport function writeU_Int40BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 4);
buf[offset++] = Math.floor(value * 2 ** -32); buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4;}
// deno-lint-ignore camelcaseexport function writeU_Int32BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3);
buf[offset + 3] = value; value = value >>> 8; buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 4;}
// deno-lint-ignore camelcaseexport function writeU_Int24BE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 2);
buf[offset + 2] = value; value = value >>> 8; buf[offset + 1] = value; value = value >>> 8; buf[offset] = value; return offset + 3;}
export function validateOffset( value, name, min = 0, max = Number.MAX_SAFE_INTEGER,) { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } if (!Number.isInteger(value)) { throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value); } if (value < min || value > max) { throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); }}
// deno-lint-ignore camelcaseexport function writeU_Int48LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 5);
const newVal = Math.floor(value * 2 ** -32); buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; buf[offset++] = newVal; buf[offset++] = newVal >>> 8; return offset;}
// deno-lint-ignore camelcaseexport function writeU_Int40LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 4);
const newVal = value; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; buf[offset++] = Math.floor(newVal * 2 ** -32); return offset;}
// deno-lint-ignore camelcaseexport function writeU_Int32LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 3);
buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; return offset;}
// deno-lint-ignore camelcaseexport function writeU_Int24LE(buf, value, offset, min, max) { value = +value; checkInt(value, min, max, buf, offset, 2);
buf[offset++] = value; value = value >>> 8; buf[offset++] = value; value = value >>> 8; buf[offset++] = value; return offset;}