bson 6.3.0 → 6.4.1

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.
@@ -165,7 +165,7 @@ function validateUtf8(bytes, start, end) {
165
165
  return !continuation;
166
166
  }
167
167
 
168
- function tryLatin(uint8array, start, end) {
168
+ function tryReadBasicLatin(uint8array, start, end) {
169
169
  if (uint8array.length === 0) {
170
170
  return '';
171
171
  }
@@ -200,6 +200,21 @@ function tryLatin(uint8array, start, end) {
200
200
  }
201
201
  return String.fromCharCode(...latinBytes);
202
202
  }
203
+ function tryWriteBasicLatin(destination, source, offset) {
204
+ if (source.length === 0)
205
+ return 0;
206
+ if (source.length > 25)
207
+ return null;
208
+ if (destination.length - offset < source.length)
209
+ return null;
210
+ for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {
211
+ const char = source.charCodeAt(charOffset);
212
+ if (char > 127)
213
+ return null;
214
+ destination[destinationOffset] = char;
215
+ }
216
+ return source.length;
217
+ }
203
218
 
204
219
  function nodejsMathRandomBytes(byteLength) {
205
220
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
@@ -232,6 +247,9 @@ const nodeJsByteUtils = {
232
247
  allocate(size) {
233
248
  return Buffer.alloc(size);
234
249
  },
250
+ allocateUnsafe(size) {
251
+ return Buffer.allocUnsafe(size);
252
+ },
235
253
  equals(a, b) {
236
254
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
237
255
  },
@@ -256,11 +274,8 @@ const nodeJsByteUtils = {
256
274
  toHex(buffer) {
257
275
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
258
276
  },
259
- fromUTF8(text) {
260
- return Buffer.from(text, 'utf8');
261
- },
262
277
  toUTF8(buffer, start, end, fatal) {
263
- const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
278
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
264
279
  if (basicLatin != null) {
265
280
  return basicLatin;
266
281
  }
@@ -281,6 +296,10 @@ const nodeJsByteUtils = {
281
296
  return Buffer.byteLength(input, 'utf8');
282
297
  },
283
298
  encodeUTF8Into(buffer, source, byteOffset) {
299
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
300
+ if (latinBytesWritten != null) {
301
+ return latinBytesWritten;
302
+ }
284
303
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
285
304
  },
286
305
  randomBytes: nodejsRandomBytes
@@ -336,6 +355,9 @@ const webByteUtils = {
336
355
  }
337
356
  return new Uint8Array(size);
338
357
  },
358
+ allocateUnsafe(size) {
359
+ return webByteUtils.allocate(size);
360
+ },
339
361
  equals(a, b) {
340
362
  if (a.byteLength !== b.byteLength) {
341
363
  return false;
@@ -382,11 +404,8 @@ const webByteUtils = {
382
404
  toHex(uint8array) {
383
405
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
384
406
  },
385
- fromUTF8(text) {
386
- return new TextEncoder().encode(text);
387
- },
388
407
  toUTF8(uint8array, start, end, fatal) {
389
- const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
408
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
390
409
  if (basicLatin != null) {
391
410
  return basicLatin;
392
411
  }
@@ -401,11 +420,11 @@ const webByteUtils = {
401
420
  return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
402
421
  },
403
422
  utf8ByteLength(input) {
404
- return webByteUtils.fromUTF8(input).byteLength;
423
+ return new TextEncoder().encode(input).byteLength;
405
424
  },
406
- encodeUTF8Into(buffer, source, byteOffset) {
407
- const bytes = webByteUtils.fromUTF8(source);
408
- buffer.set(bytes, byteOffset);
425
+ encodeUTF8Into(uint8array, source, byteOffset) {
426
+ const bytes = new TextEncoder().encode(source);
427
+ uint8array.set(bytes, byteOffset);
409
428
  return bytes.byteLength;
410
429
  },
411
430
  randomBytes: webRandomBytes
@@ -413,11 +432,6 @@ const webByteUtils = {
413
432
 
414
433
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
415
434
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
416
- class BSONDataView extends DataView {
417
- static fromUint8Array(input) {
418
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
419
- }
420
- }
421
435
 
422
436
  class BSONValue {
423
437
  get [Symbol.for('@@mdb.bson.version')]() {
@@ -1837,7 +1851,7 @@ class Decimal128 extends BSONValue {
1837
1851
  if (isNegative) {
1838
1852
  dec.high = dec.high.or(Long.fromString('9223372036854775808'));
1839
1853
  }
1840
- const buffer = ByteUtils.allocate(16);
1854
+ const buffer = ByteUtils.allocateUnsafe(16);
1841
1855
  index = 0;
1842
1856
  buffer[index++] = dec.low.low & 0xff;
1843
1857
  buffer[index++] = (dec.low.low >> 8) & 0xff;
@@ -2110,9 +2124,132 @@ class MinKey extends BSONValue {
2110
2124
  }
2111
2125
  }
2112
2126
 
2127
+ const FLOAT = new Float64Array(1);
2128
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2129
+ FLOAT[0] = -1;
2130
+ const isBigEndian = FLOAT_BYTES[7] === 0;
2131
+ const NumberUtils = {
2132
+ getInt32LE(source, offset) {
2133
+ return (source[offset] |
2134
+ (source[offset + 1] << 8) |
2135
+ (source[offset + 2] << 16) |
2136
+ (source[offset + 3] << 24));
2137
+ },
2138
+ getUint32LE(source, offset) {
2139
+ return (source[offset] +
2140
+ source[offset + 1] * 256 +
2141
+ source[offset + 2] * 65536 +
2142
+ source[offset + 3] * 16777216);
2143
+ },
2144
+ getUint32BE(source, offset) {
2145
+ return (source[offset + 3] +
2146
+ source[offset + 2] * 256 +
2147
+ source[offset + 1] * 65536 +
2148
+ source[offset] * 16777216);
2149
+ },
2150
+ getBigInt64LE(source, offset) {
2151
+ const hi = BigInt(source[offset + 4] +
2152
+ source[offset + 5] * 256 +
2153
+ source[offset + 6] * 65536 +
2154
+ (source[offset + 7] << 24));
2155
+ const lo = BigInt(source[offset] +
2156
+ source[offset + 1] * 256 +
2157
+ source[offset + 2] * 65536 +
2158
+ source[offset + 3] * 16777216);
2159
+ return (hi << BigInt(32)) + lo;
2160
+ },
2161
+ getFloat64LE: isBigEndian
2162
+ ? (source, offset) => {
2163
+ FLOAT_BYTES[7] = source[offset];
2164
+ FLOAT_BYTES[6] = source[offset + 1];
2165
+ FLOAT_BYTES[5] = source[offset + 2];
2166
+ FLOAT_BYTES[4] = source[offset + 3];
2167
+ FLOAT_BYTES[3] = source[offset + 4];
2168
+ FLOAT_BYTES[2] = source[offset + 5];
2169
+ FLOAT_BYTES[1] = source[offset + 6];
2170
+ FLOAT_BYTES[0] = source[offset + 7];
2171
+ return FLOAT[0];
2172
+ }
2173
+ : (source, offset) => {
2174
+ FLOAT_BYTES[0] = source[offset];
2175
+ FLOAT_BYTES[1] = source[offset + 1];
2176
+ FLOAT_BYTES[2] = source[offset + 2];
2177
+ FLOAT_BYTES[3] = source[offset + 3];
2178
+ FLOAT_BYTES[4] = source[offset + 4];
2179
+ FLOAT_BYTES[5] = source[offset + 5];
2180
+ FLOAT_BYTES[6] = source[offset + 6];
2181
+ FLOAT_BYTES[7] = source[offset + 7];
2182
+ return FLOAT[0];
2183
+ },
2184
+ setInt32BE(destination, offset, value) {
2185
+ destination[offset + 3] = value;
2186
+ value >>>= 8;
2187
+ destination[offset + 2] = value;
2188
+ value >>>= 8;
2189
+ destination[offset + 1] = value;
2190
+ value >>>= 8;
2191
+ destination[offset] = value;
2192
+ return 4;
2193
+ },
2194
+ setInt32LE(destination, offset, value) {
2195
+ destination[offset] = value;
2196
+ value >>>= 8;
2197
+ destination[offset + 1] = value;
2198
+ value >>>= 8;
2199
+ destination[offset + 2] = value;
2200
+ value >>>= 8;
2201
+ destination[offset + 3] = value;
2202
+ return 4;
2203
+ },
2204
+ setBigInt64LE(destination, offset, value) {
2205
+ const mask32bits = BigInt(4294967295);
2206
+ let lo = Number(value & mask32bits);
2207
+ destination[offset] = lo;
2208
+ lo >>= 8;
2209
+ destination[offset + 1] = lo;
2210
+ lo >>= 8;
2211
+ destination[offset + 2] = lo;
2212
+ lo >>= 8;
2213
+ destination[offset + 3] = lo;
2214
+ let hi = Number((value >> BigInt(32)) & mask32bits);
2215
+ destination[offset + 4] = hi;
2216
+ hi >>= 8;
2217
+ destination[offset + 5] = hi;
2218
+ hi >>= 8;
2219
+ destination[offset + 6] = hi;
2220
+ hi >>= 8;
2221
+ destination[offset + 7] = hi;
2222
+ return 8;
2223
+ },
2224
+ setFloat64LE: isBigEndian
2225
+ ? (destination, offset, value) => {
2226
+ FLOAT[0] = value;
2227
+ destination[offset] = FLOAT_BYTES[7];
2228
+ destination[offset + 1] = FLOAT_BYTES[6];
2229
+ destination[offset + 2] = FLOAT_BYTES[5];
2230
+ destination[offset + 3] = FLOAT_BYTES[4];
2231
+ destination[offset + 4] = FLOAT_BYTES[3];
2232
+ destination[offset + 5] = FLOAT_BYTES[2];
2233
+ destination[offset + 6] = FLOAT_BYTES[1];
2234
+ destination[offset + 7] = FLOAT_BYTES[0];
2235
+ return 8;
2236
+ }
2237
+ : (destination, offset, value) => {
2238
+ FLOAT[0] = value;
2239
+ destination[offset] = FLOAT_BYTES[0];
2240
+ destination[offset + 1] = FLOAT_BYTES[1];
2241
+ destination[offset + 2] = FLOAT_BYTES[2];
2242
+ destination[offset + 3] = FLOAT_BYTES[3];
2243
+ destination[offset + 4] = FLOAT_BYTES[4];
2244
+ destination[offset + 5] = FLOAT_BYTES[5];
2245
+ destination[offset + 6] = FLOAT_BYTES[6];
2246
+ destination[offset + 7] = FLOAT_BYTES[7];
2247
+ return 8;
2248
+ }
2249
+ };
2250
+
2113
2251
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2114
2252
  let PROCESS_UNIQUE = null;
2115
- const kId = Symbol('id');
2116
2253
  class ObjectId extends BSONValue {
2117
2254
  get _bsontype() {
2118
2255
  return 'ObjectId';
@@ -2135,14 +2272,14 @@ class ObjectId extends BSONValue {
2135
2272
  workingId = inputId;
2136
2273
  }
2137
2274
  if (workingId == null || typeof workingId === 'number') {
2138
- this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2275
+ this.buffer = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2139
2276
  }
2140
2277
  else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
2141
- this[kId] = ByteUtils.toLocalBufferType(workingId);
2278
+ this.buffer = ByteUtils.toLocalBufferType(workingId);
2142
2279
  }
2143
2280
  else if (typeof workingId === 'string') {
2144
2281
  if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2145
- this[kId] = ByteUtils.fromHex(workingId);
2282
+ this.buffer = ByteUtils.fromHex(workingId);
2146
2283
  }
2147
2284
  else {
2148
2285
  throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
@@ -2156,10 +2293,10 @@ class ObjectId extends BSONValue {
2156
2293
  }
2157
2294
  }
2158
2295
  get id() {
2159
- return this[kId];
2296
+ return this.buffer;
2160
2297
  }
2161
2298
  set id(value) {
2162
- this[kId] = value;
2299
+ this.buffer = value;
2163
2300
  if (ObjectId.cacheHexString) {
2164
2301
  this.__id = ByteUtils.toHex(value);
2165
2302
  }
@@ -2182,8 +2319,8 @@ class ObjectId extends BSONValue {
2182
2319
  time = Math.floor(Date.now() / 1000);
2183
2320
  }
2184
2321
  const inc = ObjectId.getInc();
2185
- const buffer = ByteUtils.allocate(12);
2186
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2322
+ const buffer = ByteUtils.allocateUnsafe(12);
2323
+ NumberUtils.setInt32BE(buffer, 0, time);
2187
2324
  if (PROCESS_UNIQUE === null) {
2188
2325
  PROCESS_UNIQUE = ByteUtils.randomBytes(5);
2189
2326
  }
@@ -2218,7 +2355,7 @@ class ObjectId extends BSONValue {
2218
2355
  return false;
2219
2356
  }
2220
2357
  if (ObjectId.is(otherId)) {
2221
- return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2358
+ return (this.buffer[11] === otherId.buffer[11] && ByteUtils.equals(this.buffer, otherId.buffer));
2222
2359
  }
2223
2360
  if (typeof otherId === 'string') {
2224
2361
  return otherId.toLowerCase() === this.toHexString();
@@ -2232,16 +2369,33 @@ class ObjectId extends BSONValue {
2232
2369
  }
2233
2370
  getTimestamp() {
2234
2371
  const timestamp = new Date();
2235
- const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
2372
+ const time = NumberUtils.getUint32BE(this.buffer, 0);
2236
2373
  timestamp.setTime(Math.floor(time) * 1000);
2237
2374
  return timestamp;
2238
2375
  }
2239
2376
  static createPk() {
2240
2377
  return new ObjectId();
2241
2378
  }
2379
+ serializeInto(uint8array, index) {
2380
+ uint8array[index] = this.buffer[0];
2381
+ uint8array[index + 1] = this.buffer[1];
2382
+ uint8array[index + 2] = this.buffer[2];
2383
+ uint8array[index + 3] = this.buffer[3];
2384
+ uint8array[index + 4] = this.buffer[4];
2385
+ uint8array[index + 5] = this.buffer[5];
2386
+ uint8array[index + 6] = this.buffer[6];
2387
+ uint8array[index + 7] = this.buffer[7];
2388
+ uint8array[index + 8] = this.buffer[8];
2389
+ uint8array[index + 9] = this.buffer[9];
2390
+ uint8array[index + 10] = this.buffer[10];
2391
+ uint8array[index + 11] = this.buffer[11];
2392
+ return 12;
2393
+ }
2242
2394
  static createFromTime(time) {
2243
- const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2244
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2395
+ const buffer = ByteUtils.allocate(12);
2396
+ for (let i = 11; i >= 4; i--)
2397
+ buffer[i] = 0;
2398
+ NumberUtils.setInt32BE(buffer, 0, time);
2245
2399
  return new ObjectId(buffer);
2246
2400
  }
2247
2401
  static createFromHexString(hexString) {
@@ -2613,10 +2767,7 @@ const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2613
2767
  function internalDeserialize(buffer, options, isArray) {
2614
2768
  options = options == null ? {} : options;
2615
2769
  const index = options && options.index ? options.index : 0;
2616
- const size = buffer[index] |
2617
- (buffer[index + 1] << 8) |
2618
- (buffer[index + 2] << 16) |
2619
- (buffer[index + 3] << 24);
2770
+ const size = NumberUtils.getInt32LE(buffer, index);
2620
2771
  if (size < 5) {
2621
2772
  throw new BSONError(`bson size must be >= 5, is ${size}`);
2622
2773
  }
@@ -2652,7 +2803,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2652
2803
  const validation = options.validation == null ? { utf8: true } : options.validation;
2653
2804
  let globalUTFValidation = true;
2654
2805
  let validationSetting;
2655
- const utf8KeysSet = new Set();
2806
+ let utf8KeysSet;
2656
2807
  const utf8ValidatedKeys = validation.utf8;
2657
2808
  if (typeof utf8ValidatedKeys === 'boolean') {
2658
2809
  validationSetting = utf8ValidatedKeys;
@@ -2674,6 +2825,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2674
2825
  }
2675
2826
  }
2676
2827
  if (!globalUTFValidation) {
2828
+ utf8KeysSet = new Set();
2677
2829
  for (const key of Object.keys(utf8ValidatedKeys)) {
2678
2830
  utf8KeysSet.add(key);
2679
2831
  }
@@ -2681,14 +2833,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
2681
2833
  const startIndex = index;
2682
2834
  if (buffer.length < 5)
2683
2835
  throw new BSONError('corrupt bson message < 5 bytes long');
2684
- const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
2836
+ const size = NumberUtils.getInt32LE(buffer, index);
2837
+ index += 4;
2685
2838
  if (size < 5 || size > buffer.length)
2686
2839
  throw new BSONError('corrupt bson message');
2687
2840
  const object = isArray ? [] : {};
2688
2841
  let arrayIndex = 0;
2689
2842
  const done = false;
2690
2843
  let isPossibleDBRef = isArray ? false : null;
2691
- const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2692
2844
  while (!done) {
2693
2845
  const elementType = buffer[index++];
2694
2846
  if (elementType === 0)
@@ -2701,7 +2853,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2701
2853
  throw new BSONError('Bad BSON Document: illegal CString');
2702
2854
  const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2703
2855
  let shouldValidateKey = true;
2704
- if (globalUTFValidation || utf8KeysSet.has(name)) {
2856
+ if (globalUTFValidation || utf8KeysSet?.has(name)) {
2705
2857
  shouldValidateKey = validationSetting;
2706
2858
  }
2707
2859
  else {
@@ -2713,10 +2865,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2713
2865
  let value;
2714
2866
  index = i + 1;
2715
2867
  if (elementType === BSON_DATA_STRING) {
2716
- const stringSize = buffer[index++] |
2717
- (buffer[index++] << 8) |
2718
- (buffer[index++] << 16) |
2719
- (buffer[index++] << 24);
2868
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
2869
+ index += 4;
2720
2870
  if (stringSize <= 0 ||
2721
2871
  stringSize > buffer.length - index ||
2722
2872
  buffer[index + stringSize - 1] !== 0) {
@@ -2726,38 +2876,30 @@ function deserializeObject(buffer, index, options, isArray = false) {
2726
2876
  index = index + stringSize;
2727
2877
  }
2728
2878
  else if (elementType === BSON_DATA_OID) {
2729
- const oid = ByteUtils.allocate(12);
2730
- oid.set(buffer.subarray(index, index + 12));
2879
+ const oid = ByteUtils.allocateUnsafe(12);
2880
+ for (let i = 0; i < 12; i++)
2881
+ oid[i] = buffer[index + i];
2731
2882
  value = new ObjectId(oid);
2732
2883
  index = index + 12;
2733
2884
  }
2734
2885
  else if (elementType === BSON_DATA_INT && promoteValues === false) {
2735
- value = new Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
2886
+ value = new Int32(NumberUtils.getInt32LE(buffer, index));
2887
+ index += 4;
2736
2888
  }
2737
2889
  else if (elementType === BSON_DATA_INT) {
2738
- value =
2739
- buffer[index++] |
2740
- (buffer[index++] << 8) |
2741
- (buffer[index++] << 16) |
2742
- (buffer[index++] << 24);
2743
- }
2744
- else if (elementType === BSON_DATA_NUMBER && promoteValues === false) {
2745
- value = new Double(dataview.getFloat64(index, true));
2746
- index = index + 8;
2890
+ value = NumberUtils.getInt32LE(buffer, index);
2891
+ index += 4;
2747
2892
  }
2748
2893
  else if (elementType === BSON_DATA_NUMBER) {
2749
- value = dataview.getFloat64(index, true);
2750
- index = index + 8;
2894
+ value = NumberUtils.getFloat64LE(buffer, index);
2895
+ index += 8;
2896
+ if (promoteValues === false)
2897
+ value = new Double(value);
2751
2898
  }
2752
2899
  else if (elementType === BSON_DATA_DATE) {
2753
- const lowBits = buffer[index++] |
2754
- (buffer[index++] << 8) |
2755
- (buffer[index++] << 16) |
2756
- (buffer[index++] << 24);
2757
- const highBits = buffer[index++] |
2758
- (buffer[index++] << 8) |
2759
- (buffer[index++] << 16) |
2760
- (buffer[index++] << 24);
2900
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2901
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2902
+ index += 8;
2761
2903
  value = new Date(new Long(lowBits, highBits).toNumber());
2762
2904
  }
2763
2905
  else if (elementType === BSON_DATA_BOOLEAN) {
@@ -2767,10 +2909,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2767
2909
  }
2768
2910
  else if (elementType === BSON_DATA_OBJECT) {
2769
2911
  const _index = index;
2770
- const objectSize = buffer[index] |
2771
- (buffer[index + 1] << 8) |
2772
- (buffer[index + 2] << 16) |
2773
- (buffer[index + 3] << 24);
2912
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2774
2913
  if (objectSize <= 0 || objectSize > buffer.length - index)
2775
2914
  throw new BSONError('bad embedded document length in bson');
2776
2915
  if (raw) {
@@ -2787,10 +2926,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2787
2926
  }
2788
2927
  else if (elementType === BSON_DATA_ARRAY) {
2789
2928
  const _index = index;
2790
- const objectSize = buffer[index] |
2791
- (buffer[index + 1] << 8) |
2792
- (buffer[index + 2] << 16) |
2793
- (buffer[index + 3] << 24);
2929
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2794
2930
  let arrayOptions = options;
2795
2931
  const stopIndex = index + objectSize;
2796
2932
  if (fieldsAsRaw && fieldsAsRaw[name]) {
@@ -2813,40 +2949,36 @@ function deserializeObject(buffer, index, options, isArray = false) {
2813
2949
  value = null;
2814
2950
  }
2815
2951
  else if (elementType === BSON_DATA_LONG) {
2816
- const dataview = BSONDataView.fromUint8Array(buffer.subarray(index, index + 8));
2817
- const lowBits = buffer[index++] |
2818
- (buffer[index++] << 8) |
2819
- (buffer[index++] << 16) |
2820
- (buffer[index++] << 24);
2821
- const highBits = buffer[index++] |
2822
- (buffer[index++] << 8) |
2823
- (buffer[index++] << 16) |
2824
- (buffer[index++] << 24);
2825
- const long = new Long(lowBits, highBits);
2826
2952
  if (useBigInt64) {
2827
- value = dataview.getBigInt64(0, true);
2828
- }
2829
- else if (promoteLongs && promoteValues === true) {
2830
- value =
2831
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2832
- ? long.toNumber()
2833
- : long;
2953
+ value = NumberUtils.getBigInt64LE(buffer, index);
2954
+ index += 8;
2834
2955
  }
2835
2956
  else {
2836
- value = long;
2957
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2958
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2959
+ index += 8;
2960
+ const long = new Long(lowBits, highBits);
2961
+ if (promoteLongs && promoteValues === true) {
2962
+ value =
2963
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2964
+ ? long.toNumber()
2965
+ : long;
2966
+ }
2967
+ else {
2968
+ value = long;
2969
+ }
2837
2970
  }
2838
2971
  }
2839
2972
  else if (elementType === BSON_DATA_DECIMAL128) {
2840
- const bytes = ByteUtils.allocate(16);
2841
- bytes.set(buffer.subarray(index, index + 16), 0);
2973
+ const bytes = ByteUtils.allocateUnsafe(16);
2974
+ for (let i = 0; i < 16; i++)
2975
+ bytes[i] = buffer[index + i];
2842
2976
  index = index + 16;
2843
2977
  value = new Decimal128(bytes);
2844
2978
  }
2845
2979
  else if (elementType === BSON_DATA_BINARY) {
2846
- let binarySize = buffer[index++] |
2847
- (buffer[index++] << 8) |
2848
- (buffer[index++] << 16) |
2849
- (buffer[index++] << 24);
2980
+ let binarySize = NumberUtils.getInt32LE(buffer, index);
2981
+ index += 4;
2850
2982
  const totalBinarySize = binarySize;
2851
2983
  const subType = buffer[index++];
2852
2984
  if (binarySize < 0)
@@ -2855,11 +2987,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2855
2987
  throw new BSONError('Binary type size larger than document size');
2856
2988
  if (buffer['slice'] != null) {
2857
2989
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2858
- binarySize =
2859
- buffer[index++] |
2860
- (buffer[index++] << 8) |
2861
- (buffer[index++] << 16) |
2862
- (buffer[index++] << 24);
2990
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2991
+ index += 4;
2863
2992
  if (binarySize < 0)
2864
2993
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2865
2994
  if (binarySize > totalBinarySize - 4)
@@ -2878,13 +3007,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2878
3007
  }
2879
3008
  }
2880
3009
  else {
2881
- const _buffer = ByteUtils.allocate(binarySize);
2882
3010
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2883
- binarySize =
2884
- buffer[index++] |
2885
- (buffer[index++] << 8) |
2886
- (buffer[index++] << 16) |
2887
- (buffer[index++] << 24);
3011
+ binarySize = NumberUtils.getInt32LE(buffer, index);
3012
+ index += 4;
2888
3013
  if (binarySize < 0)
2889
3014
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2890
3015
  if (binarySize > totalBinarySize - 4)
@@ -2892,11 +3017,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2892
3017
  if (binarySize < totalBinarySize - 4)
2893
3018
  throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
2894
3019
  }
2895
- for (i = 0; i < binarySize; i++) {
2896
- _buffer[i] = buffer[index + i];
2897
- }
2898
3020
  if (promoteBuffers && promoteValues) {
2899
- value = _buffer;
3021
+ value = ByteUtils.allocateUnsafe(binarySize);
3022
+ for (i = 0; i < binarySize; i++) {
3023
+ value[i] = buffer[index + i];
3024
+ }
2900
3025
  }
2901
3026
  else {
2902
3027
  value = new Binary(buffer.slice(index, index + binarySize), subType);
@@ -2960,10 +3085,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2960
3085
  value = new BSONRegExp(source, regExpOptions);
2961
3086
  }
2962
3087
  else if (elementType === BSON_DATA_SYMBOL) {
2963
- const stringSize = buffer[index++] |
2964
- (buffer[index++] << 8) |
2965
- (buffer[index++] << 16) |
2966
- (buffer[index++] << 24);
3088
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3089
+ index += 4;
2967
3090
  if (stringSize <= 0 ||
2968
3091
  stringSize > buffer.length - index ||
2969
3092
  buffer[index + stringSize - 1] !== 0) {
@@ -2974,15 +3097,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2974
3097
  index = index + stringSize;
2975
3098
  }
2976
3099
  else if (elementType === BSON_DATA_TIMESTAMP) {
2977
- const i = buffer[index++] +
2978
- buffer[index++] * (1 << 8) +
2979
- buffer[index++] * (1 << 16) +
2980
- buffer[index++] * (1 << 24);
2981
- const t = buffer[index++] +
2982
- buffer[index++] * (1 << 8) +
2983
- buffer[index++] * (1 << 16) +
2984
- buffer[index++] * (1 << 24);
2985
- value = new Timestamp({ i, t });
3100
+ value = new Timestamp({
3101
+ i: NumberUtils.getUint32LE(buffer, index),
3102
+ t: NumberUtils.getUint32LE(buffer, index + 4)
3103
+ });
3104
+ index += 8;
2986
3105
  }
2987
3106
  else if (elementType === BSON_DATA_MIN_KEY) {
2988
3107
  value = new MinKey();
@@ -2991,10 +3110,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2991
3110
  value = new MaxKey();
2992
3111
  }
2993
3112
  else if (elementType === BSON_DATA_CODE) {
2994
- const stringSize = buffer[index++] |
2995
- (buffer[index++] << 8) |
2996
- (buffer[index++] << 16) |
2997
- (buffer[index++] << 24);
3113
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3114
+ index += 4;
2998
3115
  if (stringSize <= 0 ||
2999
3116
  stringSize > buffer.length - index ||
3000
3117
  buffer[index + stringSize - 1] !== 0) {
@@ -3005,17 +3122,13 @@ function deserializeObject(buffer, index, options, isArray = false) {
3005
3122
  index = index + stringSize;
3006
3123
  }
3007
3124
  else if (elementType === BSON_DATA_CODE_W_SCOPE) {
3008
- const totalSize = buffer[index++] |
3009
- (buffer[index++] << 8) |
3010
- (buffer[index++] << 16) |
3011
- (buffer[index++] << 24);
3125
+ const totalSize = NumberUtils.getInt32LE(buffer, index);
3126
+ index += 4;
3012
3127
  if (totalSize < 4 + 4 + 4 + 1) {
3013
3128
  throw new BSONError('code_w_scope total size shorter minimum expected length');
3014
3129
  }
3015
- const stringSize = buffer[index++] |
3016
- (buffer[index++] << 8) |
3017
- (buffer[index++] << 16) |
3018
- (buffer[index++] << 24);
3130
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3131
+ index += 4;
3019
3132
  if (stringSize <= 0 ||
3020
3133
  stringSize > buffer.length - index ||
3021
3134
  buffer[index + stringSize - 1] !== 0) {
@@ -3024,10 +3137,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
3024
3137
  const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
3025
3138
  index = index + stringSize;
3026
3139
  const _index = index;
3027
- const objectSize = buffer[index] |
3028
- (buffer[index + 1] << 8) |
3029
- (buffer[index + 2] << 16) |
3030
- (buffer[index + 3] << 24);
3140
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
3031
3141
  const scopeObject = deserializeObject(buffer, _index, options, false);
3032
3142
  index = index + objectSize;
3033
3143
  if (totalSize < 4 + 4 + objectSize + stringSize) {
@@ -3039,10 +3149,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
3039
3149
  value = new Code(functionString, scopeObject);
3040
3150
  }
3041
3151
  else if (elementType === BSON_DATA_DBPOINTER) {
3042
- const stringSize = buffer[index++] |
3043
- (buffer[index++] << 8) |
3044
- (buffer[index++] << 16) |
3045
- (buffer[index++] << 24);
3152
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3153
+ index += 4;
3046
3154
  if (stringSize <= 0 ||
3047
3155
  stringSize > buffer.length - index ||
3048
3156
  buffer[index + stringSize - 1] !== 0)
@@ -3054,8 +3162,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
3054
3162
  }
3055
3163
  const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3056
3164
  index = index + stringSize;
3057
- const oidBuffer = ByteUtils.allocate(12);
3058
- oidBuffer.set(buffer.subarray(index, index + 12), 0);
3165
+ const oidBuffer = ByteUtils.allocateUnsafe(12);
3166
+ for (let i = 0; i < 12; i++)
3167
+ oidBuffer[i] = buffer[index + i];
3059
3168
  const oid = new ObjectId(oidBuffer);
3060
3169
  index = index + 12;
3061
3170
  value = new DBRef(namespace, oid);
@@ -3100,17 +3209,11 @@ function serializeString(buffer, key, value, index) {
3100
3209
  index = index + numberOfWrittenBytes + 1;
3101
3210
  buffer[index - 1] = 0;
3102
3211
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
3103
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
3104
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
3105
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
3106
- buffer[index] = (size + 1) & 0xff;
3212
+ NumberUtils.setInt32LE(buffer, index, size + 1);
3107
3213
  index = index + 4 + size;
3108
3214
  buffer[index++] = 0;
3109
3215
  return index;
3110
3216
  }
3111
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
3112
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
3113
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
3114
3217
  function serializeNumber(buffer, key, value, index) {
3115
3218
  const isNegativeZero = Object.is(value, -0);
3116
3219
  const type = !isNegativeZero &&
@@ -3119,19 +3222,16 @@ function serializeNumber(buffer, key, value, index) {
3119
3222
  value >= BSON_INT32_MIN
3120
3223
  ? BSON_DATA_INT
3121
3224
  : BSON_DATA_NUMBER;
3122
- if (type === BSON_DATA_INT) {
3123
- NUMBER_SPACE.setInt32(0, value, true);
3124
- }
3125
- else {
3126
- NUMBER_SPACE.setFloat64(0, value, true);
3127
- }
3128
- const bytes = type === BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
3129
3225
  buffer[index++] = type;
3130
3226
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3131
3227
  index = index + numberOfWrittenBytes;
3132
3228
  buffer[index++] = 0x00;
3133
- buffer.set(bytes, index);
3134
- index += bytes.byteLength;
3229
+ if (type === BSON_DATA_INT) {
3230
+ index += NumberUtils.setInt32LE(buffer, index, value);
3231
+ }
3232
+ else {
3233
+ index += NumberUtils.setFloat64LE(buffer, index, value);
3234
+ }
3135
3235
  return index;
3136
3236
  }
3137
3237
  function serializeBigInt(buffer, key, value, index) {
@@ -3139,9 +3239,7 @@ function serializeBigInt(buffer, key, value, index) {
3139
3239
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3140
3240
  index += numberOfWrittenBytes;
3141
3241
  buffer[index++] = 0;
3142
- NUMBER_SPACE.setBigInt64(0, value, true);
3143
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3144
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
3242
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
3145
3243
  return index;
3146
3244
  }
3147
3245
  function serializeNull(buffer, key, _, index) {
@@ -3167,14 +3265,8 @@ function serializeDate(buffer, key, value, index) {
3167
3265
  const dateInMilis = Long.fromNumber(value.getTime());
3168
3266
  const lowBits = dateInMilis.getLowBits();
3169
3267
  const highBits = dateInMilis.getHighBits();
3170
- buffer[index++] = lowBits & 0xff;
3171
- buffer[index++] = (lowBits >> 8) & 0xff;
3172
- buffer[index++] = (lowBits >> 16) & 0xff;
3173
- buffer[index++] = (lowBits >> 24) & 0xff;
3174
- buffer[index++] = highBits & 0xff;
3175
- buffer[index++] = (highBits >> 8) & 0xff;
3176
- buffer[index++] = (highBits >> 16) & 0xff;
3177
- buffer[index++] = (highBits >> 24) & 0xff;
3268
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3269
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3178
3270
  return index;
3179
3271
  }
3180
3272
  function serializeRegExp(buffer, key, value, index) {
@@ -3231,15 +3323,7 @@ function serializeObjectId(buffer, key, value, index) {
3231
3323
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3232
3324
  index = index + numberOfWrittenBytes;
3233
3325
  buffer[index++] = 0;
3234
- const idValue = value.id;
3235
- if (isUint8Array(idValue)) {
3236
- for (let i = 0; i < 12; i++) {
3237
- buffer[index++] = idValue[i];
3238
- }
3239
- }
3240
- else {
3241
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3242
- }
3326
+ index += value.serializeInto(buffer, index);
3243
3327
  return index;
3244
3328
  }
3245
3329
  function serializeBuffer(buffer, key, value, index) {
@@ -3248,12 +3332,15 @@ function serializeBuffer(buffer, key, value, index) {
3248
3332
  index = index + numberOfWrittenBytes;
3249
3333
  buffer[index++] = 0;
3250
3334
  const size = value.length;
3251
- buffer[index++] = size & 0xff;
3252
- buffer[index++] = (size >> 8) & 0xff;
3253
- buffer[index++] = (size >> 16) & 0xff;
3254
- buffer[index++] = (size >> 24) & 0xff;
3335
+ index += NumberUtils.setInt32LE(buffer, index, size);
3255
3336
  buffer[index++] = BSON_BINARY_SUBTYPE_DEFAULT;
3256
- buffer.set(value, index);
3337
+ if (size <= 16) {
3338
+ for (let i = 0; i < size; i++)
3339
+ buffer[index + i] = value[i];
3340
+ }
3341
+ else {
3342
+ buffer.set(value, index);
3343
+ }
3257
3344
  index = index + size;
3258
3345
  return index;
3259
3346
  }
@@ -3275,7 +3362,8 @@ function serializeDecimal128(buffer, key, value, index) {
3275
3362
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3276
3363
  index = index + numberOfWrittenBytes;
3277
3364
  buffer[index++] = 0;
3278
- buffer.set(value.bytes.subarray(0, 16), index);
3365
+ for (let i = 0; i < 16; i++)
3366
+ buffer[index + i] = value.bytes[i];
3279
3367
  return index + 16;
3280
3368
  }
3281
3369
  function serializeLong(buffer, key, value, index) {
@@ -3286,14 +3374,8 @@ function serializeLong(buffer, key, value, index) {
3286
3374
  buffer[index++] = 0;
3287
3375
  const lowBits = value.getLowBits();
3288
3376
  const highBits = value.getHighBits();
3289
- buffer[index++] = lowBits & 0xff;
3290
- buffer[index++] = (lowBits >> 8) & 0xff;
3291
- buffer[index++] = (lowBits >> 16) & 0xff;
3292
- buffer[index++] = (lowBits >> 24) & 0xff;
3293
- buffer[index++] = highBits & 0xff;
3294
- buffer[index++] = (highBits >> 8) & 0xff;
3295
- buffer[index++] = (highBits >> 16) & 0xff;
3296
- buffer[index++] = (highBits >> 24) & 0xff;
3377
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3378
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3297
3379
  return index;
3298
3380
  }
3299
3381
  function serializeInt32(buffer, key, value, index) {
@@ -3302,10 +3384,7 @@ function serializeInt32(buffer, key, value, index) {
3302
3384
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3303
3385
  index = index + numberOfWrittenBytes;
3304
3386
  buffer[index++] = 0;
3305
- buffer[index++] = value & 0xff;
3306
- buffer[index++] = (value >> 8) & 0xff;
3307
- buffer[index++] = (value >> 16) & 0xff;
3308
- buffer[index++] = (value >> 24) & 0xff;
3387
+ index += NumberUtils.setInt32LE(buffer, index, value);
3309
3388
  return index;
3310
3389
  }
3311
3390
  function serializeDouble(buffer, key, value, index) {
@@ -3313,9 +3392,7 @@ function serializeDouble(buffer, key, value, index) {
3313
3392
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3314
3393
  index = index + numberOfWrittenBytes;
3315
3394
  buffer[index++] = 0;
3316
- NUMBER_SPACE.setFloat64(0, value.value, true);
3317
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3318
- index = index + 8;
3395
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
3319
3396
  return index;
3320
3397
  }
3321
3398
  function serializeFunction(buffer, key, value, index) {
@@ -3325,10 +3402,7 @@ function serializeFunction(buffer, key, value, index) {
3325
3402
  buffer[index++] = 0;
3326
3403
  const functionString = value.toString();
3327
3404
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3328
- buffer[index] = size & 0xff;
3329
- buffer[index + 1] = (size >> 8) & 0xff;
3330
- buffer[index + 2] = (size >> 16) & 0xff;
3331
- buffer[index + 3] = (size >> 24) & 0xff;
3405
+ NumberUtils.setInt32LE(buffer, index, size);
3332
3406
  index = index + 4 + size - 1;
3333
3407
  buffer[index++] = 0;
3334
3408
  return index;
@@ -3343,19 +3417,13 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3343
3417
  const functionString = value.code;
3344
3418
  index = index + 4;
3345
3419
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3346
- buffer[index] = codeSize & 0xff;
3347
- buffer[index + 1] = (codeSize >> 8) & 0xff;
3348
- buffer[index + 2] = (codeSize >> 16) & 0xff;
3349
- buffer[index + 3] = (codeSize >> 24) & 0xff;
3420
+ NumberUtils.setInt32LE(buffer, index, codeSize);
3350
3421
  buffer[index + 4 + codeSize - 1] = 0;
3351
3422
  index = index + codeSize + 4;
3352
3423
  const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
3353
3424
  index = endIndex - 1;
3354
3425
  const totalSize = endIndex - startIndex;
3355
- buffer[startIndex++] = totalSize & 0xff;
3356
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
3357
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
3358
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
3426
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
3359
3427
  buffer[index++] = 0;
3360
3428
  }
3361
3429
  else {
@@ -3365,10 +3433,7 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3365
3433
  buffer[index++] = 0;
3366
3434
  const functionString = value.code.toString();
3367
3435
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3368
- buffer[index] = size & 0xff;
3369
- buffer[index + 1] = (size >> 8) & 0xff;
3370
- buffer[index + 2] = (size >> 16) & 0xff;
3371
- buffer[index + 3] = (size >> 24) & 0xff;
3436
+ NumberUtils.setInt32LE(buffer, index, size);
3372
3437
  index = index + 4 + size - 1;
3373
3438
  buffer[index++] = 0;
3374
3439
  }
@@ -3383,19 +3448,19 @@ function serializeBinary(buffer, key, value, index) {
3383
3448
  let size = value.position;
3384
3449
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY)
3385
3450
  size = size + 4;
3386
- buffer[index++] = size & 0xff;
3387
- buffer[index++] = (size >> 8) & 0xff;
3388
- buffer[index++] = (size >> 16) & 0xff;
3389
- buffer[index++] = (size >> 24) & 0xff;
3451
+ index += NumberUtils.setInt32LE(buffer, index, size);
3390
3452
  buffer[index++] = value.sub_type;
3391
3453
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
3392
3454
  size = size - 4;
3393
- buffer[index++] = size & 0xff;
3394
- buffer[index++] = (size >> 8) & 0xff;
3395
- buffer[index++] = (size >> 16) & 0xff;
3396
- buffer[index++] = (size >> 24) & 0xff;
3455
+ index += NumberUtils.setInt32LE(buffer, index, size);
3456
+ }
3457
+ if (size <= 16) {
3458
+ for (let i = 0; i < size; i++)
3459
+ buffer[index + i] = data[i];
3460
+ }
3461
+ else {
3462
+ buffer.set(data, index);
3397
3463
  }
3398
- buffer.set(data, index);
3399
3464
  index = index + value.position;
3400
3465
  return index;
3401
3466
  }
@@ -3405,12 +3470,9 @@ function serializeSymbol(buffer, key, value, index) {
3405
3470
  index = index + numberOfWrittenBytes;
3406
3471
  buffer[index++] = 0;
3407
3472
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
3408
- buffer[index] = size & 0xff;
3409
- buffer[index + 1] = (size >> 8) & 0xff;
3410
- buffer[index + 2] = (size >> 16) & 0xff;
3411
- buffer[index + 3] = (size >> 24) & 0xff;
3473
+ NumberUtils.setInt32LE(buffer, index, size);
3412
3474
  index = index + 4 + size - 1;
3413
- buffer[index++] = 0x00;
3475
+ buffer[index++] = 0;
3414
3476
  return index;
3415
3477
  }
3416
3478
  function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path) {
@@ -3429,10 +3491,7 @@ function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, pa
3429
3491
  output = Object.assign(output, value.fields);
3430
3492
  const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
3431
3493
  const size = endIndex - startIndex;
3432
- buffer[startIndex++] = size & 0xff;
3433
- buffer[startIndex++] = (size >> 8) & 0xff;
3434
- buffer[startIndex++] = (size >> 16) & 0xff;
3435
- buffer[startIndex++] = (size >> 24) & 0xff;
3494
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
3436
3495
  return endIndex;
3437
3496
  }
3438
3497
  function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
@@ -3568,7 +3627,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3568
3627
  if ('$' === key[0]) {
3569
3628
  throw new BSONError('key ' + key + " must not start with '$'");
3570
3629
  }
3571
- else if (~key.indexOf('.')) {
3630
+ else if (key.includes('.')) {
3572
3631
  throw new BSONError('key ' + key + " must not contain '.'");
3573
3632
  }
3574
3633
  }
@@ -3666,7 +3725,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3666
3725
  if ('$' === key[0]) {
3667
3726
  throw new BSONError('key ' + key + " must not start with '$'");
3668
3727
  }
3669
- else if (~key.indexOf('.')) {
3728
+ else if (key.includes('.')) {
3670
3729
  throw new BSONError('key ' + key + " must not contain '.'");
3671
3730
  }
3672
3731
  }
@@ -3750,10 +3809,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3750
3809
  path.delete(object);
3751
3810
  buffer[index++] = 0x00;
3752
3811
  const size = index - startingIndex;
3753
- buffer[startingIndex++] = size & 0xff;
3754
- buffer[startingIndex++] = (size >> 8) & 0xff;
3755
- buffer[startingIndex++] = (size >> 16) & 0xff;
3756
- buffer[startingIndex++] = (size >> 24) & 0xff;
3812
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
3757
3813
  return index;
3758
3814
  }
3759
3815
 
@@ -4083,7 +4139,7 @@ function serialize(object, options = {}) {
4083
4139
  buffer = ByteUtils.allocate(minInternalBufferSize);
4084
4140
  }
4085
4141
  const serializationIndex = serializeInto(buffer, object, checkKeys, 0, 0, serializeFunctions, ignoreUndefined, null);
4086
- const finishedBuffer = ByteUtils.allocate(serializationIndex);
4142
+ const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
4087
4143
  finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
4088
4144
  return finishedBuffer;
4089
4145
  }
@@ -4110,10 +4166,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4110
4166
  const bufferData = ByteUtils.toLocalBufferType(data);
4111
4167
  let index = startIndex;
4112
4168
  for (let i = 0; i < numberOfDocuments; i++) {
4113
- const size = bufferData[index] |
4114
- (bufferData[index + 1] << 8) |
4115
- (bufferData[index + 2] << 16) |
4116
- (bufferData[index + 3] << 24);
4169
+ const size = NumberUtils.getInt32LE(bufferData, index);
4117
4170
  internalOptions.index = index;
4118
4171
  documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
4119
4172
  index = index + size;