bson 6.9.0 → 6.10.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.
- package/bson.d.ts +104 -3
- package/lib/bson.bundle.js +326 -218
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +326 -218
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +326 -218
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.rn.cjs +326 -226
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +1 -2
- package/src/binary.ts +265 -9
- package/src/objectid.ts +18 -11
- package/src/parser/deserializer.ts +17 -45
- package/src/parser/serializer.ts +5 -1
- package/src/parser/utils.ts +30 -51
- package/src/utils/byte_utils.ts +2 -0
- package/src/utils/node_byte_utils.ts +7 -2
- package/src/utils/number_utils.ts +4 -0
- package/src/utils/web_byte_utils.ts +21 -2
package/lib/bson.mjs
CHANGED
|
@@ -1,43 +1,28 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
BigUint64Array: '[object BigUint64Array]',
|
|
8
|
-
RegExp: '[object RegExp]',
|
|
9
|
-
Map: '[object Map]',
|
|
10
|
-
Date: '[object Date]'
|
|
11
|
-
};
|
|
12
|
-
function getPrototypeString(value) {
|
|
13
|
-
let str = map.get(value);
|
|
14
|
-
if (!str) {
|
|
15
|
-
str = Object.prototype.toString.call(value);
|
|
16
|
-
if (value !== null && typeof value === 'object') {
|
|
17
|
-
map.set(value, str);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return str;
|
|
1
|
+
const TypedArrayPrototypeGetSymbolToStringTag = (() => {
|
|
2
|
+
const g = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), Symbol.toStringTag).get;
|
|
3
|
+
return (value) => g.call(value);
|
|
4
|
+
})();
|
|
5
|
+
function isUint8Array(value) {
|
|
6
|
+
return TypedArrayPrototypeGetSymbolToStringTag(value) === 'Uint8Array';
|
|
21
7
|
}
|
|
22
8
|
function isAnyArrayBuffer(value) {
|
|
23
|
-
|
|
24
|
-
|
|
9
|
+
return (typeof value === 'object' &&
|
|
10
|
+
value != null &&
|
|
11
|
+
Symbol.toStringTag in value &&
|
|
12
|
+
(value[Symbol.toStringTag] === 'ArrayBuffer' ||
|
|
13
|
+
value[Symbol.toStringTag] === 'SharedArrayBuffer'));
|
|
25
14
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
return type === TYPES.Uint8Array;
|
|
29
|
-
}
|
|
30
|
-
function isRegExp(d) {
|
|
31
|
-
const type = getPrototypeString(d);
|
|
32
|
-
return type === TYPES.RegExp;
|
|
15
|
+
function isRegExp(regexp) {
|
|
16
|
+
return regexp instanceof RegExp || Object.prototype.toString.call(regexp) === '[object RegExp]';
|
|
33
17
|
}
|
|
34
|
-
function isMap(
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
function isMap(value) {
|
|
19
|
+
return (typeof value === 'object' &&
|
|
20
|
+
value != null &&
|
|
21
|
+
Symbol.toStringTag in value &&
|
|
22
|
+
value[Symbol.toStringTag] === 'Map');
|
|
37
23
|
}
|
|
38
|
-
function isDate(
|
|
39
|
-
|
|
40
|
-
return type === TYPES.Date;
|
|
24
|
+
function isDate(date) {
|
|
25
|
+
return date instanceof Date || Object.prototype.toString.call(date) === '[object Date]';
|
|
41
26
|
}
|
|
42
27
|
function defaultInspect(x, _options) {
|
|
43
28
|
return JSON.stringify(x, (k, v) => {
|
|
@@ -254,7 +239,7 @@ const nodeJsByteUtils = {
|
|
|
254
239
|
stringTag === '[object SharedArrayBuffer]') {
|
|
255
240
|
return Buffer.from(potentialBuffer);
|
|
256
241
|
}
|
|
257
|
-
throw new BSONError(`Cannot create Buffer from
|
|
242
|
+
throw new BSONError(`Cannot create Buffer from the passed potentialBuffer.`);
|
|
258
243
|
},
|
|
259
244
|
allocate(size) {
|
|
260
245
|
return Buffer.alloc(size);
|
|
@@ -312,7 +297,10 @@ const nodeJsByteUtils = {
|
|
|
312
297
|
}
|
|
313
298
|
return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
|
|
314
299
|
},
|
|
315
|
-
randomBytes: nodejsRandomBytes
|
|
300
|
+
randomBytes: nodejsRandomBytes,
|
|
301
|
+
swap32(buffer) {
|
|
302
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).swap32();
|
|
303
|
+
}
|
|
316
304
|
};
|
|
317
305
|
|
|
318
306
|
function isReactNative() {
|
|
@@ -357,7 +345,7 @@ const webByteUtils = {
|
|
|
357
345
|
stringTag === '[object SharedArrayBuffer]') {
|
|
358
346
|
return new Uint8Array(potentialUint8array);
|
|
359
347
|
}
|
|
360
|
-
throw new BSONError(`Cannot make a Uint8Array from
|
|
348
|
+
throw new BSONError(`Cannot make a Uint8Array from passed potentialBuffer.`);
|
|
361
349
|
},
|
|
362
350
|
allocate(size) {
|
|
363
351
|
if (typeof size !== 'number') {
|
|
@@ -429,7 +417,23 @@ const webByteUtils = {
|
|
|
429
417
|
uint8array.set(bytes, byteOffset);
|
|
430
418
|
return bytes.byteLength;
|
|
431
419
|
},
|
|
432
|
-
randomBytes: webRandomBytes
|
|
420
|
+
randomBytes: webRandomBytes,
|
|
421
|
+
swap32(buffer) {
|
|
422
|
+
if (buffer.length % 4 !== 0) {
|
|
423
|
+
throw new RangeError('Buffer size must be a multiple of 32-bits');
|
|
424
|
+
}
|
|
425
|
+
for (let i = 0; i < buffer.length; i += 4) {
|
|
426
|
+
const byte0 = buffer[i];
|
|
427
|
+
const byte1 = buffer[i + 1];
|
|
428
|
+
const byte2 = buffer[i + 2];
|
|
429
|
+
const byte3 = buffer[i + 3];
|
|
430
|
+
buffer[i] = byte3;
|
|
431
|
+
buffer[i + 1] = byte2;
|
|
432
|
+
buffer[i + 2] = byte1;
|
|
433
|
+
buffer[i + 3] = byte0;
|
|
434
|
+
}
|
|
435
|
+
return buffer;
|
|
436
|
+
}
|
|
433
437
|
};
|
|
434
438
|
|
|
435
439
|
const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
|
|
@@ -444,6 +448,134 @@ class BSONValue {
|
|
|
444
448
|
}
|
|
445
449
|
}
|
|
446
450
|
|
|
451
|
+
const FLOAT = new Float64Array(1);
|
|
452
|
+
const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
|
|
453
|
+
FLOAT[0] = -1;
|
|
454
|
+
const isBigEndian = FLOAT_BYTES[7] === 0;
|
|
455
|
+
const NumberUtils = {
|
|
456
|
+
isBigEndian,
|
|
457
|
+
getNonnegativeInt32LE(source, offset) {
|
|
458
|
+
if (source[offset + 3] > 127) {
|
|
459
|
+
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
|
460
|
+
}
|
|
461
|
+
return (source[offset] |
|
|
462
|
+
(source[offset + 1] << 8) |
|
|
463
|
+
(source[offset + 2] << 16) |
|
|
464
|
+
(source[offset + 3] << 24));
|
|
465
|
+
},
|
|
466
|
+
getInt32LE(source, offset) {
|
|
467
|
+
return (source[offset] |
|
|
468
|
+
(source[offset + 1] << 8) |
|
|
469
|
+
(source[offset + 2] << 16) |
|
|
470
|
+
(source[offset + 3] << 24));
|
|
471
|
+
},
|
|
472
|
+
getUint32LE(source, offset) {
|
|
473
|
+
return (source[offset] +
|
|
474
|
+
source[offset + 1] * 256 +
|
|
475
|
+
source[offset + 2] * 65536 +
|
|
476
|
+
source[offset + 3] * 16777216);
|
|
477
|
+
},
|
|
478
|
+
getUint32BE(source, offset) {
|
|
479
|
+
return (source[offset + 3] +
|
|
480
|
+
source[offset + 2] * 256 +
|
|
481
|
+
source[offset + 1] * 65536 +
|
|
482
|
+
source[offset] * 16777216);
|
|
483
|
+
},
|
|
484
|
+
getBigInt64LE(source, offset) {
|
|
485
|
+
const lo = NumberUtils.getUint32LE(source, offset);
|
|
486
|
+
const hi = NumberUtils.getUint32LE(source, offset + 4);
|
|
487
|
+
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
|
|
488
|
+
},
|
|
489
|
+
getFloat64LE: isBigEndian
|
|
490
|
+
? (source, offset) => {
|
|
491
|
+
FLOAT_BYTES[7] = source[offset];
|
|
492
|
+
FLOAT_BYTES[6] = source[offset + 1];
|
|
493
|
+
FLOAT_BYTES[5] = source[offset + 2];
|
|
494
|
+
FLOAT_BYTES[4] = source[offset + 3];
|
|
495
|
+
FLOAT_BYTES[3] = source[offset + 4];
|
|
496
|
+
FLOAT_BYTES[2] = source[offset + 5];
|
|
497
|
+
FLOAT_BYTES[1] = source[offset + 6];
|
|
498
|
+
FLOAT_BYTES[0] = source[offset + 7];
|
|
499
|
+
return FLOAT[0];
|
|
500
|
+
}
|
|
501
|
+
: (source, offset) => {
|
|
502
|
+
FLOAT_BYTES[0] = source[offset];
|
|
503
|
+
FLOAT_BYTES[1] = source[offset + 1];
|
|
504
|
+
FLOAT_BYTES[2] = source[offset + 2];
|
|
505
|
+
FLOAT_BYTES[3] = source[offset + 3];
|
|
506
|
+
FLOAT_BYTES[4] = source[offset + 4];
|
|
507
|
+
FLOAT_BYTES[5] = source[offset + 5];
|
|
508
|
+
FLOAT_BYTES[6] = source[offset + 6];
|
|
509
|
+
FLOAT_BYTES[7] = source[offset + 7];
|
|
510
|
+
return FLOAT[0];
|
|
511
|
+
},
|
|
512
|
+
setInt32BE(destination, offset, value) {
|
|
513
|
+
destination[offset + 3] = value;
|
|
514
|
+
value >>>= 8;
|
|
515
|
+
destination[offset + 2] = value;
|
|
516
|
+
value >>>= 8;
|
|
517
|
+
destination[offset + 1] = value;
|
|
518
|
+
value >>>= 8;
|
|
519
|
+
destination[offset] = value;
|
|
520
|
+
return 4;
|
|
521
|
+
},
|
|
522
|
+
setInt32LE(destination, offset, value) {
|
|
523
|
+
destination[offset] = value;
|
|
524
|
+
value >>>= 8;
|
|
525
|
+
destination[offset + 1] = value;
|
|
526
|
+
value >>>= 8;
|
|
527
|
+
destination[offset + 2] = value;
|
|
528
|
+
value >>>= 8;
|
|
529
|
+
destination[offset + 3] = value;
|
|
530
|
+
return 4;
|
|
531
|
+
},
|
|
532
|
+
setBigInt64LE(destination, offset, value) {
|
|
533
|
+
const mask32bits = BigInt(0xffff_ffff);
|
|
534
|
+
let lo = Number(value & mask32bits);
|
|
535
|
+
destination[offset] = lo;
|
|
536
|
+
lo >>= 8;
|
|
537
|
+
destination[offset + 1] = lo;
|
|
538
|
+
lo >>= 8;
|
|
539
|
+
destination[offset + 2] = lo;
|
|
540
|
+
lo >>= 8;
|
|
541
|
+
destination[offset + 3] = lo;
|
|
542
|
+
let hi = Number((value >> BigInt(32)) & mask32bits);
|
|
543
|
+
destination[offset + 4] = hi;
|
|
544
|
+
hi >>= 8;
|
|
545
|
+
destination[offset + 5] = hi;
|
|
546
|
+
hi >>= 8;
|
|
547
|
+
destination[offset + 6] = hi;
|
|
548
|
+
hi >>= 8;
|
|
549
|
+
destination[offset + 7] = hi;
|
|
550
|
+
return 8;
|
|
551
|
+
},
|
|
552
|
+
setFloat64LE: isBigEndian
|
|
553
|
+
? (destination, offset, value) => {
|
|
554
|
+
FLOAT[0] = value;
|
|
555
|
+
destination[offset] = FLOAT_BYTES[7];
|
|
556
|
+
destination[offset + 1] = FLOAT_BYTES[6];
|
|
557
|
+
destination[offset + 2] = FLOAT_BYTES[5];
|
|
558
|
+
destination[offset + 3] = FLOAT_BYTES[4];
|
|
559
|
+
destination[offset + 4] = FLOAT_BYTES[3];
|
|
560
|
+
destination[offset + 5] = FLOAT_BYTES[2];
|
|
561
|
+
destination[offset + 6] = FLOAT_BYTES[1];
|
|
562
|
+
destination[offset + 7] = FLOAT_BYTES[0];
|
|
563
|
+
return 8;
|
|
564
|
+
}
|
|
565
|
+
: (destination, offset, value) => {
|
|
566
|
+
FLOAT[0] = value;
|
|
567
|
+
destination[offset] = FLOAT_BYTES[0];
|
|
568
|
+
destination[offset + 1] = FLOAT_BYTES[1];
|
|
569
|
+
destination[offset + 2] = FLOAT_BYTES[2];
|
|
570
|
+
destination[offset + 3] = FLOAT_BYTES[3];
|
|
571
|
+
destination[offset + 4] = FLOAT_BYTES[4];
|
|
572
|
+
destination[offset + 5] = FLOAT_BYTES[5];
|
|
573
|
+
destination[offset + 6] = FLOAT_BYTES[6];
|
|
574
|
+
destination[offset + 7] = FLOAT_BYTES[7];
|
|
575
|
+
return 8;
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
|
|
447
579
|
class Binary extends BSONValue {
|
|
448
580
|
get _bsontype() {
|
|
449
581
|
return 'Binary';
|
|
@@ -516,7 +648,8 @@ class Binary extends BSONValue {
|
|
|
516
648
|
}
|
|
517
649
|
read(position, length) {
|
|
518
650
|
length = length && length > 0 ? length : this.position;
|
|
519
|
-
|
|
651
|
+
const end = position + length;
|
|
652
|
+
return this.buffer.subarray(position, end > this.position ? this.position : end);
|
|
520
653
|
}
|
|
521
654
|
value() {
|
|
522
655
|
return this.buffer.length === this.position
|
|
@@ -540,6 +673,9 @@ class Binary extends BSONValue {
|
|
|
540
673
|
}
|
|
541
674
|
toExtendedJSON(options) {
|
|
542
675
|
options = options || {};
|
|
676
|
+
if (this.sub_type === Binary.SUBTYPE_VECTOR) {
|
|
677
|
+
validateBinaryVector(this);
|
|
678
|
+
}
|
|
543
679
|
const base64String = ByteUtils.toBase64(this.buffer);
|
|
544
680
|
const subType = Number(this.sub_type).toString(16);
|
|
545
681
|
if (options.legacy) {
|
|
@@ -557,7 +693,7 @@ class Binary extends BSONValue {
|
|
|
557
693
|
}
|
|
558
694
|
toUUID() {
|
|
559
695
|
if (this.sub_type === Binary.SUBTYPE_UUID) {
|
|
560
|
-
return new UUID(this.buffer.
|
|
696
|
+
return new UUID(this.buffer.subarray(0, this.position));
|
|
561
697
|
}
|
|
562
698
|
throw new BSONError(`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only "${Binary.SUBTYPE_UUID}" is currently supported.`);
|
|
563
699
|
}
|
|
@@ -599,6 +735,99 @@ class Binary extends BSONValue {
|
|
|
599
735
|
const subTypeArg = inspect(this.sub_type, options);
|
|
600
736
|
return `Binary.createFromBase64(${base64Arg}, ${subTypeArg})`;
|
|
601
737
|
}
|
|
738
|
+
toInt8Array() {
|
|
739
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
740
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
741
|
+
}
|
|
742
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.Int8) {
|
|
743
|
+
throw new BSONError('Binary datatype field is not Int8');
|
|
744
|
+
}
|
|
745
|
+
return new Int8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
746
|
+
}
|
|
747
|
+
toFloat32Array() {
|
|
748
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
749
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
750
|
+
}
|
|
751
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.Float32) {
|
|
752
|
+
throw new BSONError('Binary datatype field is not Float32');
|
|
753
|
+
}
|
|
754
|
+
const floatBytes = new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
755
|
+
if (NumberUtils.isBigEndian)
|
|
756
|
+
ByteUtils.swap32(floatBytes);
|
|
757
|
+
return new Float32Array(floatBytes.buffer);
|
|
758
|
+
}
|
|
759
|
+
toPackedBits() {
|
|
760
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
761
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
762
|
+
}
|
|
763
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
|
|
764
|
+
throw new BSONError('Binary datatype field is not packed bit');
|
|
765
|
+
}
|
|
766
|
+
return new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
767
|
+
}
|
|
768
|
+
toBits() {
|
|
769
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
770
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
771
|
+
}
|
|
772
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
|
|
773
|
+
throw new BSONError('Binary datatype field is not packed bit');
|
|
774
|
+
}
|
|
775
|
+
const byteCount = this.length() - 2;
|
|
776
|
+
const bitCount = byteCount * 8 - this.buffer[1];
|
|
777
|
+
const bits = new Int8Array(bitCount);
|
|
778
|
+
for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
|
|
779
|
+
const byteOffset = (bitOffset / 8) | 0;
|
|
780
|
+
const byte = this.buffer[byteOffset + 2];
|
|
781
|
+
const shift = 7 - (bitOffset % 8);
|
|
782
|
+
const bit = (byte >> shift) & 1;
|
|
783
|
+
bits[bitOffset] = bit;
|
|
784
|
+
}
|
|
785
|
+
return bits;
|
|
786
|
+
}
|
|
787
|
+
static fromInt8Array(array) {
|
|
788
|
+
const buffer = ByteUtils.allocate(array.byteLength + 2);
|
|
789
|
+
buffer[0] = Binary.VECTOR_TYPE.Int8;
|
|
790
|
+
buffer[1] = 0;
|
|
791
|
+
const intBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
792
|
+
buffer.set(intBytes, 2);
|
|
793
|
+
return new this(buffer, this.SUBTYPE_VECTOR);
|
|
794
|
+
}
|
|
795
|
+
static fromFloat32Array(array) {
|
|
796
|
+
const binaryBytes = ByteUtils.allocate(array.byteLength + 2);
|
|
797
|
+
binaryBytes[0] = Binary.VECTOR_TYPE.Float32;
|
|
798
|
+
binaryBytes[1] = 0;
|
|
799
|
+
const floatBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
800
|
+
binaryBytes.set(floatBytes, 2);
|
|
801
|
+
if (NumberUtils.isBigEndian)
|
|
802
|
+
ByteUtils.swap32(new Uint8Array(binaryBytes.buffer, 2));
|
|
803
|
+
return new this(binaryBytes, this.SUBTYPE_VECTOR);
|
|
804
|
+
}
|
|
805
|
+
static fromPackedBits(array, padding = 0) {
|
|
806
|
+
const buffer = ByteUtils.allocate(array.byteLength + 2);
|
|
807
|
+
buffer[0] = Binary.VECTOR_TYPE.PackedBit;
|
|
808
|
+
buffer[1] = padding;
|
|
809
|
+
buffer.set(array, 2);
|
|
810
|
+
return new this(buffer, this.SUBTYPE_VECTOR);
|
|
811
|
+
}
|
|
812
|
+
static fromBits(bits) {
|
|
813
|
+
const byteLength = (bits.length + 7) >>> 3;
|
|
814
|
+
const bytes = new Uint8Array(byteLength + 2);
|
|
815
|
+
bytes[0] = Binary.VECTOR_TYPE.PackedBit;
|
|
816
|
+
const remainder = bits.length % 8;
|
|
817
|
+
bytes[1] = remainder === 0 ? 0 : 8 - remainder;
|
|
818
|
+
for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
|
|
819
|
+
const byteOffset = bitOffset >>> 3;
|
|
820
|
+
const bit = bits[bitOffset];
|
|
821
|
+
if (bit !== 0 && bit !== 1) {
|
|
822
|
+
throw new BSONError(`Invalid bit value at ${bitOffset}: must be 0 or 1, found ${bits[bitOffset]}`);
|
|
823
|
+
}
|
|
824
|
+
if (bit === 0)
|
|
825
|
+
continue;
|
|
826
|
+
const shift = 7 - (bitOffset % 8);
|
|
827
|
+
bytes[byteOffset + 2] |= bit << shift;
|
|
828
|
+
}
|
|
829
|
+
return new this(bytes, Binary.SUBTYPE_VECTOR);
|
|
830
|
+
}
|
|
602
831
|
}
|
|
603
832
|
Binary.BSON_BINARY_SUBTYPE_DEFAULT = 0;
|
|
604
833
|
Binary.BUFFER_SIZE = 256;
|
|
@@ -611,7 +840,30 @@ Binary.SUBTYPE_MD5 = 5;
|
|
|
611
840
|
Binary.SUBTYPE_ENCRYPTED = 6;
|
|
612
841
|
Binary.SUBTYPE_COLUMN = 7;
|
|
613
842
|
Binary.SUBTYPE_SENSITIVE = 8;
|
|
843
|
+
Binary.SUBTYPE_VECTOR = 9;
|
|
614
844
|
Binary.SUBTYPE_USER_DEFINED = 128;
|
|
845
|
+
Binary.VECTOR_TYPE = Object.freeze({
|
|
846
|
+
Int8: 0x03,
|
|
847
|
+
Float32: 0x27,
|
|
848
|
+
PackedBit: 0x10
|
|
849
|
+
});
|
|
850
|
+
function validateBinaryVector(vector) {
|
|
851
|
+
if (vector.sub_type !== Binary.SUBTYPE_VECTOR)
|
|
852
|
+
return;
|
|
853
|
+
const size = vector.position;
|
|
854
|
+
const datatype = vector.buffer[0];
|
|
855
|
+
const padding = vector.buffer[1];
|
|
856
|
+
if ((datatype === Binary.VECTOR_TYPE.Float32 || datatype === Binary.VECTOR_TYPE.Int8) &&
|
|
857
|
+
padding !== 0) {
|
|
858
|
+
throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');
|
|
859
|
+
}
|
|
860
|
+
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {
|
|
861
|
+
throw new BSONError('Invalid Vector: padding must be zero for packed bit vectors that are empty');
|
|
862
|
+
}
|
|
863
|
+
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding > 7) {
|
|
864
|
+
throw new BSONError(`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
615
867
|
const UUID_BYTE_LENGTH = 16;
|
|
616
868
|
const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
|
|
617
869
|
const UUID_WITH_DASHES = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;
|
|
@@ -2223,134 +2475,8 @@ class MinKey extends BSONValue {
|
|
|
2223
2475
|
}
|
|
2224
2476
|
}
|
|
2225
2477
|
|
|
2226
|
-
const FLOAT = new Float64Array(1);
|
|
2227
|
-
const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
|
|
2228
|
-
FLOAT[0] = -1;
|
|
2229
|
-
const isBigEndian = FLOAT_BYTES[7] === 0;
|
|
2230
|
-
const NumberUtils = {
|
|
2231
|
-
getNonnegativeInt32LE(source, offset) {
|
|
2232
|
-
if (source[offset + 3] > 127) {
|
|
2233
|
-
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
|
2234
|
-
}
|
|
2235
|
-
return (source[offset] |
|
|
2236
|
-
(source[offset + 1] << 8) |
|
|
2237
|
-
(source[offset + 2] << 16) |
|
|
2238
|
-
(source[offset + 3] << 24));
|
|
2239
|
-
},
|
|
2240
|
-
getInt32LE(source, offset) {
|
|
2241
|
-
return (source[offset] |
|
|
2242
|
-
(source[offset + 1] << 8) |
|
|
2243
|
-
(source[offset + 2] << 16) |
|
|
2244
|
-
(source[offset + 3] << 24));
|
|
2245
|
-
},
|
|
2246
|
-
getUint32LE(source, offset) {
|
|
2247
|
-
return (source[offset] +
|
|
2248
|
-
source[offset + 1] * 256 +
|
|
2249
|
-
source[offset + 2] * 65536 +
|
|
2250
|
-
source[offset + 3] * 16777216);
|
|
2251
|
-
},
|
|
2252
|
-
getUint32BE(source, offset) {
|
|
2253
|
-
return (source[offset + 3] +
|
|
2254
|
-
source[offset + 2] * 256 +
|
|
2255
|
-
source[offset + 1] * 65536 +
|
|
2256
|
-
source[offset] * 16777216);
|
|
2257
|
-
},
|
|
2258
|
-
getBigInt64LE(source, offset) {
|
|
2259
|
-
const lo = NumberUtils.getUint32LE(source, offset);
|
|
2260
|
-
const hi = NumberUtils.getUint32LE(source, offset + 4);
|
|
2261
|
-
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
|
|
2262
|
-
},
|
|
2263
|
-
getFloat64LE: isBigEndian
|
|
2264
|
-
? (source, offset) => {
|
|
2265
|
-
FLOAT_BYTES[7] = source[offset];
|
|
2266
|
-
FLOAT_BYTES[6] = source[offset + 1];
|
|
2267
|
-
FLOAT_BYTES[5] = source[offset + 2];
|
|
2268
|
-
FLOAT_BYTES[4] = source[offset + 3];
|
|
2269
|
-
FLOAT_BYTES[3] = source[offset + 4];
|
|
2270
|
-
FLOAT_BYTES[2] = source[offset + 5];
|
|
2271
|
-
FLOAT_BYTES[1] = source[offset + 6];
|
|
2272
|
-
FLOAT_BYTES[0] = source[offset + 7];
|
|
2273
|
-
return FLOAT[0];
|
|
2274
|
-
}
|
|
2275
|
-
: (source, offset) => {
|
|
2276
|
-
FLOAT_BYTES[0] = source[offset];
|
|
2277
|
-
FLOAT_BYTES[1] = source[offset + 1];
|
|
2278
|
-
FLOAT_BYTES[2] = source[offset + 2];
|
|
2279
|
-
FLOAT_BYTES[3] = source[offset + 3];
|
|
2280
|
-
FLOAT_BYTES[4] = source[offset + 4];
|
|
2281
|
-
FLOAT_BYTES[5] = source[offset + 5];
|
|
2282
|
-
FLOAT_BYTES[6] = source[offset + 6];
|
|
2283
|
-
FLOAT_BYTES[7] = source[offset + 7];
|
|
2284
|
-
return FLOAT[0];
|
|
2285
|
-
},
|
|
2286
|
-
setInt32BE(destination, offset, value) {
|
|
2287
|
-
destination[offset + 3] = value;
|
|
2288
|
-
value >>>= 8;
|
|
2289
|
-
destination[offset + 2] = value;
|
|
2290
|
-
value >>>= 8;
|
|
2291
|
-
destination[offset + 1] = value;
|
|
2292
|
-
value >>>= 8;
|
|
2293
|
-
destination[offset] = value;
|
|
2294
|
-
return 4;
|
|
2295
|
-
},
|
|
2296
|
-
setInt32LE(destination, offset, value) {
|
|
2297
|
-
destination[offset] = value;
|
|
2298
|
-
value >>>= 8;
|
|
2299
|
-
destination[offset + 1] = value;
|
|
2300
|
-
value >>>= 8;
|
|
2301
|
-
destination[offset + 2] = value;
|
|
2302
|
-
value >>>= 8;
|
|
2303
|
-
destination[offset + 3] = value;
|
|
2304
|
-
return 4;
|
|
2305
|
-
},
|
|
2306
|
-
setBigInt64LE(destination, offset, value) {
|
|
2307
|
-
const mask32bits = BigInt(0xffff_ffff);
|
|
2308
|
-
let lo = Number(value & mask32bits);
|
|
2309
|
-
destination[offset] = lo;
|
|
2310
|
-
lo >>= 8;
|
|
2311
|
-
destination[offset + 1] = lo;
|
|
2312
|
-
lo >>= 8;
|
|
2313
|
-
destination[offset + 2] = lo;
|
|
2314
|
-
lo >>= 8;
|
|
2315
|
-
destination[offset + 3] = lo;
|
|
2316
|
-
let hi = Number((value >> BigInt(32)) & mask32bits);
|
|
2317
|
-
destination[offset + 4] = hi;
|
|
2318
|
-
hi >>= 8;
|
|
2319
|
-
destination[offset + 5] = hi;
|
|
2320
|
-
hi >>= 8;
|
|
2321
|
-
destination[offset + 6] = hi;
|
|
2322
|
-
hi >>= 8;
|
|
2323
|
-
destination[offset + 7] = hi;
|
|
2324
|
-
return 8;
|
|
2325
|
-
},
|
|
2326
|
-
setFloat64LE: isBigEndian
|
|
2327
|
-
? (destination, offset, value) => {
|
|
2328
|
-
FLOAT[0] = value;
|
|
2329
|
-
destination[offset] = FLOAT_BYTES[7];
|
|
2330
|
-
destination[offset + 1] = FLOAT_BYTES[6];
|
|
2331
|
-
destination[offset + 2] = FLOAT_BYTES[5];
|
|
2332
|
-
destination[offset + 3] = FLOAT_BYTES[4];
|
|
2333
|
-
destination[offset + 4] = FLOAT_BYTES[3];
|
|
2334
|
-
destination[offset + 5] = FLOAT_BYTES[2];
|
|
2335
|
-
destination[offset + 6] = FLOAT_BYTES[1];
|
|
2336
|
-
destination[offset + 7] = FLOAT_BYTES[0];
|
|
2337
|
-
return 8;
|
|
2338
|
-
}
|
|
2339
|
-
: (destination, offset, value) => {
|
|
2340
|
-
FLOAT[0] = value;
|
|
2341
|
-
destination[offset] = FLOAT_BYTES[0];
|
|
2342
|
-
destination[offset + 1] = FLOAT_BYTES[1];
|
|
2343
|
-
destination[offset + 2] = FLOAT_BYTES[2];
|
|
2344
|
-
destination[offset + 3] = FLOAT_BYTES[3];
|
|
2345
|
-
destination[offset + 4] = FLOAT_BYTES[4];
|
|
2346
|
-
destination[offset + 5] = FLOAT_BYTES[5];
|
|
2347
|
-
destination[offset + 6] = FLOAT_BYTES[6];
|
|
2348
|
-
destination[offset + 7] = FLOAT_BYTES[7];
|
|
2349
|
-
return 8;
|
|
2350
|
-
}
|
|
2351
|
-
};
|
|
2352
|
-
|
|
2353
2478
|
let PROCESS_UNIQUE = null;
|
|
2479
|
+
const __idCache = new WeakMap();
|
|
2354
2480
|
class ObjectId extends BSONValue {
|
|
2355
2481
|
get _bsontype() {
|
|
2356
2482
|
return 'ObjectId';
|
|
@@ -2381,6 +2507,9 @@ class ObjectId extends BSONValue {
|
|
|
2381
2507
|
else if (typeof workingId === 'string') {
|
|
2382
2508
|
if (ObjectId.validateHexString(workingId)) {
|
|
2383
2509
|
this.buffer = ByteUtils.fromHex(workingId);
|
|
2510
|
+
if (ObjectId.cacheHexString) {
|
|
2511
|
+
__idCache.set(this, workingId);
|
|
2512
|
+
}
|
|
2384
2513
|
}
|
|
2385
2514
|
else {
|
|
2386
2515
|
throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
|
|
@@ -2389,9 +2518,6 @@ class ObjectId extends BSONValue {
|
|
|
2389
2518
|
else {
|
|
2390
2519
|
throw new BSONError('Argument passed in does not match the accepted types');
|
|
2391
2520
|
}
|
|
2392
|
-
if (ObjectId.cacheHexString) {
|
|
2393
|
-
this.__id = ByteUtils.toHex(this.id);
|
|
2394
|
-
}
|
|
2395
2521
|
}
|
|
2396
2522
|
get id() {
|
|
2397
2523
|
return this.buffer;
|
|
@@ -2399,7 +2525,7 @@ class ObjectId extends BSONValue {
|
|
|
2399
2525
|
set id(value) {
|
|
2400
2526
|
this.buffer = value;
|
|
2401
2527
|
if (ObjectId.cacheHexString) {
|
|
2402
|
-
this
|
|
2528
|
+
__idCache.set(this, ByteUtils.toHex(value));
|
|
2403
2529
|
}
|
|
2404
2530
|
}
|
|
2405
2531
|
static validateHexString(string) {
|
|
@@ -2417,12 +2543,14 @@ class ObjectId extends BSONValue {
|
|
|
2417
2543
|
return true;
|
|
2418
2544
|
}
|
|
2419
2545
|
toHexString() {
|
|
2420
|
-
if (ObjectId.cacheHexString
|
|
2421
|
-
|
|
2546
|
+
if (ObjectId.cacheHexString) {
|
|
2547
|
+
const __id = __idCache.get(this);
|
|
2548
|
+
if (__id)
|
|
2549
|
+
return __id;
|
|
2422
2550
|
}
|
|
2423
2551
|
const hexString = ByteUtils.toHex(this.id);
|
|
2424
|
-
if (ObjectId.cacheHexString
|
|
2425
|
-
this
|
|
2552
|
+
if (ObjectId.cacheHexString) {
|
|
2553
|
+
__idCache.set(this, hexString);
|
|
2426
2554
|
}
|
|
2427
2555
|
return hexString;
|
|
2428
2556
|
}
|
|
@@ -2546,6 +2674,9 @@ class ObjectId extends BSONValue {
|
|
|
2546
2674
|
static fromExtendedJSON(doc) {
|
|
2547
2675
|
return new ObjectId(doc.$oid);
|
|
2548
2676
|
}
|
|
2677
|
+
isCached() {
|
|
2678
|
+
return ObjectId.cacheHexString && __idCache.has(this);
|
|
2679
|
+
}
|
|
2549
2680
|
inspect(depth, options, inspect) {
|
|
2550
2681
|
inspect ??= defaultInspect;
|
|
2551
2682
|
return `new ObjectId(${inspect(this.toHexString(), options)})`;
|
|
@@ -3036,7 +3167,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3036
3167
|
if (objectSize <= 0 || objectSize > buffer.length - index)
|
|
3037
3168
|
throw new BSONError('bad embedded document length in bson');
|
|
3038
3169
|
if (raw) {
|
|
3039
|
-
value = buffer.
|
|
3170
|
+
value = buffer.subarray(index, index + objectSize);
|
|
3040
3171
|
}
|
|
3041
3172
|
else {
|
|
3042
3173
|
let objectOptions = options;
|
|
@@ -3108,49 +3239,23 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3108
3239
|
throw new BSONError('Negative binary type element size found');
|
|
3109
3240
|
if (binarySize > buffer.byteLength)
|
|
3110
3241
|
throw new BSONError('Binary type size larger than document size');
|
|
3111
|
-
if (
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
|
|
3124
|
-
}
|
|
3125
|
-
else {
|
|
3126
|
-
value = new Binary(buffer.slice(index, index + binarySize), subType);
|
|
3127
|
-
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3128
|
-
value = value.toUUID();
|
|
3129
|
-
}
|
|
3130
|
-
}
|
|
3242
|
+
if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
|
|
3243
|
+
binarySize = NumberUtils.getInt32LE(buffer, index);
|
|
3244
|
+
index += 4;
|
|
3245
|
+
if (binarySize < 0)
|
|
3246
|
+
throw new BSONError('Negative binary type element size found for subtype 0x02');
|
|
3247
|
+
if (binarySize > totalBinarySize - 4)
|
|
3248
|
+
throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
|
|
3249
|
+
if (binarySize < totalBinarySize - 4)
|
|
3250
|
+
throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
|
|
3251
|
+
}
|
|
3252
|
+
if (promoteBuffers && promoteValues) {
|
|
3253
|
+
value = ByteUtils.toLocalBufferType(buffer.subarray(index, index + binarySize));
|
|
3131
3254
|
}
|
|
3132
3255
|
else {
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
if (binarySize < 0)
|
|
3137
|
-
throw new BSONError('Negative binary type element size found for subtype 0x02');
|
|
3138
|
-
if (binarySize > totalBinarySize - 4)
|
|
3139
|
-
throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
|
|
3140
|
-
if (binarySize < totalBinarySize - 4)
|
|
3141
|
-
throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
|
|
3142
|
-
}
|
|
3143
|
-
if (promoteBuffers && promoteValues) {
|
|
3144
|
-
value = ByteUtils.allocateUnsafe(binarySize);
|
|
3145
|
-
for (i = 0; i < binarySize; i++) {
|
|
3146
|
-
value[i] = buffer[index + i];
|
|
3147
|
-
}
|
|
3148
|
-
}
|
|
3149
|
-
else {
|
|
3150
|
-
value = new Binary(buffer.slice(index, index + binarySize), subType);
|
|
3151
|
-
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3152
|
-
value = value.toUUID();
|
|
3153
|
-
}
|
|
3256
|
+
value = new Binary(buffer.subarray(index, index + binarySize), subType);
|
|
3257
|
+
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3258
|
+
value = value.toUUID();
|
|
3154
3259
|
}
|
|
3155
3260
|
}
|
|
3156
3261
|
index = index + binarySize;
|
|
@@ -3572,6 +3677,9 @@ function serializeBinary(buffer, key, value, index) {
|
|
|
3572
3677
|
size = size - 4;
|
|
3573
3678
|
index += NumberUtils.setInt32LE(buffer, index, size);
|
|
3574
3679
|
}
|
|
3680
|
+
if (value.sub_type === Binary.SUBTYPE_VECTOR) {
|
|
3681
|
+
validateBinaryVector(value);
|
|
3682
|
+
}
|
|
3575
3683
|
if (size <= 16) {
|
|
3576
3684
|
for (let i = 0; i < size; i++)
|
|
3577
3685
|
buffer[index + i] = data[i];
|