initial commit
This commit is contained in:
321
node_modules/uint8array-extras/index.js
generated
vendored
Normal file
321
node_modules/uint8array-extras/index.js
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
const objectToString = Object.prototype.toString;
|
||||
const uint8ArrayStringified = '[object Uint8Array]';
|
||||
const arrayBufferStringified = '[object ArrayBuffer]';
|
||||
|
||||
function isType(value, typeConstructor, typeStringified) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value.constructor === typeConstructor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return objectToString.call(value) === typeStringified;
|
||||
}
|
||||
|
||||
export function isUint8Array(value) {
|
||||
return isType(value, Uint8Array, uint8ArrayStringified);
|
||||
}
|
||||
|
||||
function isArrayBuffer(value) {
|
||||
return isType(value, ArrayBuffer, arrayBufferStringified);
|
||||
}
|
||||
|
||||
function isUint8ArrayOrArrayBuffer(value) {
|
||||
return isUint8Array(value) || isArrayBuffer(value);
|
||||
}
|
||||
|
||||
export function assertUint8Array(value) {
|
||||
if (!isUint8Array(value)) {
|
||||
throw new TypeError(`Expected \`Uint8Array\`, got \`${typeof value}\``);
|
||||
}
|
||||
}
|
||||
|
||||
export function assertUint8ArrayOrArrayBuffer(value) {
|
||||
if (!isUint8ArrayOrArrayBuffer(value)) {
|
||||
throw new TypeError(`Expected \`Uint8Array\` or \`ArrayBuffer\`, got \`${typeof value}\``);
|
||||
}
|
||||
}
|
||||
|
||||
export function toUint8Array(value) {
|
||||
if (value instanceof ArrayBuffer) {
|
||||
return new Uint8Array(value);
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(value)) {
|
||||
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
||||
}
|
||||
|
||||
throw new TypeError(`Unsupported value, got \`${typeof value}\`.`);
|
||||
}
|
||||
|
||||
export function concatUint8Arrays(arrays, totalLength) {
|
||||
if (arrays.length === 0) {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
|
||||
totalLength ??= arrays.reduce((accumulator, currentValue) => accumulator + currentValue.length, 0);
|
||||
|
||||
const returnValue = new Uint8Array(totalLength);
|
||||
|
||||
let offset = 0;
|
||||
for (const array of arrays) {
|
||||
assertUint8Array(array);
|
||||
returnValue.set(array, offset);
|
||||
offset += array.length;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
export function areUint8ArraysEqual(a, b) {
|
||||
assertUint8Array(a);
|
||||
assertUint8Array(b);
|
||||
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/no-for-loop
|
||||
for (let index = 0; index < a.length; index++) {
|
||||
if (a[index] !== b[index]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function compareUint8Arrays(a, b) {
|
||||
assertUint8Array(a);
|
||||
assertUint8Array(b);
|
||||
|
||||
const length = Math.min(a.length, b.length);
|
||||
|
||||
for (let index = 0; index < length; index++) {
|
||||
const diff = a[index] - b[index];
|
||||
if (diff !== 0) {
|
||||
return Math.sign(diff);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, all the compared elements are equal.
|
||||
// The shorter array should come first if the arrays are of different lengths.
|
||||
return Math.sign(a.length - b.length);
|
||||
}
|
||||
|
||||
const cachedDecoders = {
|
||||
utf8: new globalThis.TextDecoder('utf8'),
|
||||
};
|
||||
|
||||
export function uint8ArrayToString(array, encoding = 'utf8') {
|
||||
assertUint8ArrayOrArrayBuffer(array);
|
||||
cachedDecoders[encoding] ??= new globalThis.TextDecoder(encoding);
|
||||
return cachedDecoders[encoding].decode(array);
|
||||
}
|
||||
|
||||
function assertString(value) {
|
||||
if (typeof value !== 'string') {
|
||||
throw new TypeError(`Expected \`string\`, got \`${typeof value}\``);
|
||||
}
|
||||
}
|
||||
|
||||
const cachedEncoder = new globalThis.TextEncoder();
|
||||
|
||||
export function stringToUint8Array(string) {
|
||||
assertString(string);
|
||||
return cachedEncoder.encode(string);
|
||||
}
|
||||
|
||||
function base64ToBase64Url(base64) {
|
||||
return base64.replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');
|
||||
}
|
||||
|
||||
function base64UrlToBase64(base64url) {
|
||||
return base64url.replaceAll('-', '+').replaceAll('_', '/');
|
||||
}
|
||||
|
||||
// Reference: https://phuoc.ng/collection/this-vs-that/concat-vs-push/
|
||||
const MAX_BLOCK_SIZE = 65_535;
|
||||
|
||||
export function uint8ArrayToBase64(array, {urlSafe = false} = {}) {
|
||||
assertUint8Array(array);
|
||||
|
||||
let base64;
|
||||
|
||||
if (array.length < MAX_BLOCK_SIZE) {
|
||||
// Required as `btoa` and `atob` don't properly support Unicode: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem
|
||||
base64 = globalThis.btoa(String.fromCodePoint.apply(this, array));
|
||||
} else {
|
||||
base64 = '';
|
||||
for (const value of array) {
|
||||
base64 += String.fromCodePoint(value);
|
||||
}
|
||||
|
||||
base64 = globalThis.btoa(base64);
|
||||
}
|
||||
|
||||
return urlSafe ? base64ToBase64Url(base64) : base64;
|
||||
}
|
||||
|
||||
export function base64ToUint8Array(base64String) {
|
||||
assertString(base64String);
|
||||
return Uint8Array.from(globalThis.atob(base64UrlToBase64(base64String)), x => x.codePointAt(0));
|
||||
}
|
||||
|
||||
export function stringToBase64(string, {urlSafe = false} = {}) {
|
||||
assertString(string);
|
||||
return uint8ArrayToBase64(stringToUint8Array(string), {urlSafe});
|
||||
}
|
||||
|
||||
export function base64ToString(base64String) {
|
||||
assertString(base64String);
|
||||
return uint8ArrayToString(base64ToUint8Array(base64String));
|
||||
}
|
||||
|
||||
const byteToHexLookupTable = Array.from({length: 256}, (_, index) => index.toString(16).padStart(2, '0'));
|
||||
|
||||
export function uint8ArrayToHex(array) {
|
||||
assertUint8Array(array);
|
||||
|
||||
// Concatenating a string is faster than using an array.
|
||||
let hexString = '';
|
||||
|
||||
// eslint-disable-next-line unicorn/no-for-loop -- Max performance is critical.
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
hexString += byteToHexLookupTable[array[index]];
|
||||
}
|
||||
|
||||
return hexString;
|
||||
}
|
||||
|
||||
const hexToDecimalLookupTable = {
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8,
|
||||
9: 9,
|
||||
a: 10,
|
||||
b: 11,
|
||||
c: 12,
|
||||
d: 13,
|
||||
e: 14,
|
||||
f: 15,
|
||||
A: 10,
|
||||
B: 11,
|
||||
C: 12,
|
||||
D: 13,
|
||||
E: 14,
|
||||
F: 15,
|
||||
};
|
||||
|
||||
export function hexToUint8Array(hexString) {
|
||||
assertString(hexString);
|
||||
|
||||
if (hexString.length % 2 !== 0) {
|
||||
throw new Error('Invalid Hex string length.');
|
||||
}
|
||||
|
||||
const resultLength = hexString.length / 2;
|
||||
const bytes = new Uint8Array(resultLength);
|
||||
|
||||
for (let index = 0; index < resultLength; index++) {
|
||||
const highNibble = hexToDecimalLookupTable[hexString[index * 2]];
|
||||
const lowNibble = hexToDecimalLookupTable[hexString[(index * 2) + 1]];
|
||||
|
||||
if (highNibble === undefined || lowNibble === undefined) {
|
||||
throw new Error(`Invalid Hex character encountered at position ${index * 2}`);
|
||||
}
|
||||
|
||||
bytes[index] = (highNibble << 4) | lowNibble; // eslint-disable-line no-bitwise
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
@param {DataView} view
|
||||
@returns {number}
|
||||
*/
|
||||
export function getUintBE(view) {
|
||||
const {byteLength} = view;
|
||||
|
||||
if (byteLength === 6) {
|
||||
return (view.getUint16(0) * (2 ** 32)) + view.getUint32(2);
|
||||
}
|
||||
|
||||
if (byteLength === 5) {
|
||||
return (view.getUint8(0) * (2 ** 32)) + view.getUint32(1);
|
||||
}
|
||||
|
||||
if (byteLength === 4) {
|
||||
return view.getUint32(0);
|
||||
}
|
||||
|
||||
if (byteLength === 3) {
|
||||
return (view.getUint8(0) * (2 ** 16)) + view.getUint16(1);
|
||||
}
|
||||
|
||||
if (byteLength === 2) {
|
||||
return view.getUint16(0);
|
||||
}
|
||||
|
||||
if (byteLength === 1) {
|
||||
return view.getUint8(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param {Uint8Array} array
|
||||
@param {Uint8Array} value
|
||||
@returns {number}
|
||||
*/
|
||||
export function indexOf(array, value) {
|
||||
const arrayLength = array.length;
|
||||
const valueLength = value.length;
|
||||
|
||||
if (valueLength === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (valueLength > arrayLength) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const validOffsetLength = arrayLength - valueLength;
|
||||
|
||||
for (let index = 0; index <= validOffsetLength; index++) {
|
||||
let isMatch = true;
|
||||
for (let index2 = 0; index2 < valueLength; index2++) {
|
||||
if (array[index + index2] !== value[index2]) {
|
||||
isMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMatch) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@param {Uint8Array} array
|
||||
@param {Uint8Array} value
|
||||
@returns {boolean}
|
||||
*/
|
||||
export function includes(array, value) {
|
||||
return indexOf(array, value) !== -1;
|
||||
}
|
||||
Reference in New Issue
Block a user