63
node_modules/bson/src/utils/byte_utils.ts
generated
vendored
Normal file
63
node_modules/bson/src/utils/byte_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import { nodeJsByteUtils } from './node_byte_utils';
|
||||
import { webByteUtils } from './web_byte_utils';
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @experimental
|
||||
*
|
||||
* A collection of functions that help work with data in a Uint8Array.
|
||||
* ByteUtils is configured at load time to use Node.js or Web based APIs for the internal implementations.
|
||||
*/
|
||||
export type ByteUtils = {
|
||||
/** Transforms the input to an instance of Buffer if running on node, otherwise Uint8Array */
|
||||
toLocalBufferType: (buffer: Uint8Array | ArrayBufferView | ArrayBuffer) => Uint8Array;
|
||||
/** Create empty space of size */
|
||||
allocate: (size: number) => Uint8Array;
|
||||
/** Create empty space of size, use pooled memory when available */
|
||||
allocateUnsafe: (size: number) => Uint8Array;
|
||||
/** Check if two Uint8Arrays are deep equal */
|
||||
equals: (a: Uint8Array, b: Uint8Array) => boolean;
|
||||
/** Check if two Uint8Arrays are deep equal */
|
||||
fromNumberArray: (array: number[]) => Uint8Array;
|
||||
/** Create a Uint8Array from a base64 string */
|
||||
fromBase64: (base64: string) => Uint8Array;
|
||||
/** Create a base64 string from bytes */
|
||||
toBase64: (buffer: Uint8Array) => string;
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
fromISO88591: (codePoints: string) => Uint8Array;
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
toISO88591: (buffer: Uint8Array) => string;
|
||||
/** Create a Uint8Array from a hex string */
|
||||
fromHex: (hex: string) => Uint8Array;
|
||||
/** Create a lowercase hex string from bytes */
|
||||
toHex: (buffer: Uint8Array) => string;
|
||||
/** Create a string from utf8 code units, fatal=true will throw an error if UTF-8 bytes are invalid, fatal=false will insert replacement characters */
|
||||
toUTF8: (buffer: Uint8Array, start: number, end: number, fatal: boolean) => string;
|
||||
/** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
|
||||
utf8ByteLength: (input: string) => number;
|
||||
/** Encode UTF8 bytes generated from `source` string into `destination` at byteOffset. Returns the number of bytes encoded. */
|
||||
encodeUTF8Into: (destination: Uint8Array, source: string, byteOffset: number) => number;
|
||||
/** Generate a Uint8Array filled with random bytes with byteLength */
|
||||
randomBytes: (byteLength: number) => Uint8Array;
|
||||
/** Interprets `buffer` as an array of 32-bit values and swaps the byte order in-place. */
|
||||
swap32: (buffer: Uint8Array) => Uint8Array;
|
||||
};
|
||||
|
||||
declare const Buffer: { new (): unknown; prototype?: { _isBuffer?: boolean } } | undefined;
|
||||
|
||||
/**
|
||||
* Check that a global Buffer exists that is a function and
|
||||
* does not have a '_isBuffer' property defined on the prototype
|
||||
* (this is to prevent using the npm buffer)
|
||||
*/
|
||||
const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
|
||||
|
||||
/**
|
||||
* This is the only ByteUtils that should be used across the rest of the BSON library.
|
||||
*
|
||||
* The type annotation is important here, it asserts that each of the platform specific
|
||||
* utils implementations are compatible with the common one.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const ByteUtils: ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
|
||||
104
node_modules/bson/src/utils/latin.ts
generated
vendored
Normal file
104
node_modules/bson/src/utils/latin.ts
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* This function is an optimization for small basic latin strings.
|
||||
* @internal
|
||||
* @remarks
|
||||
* ### Important characteristics:
|
||||
* - If the uint8array or distance between start and end is 0 this function returns an empty string
|
||||
* - If the byteLength of the string is 1, 2, or 3 we invoke String.fromCharCode and manually offset into the buffer
|
||||
* - If the byteLength of the string is less than or equal to 20 an array of bytes is built and `String.fromCharCode.apply` is called with the result
|
||||
* - If any byte exceeds 128 this function returns null
|
||||
*
|
||||
* @param uint8array - A sequence of bytes that may contain basic latin characters
|
||||
* @param start - The start index from which to search the uint8array
|
||||
* @param end - The index to stop searching the uint8array
|
||||
* @returns string if all bytes are within the basic latin range, otherwise null
|
||||
*/
|
||||
export function tryReadBasicLatin(
|
||||
uint8array: Uint8Array,
|
||||
start: number,
|
||||
end: number
|
||||
): string | null {
|
||||
if (uint8array.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const stringByteLength = end - start;
|
||||
if (stringByteLength === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (stringByteLength > 20) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (stringByteLength === 1 && uint8array[start] < 128) {
|
||||
return String.fromCharCode(uint8array[start]);
|
||||
}
|
||||
|
||||
if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
|
||||
return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
|
||||
}
|
||||
|
||||
if (
|
||||
stringByteLength === 3 &&
|
||||
uint8array[start] < 128 &&
|
||||
uint8array[start + 1] < 128 &&
|
||||
uint8array[start + 2] < 128
|
||||
) {
|
||||
return (
|
||||
String.fromCharCode(uint8array[start]) +
|
||||
String.fromCharCode(uint8array[start + 1]) +
|
||||
String.fromCharCode(uint8array[start + 2])
|
||||
);
|
||||
}
|
||||
|
||||
const latinBytes = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
const byte = uint8array[i];
|
||||
if (byte > 127) {
|
||||
return null;
|
||||
}
|
||||
latinBytes.push(byte);
|
||||
}
|
||||
|
||||
return String.fromCharCode(...latinBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is an optimization for writing small basic latin strings.
|
||||
* @internal
|
||||
* @remarks
|
||||
* ### Important characteristics:
|
||||
* - If the string length is 0 return 0, do not perform any work
|
||||
* - If a string is longer than 25 code units return null
|
||||
* - If any code unit exceeds 128 this function returns null
|
||||
*
|
||||
* @param destination - The uint8array to serialize the string to
|
||||
* @param source - The string to turn into UTF-8 bytes if it fits in the basic latin range
|
||||
* @param offset - The position in the destination to begin writing bytes to
|
||||
* @returns the number of bytes written to destination if all code units are below 128, otherwise null
|
||||
*/
|
||||
export function tryWriteBasicLatin(
|
||||
destination: Uint8Array,
|
||||
source: string,
|
||||
offset: number
|
||||
): number | null {
|
||||
if (source.length === 0) return 0;
|
||||
|
||||
if (source.length > 25) return null;
|
||||
|
||||
if (destination.length - offset < source.length) return null;
|
||||
|
||||
for (
|
||||
let charOffset = 0, destinationOffset = offset;
|
||||
charOffset < source.length;
|
||||
charOffset++, destinationOffset++
|
||||
) {
|
||||
const char = source.charCodeAt(charOffset);
|
||||
if (char > 127) return null;
|
||||
|
||||
destination[destinationOffset] = char;
|
||||
}
|
||||
|
||||
return source.length;
|
||||
}
|
||||
168
node_modules/bson/src/utils/node_byte_utils.ts
generated
vendored
Normal file
168
node_modules/bson/src/utils/node_byte_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
import { BSONError } from '../error';
|
||||
import { parseUtf8 } from '../parse_utf8';
|
||||
import { tryReadBasicLatin, tryWriteBasicLatin } from './latin';
|
||||
|
||||
type NodeJsEncoding = 'base64' | 'hex' | 'utf8' | 'binary';
|
||||
type NodeJsBuffer = ArrayBufferView &
|
||||
Uint8Array & {
|
||||
write(string: string, offset: number, length: undefined, encoding: 'utf8'): number;
|
||||
copy(target: Uint8Array, targetStart: number, sourceStart: number, sourceEnd: number): number;
|
||||
toString: (this: Uint8Array, encoding: NodeJsEncoding, start?: number, end?: number) => string;
|
||||
equals: (this: Uint8Array, other: Uint8Array) => boolean;
|
||||
swap32: (this: NodeJsBuffer) => NodeJsBuffer;
|
||||
};
|
||||
type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
|
||||
alloc: (size: number) => NodeJsBuffer;
|
||||
allocUnsafe: (size: number) => NodeJsBuffer;
|
||||
from(array: number[]): NodeJsBuffer;
|
||||
from(array: Uint8Array): NodeJsBuffer;
|
||||
from(array: ArrayBuffer): NodeJsBuffer;
|
||||
from(array: ArrayBuffer, byteOffset: number, byteLength: number): NodeJsBuffer;
|
||||
from(base64: string, encoding: NodeJsEncoding): NodeJsBuffer;
|
||||
byteLength(input: string, encoding: 'utf8'): number;
|
||||
isBuffer(value: unknown): value is NodeJsBuffer;
|
||||
};
|
||||
|
||||
// This can be nullish, but we gate the nodejs functions on being exported whether or not this exists
|
||||
// Node.js global
|
||||
declare const Buffer: NodeJsBufferConstructor;
|
||||
declare const require: (mod: 'crypto') => { randomBytes: (byteLength: number) => Uint8Array };
|
||||
|
||||
/** @internal */
|
||||
export function nodejsMathRandomBytes(byteLength: number) {
|
||||
return nodeJsByteUtils.fromNumberArray(
|
||||
Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* WARNING: REQUIRE WILL BE REWRITTEN
|
||||
*
|
||||
* This code is carefully used by require_rewriter.mjs any modifications must be reflected in the plugin.
|
||||
*
|
||||
* @remarks
|
||||
* "crypto" is the only dependency BSON needs. This presents a problem for creating a bundle of the BSON library
|
||||
* in an es module format that can be used both on the browser and in Node.js. In Node.js when BSON is imported as
|
||||
* an es module, there will be no global require function defined, making the code below fallback to the much less desireable math.random bytes.
|
||||
* In order to make our es module bundle work as expected on Node.js we need to change this `require()` to a dynamic import, and the dynamic
|
||||
* import must be top-level awaited since es modules are async. So we rely on a custom rollup plugin to seek out the following lines of code
|
||||
* and replace `require` with `await import` and the IIFE line (`nodejsRandomBytes = (() => { ... })()`) with `nodejsRandomBytes = await (async () => { ... })()`
|
||||
* when generating an es module bundle.
|
||||
*/
|
||||
const nodejsRandomBytes: (byteLength: number) => Uint8Array = (() => {
|
||||
try {
|
||||
return require('crypto').randomBytes;
|
||||
} catch {
|
||||
return nodejsMathRandomBytes;
|
||||
}
|
||||
})();
|
||||
|
||||
/** @internal */
|
||||
export const nodeJsByteUtils = {
|
||||
toLocalBufferType(potentialBuffer: Uint8Array | NodeJsBuffer | ArrayBuffer): NodeJsBuffer {
|
||||
if (Buffer.isBuffer(potentialBuffer)) {
|
||||
return potentialBuffer;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(potentialBuffer)) {
|
||||
return Buffer.from(
|
||||
potentialBuffer.buffer,
|
||||
potentialBuffer.byteOffset,
|
||||
potentialBuffer.byteLength
|
||||
);
|
||||
}
|
||||
|
||||
const stringTag =
|
||||
potentialBuffer?.[Symbol.toStringTag] ?? Object.prototype.toString.call(potentialBuffer);
|
||||
if (
|
||||
stringTag === 'ArrayBuffer' ||
|
||||
stringTag === 'SharedArrayBuffer' ||
|
||||
stringTag === '[object ArrayBuffer]' ||
|
||||
stringTag === '[object SharedArrayBuffer]'
|
||||
) {
|
||||
return Buffer.from(potentialBuffer);
|
||||
}
|
||||
|
||||
throw new BSONError(`Cannot create Buffer from the passed potentialBuffer.`);
|
||||
},
|
||||
|
||||
allocate(size: number): NodeJsBuffer {
|
||||
return Buffer.alloc(size);
|
||||
},
|
||||
|
||||
allocateUnsafe(size: number): NodeJsBuffer {
|
||||
return Buffer.allocUnsafe(size);
|
||||
},
|
||||
|
||||
equals(a: Uint8Array, b: Uint8Array): boolean {
|
||||
return nodeJsByteUtils.toLocalBufferType(a).equals(b);
|
||||
},
|
||||
|
||||
fromNumberArray(array: number[]): NodeJsBuffer {
|
||||
return Buffer.from(array);
|
||||
},
|
||||
|
||||
fromBase64(base64: string): NodeJsBuffer {
|
||||
return Buffer.from(base64, 'base64');
|
||||
},
|
||||
|
||||
toBase64(buffer: Uint8Array): string {
|
||||
return nodeJsByteUtils.toLocalBufferType(buffer).toString('base64');
|
||||
},
|
||||
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
fromISO88591(codePoints: string): NodeJsBuffer {
|
||||
return Buffer.from(codePoints, 'binary');
|
||||
},
|
||||
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
toISO88591(buffer: Uint8Array): string {
|
||||
return nodeJsByteUtils.toLocalBufferType(buffer).toString('binary');
|
||||
},
|
||||
|
||||
fromHex(hex: string): NodeJsBuffer {
|
||||
return Buffer.from(hex, 'hex');
|
||||
},
|
||||
|
||||
toHex(buffer: Uint8Array): string {
|
||||
return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
|
||||
},
|
||||
|
||||
toUTF8(buffer: Uint8Array, start: number, end: number, fatal: boolean): string {
|
||||
const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
|
||||
if (basicLatin != null) {
|
||||
return basicLatin;
|
||||
}
|
||||
|
||||
const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
|
||||
if (fatal) {
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
if (string.charCodeAt(i) === 0xfffd) {
|
||||
parseUtf8(buffer, start, end, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return string;
|
||||
},
|
||||
|
||||
utf8ByteLength(input: string): number {
|
||||
return Buffer.byteLength(input, 'utf8');
|
||||
},
|
||||
|
||||
encodeUTF8Into(buffer: Uint8Array, source: string, byteOffset: number): number {
|
||||
const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
|
||||
if (latinBytesWritten != null) {
|
||||
return latinBytesWritten;
|
||||
}
|
||||
|
||||
return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
|
||||
},
|
||||
|
||||
randomBytes: nodejsRandomBytes,
|
||||
|
||||
swap32(buffer: Uint8Array): NodeJsBuffer {
|
||||
return nodeJsByteUtils.toLocalBufferType(buffer).swap32();
|
||||
}
|
||||
};
|
||||
213
node_modules/bson/src/utils/number_utils.ts
generated
vendored
Normal file
213
node_modules/bson/src/utils/number_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
const FLOAT = new Float64Array(1);
|
||||
const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
|
||||
|
||||
FLOAT[0] = -1;
|
||||
// Little endian [0, 0, 0, 0, 0, 0, 240, 191]
|
||||
// Big endian [191, 240, 0, 0, 0, 0, 0, 0]
|
||||
const isBigEndian = FLOAT_BYTES[7] === 0;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* @public
|
||||
*
|
||||
* A collection of functions that get or set various numeric types and bit widths from a Uint8Array.
|
||||
*/
|
||||
export type NumberUtils = {
|
||||
/** Is true if the current system is big endian. */
|
||||
isBigEndian: boolean;
|
||||
/**
|
||||
* Parses a signed int32 at offset. Throws a `RangeError` if value is negative.
|
||||
*/
|
||||
getNonnegativeInt32LE: (source: Uint8Array, offset: number) => number;
|
||||
getInt32LE: (source: Uint8Array, offset: number) => number;
|
||||
getUint32LE: (source: Uint8Array, offset: number) => number;
|
||||
getUint32BE: (source: Uint8Array, offset: number) => number;
|
||||
getBigInt64LE: (source: Uint8Array, offset: number) => bigint;
|
||||
getFloat64LE: (source: Uint8Array, offset: number) => number;
|
||||
setInt32BE: (destination: Uint8Array, offset: number, value: number) => 4;
|
||||
setInt32LE: (destination: Uint8Array, offset: number, value: number) => 4;
|
||||
setBigInt64LE: (destination: Uint8Array, offset: number, value: bigint) => 8;
|
||||
setFloat64LE: (destination: Uint8Array, offset: number, value: number) => 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* Number parsing and serializing utilities.
|
||||
*
|
||||
* @experimental
|
||||
* @public
|
||||
*/
|
||||
export const NumberUtils: NumberUtils = {
|
||||
isBigEndian,
|
||||
|
||||
getNonnegativeInt32LE(source: Uint8Array, offset: number): number {
|
||||
if (source[offset + 3] > 127) {
|
||||
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
||||
}
|
||||
return (
|
||||
source[offset] |
|
||||
(source[offset + 1] << 8) |
|
||||
(source[offset + 2] << 16) |
|
||||
(source[offset + 3] << 24)
|
||||
);
|
||||
},
|
||||
|
||||
/** Reads a little-endian 32-bit integer from source */
|
||||
getInt32LE(source: Uint8Array, offset: number): number {
|
||||
return (
|
||||
source[offset] |
|
||||
(source[offset + 1] << 8) |
|
||||
(source[offset + 2] << 16) |
|
||||
(source[offset + 3] << 24)
|
||||
);
|
||||
},
|
||||
|
||||
/** Reads a little-endian 32-bit unsigned integer from source */
|
||||
getUint32LE(source: Uint8Array, offset: number): number {
|
||||
return (
|
||||
source[offset] +
|
||||
source[offset + 1] * 256 +
|
||||
source[offset + 2] * 65536 +
|
||||
source[offset + 3] * 16777216
|
||||
);
|
||||
},
|
||||
|
||||
/** Reads a big-endian 32-bit integer from source */
|
||||
getUint32BE(source: Uint8Array, offset: number): number {
|
||||
return (
|
||||
source[offset + 3] +
|
||||
source[offset + 2] * 256 +
|
||||
source[offset + 1] * 65536 +
|
||||
source[offset] * 16777216
|
||||
);
|
||||
},
|
||||
|
||||
/** Reads a little-endian 64-bit integer from source */
|
||||
getBigInt64LE(source: Uint8Array, offset: number): bigint {
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const hi = BigInt(
|
||||
source[offset + 4] +
|
||||
source[offset + 5] * 256 +
|
||||
source[offset + 6] * 65536 +
|
||||
(source[offset + 7] << 24)
|
||||
); // Overflow
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const lo = BigInt(
|
||||
source[offset] +
|
||||
source[offset + 1] * 256 +
|
||||
source[offset + 2] * 65536 +
|
||||
source[offset + 3] * 16777216
|
||||
);
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
return (hi << BigInt(32)) + lo;
|
||||
},
|
||||
|
||||
/** Reads a little-endian 64-bit float from source */
|
||||
getFloat64LE: isBigEndian
|
||||
? (source: Uint8Array, offset: number) => {
|
||||
FLOAT_BYTES[7] = source[offset];
|
||||
FLOAT_BYTES[6] = source[offset + 1];
|
||||
FLOAT_BYTES[5] = source[offset + 2];
|
||||
FLOAT_BYTES[4] = source[offset + 3];
|
||||
FLOAT_BYTES[3] = source[offset + 4];
|
||||
FLOAT_BYTES[2] = source[offset + 5];
|
||||
FLOAT_BYTES[1] = source[offset + 6];
|
||||
FLOAT_BYTES[0] = source[offset + 7];
|
||||
return FLOAT[0];
|
||||
}
|
||||
: (source: Uint8Array, offset: number) => {
|
||||
FLOAT_BYTES[0] = source[offset];
|
||||
FLOAT_BYTES[1] = source[offset + 1];
|
||||
FLOAT_BYTES[2] = source[offset + 2];
|
||||
FLOAT_BYTES[3] = source[offset + 3];
|
||||
FLOAT_BYTES[4] = source[offset + 4];
|
||||
FLOAT_BYTES[5] = source[offset + 5];
|
||||
FLOAT_BYTES[6] = source[offset + 6];
|
||||
FLOAT_BYTES[7] = source[offset + 7];
|
||||
return FLOAT[0];
|
||||
},
|
||||
|
||||
/** Writes a big-endian 32-bit integer to destination, can be signed or unsigned */
|
||||
setInt32BE(destination: Uint8Array, offset: number, value: number): 4 {
|
||||
destination[offset + 3] = value;
|
||||
value >>>= 8;
|
||||
destination[offset + 2] = value;
|
||||
value >>>= 8;
|
||||
destination[offset + 1] = value;
|
||||
value >>>= 8;
|
||||
destination[offset] = value;
|
||||
return 4;
|
||||
},
|
||||
|
||||
/** Writes a little-endian 32-bit integer to destination, can be signed or unsigned */
|
||||
setInt32LE(destination: Uint8Array, offset: number, value: number): 4 {
|
||||
destination[offset] = value;
|
||||
value >>>= 8;
|
||||
destination[offset + 1] = value;
|
||||
value >>>= 8;
|
||||
destination[offset + 2] = value;
|
||||
value >>>= 8;
|
||||
destination[offset + 3] = value;
|
||||
return 4;
|
||||
},
|
||||
|
||||
/** Write a little-endian 64-bit integer to source */
|
||||
setBigInt64LE(destination: Uint8Array, offset: number, value: bigint): 8 {
|
||||
/* eslint-disable-next-line no-restricted-globals -- This is allowed here as useBigInt64=true */
|
||||
const mask32bits = BigInt(0xffff_ffff);
|
||||
|
||||
/** lower 32 bits */
|
||||
let lo = Number(value & mask32bits);
|
||||
destination[offset] = lo;
|
||||
lo >>= 8;
|
||||
destination[offset + 1] = lo;
|
||||
lo >>= 8;
|
||||
destination[offset + 2] = lo;
|
||||
lo >>= 8;
|
||||
destination[offset + 3] = lo;
|
||||
|
||||
/*
|
||||
eslint-disable-next-line no-restricted-globals
|
||||
-- This is allowed here as useBigInt64=true
|
||||
|
||||
upper 32 bits
|
||||
*/
|
||||
let hi = Number((value >> BigInt(32)) & mask32bits);
|
||||
destination[offset + 4] = hi;
|
||||
hi >>= 8;
|
||||
destination[offset + 5] = hi;
|
||||
hi >>= 8;
|
||||
destination[offset + 6] = hi;
|
||||
hi >>= 8;
|
||||
destination[offset + 7] = hi;
|
||||
|
||||
return 8;
|
||||
},
|
||||
|
||||
/** Writes a little-endian 64-bit float to destination */
|
||||
setFloat64LE: isBigEndian
|
||||
? (destination: Uint8Array, offset: number, value: number) => {
|
||||
FLOAT[0] = value;
|
||||
destination[offset] = FLOAT_BYTES[7];
|
||||
destination[offset + 1] = FLOAT_BYTES[6];
|
||||
destination[offset + 2] = FLOAT_BYTES[5];
|
||||
destination[offset + 3] = FLOAT_BYTES[4];
|
||||
destination[offset + 4] = FLOAT_BYTES[3];
|
||||
destination[offset + 5] = FLOAT_BYTES[2];
|
||||
destination[offset + 6] = FLOAT_BYTES[1];
|
||||
destination[offset + 7] = FLOAT_BYTES[0];
|
||||
return 8;
|
||||
}
|
||||
: (destination: Uint8Array, offset: number, value: number) => {
|
||||
FLOAT[0] = value;
|
||||
destination[offset] = FLOAT_BYTES[0];
|
||||
destination[offset + 1] = FLOAT_BYTES[1];
|
||||
destination[offset + 2] = FLOAT_BYTES[2];
|
||||
destination[offset + 3] = FLOAT_BYTES[3];
|
||||
destination[offset + 4] = FLOAT_BYTES[4];
|
||||
destination[offset + 5] = FLOAT_BYTES[5];
|
||||
destination[offset + 6] = FLOAT_BYTES[6];
|
||||
destination[offset + 7] = FLOAT_BYTES[7];
|
||||
return 8;
|
||||
}
|
||||
};
|
||||
44
node_modules/bson/src/utils/string_utils.ts
generated
vendored
Normal file
44
node_modules/bson/src/utils/string_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @internal
|
||||
* Removes leading zeros and explicit plus from textual representation of a number.
|
||||
*/
|
||||
export function removeLeadingZerosAndExplicitPlus(str: string): string {
|
||||
if (str === '') {
|
||||
return str;
|
||||
}
|
||||
|
||||
let startIndex = 0;
|
||||
|
||||
const isNegative = str[startIndex] === '-';
|
||||
const isExplicitlyPositive = str[startIndex] === '+';
|
||||
|
||||
if (isExplicitlyPositive || isNegative) {
|
||||
startIndex += 1;
|
||||
}
|
||||
|
||||
let foundInsignificantZero = false;
|
||||
|
||||
for (; startIndex < str.length && str[startIndex] === '0'; ++startIndex) {
|
||||
foundInsignificantZero = true;
|
||||
}
|
||||
|
||||
if (!foundInsignificantZero) {
|
||||
return isExplicitlyPositive ? str.slice(1) : str;
|
||||
}
|
||||
|
||||
return `${isNegative ? '-' : ''}${str.length === startIndex ? '0' : str.slice(startIndex)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Returns false for an string that contains invalid characters for its radix, else returns the original string.
|
||||
* @param str - The textual representation of the Long
|
||||
* @param radix - The radix in which the text is written (2-36), defaults to 10
|
||||
*/
|
||||
export function validateStringCharacters(str: string, radix?: number): false | string {
|
||||
radix = radix ?? 10;
|
||||
const validCharacters = '0123456789abcdefghijklmnopqrstuvwxyz'.slice(0, radix);
|
||||
// regex is case insensitive and checks that each character within the string is one of the validCharacters
|
||||
const regex = new RegExp(`[^-+${validCharacters}]`, 'i');
|
||||
return regex.test(str) ? false : str;
|
||||
}
|
||||
216
node_modules/bson/src/utils/web_byte_utils.ts
generated
vendored
Normal file
216
node_modules/bson/src/utils/web_byte_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
import { BSONError } from '../error';
|
||||
import { tryReadBasicLatin } from './latin';
|
||||
import { parseUtf8 } from '../parse_utf8';
|
||||
|
||||
type TextDecoder = {
|
||||
readonly encoding: string;
|
||||
readonly fatal: boolean;
|
||||
readonly ignoreBOM: boolean;
|
||||
decode(input?: Uint8Array): string;
|
||||
};
|
||||
type TextDecoderConstructor = {
|
||||
new (label: 'utf8', options: { fatal: boolean; ignoreBOM?: boolean }): TextDecoder;
|
||||
};
|
||||
|
||||
type TextEncoder = {
|
||||
readonly encoding: string;
|
||||
encode(input?: string): Uint8Array;
|
||||
};
|
||||
type TextEncoderConstructor = {
|
||||
new (): TextEncoder;
|
||||
};
|
||||
|
||||
// Web global
|
||||
declare const TextDecoder: TextDecoderConstructor;
|
||||
declare const TextEncoder: TextEncoderConstructor;
|
||||
declare const atob: (base64: string) => string;
|
||||
declare const btoa: (binary: string) => string;
|
||||
|
||||
type ArrayBufferViewWithTag = ArrayBufferView & {
|
||||
[Symbol.toStringTag]?: string;
|
||||
};
|
||||
|
||||
function isReactNative() {
|
||||
const { navigator } = globalThis as { navigator?: { product?: string } };
|
||||
return typeof navigator === 'object' && navigator.product === 'ReactNative';
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function webMathRandomBytes(byteLength: number) {
|
||||
if (byteLength < 0) {
|
||||
throw new RangeError(`The argument 'byteLength' is invalid. Received ${byteLength}`);
|
||||
}
|
||||
return webByteUtils.fromNumberArray(
|
||||
Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256))
|
||||
);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
const webRandomBytes: (byteLength: number) => Uint8Array = (() => {
|
||||
const { crypto } = globalThis as {
|
||||
crypto?: { getRandomValues?: (space: Uint8Array) => Uint8Array };
|
||||
};
|
||||
if (crypto != null && typeof crypto.getRandomValues === 'function') {
|
||||
return (byteLength: number) => {
|
||||
// @ts-expect-error: crypto.getRandomValues cannot actually be null here
|
||||
// You cannot separate getRandomValues from crypto (need to have this === crypto)
|
||||
return crypto.getRandomValues(webByteUtils.allocate(byteLength));
|
||||
};
|
||||
} else {
|
||||
if (isReactNative()) {
|
||||
const { console } = globalThis as { console?: { warn?: (message: string) => void } };
|
||||
console?.warn?.(
|
||||
'BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.'
|
||||
);
|
||||
}
|
||||
return webMathRandomBytes;
|
||||
}
|
||||
})();
|
||||
|
||||
const HEX_DIGIT = /(\d|[a-f])/i;
|
||||
|
||||
/** @internal */
|
||||
export const webByteUtils = {
|
||||
toLocalBufferType(
|
||||
potentialUint8array: Uint8Array | ArrayBufferViewWithTag | ArrayBuffer
|
||||
): Uint8Array {
|
||||
const stringTag =
|
||||
potentialUint8array?.[Symbol.toStringTag] ??
|
||||
Object.prototype.toString.call(potentialUint8array);
|
||||
|
||||
if (stringTag === 'Uint8Array') {
|
||||
return potentialUint8array as Uint8Array;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(potentialUint8array)) {
|
||||
return new Uint8Array(
|
||||
potentialUint8array.buffer.slice(
|
||||
potentialUint8array.byteOffset,
|
||||
potentialUint8array.byteOffset + potentialUint8array.byteLength
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
stringTag === 'ArrayBuffer' ||
|
||||
stringTag === 'SharedArrayBuffer' ||
|
||||
stringTag === '[object ArrayBuffer]' ||
|
||||
stringTag === '[object SharedArrayBuffer]'
|
||||
) {
|
||||
return new Uint8Array(potentialUint8array);
|
||||
}
|
||||
|
||||
throw new BSONError(`Cannot make a Uint8Array from passed potentialBuffer.`);
|
||||
},
|
||||
|
||||
allocate(size: number): Uint8Array {
|
||||
if (typeof size !== 'number') {
|
||||
throw new TypeError(`The "size" argument must be of type number. Received ${String(size)}`);
|
||||
}
|
||||
return new Uint8Array(size);
|
||||
},
|
||||
|
||||
allocateUnsafe(size: number): Uint8Array {
|
||||
return webByteUtils.allocate(size);
|
||||
},
|
||||
|
||||
equals(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.byteLength !== b.byteLength) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.byteLength; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
fromNumberArray(array: number[]): Uint8Array {
|
||||
return Uint8Array.from(array);
|
||||
},
|
||||
|
||||
fromBase64(base64: string): Uint8Array {
|
||||
return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
|
||||
},
|
||||
|
||||
toBase64(uint8array: Uint8Array): string {
|
||||
return btoa(webByteUtils.toISO88591(uint8array));
|
||||
},
|
||||
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
fromISO88591(codePoints: string): Uint8Array {
|
||||
return Uint8Array.from(codePoints, c => c.charCodeAt(0) & 0xff);
|
||||
},
|
||||
|
||||
/** **Legacy** binary strings are an outdated method of data transfer. Do not add public API support for interpreting this format */
|
||||
toISO88591(uint8array: Uint8Array): string {
|
||||
return Array.from(Uint16Array.from(uint8array), b => String.fromCharCode(b)).join('');
|
||||
},
|
||||
|
||||
fromHex(hex: string): Uint8Array {
|
||||
const evenLengthHex = hex.length % 2 === 0 ? hex : hex.slice(0, hex.length - 1);
|
||||
const buffer = [];
|
||||
|
||||
for (let i = 0; i < evenLengthHex.length; i += 2) {
|
||||
const firstDigit = evenLengthHex[i];
|
||||
const secondDigit = evenLengthHex[i + 1];
|
||||
|
||||
if (!HEX_DIGIT.test(firstDigit)) {
|
||||
break;
|
||||
}
|
||||
if (!HEX_DIGIT.test(secondDigit)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const hexDigit = Number.parseInt(`${firstDigit}${secondDigit}`, 16);
|
||||
buffer.push(hexDigit);
|
||||
}
|
||||
|
||||
return Uint8Array.from(buffer);
|
||||
},
|
||||
|
||||
toHex(uint8array: Uint8Array): string {
|
||||
return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
|
||||
},
|
||||
|
||||
toUTF8(uint8array: Uint8Array, start: number, end: number, fatal: boolean): string {
|
||||
const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
|
||||
if (basicLatin != null) {
|
||||
return basicLatin;
|
||||
}
|
||||
|
||||
return parseUtf8(uint8array, start, end, fatal);
|
||||
},
|
||||
|
||||
utf8ByteLength(input: string): number {
|
||||
return new TextEncoder().encode(input).byteLength;
|
||||
},
|
||||
|
||||
encodeUTF8Into(uint8array: Uint8Array, source: string, byteOffset: number): number {
|
||||
const bytes = new TextEncoder().encode(source);
|
||||
uint8array.set(bytes, byteOffset);
|
||||
return bytes.byteLength;
|
||||
},
|
||||
|
||||
randomBytes: webRandomBytes,
|
||||
|
||||
swap32(buffer: Uint8Array): Uint8Array {
|
||||
if (buffer.length % 4 !== 0) {
|
||||
throw new RangeError('Buffer size must be a multiple of 32-bits');
|
||||
}
|
||||
|
||||
for (let i = 0; i < buffer.length; i += 4) {
|
||||
const byte0 = buffer[i];
|
||||
const byte1 = buffer[i + 1];
|
||||
const byte2 = buffer[i + 2];
|
||||
const byte3 = buffer[i + 3];
|
||||
buffer[i] = byte3;
|
||||
buffer[i + 1] = byte2;
|
||||
buffer[i + 2] = byte1;
|
||||
buffer[i + 3] = byte0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user