bson 6.3.0 → 6.5.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.
package/lib/bson.cjs CHANGED
@@ -126,6 +126,15 @@ class BSONRuntimeError extends BSONError {
126
126
  super(message);
127
127
  }
128
128
  }
129
+ class BSONOffsetError extends BSONError {
130
+ get name() {
131
+ return 'BSONOffsetError';
132
+ }
133
+ constructor(message, offset) {
134
+ super(`${message}. offset: ${offset}`);
135
+ this.offset = offset;
136
+ }
137
+ }
129
138
 
130
139
  const FIRST_BIT = 0x80;
131
140
  const FIRST_TWO_BITS = 0xc0;
@@ -164,7 +173,7 @@ function validateUtf8(bytes, start, end) {
164
173
  return !continuation;
165
174
  }
166
175
 
167
- function tryLatin(uint8array, start, end) {
176
+ function tryReadBasicLatin(uint8array, start, end) {
168
177
  if (uint8array.length === 0) {
169
178
  return '';
170
179
  }
@@ -199,6 +208,21 @@ function tryLatin(uint8array, start, end) {
199
208
  }
200
209
  return String.fromCharCode(...latinBytes);
201
210
  }
211
+ function tryWriteBasicLatin(destination, source, offset) {
212
+ if (source.length === 0)
213
+ return 0;
214
+ if (source.length > 25)
215
+ return null;
216
+ if (destination.length - offset < source.length)
217
+ return null;
218
+ for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {
219
+ const char = source.charCodeAt(charOffset);
220
+ if (char > 127)
221
+ return null;
222
+ destination[destinationOffset] = char;
223
+ }
224
+ return source.length;
225
+ }
202
226
 
203
227
  function nodejsMathRandomBytes(byteLength) {
204
228
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
@@ -231,6 +255,9 @@ const nodeJsByteUtils = {
231
255
  allocate(size) {
232
256
  return Buffer.alloc(size);
233
257
  },
258
+ allocateUnsafe(size) {
259
+ return Buffer.allocUnsafe(size);
260
+ },
234
261
  equals(a, b) {
235
262
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
236
263
  },
@@ -255,11 +282,8 @@ const nodeJsByteUtils = {
255
282
  toHex(buffer) {
256
283
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
257
284
  },
258
- fromUTF8(text) {
259
- return Buffer.from(text, 'utf8');
260
- },
261
285
  toUTF8(buffer, start, end, fatal) {
262
- const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
286
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
263
287
  if (basicLatin != null) {
264
288
  return basicLatin;
265
289
  }
@@ -280,6 +304,10 @@ const nodeJsByteUtils = {
280
304
  return Buffer.byteLength(input, 'utf8');
281
305
  },
282
306
  encodeUTF8Into(buffer, source, byteOffset) {
307
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
308
+ if (latinBytesWritten != null) {
309
+ return latinBytesWritten;
310
+ }
283
311
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
284
312
  },
285
313
  randomBytes: nodejsRandomBytes
@@ -335,6 +363,9 @@ const webByteUtils = {
335
363
  }
336
364
  return new Uint8Array(size);
337
365
  },
366
+ allocateUnsafe(size) {
367
+ return webByteUtils.allocate(size);
368
+ },
338
369
  equals(a, b) {
339
370
  if (a.byteLength !== b.byteLength) {
340
371
  return false;
@@ -381,11 +412,8 @@ const webByteUtils = {
381
412
  toHex(uint8array) {
382
413
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
383
414
  },
384
- fromUTF8(text) {
385
- return new TextEncoder().encode(text);
386
- },
387
415
  toUTF8(uint8array, start, end, fatal) {
388
- const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
416
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
389
417
  if (basicLatin != null) {
390
418
  return basicLatin;
391
419
  }
@@ -400,11 +428,11 @@ const webByteUtils = {
400
428
  return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
401
429
  },
402
430
  utf8ByteLength(input) {
403
- return webByteUtils.fromUTF8(input).byteLength;
431
+ return new TextEncoder().encode(input).byteLength;
404
432
  },
405
- encodeUTF8Into(buffer, source, byteOffset) {
406
- const bytes = webByteUtils.fromUTF8(source);
407
- buffer.set(bytes, byteOffset);
433
+ encodeUTF8Into(uint8array, source, byteOffset) {
434
+ const bytes = new TextEncoder().encode(source);
435
+ uint8array.set(bytes, byteOffset);
408
436
  return bytes.byteLength;
409
437
  },
410
438
  randomBytes: webRandomBytes
@@ -412,11 +440,6 @@ const webByteUtils = {
412
440
 
413
441
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
414
442
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
415
- class BSONDataView extends DataView {
416
- static fromUint8Array(input) {
417
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
418
- }
419
- }
420
443
 
421
444
  class BSONValue {
422
445
  get [Symbol.for('@@mdb.bson.version')]() {
@@ -593,6 +616,7 @@ Binary.SUBTYPE_UUID = 4;
593
616
  Binary.SUBTYPE_MD5 = 5;
594
617
  Binary.SUBTYPE_ENCRYPTED = 6;
595
618
  Binary.SUBTYPE_COLUMN = 7;
619
+ Binary.SUBTYPE_SENSITIVE = 8;
596
620
  Binary.SUBTYPE_USER_DEFINED = 128;
597
621
  const UUID_BYTE_LENGTH = 16;
598
622
  const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
@@ -1836,7 +1860,7 @@ class Decimal128 extends BSONValue {
1836
1860
  if (isNegative) {
1837
1861
  dec.high = dec.high.or(Long.fromString('9223372036854775808'));
1838
1862
  }
1839
- const buffer = ByteUtils.allocate(16);
1863
+ const buffer = ByteUtils.allocateUnsafe(16);
1840
1864
  index = 0;
1841
1865
  buffer[index++] = dec.low.low & 0xff;
1842
1866
  buffer[index++] = (dec.low.low >> 8) & 0xff;
@@ -2109,9 +2133,126 @@ class MinKey extends BSONValue {
2109
2133
  }
2110
2134
  }
2111
2135
 
2136
+ const FLOAT = new Float64Array(1);
2137
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2138
+ FLOAT[0] = -1;
2139
+ const isBigEndian = FLOAT_BYTES[7] === 0;
2140
+ const NumberUtils = {
2141
+ getInt32LE(source, offset) {
2142
+ return (source[offset] |
2143
+ (source[offset + 1] << 8) |
2144
+ (source[offset + 2] << 16) |
2145
+ (source[offset + 3] << 24));
2146
+ },
2147
+ getUint32LE(source, offset) {
2148
+ return (source[offset] +
2149
+ source[offset + 1] * 256 +
2150
+ source[offset + 2] * 65536 +
2151
+ source[offset + 3] * 16777216);
2152
+ },
2153
+ getUint32BE(source, offset) {
2154
+ return (source[offset + 3] +
2155
+ source[offset + 2] * 256 +
2156
+ source[offset + 1] * 65536 +
2157
+ source[offset] * 16777216);
2158
+ },
2159
+ getBigInt64LE(source, offset) {
2160
+ const lo = NumberUtils.getUint32LE(source, offset);
2161
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
2162
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2163
+ },
2164
+ getFloat64LE: isBigEndian
2165
+ ? (source, offset) => {
2166
+ FLOAT_BYTES[7] = source[offset];
2167
+ FLOAT_BYTES[6] = source[offset + 1];
2168
+ FLOAT_BYTES[5] = source[offset + 2];
2169
+ FLOAT_BYTES[4] = source[offset + 3];
2170
+ FLOAT_BYTES[3] = source[offset + 4];
2171
+ FLOAT_BYTES[2] = source[offset + 5];
2172
+ FLOAT_BYTES[1] = source[offset + 6];
2173
+ FLOAT_BYTES[0] = source[offset + 7];
2174
+ return FLOAT[0];
2175
+ }
2176
+ : (source, offset) => {
2177
+ FLOAT_BYTES[0] = source[offset];
2178
+ FLOAT_BYTES[1] = source[offset + 1];
2179
+ FLOAT_BYTES[2] = source[offset + 2];
2180
+ FLOAT_BYTES[3] = source[offset + 3];
2181
+ FLOAT_BYTES[4] = source[offset + 4];
2182
+ FLOAT_BYTES[5] = source[offset + 5];
2183
+ FLOAT_BYTES[6] = source[offset + 6];
2184
+ FLOAT_BYTES[7] = source[offset + 7];
2185
+ return FLOAT[0];
2186
+ },
2187
+ setInt32BE(destination, offset, value) {
2188
+ destination[offset + 3] = value;
2189
+ value >>>= 8;
2190
+ destination[offset + 2] = value;
2191
+ value >>>= 8;
2192
+ destination[offset + 1] = value;
2193
+ value >>>= 8;
2194
+ destination[offset] = value;
2195
+ return 4;
2196
+ },
2197
+ setInt32LE(destination, offset, value) {
2198
+ destination[offset] = value;
2199
+ value >>>= 8;
2200
+ destination[offset + 1] = value;
2201
+ value >>>= 8;
2202
+ destination[offset + 2] = value;
2203
+ value >>>= 8;
2204
+ destination[offset + 3] = value;
2205
+ return 4;
2206
+ },
2207
+ setBigInt64LE(destination, offset, value) {
2208
+ const mask32bits = BigInt(4294967295);
2209
+ let lo = Number(value & mask32bits);
2210
+ destination[offset] = lo;
2211
+ lo >>= 8;
2212
+ destination[offset + 1] = lo;
2213
+ lo >>= 8;
2214
+ destination[offset + 2] = lo;
2215
+ lo >>= 8;
2216
+ destination[offset + 3] = lo;
2217
+ let hi = Number((value >> BigInt(32)) & mask32bits);
2218
+ destination[offset + 4] = hi;
2219
+ hi >>= 8;
2220
+ destination[offset + 5] = hi;
2221
+ hi >>= 8;
2222
+ destination[offset + 6] = hi;
2223
+ hi >>= 8;
2224
+ destination[offset + 7] = hi;
2225
+ return 8;
2226
+ },
2227
+ setFloat64LE: isBigEndian
2228
+ ? (destination, offset, value) => {
2229
+ FLOAT[0] = value;
2230
+ destination[offset] = FLOAT_BYTES[7];
2231
+ destination[offset + 1] = FLOAT_BYTES[6];
2232
+ destination[offset + 2] = FLOAT_BYTES[5];
2233
+ destination[offset + 3] = FLOAT_BYTES[4];
2234
+ destination[offset + 4] = FLOAT_BYTES[3];
2235
+ destination[offset + 5] = FLOAT_BYTES[2];
2236
+ destination[offset + 6] = FLOAT_BYTES[1];
2237
+ destination[offset + 7] = FLOAT_BYTES[0];
2238
+ return 8;
2239
+ }
2240
+ : (destination, offset, value) => {
2241
+ FLOAT[0] = value;
2242
+ destination[offset] = FLOAT_BYTES[0];
2243
+ destination[offset + 1] = FLOAT_BYTES[1];
2244
+ destination[offset + 2] = FLOAT_BYTES[2];
2245
+ destination[offset + 3] = FLOAT_BYTES[3];
2246
+ destination[offset + 4] = FLOAT_BYTES[4];
2247
+ destination[offset + 5] = FLOAT_BYTES[5];
2248
+ destination[offset + 6] = FLOAT_BYTES[6];
2249
+ destination[offset + 7] = FLOAT_BYTES[7];
2250
+ return 8;
2251
+ }
2252
+ };
2253
+
2112
2254
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2113
2255
  let PROCESS_UNIQUE = null;
2114
- const kId = Symbol('id');
2115
2256
  class ObjectId extends BSONValue {
2116
2257
  get _bsontype() {
2117
2258
  return 'ObjectId';
@@ -2134,14 +2275,14 @@ class ObjectId extends BSONValue {
2134
2275
  workingId = inputId;
2135
2276
  }
2136
2277
  if (workingId == null || typeof workingId === 'number') {
2137
- this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2278
+ this.buffer = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2138
2279
  }
2139
2280
  else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
2140
- this[kId] = ByteUtils.toLocalBufferType(workingId);
2281
+ this.buffer = ByteUtils.toLocalBufferType(workingId);
2141
2282
  }
2142
2283
  else if (typeof workingId === 'string') {
2143
2284
  if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2144
- this[kId] = ByteUtils.fromHex(workingId);
2285
+ this.buffer = ByteUtils.fromHex(workingId);
2145
2286
  }
2146
2287
  else {
2147
2288
  throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
@@ -2155,10 +2296,10 @@ class ObjectId extends BSONValue {
2155
2296
  }
2156
2297
  }
2157
2298
  get id() {
2158
- return this[kId];
2299
+ return this.buffer;
2159
2300
  }
2160
2301
  set id(value) {
2161
- this[kId] = value;
2302
+ this.buffer = value;
2162
2303
  if (ObjectId.cacheHexString) {
2163
2304
  this.__id = ByteUtils.toHex(value);
2164
2305
  }
@@ -2181,8 +2322,8 @@ class ObjectId extends BSONValue {
2181
2322
  time = Math.floor(Date.now() / 1000);
2182
2323
  }
2183
2324
  const inc = ObjectId.getInc();
2184
- const buffer = ByteUtils.allocate(12);
2185
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2325
+ const buffer = ByteUtils.allocateUnsafe(12);
2326
+ NumberUtils.setInt32BE(buffer, 0, time);
2186
2327
  if (PROCESS_UNIQUE === null) {
2187
2328
  PROCESS_UNIQUE = ByteUtils.randomBytes(5);
2188
2329
  }
@@ -2217,7 +2358,7 @@ class ObjectId extends BSONValue {
2217
2358
  return false;
2218
2359
  }
2219
2360
  if (ObjectId.is(otherId)) {
2220
- return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2361
+ return (this.buffer[11] === otherId.buffer[11] && ByteUtils.equals(this.buffer, otherId.buffer));
2221
2362
  }
2222
2363
  if (typeof otherId === 'string') {
2223
2364
  return otherId.toLowerCase() === this.toHexString();
@@ -2231,16 +2372,33 @@ class ObjectId extends BSONValue {
2231
2372
  }
2232
2373
  getTimestamp() {
2233
2374
  const timestamp = new Date();
2234
- const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
2375
+ const time = NumberUtils.getUint32BE(this.buffer, 0);
2235
2376
  timestamp.setTime(Math.floor(time) * 1000);
2236
2377
  return timestamp;
2237
2378
  }
2238
2379
  static createPk() {
2239
2380
  return new ObjectId();
2240
2381
  }
2382
+ serializeInto(uint8array, index) {
2383
+ uint8array[index] = this.buffer[0];
2384
+ uint8array[index + 1] = this.buffer[1];
2385
+ uint8array[index + 2] = this.buffer[2];
2386
+ uint8array[index + 3] = this.buffer[3];
2387
+ uint8array[index + 4] = this.buffer[4];
2388
+ uint8array[index + 5] = this.buffer[5];
2389
+ uint8array[index + 6] = this.buffer[6];
2390
+ uint8array[index + 7] = this.buffer[7];
2391
+ uint8array[index + 8] = this.buffer[8];
2392
+ uint8array[index + 9] = this.buffer[9];
2393
+ uint8array[index + 10] = this.buffer[10];
2394
+ uint8array[index + 11] = this.buffer[11];
2395
+ return 12;
2396
+ }
2241
2397
  static createFromTime(time) {
2242
- const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2243
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2398
+ const buffer = ByteUtils.allocate(12);
2399
+ for (let i = 11; i >= 4; i--)
2400
+ buffer[i] = 0;
2401
+ NumberUtils.setInt32BE(buffer, 0, time);
2244
2402
  return new ObjectId(buffer);
2245
2403
  }
2246
2404
  static createFromHexString(hexString) {
@@ -2612,10 +2770,7 @@ const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2612
2770
  function internalDeserialize(buffer, options, isArray) {
2613
2771
  options = options == null ? {} : options;
2614
2772
  const index = options && options.index ? options.index : 0;
2615
- const size = buffer[index] |
2616
- (buffer[index + 1] << 8) |
2617
- (buffer[index + 2] << 16) |
2618
- (buffer[index + 3] << 24);
2773
+ const size = NumberUtils.getInt32LE(buffer, index);
2619
2774
  if (size < 5) {
2620
2775
  throw new BSONError(`bson size must be >= 5, is ${size}`);
2621
2776
  }
@@ -2651,7 +2806,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2651
2806
  const validation = options.validation == null ? { utf8: true } : options.validation;
2652
2807
  let globalUTFValidation = true;
2653
2808
  let validationSetting;
2654
- const utf8KeysSet = new Set();
2809
+ let utf8KeysSet;
2655
2810
  const utf8ValidatedKeys = validation.utf8;
2656
2811
  if (typeof utf8ValidatedKeys === 'boolean') {
2657
2812
  validationSetting = utf8ValidatedKeys;
@@ -2673,6 +2828,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2673
2828
  }
2674
2829
  }
2675
2830
  if (!globalUTFValidation) {
2831
+ utf8KeysSet = new Set();
2676
2832
  for (const key of Object.keys(utf8ValidatedKeys)) {
2677
2833
  utf8KeysSet.add(key);
2678
2834
  }
@@ -2680,14 +2836,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
2680
2836
  const startIndex = index;
2681
2837
  if (buffer.length < 5)
2682
2838
  throw new BSONError('corrupt bson message < 5 bytes long');
2683
- const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
2839
+ const size = NumberUtils.getInt32LE(buffer, index);
2840
+ index += 4;
2684
2841
  if (size < 5 || size > buffer.length)
2685
2842
  throw new BSONError('corrupt bson message');
2686
2843
  const object = isArray ? [] : {};
2687
2844
  let arrayIndex = 0;
2688
2845
  const done = false;
2689
2846
  let isPossibleDBRef = isArray ? false : null;
2690
- const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2691
2847
  while (!done) {
2692
2848
  const elementType = buffer[index++];
2693
2849
  if (elementType === 0)
@@ -2700,7 +2856,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2700
2856
  throw new BSONError('Bad BSON Document: illegal CString');
2701
2857
  const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2702
2858
  let shouldValidateKey = true;
2703
- if (globalUTFValidation || utf8KeysSet.has(name)) {
2859
+ if (globalUTFValidation || utf8KeysSet?.has(name)) {
2704
2860
  shouldValidateKey = validationSetting;
2705
2861
  }
2706
2862
  else {
@@ -2712,10 +2868,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2712
2868
  let value;
2713
2869
  index = i + 1;
2714
2870
  if (elementType === BSON_DATA_STRING) {
2715
- const stringSize = buffer[index++] |
2716
- (buffer[index++] << 8) |
2717
- (buffer[index++] << 16) |
2718
- (buffer[index++] << 24);
2871
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
2872
+ index += 4;
2719
2873
  if (stringSize <= 0 ||
2720
2874
  stringSize > buffer.length - index ||
2721
2875
  buffer[index + stringSize - 1] !== 0) {
@@ -2725,38 +2879,30 @@ function deserializeObject(buffer, index, options, isArray = false) {
2725
2879
  index = index + stringSize;
2726
2880
  }
2727
2881
  else if (elementType === BSON_DATA_OID) {
2728
- const oid = ByteUtils.allocate(12);
2729
- oid.set(buffer.subarray(index, index + 12));
2882
+ const oid = ByteUtils.allocateUnsafe(12);
2883
+ for (let i = 0; i < 12; i++)
2884
+ oid[i] = buffer[index + i];
2730
2885
  value = new ObjectId(oid);
2731
2886
  index = index + 12;
2732
2887
  }
2733
2888
  else if (elementType === BSON_DATA_INT && promoteValues === false) {
2734
- value = new Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
2889
+ value = new Int32(NumberUtils.getInt32LE(buffer, index));
2890
+ index += 4;
2735
2891
  }
2736
2892
  else if (elementType === BSON_DATA_INT) {
2737
- value =
2738
- buffer[index++] |
2739
- (buffer[index++] << 8) |
2740
- (buffer[index++] << 16) |
2741
- (buffer[index++] << 24);
2742
- }
2743
- else if (elementType === BSON_DATA_NUMBER && promoteValues === false) {
2744
- value = new Double(dataview.getFloat64(index, true));
2745
- index = index + 8;
2893
+ value = NumberUtils.getInt32LE(buffer, index);
2894
+ index += 4;
2746
2895
  }
2747
2896
  else if (elementType === BSON_DATA_NUMBER) {
2748
- value = dataview.getFloat64(index, true);
2749
- index = index + 8;
2897
+ value = NumberUtils.getFloat64LE(buffer, index);
2898
+ index += 8;
2899
+ if (promoteValues === false)
2900
+ value = new Double(value);
2750
2901
  }
2751
2902
  else if (elementType === BSON_DATA_DATE) {
2752
- const lowBits = buffer[index++] |
2753
- (buffer[index++] << 8) |
2754
- (buffer[index++] << 16) |
2755
- (buffer[index++] << 24);
2756
- const highBits = buffer[index++] |
2757
- (buffer[index++] << 8) |
2758
- (buffer[index++] << 16) |
2759
- (buffer[index++] << 24);
2903
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2904
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2905
+ index += 8;
2760
2906
  value = new Date(new Long(lowBits, highBits).toNumber());
2761
2907
  }
2762
2908
  else if (elementType === BSON_DATA_BOOLEAN) {
@@ -2766,10 +2912,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2766
2912
  }
2767
2913
  else if (elementType === BSON_DATA_OBJECT) {
2768
2914
  const _index = index;
2769
- const objectSize = buffer[index] |
2770
- (buffer[index + 1] << 8) |
2771
- (buffer[index + 2] << 16) |
2772
- (buffer[index + 3] << 24);
2915
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2773
2916
  if (objectSize <= 0 || objectSize > buffer.length - index)
2774
2917
  throw new BSONError('bad embedded document length in bson');
2775
2918
  if (raw) {
@@ -2786,10 +2929,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2786
2929
  }
2787
2930
  else if (elementType === BSON_DATA_ARRAY) {
2788
2931
  const _index = index;
2789
- const objectSize = buffer[index] |
2790
- (buffer[index + 1] << 8) |
2791
- (buffer[index + 2] << 16) |
2792
- (buffer[index + 3] << 24);
2932
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2793
2933
  let arrayOptions = options;
2794
2934
  const stopIndex = index + objectSize;
2795
2935
  if (fieldsAsRaw && fieldsAsRaw[name]) {
@@ -2812,40 +2952,36 @@ function deserializeObject(buffer, index, options, isArray = false) {
2812
2952
  value = null;
2813
2953
  }
2814
2954
  else if (elementType === BSON_DATA_LONG) {
2815
- const dataview = BSONDataView.fromUint8Array(buffer.subarray(index, index + 8));
2816
- const lowBits = buffer[index++] |
2817
- (buffer[index++] << 8) |
2818
- (buffer[index++] << 16) |
2819
- (buffer[index++] << 24);
2820
- const highBits = buffer[index++] |
2821
- (buffer[index++] << 8) |
2822
- (buffer[index++] << 16) |
2823
- (buffer[index++] << 24);
2824
- const long = new Long(lowBits, highBits);
2825
2955
  if (useBigInt64) {
2826
- value = dataview.getBigInt64(0, true);
2827
- }
2828
- else if (promoteLongs && promoteValues === true) {
2829
- value =
2830
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2831
- ? long.toNumber()
2832
- : long;
2956
+ value = NumberUtils.getBigInt64LE(buffer, index);
2957
+ index += 8;
2833
2958
  }
2834
2959
  else {
2835
- value = long;
2960
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2961
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2962
+ index += 8;
2963
+ const long = new Long(lowBits, highBits);
2964
+ if (promoteLongs && promoteValues === true) {
2965
+ value =
2966
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2967
+ ? long.toNumber()
2968
+ : long;
2969
+ }
2970
+ else {
2971
+ value = long;
2972
+ }
2836
2973
  }
2837
2974
  }
2838
2975
  else if (elementType === BSON_DATA_DECIMAL128) {
2839
- const bytes = ByteUtils.allocate(16);
2840
- bytes.set(buffer.subarray(index, index + 16), 0);
2976
+ const bytes = ByteUtils.allocateUnsafe(16);
2977
+ for (let i = 0; i < 16; i++)
2978
+ bytes[i] = buffer[index + i];
2841
2979
  index = index + 16;
2842
2980
  value = new Decimal128(bytes);
2843
2981
  }
2844
2982
  else if (elementType === BSON_DATA_BINARY) {
2845
- let binarySize = buffer[index++] |
2846
- (buffer[index++] << 8) |
2847
- (buffer[index++] << 16) |
2848
- (buffer[index++] << 24);
2983
+ let binarySize = NumberUtils.getInt32LE(buffer, index);
2984
+ index += 4;
2849
2985
  const totalBinarySize = binarySize;
2850
2986
  const subType = buffer[index++];
2851
2987
  if (binarySize < 0)
@@ -2854,11 +2990,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2854
2990
  throw new BSONError('Binary type size larger than document size');
2855
2991
  if (buffer['slice'] != null) {
2856
2992
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2857
- binarySize =
2858
- buffer[index++] |
2859
- (buffer[index++] << 8) |
2860
- (buffer[index++] << 16) |
2861
- (buffer[index++] << 24);
2993
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2994
+ index += 4;
2862
2995
  if (binarySize < 0)
2863
2996
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2864
2997
  if (binarySize > totalBinarySize - 4)
@@ -2877,13 +3010,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2877
3010
  }
2878
3011
  }
2879
3012
  else {
2880
- const _buffer = ByteUtils.allocate(binarySize);
2881
3013
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2882
- binarySize =
2883
- buffer[index++] |
2884
- (buffer[index++] << 8) |
2885
- (buffer[index++] << 16) |
2886
- (buffer[index++] << 24);
3014
+ binarySize = NumberUtils.getInt32LE(buffer, index);
3015
+ index += 4;
2887
3016
  if (binarySize < 0)
2888
3017
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2889
3018
  if (binarySize > totalBinarySize - 4)
@@ -2891,11 +3020,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2891
3020
  if (binarySize < totalBinarySize - 4)
2892
3021
  throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
2893
3022
  }
2894
- for (i = 0; i < binarySize; i++) {
2895
- _buffer[i] = buffer[index + i];
2896
- }
2897
3023
  if (promoteBuffers && promoteValues) {
2898
- value = _buffer;
3024
+ value = ByteUtils.allocateUnsafe(binarySize);
3025
+ for (i = 0; i < binarySize; i++) {
3026
+ value[i] = buffer[index + i];
3027
+ }
2899
3028
  }
2900
3029
  else {
2901
3030
  value = new Binary(buffer.slice(index, index + binarySize), subType);
@@ -2959,10 +3088,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2959
3088
  value = new BSONRegExp(source, regExpOptions);
2960
3089
  }
2961
3090
  else if (elementType === BSON_DATA_SYMBOL) {
2962
- const stringSize = buffer[index++] |
2963
- (buffer[index++] << 8) |
2964
- (buffer[index++] << 16) |
2965
- (buffer[index++] << 24);
3091
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3092
+ index += 4;
2966
3093
  if (stringSize <= 0 ||
2967
3094
  stringSize > buffer.length - index ||
2968
3095
  buffer[index + stringSize - 1] !== 0) {
@@ -2973,15 +3100,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2973
3100
  index = index + stringSize;
2974
3101
  }
2975
3102
  else if (elementType === BSON_DATA_TIMESTAMP) {
2976
- const i = buffer[index++] +
2977
- buffer[index++] * (1 << 8) +
2978
- buffer[index++] * (1 << 16) +
2979
- buffer[index++] * (1 << 24);
2980
- const t = buffer[index++] +
2981
- buffer[index++] * (1 << 8) +
2982
- buffer[index++] * (1 << 16) +
2983
- buffer[index++] * (1 << 24);
2984
- value = new Timestamp({ i, t });
3103
+ value = new Timestamp({
3104
+ i: NumberUtils.getUint32LE(buffer, index),
3105
+ t: NumberUtils.getUint32LE(buffer, index + 4)
3106
+ });
3107
+ index += 8;
2985
3108
  }
2986
3109
  else if (elementType === BSON_DATA_MIN_KEY) {
2987
3110
  value = new MinKey();
@@ -2990,10 +3113,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2990
3113
  value = new MaxKey();
2991
3114
  }
2992
3115
  else if (elementType === BSON_DATA_CODE) {
2993
- const stringSize = buffer[index++] |
2994
- (buffer[index++] << 8) |
2995
- (buffer[index++] << 16) |
2996
- (buffer[index++] << 24);
3116
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3117
+ index += 4;
2997
3118
  if (stringSize <= 0 ||
2998
3119
  stringSize > buffer.length - index ||
2999
3120
  buffer[index + stringSize - 1] !== 0) {
@@ -3004,17 +3125,13 @@ function deserializeObject(buffer, index, options, isArray = false) {
3004
3125
  index = index + stringSize;
3005
3126
  }
3006
3127
  else if (elementType === BSON_DATA_CODE_W_SCOPE) {
3007
- const totalSize = buffer[index++] |
3008
- (buffer[index++] << 8) |
3009
- (buffer[index++] << 16) |
3010
- (buffer[index++] << 24);
3128
+ const totalSize = NumberUtils.getInt32LE(buffer, index);
3129
+ index += 4;
3011
3130
  if (totalSize < 4 + 4 + 4 + 1) {
3012
3131
  throw new BSONError('code_w_scope total size shorter minimum expected length');
3013
3132
  }
3014
- const stringSize = buffer[index++] |
3015
- (buffer[index++] << 8) |
3016
- (buffer[index++] << 16) |
3017
- (buffer[index++] << 24);
3133
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3134
+ index += 4;
3018
3135
  if (stringSize <= 0 ||
3019
3136
  stringSize > buffer.length - index ||
3020
3137
  buffer[index + stringSize - 1] !== 0) {
@@ -3023,10 +3140,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
3023
3140
  const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
3024
3141
  index = index + stringSize;
3025
3142
  const _index = index;
3026
- const objectSize = buffer[index] |
3027
- (buffer[index + 1] << 8) |
3028
- (buffer[index + 2] << 16) |
3029
- (buffer[index + 3] << 24);
3143
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
3030
3144
  const scopeObject = deserializeObject(buffer, _index, options, false);
3031
3145
  index = index + objectSize;
3032
3146
  if (totalSize < 4 + 4 + objectSize + stringSize) {
@@ -3038,10 +3152,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
3038
3152
  value = new Code(functionString, scopeObject);
3039
3153
  }
3040
3154
  else if (elementType === BSON_DATA_DBPOINTER) {
3041
- const stringSize = buffer[index++] |
3042
- (buffer[index++] << 8) |
3043
- (buffer[index++] << 16) |
3044
- (buffer[index++] << 24);
3155
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3156
+ index += 4;
3045
3157
  if (stringSize <= 0 ||
3046
3158
  stringSize > buffer.length - index ||
3047
3159
  buffer[index + stringSize - 1] !== 0)
@@ -3053,8 +3165,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
3053
3165
  }
3054
3166
  const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3055
3167
  index = index + stringSize;
3056
- const oidBuffer = ByteUtils.allocate(12);
3057
- oidBuffer.set(buffer.subarray(index, index + 12), 0);
3168
+ const oidBuffer = ByteUtils.allocateUnsafe(12);
3169
+ for (let i = 0; i < 12; i++)
3170
+ oidBuffer[i] = buffer[index + i];
3058
3171
  const oid = new ObjectId(oidBuffer);
3059
3172
  index = index + 12;
3060
3173
  value = new DBRef(namespace, oid);
@@ -3099,17 +3212,11 @@ function serializeString(buffer, key, value, index) {
3099
3212
  index = index + numberOfWrittenBytes + 1;
3100
3213
  buffer[index - 1] = 0;
3101
3214
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
3102
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
3103
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
3104
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
3105
- buffer[index] = (size + 1) & 0xff;
3215
+ NumberUtils.setInt32LE(buffer, index, size + 1);
3106
3216
  index = index + 4 + size;
3107
3217
  buffer[index++] = 0;
3108
3218
  return index;
3109
3219
  }
3110
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
3111
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
3112
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
3113
3220
  function serializeNumber(buffer, key, value, index) {
3114
3221
  const isNegativeZero = Object.is(value, -0);
3115
3222
  const type = !isNegativeZero &&
@@ -3118,19 +3225,16 @@ function serializeNumber(buffer, key, value, index) {
3118
3225
  value >= BSON_INT32_MIN
3119
3226
  ? BSON_DATA_INT
3120
3227
  : BSON_DATA_NUMBER;
3121
- if (type === BSON_DATA_INT) {
3122
- NUMBER_SPACE.setInt32(0, value, true);
3123
- }
3124
- else {
3125
- NUMBER_SPACE.setFloat64(0, value, true);
3126
- }
3127
- const bytes = type === BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
3128
3228
  buffer[index++] = type;
3129
3229
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3130
3230
  index = index + numberOfWrittenBytes;
3131
3231
  buffer[index++] = 0x00;
3132
- buffer.set(bytes, index);
3133
- index += bytes.byteLength;
3232
+ if (type === BSON_DATA_INT) {
3233
+ index += NumberUtils.setInt32LE(buffer, index, value);
3234
+ }
3235
+ else {
3236
+ index += NumberUtils.setFloat64LE(buffer, index, value);
3237
+ }
3134
3238
  return index;
3135
3239
  }
3136
3240
  function serializeBigInt(buffer, key, value, index) {
@@ -3138,9 +3242,7 @@ function serializeBigInt(buffer, key, value, index) {
3138
3242
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3139
3243
  index += numberOfWrittenBytes;
3140
3244
  buffer[index++] = 0;
3141
- NUMBER_SPACE.setBigInt64(0, value, true);
3142
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3143
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
3245
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
3144
3246
  return index;
3145
3247
  }
3146
3248
  function serializeNull(buffer, key, _, index) {
@@ -3166,14 +3268,8 @@ function serializeDate(buffer, key, value, index) {
3166
3268
  const dateInMilis = Long.fromNumber(value.getTime());
3167
3269
  const lowBits = dateInMilis.getLowBits();
3168
3270
  const highBits = dateInMilis.getHighBits();
3169
- buffer[index++] = lowBits & 0xff;
3170
- buffer[index++] = (lowBits >> 8) & 0xff;
3171
- buffer[index++] = (lowBits >> 16) & 0xff;
3172
- buffer[index++] = (lowBits >> 24) & 0xff;
3173
- buffer[index++] = highBits & 0xff;
3174
- buffer[index++] = (highBits >> 8) & 0xff;
3175
- buffer[index++] = (highBits >> 16) & 0xff;
3176
- buffer[index++] = (highBits >> 24) & 0xff;
3271
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3272
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3177
3273
  return index;
3178
3274
  }
3179
3275
  function serializeRegExp(buffer, key, value, index) {
@@ -3230,15 +3326,7 @@ function serializeObjectId(buffer, key, value, index) {
3230
3326
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3231
3327
  index = index + numberOfWrittenBytes;
3232
3328
  buffer[index++] = 0;
3233
- const idValue = value.id;
3234
- if (isUint8Array(idValue)) {
3235
- for (let i = 0; i < 12; i++) {
3236
- buffer[index++] = idValue[i];
3237
- }
3238
- }
3239
- else {
3240
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3241
- }
3329
+ index += value.serializeInto(buffer, index);
3242
3330
  return index;
3243
3331
  }
3244
3332
  function serializeBuffer(buffer, key, value, index) {
@@ -3247,12 +3335,15 @@ function serializeBuffer(buffer, key, value, index) {
3247
3335
  index = index + numberOfWrittenBytes;
3248
3336
  buffer[index++] = 0;
3249
3337
  const size = value.length;
3250
- buffer[index++] = size & 0xff;
3251
- buffer[index++] = (size >> 8) & 0xff;
3252
- buffer[index++] = (size >> 16) & 0xff;
3253
- buffer[index++] = (size >> 24) & 0xff;
3338
+ index += NumberUtils.setInt32LE(buffer, index, size);
3254
3339
  buffer[index++] = BSON_BINARY_SUBTYPE_DEFAULT;
3255
- buffer.set(value, index);
3340
+ if (size <= 16) {
3341
+ for (let i = 0; i < size; i++)
3342
+ buffer[index + i] = value[i];
3343
+ }
3344
+ else {
3345
+ buffer.set(value, index);
3346
+ }
3256
3347
  index = index + size;
3257
3348
  return index;
3258
3349
  }
@@ -3274,7 +3365,8 @@ function serializeDecimal128(buffer, key, value, index) {
3274
3365
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3275
3366
  index = index + numberOfWrittenBytes;
3276
3367
  buffer[index++] = 0;
3277
- buffer.set(value.bytes.subarray(0, 16), index);
3368
+ for (let i = 0; i < 16; i++)
3369
+ buffer[index + i] = value.bytes[i];
3278
3370
  return index + 16;
3279
3371
  }
3280
3372
  function serializeLong(buffer, key, value, index) {
@@ -3285,14 +3377,8 @@ function serializeLong(buffer, key, value, index) {
3285
3377
  buffer[index++] = 0;
3286
3378
  const lowBits = value.getLowBits();
3287
3379
  const highBits = value.getHighBits();
3288
- buffer[index++] = lowBits & 0xff;
3289
- buffer[index++] = (lowBits >> 8) & 0xff;
3290
- buffer[index++] = (lowBits >> 16) & 0xff;
3291
- buffer[index++] = (lowBits >> 24) & 0xff;
3292
- buffer[index++] = highBits & 0xff;
3293
- buffer[index++] = (highBits >> 8) & 0xff;
3294
- buffer[index++] = (highBits >> 16) & 0xff;
3295
- buffer[index++] = (highBits >> 24) & 0xff;
3380
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3381
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3296
3382
  return index;
3297
3383
  }
3298
3384
  function serializeInt32(buffer, key, value, index) {
@@ -3301,10 +3387,7 @@ function serializeInt32(buffer, key, value, index) {
3301
3387
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3302
3388
  index = index + numberOfWrittenBytes;
3303
3389
  buffer[index++] = 0;
3304
- buffer[index++] = value & 0xff;
3305
- buffer[index++] = (value >> 8) & 0xff;
3306
- buffer[index++] = (value >> 16) & 0xff;
3307
- buffer[index++] = (value >> 24) & 0xff;
3390
+ index += NumberUtils.setInt32LE(buffer, index, value);
3308
3391
  return index;
3309
3392
  }
3310
3393
  function serializeDouble(buffer, key, value, index) {
@@ -3312,9 +3395,7 @@ function serializeDouble(buffer, key, value, index) {
3312
3395
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3313
3396
  index = index + numberOfWrittenBytes;
3314
3397
  buffer[index++] = 0;
3315
- NUMBER_SPACE.setFloat64(0, value.value, true);
3316
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3317
- index = index + 8;
3398
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
3318
3399
  return index;
3319
3400
  }
3320
3401
  function serializeFunction(buffer, key, value, index) {
@@ -3324,10 +3405,7 @@ function serializeFunction(buffer, key, value, index) {
3324
3405
  buffer[index++] = 0;
3325
3406
  const functionString = value.toString();
3326
3407
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3327
- buffer[index] = size & 0xff;
3328
- buffer[index + 1] = (size >> 8) & 0xff;
3329
- buffer[index + 2] = (size >> 16) & 0xff;
3330
- buffer[index + 3] = (size >> 24) & 0xff;
3408
+ NumberUtils.setInt32LE(buffer, index, size);
3331
3409
  index = index + 4 + size - 1;
3332
3410
  buffer[index++] = 0;
3333
3411
  return index;
@@ -3342,19 +3420,13 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3342
3420
  const functionString = value.code;
3343
3421
  index = index + 4;
3344
3422
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3345
- buffer[index] = codeSize & 0xff;
3346
- buffer[index + 1] = (codeSize >> 8) & 0xff;
3347
- buffer[index + 2] = (codeSize >> 16) & 0xff;
3348
- buffer[index + 3] = (codeSize >> 24) & 0xff;
3423
+ NumberUtils.setInt32LE(buffer, index, codeSize);
3349
3424
  buffer[index + 4 + codeSize - 1] = 0;
3350
3425
  index = index + codeSize + 4;
3351
3426
  const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
3352
3427
  index = endIndex - 1;
3353
3428
  const totalSize = endIndex - startIndex;
3354
- buffer[startIndex++] = totalSize & 0xff;
3355
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
3356
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
3357
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
3429
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
3358
3430
  buffer[index++] = 0;
3359
3431
  }
3360
3432
  else {
@@ -3364,10 +3436,7 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3364
3436
  buffer[index++] = 0;
3365
3437
  const functionString = value.code.toString();
3366
3438
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3367
- buffer[index] = size & 0xff;
3368
- buffer[index + 1] = (size >> 8) & 0xff;
3369
- buffer[index + 2] = (size >> 16) & 0xff;
3370
- buffer[index + 3] = (size >> 24) & 0xff;
3439
+ NumberUtils.setInt32LE(buffer, index, size);
3371
3440
  index = index + 4 + size - 1;
3372
3441
  buffer[index++] = 0;
3373
3442
  }
@@ -3382,19 +3451,19 @@ function serializeBinary(buffer, key, value, index) {
3382
3451
  let size = value.position;
3383
3452
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY)
3384
3453
  size = size + 4;
3385
- buffer[index++] = size & 0xff;
3386
- buffer[index++] = (size >> 8) & 0xff;
3387
- buffer[index++] = (size >> 16) & 0xff;
3388
- buffer[index++] = (size >> 24) & 0xff;
3454
+ index += NumberUtils.setInt32LE(buffer, index, size);
3389
3455
  buffer[index++] = value.sub_type;
3390
3456
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
3391
3457
  size = size - 4;
3392
- buffer[index++] = size & 0xff;
3393
- buffer[index++] = (size >> 8) & 0xff;
3394
- buffer[index++] = (size >> 16) & 0xff;
3395
- buffer[index++] = (size >> 24) & 0xff;
3458
+ index += NumberUtils.setInt32LE(buffer, index, size);
3459
+ }
3460
+ if (size <= 16) {
3461
+ for (let i = 0; i < size; i++)
3462
+ buffer[index + i] = data[i];
3463
+ }
3464
+ else {
3465
+ buffer.set(data, index);
3396
3466
  }
3397
- buffer.set(data, index);
3398
3467
  index = index + value.position;
3399
3468
  return index;
3400
3469
  }
@@ -3404,12 +3473,9 @@ function serializeSymbol(buffer, key, value, index) {
3404
3473
  index = index + numberOfWrittenBytes;
3405
3474
  buffer[index++] = 0;
3406
3475
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
3407
- buffer[index] = size & 0xff;
3408
- buffer[index + 1] = (size >> 8) & 0xff;
3409
- buffer[index + 2] = (size >> 16) & 0xff;
3410
- buffer[index + 3] = (size >> 24) & 0xff;
3476
+ NumberUtils.setInt32LE(buffer, index, size);
3411
3477
  index = index + 4 + size - 1;
3412
- buffer[index++] = 0x00;
3478
+ buffer[index++] = 0;
3413
3479
  return index;
3414
3480
  }
3415
3481
  function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path) {
@@ -3428,10 +3494,7 @@ function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, pa
3428
3494
  output = Object.assign(output, value.fields);
3429
3495
  const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
3430
3496
  const size = endIndex - startIndex;
3431
- buffer[startIndex++] = size & 0xff;
3432
- buffer[startIndex++] = (size >> 8) & 0xff;
3433
- buffer[startIndex++] = (size >> 16) & 0xff;
3434
- buffer[startIndex++] = (size >> 24) & 0xff;
3497
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
3435
3498
  return endIndex;
3436
3499
  }
3437
3500
  function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
@@ -3567,7 +3630,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3567
3630
  if ('$' === key[0]) {
3568
3631
  throw new BSONError('key ' + key + " must not start with '$'");
3569
3632
  }
3570
- else if (~key.indexOf('.')) {
3633
+ else if (key.includes('.')) {
3571
3634
  throw new BSONError('key ' + key + " must not contain '.'");
3572
3635
  }
3573
3636
  }
@@ -3665,7 +3728,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3665
3728
  if ('$' === key[0]) {
3666
3729
  throw new BSONError('key ' + key + " must not start with '$'");
3667
3730
  }
3668
- else if (~key.indexOf('.')) {
3731
+ else if (key.includes('.')) {
3669
3732
  throw new BSONError('key ' + key + " must not contain '.'");
3670
3733
  }
3671
3734
  }
@@ -3749,10 +3812,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3749
3812
  path.delete(object);
3750
3813
  buffer[index++] = 0x00;
3751
3814
  const size = index - startingIndex;
3752
- buffer[startingIndex++] = size & 0xff;
3753
- buffer[startingIndex++] = (size >> 8) & 0xff;
3754
- buffer[startingIndex++] = (size >> 16) & 0xff;
3755
- buffer[startingIndex++] = (size >> 24) & 0xff;
3815
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
3756
3816
  return index;
3757
3817
  }
3758
3818
 
@@ -4066,6 +4126,104 @@ EJSON.serialize = EJSONserialize;
4066
4126
  EJSON.deserialize = EJSONdeserialize;
4067
4127
  Object.freeze(EJSON);
4068
4128
 
4129
+ function getSize(source, offset) {
4130
+ if (source[offset + 3] > 127) {
4131
+ throw new BSONOffsetError('BSON size cannot be negative', offset);
4132
+ }
4133
+ return (source[offset] |
4134
+ (source[offset + 1] << 8) |
4135
+ (source[offset + 2] << 16) |
4136
+ (source[offset + 3] << 24));
4137
+ }
4138
+ function findNull(bytes, offset) {
4139
+ let nullTerminatorOffset = offset;
4140
+ for (; bytes[nullTerminatorOffset] !== 0x00; nullTerminatorOffset++)
4141
+ ;
4142
+ if (nullTerminatorOffset === bytes.length - 1) {
4143
+ throw new BSONOffsetError('Null terminator not found', offset);
4144
+ }
4145
+ return nullTerminatorOffset;
4146
+ }
4147
+ function parseToElements(bytes, startOffset = 0) {
4148
+ if (bytes.length < 5) {
4149
+ throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4150
+ }
4151
+ const documentSize = getSize(bytes, startOffset);
4152
+ if (documentSize > bytes.length - startOffset) {
4153
+ throw new BSONOffsetError(`Parsed documentSize (${documentSize} bytes) does not match input length (${bytes.length} bytes)`, startOffset);
4154
+ }
4155
+ if (bytes[startOffset + documentSize - 1] !== 0x00) {
4156
+ throw new BSONOffsetError('BSON documents must end in 0x00', startOffset + documentSize);
4157
+ }
4158
+ const elements = [];
4159
+ let offset = startOffset + 4;
4160
+ while (offset <= documentSize + startOffset) {
4161
+ const type = bytes[offset];
4162
+ offset += 1;
4163
+ if (type === 0) {
4164
+ if (offset - startOffset !== documentSize) {
4165
+ throw new BSONOffsetError(`Invalid 0x00 type byte`, offset);
4166
+ }
4167
+ break;
4168
+ }
4169
+ const nameOffset = offset;
4170
+ const nameLength = findNull(bytes, offset) - nameOffset;
4171
+ offset += nameLength + 1;
4172
+ let length;
4173
+ if (type === 1 || type === 18 || type === 9 || type === 17) {
4174
+ length = 8;
4175
+ }
4176
+ else if (type === 16) {
4177
+ length = 4;
4178
+ }
4179
+ else if (type === 7) {
4180
+ length = 12;
4181
+ }
4182
+ else if (type === 19) {
4183
+ length = 16;
4184
+ }
4185
+ else if (type === 8) {
4186
+ length = 1;
4187
+ }
4188
+ else if (type === 10 || type === 6 || type === 127 || type === 255) {
4189
+ length = 0;
4190
+ }
4191
+ else if (type === 11) {
4192
+ length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4193
+ }
4194
+ else if (type === 3 || type === 4 || type === 15) {
4195
+ length = getSize(bytes, offset);
4196
+ }
4197
+ else if (type === 2 ||
4198
+ type === 5 ||
4199
+ type === 12 ||
4200
+ type === 13 ||
4201
+ type === 14) {
4202
+ length = getSize(bytes, offset) + 4;
4203
+ if (type === 5) {
4204
+ length += 1;
4205
+ }
4206
+ if (type === 12) {
4207
+ length += 12;
4208
+ }
4209
+ }
4210
+ else {
4211
+ throw new BSONOffsetError(`Invalid 0x${type.toString(16).padStart(2, '0')} type byte`, offset);
4212
+ }
4213
+ if (length > documentSize) {
4214
+ throw new BSONOffsetError('value reports length larger than document', offset);
4215
+ }
4216
+ elements.push([type, nameOffset, nameLength, offset, length]);
4217
+ offset += length;
4218
+ }
4219
+ return elements;
4220
+ }
4221
+
4222
+ const onDemand = Object.create(null);
4223
+ onDemand.parseToElements = parseToElements;
4224
+ onDemand.BSONOffsetError = BSONOffsetError;
4225
+ Object.freeze(onDemand);
4226
+
4069
4227
  const MAXSIZE = 1024 * 1024 * 17;
4070
4228
  let buffer = ByteUtils.allocate(MAXSIZE);
4071
4229
  function setInternalBufferSize(size) {
@@ -4082,7 +4240,7 @@ function serialize(object, options = {}) {
4082
4240
  buffer = ByteUtils.allocate(minInternalBufferSize);
4083
4241
  }
4084
4242
  const serializationIndex = serializeInto(buffer, object, checkKeys, 0, 0, serializeFunctions, ignoreUndefined, null);
4085
- const finishedBuffer = ByteUtils.allocate(serializationIndex);
4243
+ const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
4086
4244
  finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
4087
4245
  return finishedBuffer;
4088
4246
  }
@@ -4109,10 +4267,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4109
4267
  const bufferData = ByteUtils.toLocalBufferType(data);
4110
4268
  let index = startIndex;
4111
4269
  for (let i = 0; i < numberOfDocuments; i++) {
4112
- const size = bufferData[index] |
4113
- (bufferData[index + 1] << 8) |
4114
- (bufferData[index + 2] << 16) |
4115
- (bufferData[index + 3] << 24);
4270
+ const size = NumberUtils.getInt32LE(bufferData, index);
4116
4271
  internalOptions.index = index;
4117
4272
  documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
4118
4273
  index = index + size;
@@ -4145,6 +4300,7 @@ var bson = /*#__PURE__*/Object.freeze({
4145
4300
  calculateObjectSize: calculateObjectSize,
4146
4301
  deserialize: deserialize,
4147
4302
  deserializeStream: deserializeStream,
4303
+ onDemand: onDemand,
4148
4304
  serialize: serialize,
4149
4305
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
4150
4306
  setInternalBufferSize: setInternalBufferSize
@@ -4174,6 +4330,7 @@ exports.UUID = UUID;
4174
4330
  exports.calculateObjectSize = calculateObjectSize;
4175
4331
  exports.deserialize = deserialize;
4176
4332
  exports.deserializeStream = deserializeStream;
4333
+ exports.onDemand = onDemand;
4177
4334
  exports.serialize = serialize;
4178
4335
  exports.serializeWithBufferAndIndex = serializeWithBufferAndIndex;
4179
4336
  exports.setInternalBufferSize = setInternalBufferSize;