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