bson 6.3.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,7 @@ import type { MinKey } from '../min_key';
12
12
  import type { ObjectId } from '../objectid';
13
13
  import type { BSONRegExp } from '../regexp';
14
14
  import { ByteUtils } from '../utils/byte_utils';
15
+ import { NumberUtils } from '../utils/number_utils';
15
16
  import { isAnyArrayBuffer, isDate, isMap, isRegExp, isUint8Array } from './utils';
16
17
 
17
18
  /** @public */
@@ -61,10 +62,7 @@ function serializeString(buffer: Uint8Array, key: string, value: string, index:
61
62
  // Write the string
62
63
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
63
64
  // Write the size of the string to buffer
64
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
65
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
66
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
67
- buffer[index] = (size + 1) & 0xff;
65
+ NumberUtils.setInt32LE(buffer, index, size + 1);
68
66
  // Update index
69
67
  index = index + 4 + size;
70
68
  // Write zero
@@ -72,10 +70,6 @@ function serializeString(buffer: Uint8Array, key: string, value: string, index:
72
70
  return index;
73
71
  }
74
72
 
75
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
76
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
77
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
78
-
79
73
  function serializeNumber(buffer: Uint8Array, key: string, value: number, index: number) {
80
74
  const isNegativeZero = Object.is(value, -0);
81
75
 
@@ -87,23 +81,17 @@ function serializeNumber(buffer: Uint8Array, key: string, value: number, index:
87
81
  ? constants.BSON_DATA_INT
88
82
  : constants.BSON_DATA_NUMBER;
89
83
 
90
- if (type === constants.BSON_DATA_INT) {
91
- NUMBER_SPACE.setInt32(0, value, true);
92
- } else {
93
- NUMBER_SPACE.setFloat64(0, value, true);
94
- }
95
-
96
- const bytes =
97
- type === constants.BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
98
-
99
84
  buffer[index++] = type;
100
85
 
101
86
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
102
87
  index = index + numberOfWrittenBytes;
103
88
  buffer[index++] = 0x00;
104
89
 
105
- buffer.set(bytes, index);
106
- index += bytes.byteLength;
90
+ if (type === constants.BSON_DATA_INT) {
91
+ index += NumberUtils.setInt32LE(buffer, index, value);
92
+ } else {
93
+ index += NumberUtils.setFloat64LE(buffer, index, value);
94
+ }
107
95
 
108
96
  return index;
109
97
  }
@@ -115,10 +103,9 @@ function serializeBigInt(buffer: Uint8Array, key: string, value: bigint, index:
115
103
  // Encode the name
116
104
  index += numberOfWrittenBytes;
117
105
  buffer[index++] = 0;
118
- NUMBER_SPACE.setBigInt64(0, value, true);
119
- // Write BigInt value
120
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
121
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
106
+
107
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
108
+
122
109
  return index;
123
110
  }
124
111
 
@@ -162,15 +149,9 @@ function serializeDate(buffer: Uint8Array, key: string, value: Date, index: numb
162
149
  const lowBits = dateInMilis.getLowBits();
163
150
  const highBits = dateInMilis.getHighBits();
164
151
  // Encode low bits
165
- buffer[index++] = lowBits & 0xff;
166
- buffer[index++] = (lowBits >> 8) & 0xff;
167
- buffer[index++] = (lowBits >> 16) & 0xff;
168
- buffer[index++] = (lowBits >> 24) & 0xff;
152
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
169
153
  // Encode high bits
170
- buffer[index++] = highBits & 0xff;
171
- buffer[index++] = (highBits >> 8) & 0xff;
172
- buffer[index++] = (highBits >> 16) & 0xff;
173
- buffer[index++] = (highBits >> 24) & 0xff;
154
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
174
155
  return index;
175
156
  }
176
157
 
@@ -256,16 +237,7 @@ function serializeObjectId(buffer: Uint8Array, key: string, value: ObjectId, ind
256
237
  index = index + numberOfWrittenBytes;
257
238
  buffer[index++] = 0;
258
239
 
259
- // Write the objectId into the shared buffer
260
- const idValue = value.id;
261
-
262
- if (isUint8Array(idValue)) {
263
- for (let i = 0; i < 12; i++) {
264
- buffer[index++] = idValue[i];
265
- }
266
- } else {
267
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
268
- }
240
+ index += value.serializeInto(buffer, index);
269
241
 
270
242
  // Adjust index
271
243
  return index;
@@ -282,14 +254,15 @@ function serializeBuffer(buffer: Uint8Array, key: string, value: Uint8Array, ind
282
254
  // Get size of the buffer (current write point)
283
255
  const size = value.length;
284
256
  // Write the size of the string to buffer
285
- buffer[index++] = size & 0xff;
286
- buffer[index++] = (size >> 8) & 0xff;
287
- buffer[index++] = (size >> 16) & 0xff;
288
- buffer[index++] = (size >> 24) & 0xff;
257
+ index += NumberUtils.setInt32LE(buffer, index, size);
289
258
  // Write the default subtype
290
259
  buffer[index++] = constants.BSON_BINARY_SUBTYPE_DEFAULT;
291
260
  // Copy the content form the binary field to the buffer
292
- buffer.set(value, index);
261
+ if (size <= 16) {
262
+ for (let i = 0; i < size; i++) buffer[index + i] = value[i];
263
+ } else {
264
+ buffer.set(value, index);
265
+ }
293
266
  // Adjust the index
294
267
  index = index + size;
295
268
  return index;
@@ -343,7 +316,7 @@ function serializeDecimal128(buffer: Uint8Array, key: string, value: Decimal128,
343
316
  index = index + numberOfWrittenBytes;
344
317
  buffer[index++] = 0;
345
318
  // Write the data from the value
346
- buffer.set(value.bytes.subarray(0, 16), index);
319
+ for (let i = 0; i < 16; i++) buffer[index + i] = value.bytes[i];
347
320
  return index + 16;
348
321
  }
349
322
 
@@ -360,15 +333,9 @@ function serializeLong(buffer: Uint8Array, key: string, value: Long, index: numb
360
333
  const lowBits = value.getLowBits();
361
334
  const highBits = value.getHighBits();
362
335
  // Encode low bits
363
- buffer[index++] = lowBits & 0xff;
364
- buffer[index++] = (lowBits >> 8) & 0xff;
365
- buffer[index++] = (lowBits >> 16) & 0xff;
366
- buffer[index++] = (lowBits >> 24) & 0xff;
336
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
367
337
  // Encode high bits
368
- buffer[index++] = highBits & 0xff;
369
- buffer[index++] = (highBits >> 8) & 0xff;
370
- buffer[index++] = (highBits >> 16) & 0xff;
371
- buffer[index++] = (highBits >> 24) & 0xff;
338
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
372
339
  return index;
373
340
  }
374
341
 
@@ -382,10 +349,7 @@ function serializeInt32(buffer: Uint8Array, key: string, value: Int32 | number,
382
349
  index = index + numberOfWrittenBytes;
383
350
  buffer[index++] = 0;
384
351
  // Write the int value
385
- buffer[index++] = value & 0xff;
386
- buffer[index++] = (value >> 8) & 0xff;
387
- buffer[index++] = (value >> 16) & 0xff;
388
- buffer[index++] = (value >> 24) & 0xff;
352
+ index += NumberUtils.setInt32LE(buffer, index, value);
389
353
  return index;
390
354
  }
391
355
 
@@ -401,11 +365,8 @@ function serializeDouble(buffer: Uint8Array, key: string, value: Double, index:
401
365
  buffer[index++] = 0;
402
366
 
403
367
  // Write float
404
- NUMBER_SPACE.setFloat64(0, value.value, true);
405
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
368
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
406
369
 
407
- // Adjust index
408
- index = index + 8;
409
370
  return index;
410
371
  }
411
372
 
@@ -422,10 +383,7 @@ function serializeFunction(buffer: Uint8Array, key: string, value: Function, ind
422
383
  // Write the string
423
384
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
424
385
  // Write the size of the string to buffer
425
- buffer[index] = size & 0xff;
426
- buffer[index + 1] = (size >> 8) & 0xff;
427
- buffer[index + 2] = (size >> 16) & 0xff;
428
- buffer[index + 3] = (size >> 24) & 0xff;
386
+ NumberUtils.setInt32LE(buffer, index, size);
429
387
  // Update index
430
388
  index = index + 4 + size - 1;
431
389
  // Write zero
@@ -464,10 +422,7 @@ function serializeCode(
464
422
  // Write string into buffer
465
423
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
466
424
  // Write the size of the string to buffer
467
- buffer[index] = codeSize & 0xff;
468
- buffer[index + 1] = (codeSize >> 8) & 0xff;
469
- buffer[index + 2] = (codeSize >> 16) & 0xff;
470
- buffer[index + 3] = (codeSize >> 24) & 0xff;
425
+ NumberUtils.setInt32LE(buffer, index, codeSize);
471
426
  // Write end 0
472
427
  buffer[index + 4 + codeSize - 1] = 0;
473
428
  // Write the
@@ -490,10 +445,7 @@ function serializeCode(
490
445
  const totalSize = endIndex - startIndex;
491
446
 
492
447
  // Write the total size of the object
493
- buffer[startIndex++] = totalSize & 0xff;
494
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
495
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
496
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
448
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
497
449
  // Write trailing zero
498
450
  buffer[index++] = 0;
499
451
  } else {
@@ -508,10 +460,7 @@ function serializeCode(
508
460
  // Write the string
509
461
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
510
462
  // Write the size of the string to buffer
511
- buffer[index] = size & 0xff;
512
- buffer[index + 1] = (size >> 8) & 0xff;
513
- buffer[index + 2] = (size >> 16) & 0xff;
514
- buffer[index + 3] = (size >> 24) & 0xff;
463
+ NumberUtils.setInt32LE(buffer, index, size);
515
464
  // Update index
516
465
  index = index + 4 + size - 1;
517
466
  // Write zero
@@ -536,24 +485,21 @@ function serializeBinary(buffer: Uint8Array, key: string, value: Binary, index:
536
485
  // Add the deprecated 02 type 4 bytes of size to total
537
486
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) size = size + 4;
538
487
  // Write the size of the string to buffer
539
- buffer[index++] = size & 0xff;
540
- buffer[index++] = (size >> 8) & 0xff;
541
- buffer[index++] = (size >> 16) & 0xff;
542
- buffer[index++] = (size >> 24) & 0xff;
488
+ index += NumberUtils.setInt32LE(buffer, index, size);
543
489
  // Write the subtype to the buffer
544
490
  buffer[index++] = value.sub_type;
545
491
 
546
492
  // If we have binary type 2 the 4 first bytes are the size
547
493
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
548
494
  size = size - 4;
549
- buffer[index++] = size & 0xff;
550
- buffer[index++] = (size >> 8) & 0xff;
551
- buffer[index++] = (size >> 16) & 0xff;
552
- buffer[index++] = (size >> 24) & 0xff;
495
+ index += NumberUtils.setInt32LE(buffer, index, size);
553
496
  }
554
497
 
555
- // Write the data to the object
556
- buffer.set(data, index);
498
+ if (size <= 16) {
499
+ for (let i = 0; i < size; i++) buffer[index + i] = data[i];
500
+ } else {
501
+ buffer.set(data, index);
502
+ }
557
503
  // Adjust the index
558
504
  index = index + value.position;
559
505
  return index;
@@ -570,14 +516,11 @@ function serializeSymbol(buffer: Uint8Array, key: string, value: BSONSymbol, ind
570
516
  // Write the string
571
517
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
572
518
  // Write the size of the string to buffer
573
- buffer[index] = size & 0xff;
574
- buffer[index + 1] = (size >> 8) & 0xff;
575
- buffer[index + 2] = (size >> 16) & 0xff;
576
- buffer[index + 3] = (size >> 24) & 0xff;
519
+ NumberUtils.setInt32LE(buffer, index, size);
577
520
  // Update index
578
521
  index = index + 4 + size - 1;
579
522
  // Write zero
580
- buffer[index++] = 0x00;
523
+ buffer[index++] = 0;
581
524
  return index;
582
525
  }
583
526
 
@@ -624,10 +567,7 @@ function serializeDBRef(
624
567
  // Calculate object size
625
568
  const size = endIndex - startIndex;
626
569
  // Write the size
627
- buffer[startIndex++] = size & 0xff;
628
- buffer[startIndex++] = (size >> 8) & 0xff;
629
- buffer[startIndex++] = (size >> 16) & 0xff;
630
- buffer[startIndex++] = (size >> 24) & 0xff;
570
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
631
571
  // Set index
632
572
  return endIndex;
633
573
  }
@@ -799,7 +739,7 @@ export function serializeInto(
799
739
  if (checkKeys) {
800
740
  if ('$' === key[0]) {
801
741
  throw new BSONError('key ' + key + " must not start with '$'");
802
- } else if (~key.indexOf('.')) {
742
+ } else if (key.includes('.')) {
803
743
  throw new BSONError('key ' + key + " must not contain '.'");
804
744
  }
805
745
  }
@@ -907,7 +847,7 @@ export function serializeInto(
907
847
  if (checkKeys) {
908
848
  if ('$' === key[0]) {
909
849
  throw new BSONError('key ' + key + " must not start with '$'");
910
- } else if (~key.indexOf('.')) {
850
+ } else if (key.includes('.')) {
911
851
  throw new BSONError('key ' + key + " must not contain '.'");
912
852
  }
913
853
  }
@@ -997,9 +937,6 @@ export function serializeInto(
997
937
  // Final size
998
938
  const size = index - startingIndex;
999
939
  // Write the size of the object
1000
- buffer[startingIndex++] = size & 0xff;
1001
- buffer[startingIndex++] = (size >> 8) & 0xff;
1002
- buffer[startingIndex++] = (size >> 16) & 0xff;
1003
- buffer[startingIndex++] = (size >> 24) & 0xff;
940
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
1004
941
  return index;
1005
942
  }
@@ -7,6 +7,8 @@ export type ByteUtils = {
7
7
  toLocalBufferType(buffer: Uint8Array | ArrayBufferView | ArrayBuffer): Uint8Array;
8
8
  /** Create empty space of size */
9
9
  allocate: (size: number) => Uint8Array;
10
+ /** Create empty space of size, use pooled memory when available */
11
+ allocateUnsafe: (size: number) => Uint8Array;
10
12
  /** Check if two Uint8Arrays are deep equal */
11
13
  equals: (a: Uint8Array, b: Uint8Array) => boolean;
12
14
  /** Check if two Uint8Arrays are deep equal */
@@ -23,8 +25,6 @@ export type ByteUtils = {
23
25
  fromHex: (hex: string) => Uint8Array;
24
26
  /** Create a lowercase hex string from bytes */
25
27
  toHex: (buffer: Uint8Array) => string;
26
- /** Create a Uint8Array containing utf8 code units from a string */
27
- fromUTF8: (text: string) => Uint8Array;
28
28
  /** 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 */
29
29
  toUTF8: (buffer: Uint8Array, start: number, end: number, fatal: boolean) => string;
30
30
  /** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
@@ -53,9 +53,3 @@ const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuf
53
53
  * @internal
54
54
  */
55
55
  export const ByteUtils: ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
56
-
57
- export class BSONDataView extends DataView {
58
- static fromUint8Array(input: Uint8Array) {
59
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
60
- }
61
- }
@@ -13,7 +13,11 @@
13
13
  * @param end - The index to stop searching the uint8array
14
14
  * @returns string if all bytes are within the basic latin range, otherwise null
15
15
  */
16
- export function tryLatin(uint8array: Uint8Array, start: number, end: number): string | null {
16
+ export function tryReadBasicLatin(
17
+ uint8array: Uint8Array,
18
+ start: number,
19
+ end: number
20
+ ): string | null {
17
21
  if (uint8array.length === 0) {
18
22
  return '';
19
23
  }
@@ -59,3 +63,42 @@ export function tryLatin(uint8array: Uint8Array, start: number, end: number): st
59
63
 
60
64
  return String.fromCharCode(...latinBytes);
61
65
  }
66
+
67
+ /**
68
+ * This function is an optimization for writing small basic latin strings.
69
+ * @internal
70
+ * @remarks
71
+ * ### Important characteristics:
72
+ * - If the string length is 0 return 0, do not perform any work
73
+ * - If a string is longer than 25 code units return null
74
+ * - If any code unit exceeds 128 this function returns null
75
+ *
76
+ * @param destination - The uint8array to serialize the string to
77
+ * @param source - The string to turn into UTF-8 bytes if it fits in the basic latin range
78
+ * @param offset - The position in the destination to begin writing bytes to
79
+ * @returns the number of bytes written to destination if all code units are below 128, otherwise null
80
+ */
81
+ export function tryWriteBasicLatin(
82
+ destination: Uint8Array,
83
+ source: string,
84
+ offset: number
85
+ ): number | null {
86
+ if (source.length === 0) return 0;
87
+
88
+ if (source.length > 25) return null;
89
+
90
+ if (destination.length - offset < source.length) return null;
91
+
92
+ for (
93
+ let charOffset = 0, destinationOffset = offset;
94
+ charOffset < source.length;
95
+ charOffset++, destinationOffset++
96
+ ) {
97
+ const char = source.charCodeAt(charOffset);
98
+ if (char > 127) return null;
99
+
100
+ destination[destinationOffset] = char;
101
+ }
102
+
103
+ return source.length;
104
+ }
@@ -1,6 +1,6 @@
1
1
  import { BSONError } from '../error';
2
2
  import { validateUtf8 } from '../validate_utf8';
3
- import { tryLatin } from './latin';
3
+ import { tryReadBasicLatin, tryWriteBasicLatin } from './latin';
4
4
 
5
5
  type NodeJsEncoding = 'base64' | 'hex' | 'utf8' | 'binary';
6
6
  type NodeJsBuffer = ArrayBufferView &
@@ -12,6 +12,7 @@ type NodeJsBuffer = ArrayBufferView &
12
12
  };
13
13
  type NodeJsBufferConstructor = Omit<Uint8ArrayConstructor, 'from'> & {
14
14
  alloc: (size: number) => NodeJsBuffer;
15
+ allocUnsafe: (size: number) => NodeJsBuffer;
15
16
  from(array: number[]): NodeJsBuffer;
16
17
  from(array: Uint8Array): NodeJsBuffer;
17
18
  from(array: ArrayBuffer): NodeJsBuffer;
@@ -89,6 +90,10 @@ export const nodeJsByteUtils = {
89
90
  return Buffer.alloc(size);
90
91
  },
91
92
 
93
+ allocateUnsafe(size: number): NodeJsBuffer {
94
+ return Buffer.allocUnsafe(size);
95
+ },
96
+
92
97
  equals(a: Uint8Array, b: Uint8Array): boolean {
93
98
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
94
99
  },
@@ -123,12 +128,8 @@ export const nodeJsByteUtils = {
123
128
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
124
129
  },
125
130
 
126
- fromUTF8(text: string): NodeJsBuffer {
127
- return Buffer.from(text, 'utf8');
128
- },
129
-
130
131
  toUTF8(buffer: Uint8Array, start: number, end: number, fatal: boolean): string {
131
- const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
132
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
132
133
  if (basicLatin != null) {
133
134
  return basicLatin;
134
135
  }
@@ -153,6 +154,11 @@ export const nodeJsByteUtils = {
153
154
  },
154
155
 
155
156
  encodeUTF8Into(buffer: Uint8Array, source: string, byteOffset: number): number {
157
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
158
+ if (latinBytesWritten != null) {
159
+ return latinBytesWritten;
160
+ }
161
+
156
162
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
157
163
  },
158
164
 
@@ -0,0 +1,135 @@
1
+ const FLOAT = new Float64Array(1);
2
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
3
+
4
+ /**
5
+ * Number parsing and serializing utilities.
6
+ *
7
+ * @internal
8
+ */
9
+ export const NumberUtils = {
10
+ /** Reads a little-endian 32-bit integer from source */
11
+ getInt32LE(source: Uint8Array, offset: number): number {
12
+ return (
13
+ source[offset] |
14
+ (source[offset + 1] << 8) |
15
+ (source[offset + 2] << 16) |
16
+ (source[offset + 3] << 24)
17
+ );
18
+ },
19
+
20
+ /** Reads a little-endian 32-bit unsigned integer from source */
21
+ getUint32LE(source: Uint8Array, offset: number): number {
22
+ return (
23
+ source[offset] +
24
+ source[offset + 1] * 256 +
25
+ source[offset + 2] * 65536 +
26
+ source[offset + 3] * 16777216
27
+ );
28
+ },
29
+
30
+ /** Reads a big-endian 32-bit integer from source */
31
+ getUint32BE(source: Uint8Array, offset: number): number {
32
+ return (
33
+ source[offset + 3] +
34
+ source[offset + 2] * 256 +
35
+ source[offset + 1] * 65536 +
36
+ source[offset] * 16777216
37
+ );
38
+ },
39
+
40
+ /** Reads a little-endian 64-bit integer from source */
41
+ getBigInt64LE(source: Uint8Array, offset: number): bigint {
42
+ const lo = NumberUtils.getUint32LE(source, offset);
43
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
44
+
45
+ /*
46
+ eslint-disable-next-line no-restricted-globals
47
+ -- This is allowed since this helper should not be called unless bigint features are enabled
48
+ */
49
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
50
+ },
51
+
52
+ /** Reads a little-endian 64-bit float from source */
53
+ getFloat64LE(source: Uint8Array, offset: number): number {
54
+ FLOAT_BYTES[0] = source[offset];
55
+ FLOAT_BYTES[1] = source[offset + 1];
56
+ FLOAT_BYTES[2] = source[offset + 2];
57
+ FLOAT_BYTES[3] = source[offset + 3];
58
+ FLOAT_BYTES[4] = source[offset + 4];
59
+ FLOAT_BYTES[5] = source[offset + 5];
60
+ FLOAT_BYTES[6] = source[offset + 6];
61
+ FLOAT_BYTES[7] = source[offset + 7];
62
+ return FLOAT[0];
63
+ },
64
+
65
+ /** Writes a big-endian 32-bit integer to destination, can be signed or unsigned */
66
+ setInt32BE(destination: Uint8Array, offset: number, value: number): 4 {
67
+ destination[offset + 3] = value;
68
+ value >>>= 8;
69
+ destination[offset + 2] = value;
70
+ value >>>= 8;
71
+ destination[offset + 1] = value;
72
+ value >>>= 8;
73
+ destination[offset] = value;
74
+ return 4;
75
+ },
76
+
77
+ /** Writes a little-endian 32-bit integer to destination, can be signed or unsigned */
78
+ setInt32LE(destination: Uint8Array, offset: number, value: number): 4 {
79
+ destination[offset] = value;
80
+ value >>>= 8;
81
+ destination[offset + 1] = value;
82
+ value >>>= 8;
83
+ destination[offset + 2] = value;
84
+ value >>>= 8;
85
+ destination[offset + 3] = value;
86
+ return 4;
87
+ },
88
+
89
+ /** Write a little-endian 64-bit integer to source */
90
+ setBigInt64LE(destination: Uint8Array, offset: number, value: bigint): 8 {
91
+ /* eslint-disable-next-line no-restricted-globals -- This is allowed here as useBigInt64=true */
92
+ const mask32bits = BigInt(0xffff_ffff);
93
+
94
+ /** lower 32 bits */
95
+ let lo = Number(value & mask32bits);
96
+ destination[offset] = lo;
97
+ lo >>= 8;
98
+ destination[offset + 1] = lo;
99
+ lo >>= 8;
100
+ destination[offset + 2] = lo;
101
+ lo >>= 8;
102
+ destination[offset + 3] = lo;
103
+
104
+ /*
105
+ eslint-disable-next-line no-restricted-globals
106
+ -- This is allowed here as useBigInt64=true
107
+
108
+ upper 32 bits
109
+ */
110
+ let hi = Number((value >> BigInt(32)) & mask32bits);
111
+ destination[offset + 4] = hi;
112
+ hi >>= 8;
113
+ destination[offset + 5] = hi;
114
+ hi >>= 8;
115
+ destination[offset + 6] = hi;
116
+ hi >>= 8;
117
+ destination[offset + 7] = hi;
118
+
119
+ return 8;
120
+ },
121
+
122
+ /** Writes a little-endian 64-bit float to destination */
123
+ setFloat64LE(destination: Uint8Array, offset: number, value: number): 8 {
124
+ FLOAT[0] = value;
125
+ destination[offset] = FLOAT_BYTES[0];
126
+ destination[offset + 1] = FLOAT_BYTES[1];
127
+ destination[offset + 2] = FLOAT_BYTES[2];
128
+ destination[offset + 3] = FLOAT_BYTES[3];
129
+ destination[offset + 4] = FLOAT_BYTES[4];
130
+ destination[offset + 5] = FLOAT_BYTES[5];
131
+ destination[offset + 6] = FLOAT_BYTES[6];
132
+ destination[offset + 7] = FLOAT_BYTES[7];
133
+ return 8;
134
+ }
135
+ };
@@ -1,5 +1,5 @@
1
1
  import { BSONError } from '../error';
2
- import { tryLatin } from './latin';
2
+ import { tryReadBasicLatin } from './latin';
3
3
 
4
4
  type TextDecoder = {
5
5
  readonly encoding: string;
@@ -109,6 +109,10 @@ export const webByteUtils = {
109
109
  return new Uint8Array(size);
110
110
  },
111
111
 
112
+ allocateUnsafe(size: number): Uint8Array {
113
+ return webByteUtils.allocate(size);
114
+ },
115
+
112
116
  equals(a: Uint8Array, b: Uint8Array): boolean {
113
117
  if (a.byteLength !== b.byteLength) {
114
118
  return false;
@@ -169,12 +173,8 @@ export const webByteUtils = {
169
173
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
170
174
  },
171
175
 
172
- fromUTF8(text: string): Uint8Array {
173
- return new TextEncoder().encode(text);
174
- },
175
-
176
176
  toUTF8(uint8array: Uint8Array, start: number, end: number, fatal: boolean): string {
177
- const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
177
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
178
178
  if (basicLatin != null) {
179
179
  return basicLatin;
180
180
  }
@@ -190,12 +190,12 @@ export const webByteUtils = {
190
190
  },
191
191
 
192
192
  utf8ByteLength(input: string): number {
193
- return webByteUtils.fromUTF8(input).byteLength;
193
+ return new TextEncoder().encode(input).byteLength;
194
194
  },
195
195
 
196
- encodeUTF8Into(buffer: Uint8Array, source: string, byteOffset: number): number {
197
- const bytes = webByteUtils.fromUTF8(source);
198
- buffer.set(bytes, byteOffset);
196
+ encodeUTF8Into(uint8array: Uint8Array, source: string, byteOffset: number): number {
197
+ const bytes = new TextEncoder().encode(source);
198
+ uint8array.set(bytes, byteOffset);
199
199
  return bytes.byteLength;
200
200
  },
201
201