changes
This commit is contained in:
204
backend/node_modules/bson/src/utils/number_utils.ts
generated
vendored
Normal file
204
backend/node_modules/bson/src/utils/number_utils.ts
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
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 {
|
||||
const hi = BigInt(
|
||||
source[offset + 4] +
|
||||
source[offset + 5] * 256 +
|
||||
source[offset + 6] * 65536 +
|
||||
(source[offset + 7] << 24)
|
||||
); // Overflow
|
||||
|
||||
const lo = BigInt(
|
||||
source[offset] +
|
||||
source[offset + 1] * 256 +
|
||||
source[offset + 2] * 65536 +
|
||||
source[offset + 3] * 16777216
|
||||
);
|
||||
|
||||
return (hi << 32n) + 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 {
|
||||
const mask32bits = 0xffff_ffffn;
|
||||
|
||||
/** 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;
|
||||
|
||||
let hi = Number((value >> 32n) & 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;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user