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.rn.cjs
CHANGED
|
@@ -1,53 +1,30 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Uint8Array: '[object Uint8Array]',
|
|
8
|
-
BigInt64Array: '[object BigInt64Array]',
|
|
9
|
-
BigUint64Array: '[object BigUint64Array]',
|
|
10
|
-
RegExp: '[object RegExp]',
|
|
11
|
-
Map: '[object Map]',
|
|
12
|
-
Date: '[object Date]'
|
|
13
|
-
};
|
|
14
|
-
function getPrototypeString(value) {
|
|
15
|
-
let str = map.get(value);
|
|
16
|
-
if (!str) {
|
|
17
|
-
str = Object.prototype.toString.call(value);
|
|
18
|
-
if (value !== null && typeof value === 'object') {
|
|
19
|
-
map.set(value, str);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return str;
|
|
23
|
-
}
|
|
24
|
-
function isAnyArrayBuffer(value) {
|
|
25
|
-
const type = getPrototypeString(value);
|
|
26
|
-
return type === TYPES.ArrayBuffer || type === TYPES.SharedArrayBuffer;
|
|
27
|
-
}
|
|
3
|
+
const TypedArrayPrototypeGetSymbolToStringTag = (() => {
|
|
4
|
+
const g = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), Symbol.toStringTag).get;
|
|
5
|
+
return (value) => g.call(value);
|
|
6
|
+
})();
|
|
28
7
|
function isUint8Array(value) {
|
|
29
|
-
|
|
30
|
-
return type === TYPES.Uint8Array;
|
|
31
|
-
}
|
|
32
|
-
function isBigInt64Array(value) {
|
|
33
|
-
const type = getPrototypeString(value);
|
|
34
|
-
return type === TYPES.BigInt64Array;
|
|
8
|
+
return TypedArrayPrototypeGetSymbolToStringTag(value) === 'Uint8Array';
|
|
35
9
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
|
|
10
|
+
function isAnyArrayBuffer(value) {
|
|
11
|
+
return (typeof value === 'object' &&
|
|
12
|
+
value != null &&
|
|
13
|
+
Symbol.toStringTag in value &&
|
|
14
|
+
(value[Symbol.toStringTag] === 'ArrayBuffer' ||
|
|
15
|
+
value[Symbol.toStringTag] === 'SharedArrayBuffer'));
|
|
39
16
|
}
|
|
40
|
-
function isRegExp(
|
|
41
|
-
|
|
42
|
-
return type === TYPES.RegExp;
|
|
17
|
+
function isRegExp(regexp) {
|
|
18
|
+
return regexp instanceof RegExp || Object.prototype.toString.call(regexp) === '[object RegExp]';
|
|
43
19
|
}
|
|
44
|
-
function isMap(
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
function isMap(value) {
|
|
21
|
+
return (typeof value === 'object' &&
|
|
22
|
+
value != null &&
|
|
23
|
+
Symbol.toStringTag in value &&
|
|
24
|
+
value[Symbol.toStringTag] === 'Map');
|
|
47
25
|
}
|
|
48
|
-
function isDate(
|
|
49
|
-
|
|
50
|
-
return type === TYPES.Date;
|
|
26
|
+
function isDate(date) {
|
|
27
|
+
return date instanceof Date || Object.prototype.toString.call(date) === '[object Date]';
|
|
51
28
|
}
|
|
52
29
|
function defaultInspect(x, _options) {
|
|
53
30
|
return JSON.stringify(x, (k, v) => {
|
|
@@ -273,7 +250,7 @@ const nodeJsByteUtils = {
|
|
|
273
250
|
stringTag === '[object SharedArrayBuffer]') {
|
|
274
251
|
return Buffer.from(potentialBuffer);
|
|
275
252
|
}
|
|
276
|
-
throw new BSONError(`Cannot create Buffer from
|
|
253
|
+
throw new BSONError(`Cannot create Buffer from the passed potentialBuffer.`);
|
|
277
254
|
},
|
|
278
255
|
allocate(size) {
|
|
279
256
|
return Buffer.alloc(size);
|
|
@@ -331,7 +308,10 @@ const nodeJsByteUtils = {
|
|
|
331
308
|
}
|
|
332
309
|
return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
|
|
333
310
|
},
|
|
334
|
-
randomBytes: nodejsRandomBytes
|
|
311
|
+
randomBytes: nodejsRandomBytes,
|
|
312
|
+
swap32(buffer) {
|
|
313
|
+
return nodeJsByteUtils.toLocalBufferType(buffer).swap32();
|
|
314
|
+
}
|
|
335
315
|
};
|
|
336
316
|
|
|
337
317
|
const { TextEncoder } = require('../vendor/text-encoding');
|
|
@@ -378,7 +358,7 @@ const webByteUtils = {
|
|
|
378
358
|
stringTag === '[object SharedArrayBuffer]') {
|
|
379
359
|
return new Uint8Array(potentialUint8array);
|
|
380
360
|
}
|
|
381
|
-
throw new BSONError(`Cannot make a Uint8Array from
|
|
361
|
+
throw new BSONError(`Cannot make a Uint8Array from passed potentialBuffer.`);
|
|
382
362
|
},
|
|
383
363
|
allocate(size) {
|
|
384
364
|
if (typeof size !== 'number') {
|
|
@@ -450,7 +430,23 @@ const webByteUtils = {
|
|
|
450
430
|
uint8array.set(bytes, byteOffset);
|
|
451
431
|
return bytes.byteLength;
|
|
452
432
|
},
|
|
453
|
-
randomBytes: webRandomBytes
|
|
433
|
+
randomBytes: webRandomBytes,
|
|
434
|
+
swap32(buffer) {
|
|
435
|
+
if (buffer.length % 4 !== 0) {
|
|
436
|
+
throw new RangeError('Buffer size must be a multiple of 32-bits');
|
|
437
|
+
}
|
|
438
|
+
for (let i = 0; i < buffer.length; i += 4) {
|
|
439
|
+
const byte0 = buffer[i];
|
|
440
|
+
const byte1 = buffer[i + 1];
|
|
441
|
+
const byte2 = buffer[i + 2];
|
|
442
|
+
const byte3 = buffer[i + 3];
|
|
443
|
+
buffer[i] = byte3;
|
|
444
|
+
buffer[i + 1] = byte2;
|
|
445
|
+
buffer[i + 2] = byte1;
|
|
446
|
+
buffer[i + 3] = byte0;
|
|
447
|
+
}
|
|
448
|
+
return buffer;
|
|
449
|
+
}
|
|
454
450
|
};
|
|
455
451
|
|
|
456
452
|
const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
|
|
@@ -465,6 +461,134 @@ class BSONValue {
|
|
|
465
461
|
}
|
|
466
462
|
}
|
|
467
463
|
|
|
464
|
+
const FLOAT = new Float64Array(1);
|
|
465
|
+
const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
|
|
466
|
+
FLOAT[0] = -1;
|
|
467
|
+
const isBigEndian = FLOAT_BYTES[7] === 0;
|
|
468
|
+
const NumberUtils = {
|
|
469
|
+
isBigEndian,
|
|
470
|
+
getNonnegativeInt32LE(source, offset) {
|
|
471
|
+
if (source[offset + 3] > 127) {
|
|
472
|
+
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
|
473
|
+
}
|
|
474
|
+
return (source[offset] |
|
|
475
|
+
(source[offset + 1] << 8) |
|
|
476
|
+
(source[offset + 2] << 16) |
|
|
477
|
+
(source[offset + 3] << 24));
|
|
478
|
+
},
|
|
479
|
+
getInt32LE(source, offset) {
|
|
480
|
+
return (source[offset] |
|
|
481
|
+
(source[offset + 1] << 8) |
|
|
482
|
+
(source[offset + 2] << 16) |
|
|
483
|
+
(source[offset + 3] << 24));
|
|
484
|
+
},
|
|
485
|
+
getUint32LE(source, offset) {
|
|
486
|
+
return (source[offset] +
|
|
487
|
+
source[offset + 1] * 256 +
|
|
488
|
+
source[offset + 2] * 65536 +
|
|
489
|
+
source[offset + 3] * 16777216);
|
|
490
|
+
},
|
|
491
|
+
getUint32BE(source, offset) {
|
|
492
|
+
return (source[offset + 3] +
|
|
493
|
+
source[offset + 2] * 256 +
|
|
494
|
+
source[offset + 1] * 65536 +
|
|
495
|
+
source[offset] * 16777216);
|
|
496
|
+
},
|
|
497
|
+
getBigInt64LE(source, offset) {
|
|
498
|
+
const lo = NumberUtils.getUint32LE(source, offset);
|
|
499
|
+
const hi = NumberUtils.getUint32LE(source, offset + 4);
|
|
500
|
+
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
|
|
501
|
+
},
|
|
502
|
+
getFloat64LE: isBigEndian
|
|
503
|
+
? (source, offset) => {
|
|
504
|
+
FLOAT_BYTES[7] = source[offset];
|
|
505
|
+
FLOAT_BYTES[6] = source[offset + 1];
|
|
506
|
+
FLOAT_BYTES[5] = source[offset + 2];
|
|
507
|
+
FLOAT_BYTES[4] = source[offset + 3];
|
|
508
|
+
FLOAT_BYTES[3] = source[offset + 4];
|
|
509
|
+
FLOAT_BYTES[2] = source[offset + 5];
|
|
510
|
+
FLOAT_BYTES[1] = source[offset + 6];
|
|
511
|
+
FLOAT_BYTES[0] = source[offset + 7];
|
|
512
|
+
return FLOAT[0];
|
|
513
|
+
}
|
|
514
|
+
: (source, offset) => {
|
|
515
|
+
FLOAT_BYTES[0] = source[offset];
|
|
516
|
+
FLOAT_BYTES[1] = source[offset + 1];
|
|
517
|
+
FLOAT_BYTES[2] = source[offset + 2];
|
|
518
|
+
FLOAT_BYTES[3] = source[offset + 3];
|
|
519
|
+
FLOAT_BYTES[4] = source[offset + 4];
|
|
520
|
+
FLOAT_BYTES[5] = source[offset + 5];
|
|
521
|
+
FLOAT_BYTES[6] = source[offset + 6];
|
|
522
|
+
FLOAT_BYTES[7] = source[offset + 7];
|
|
523
|
+
return FLOAT[0];
|
|
524
|
+
},
|
|
525
|
+
setInt32BE(destination, offset, value) {
|
|
526
|
+
destination[offset + 3] = value;
|
|
527
|
+
value >>>= 8;
|
|
528
|
+
destination[offset + 2] = value;
|
|
529
|
+
value >>>= 8;
|
|
530
|
+
destination[offset + 1] = value;
|
|
531
|
+
value >>>= 8;
|
|
532
|
+
destination[offset] = value;
|
|
533
|
+
return 4;
|
|
534
|
+
},
|
|
535
|
+
setInt32LE(destination, offset, value) {
|
|
536
|
+
destination[offset] = value;
|
|
537
|
+
value >>>= 8;
|
|
538
|
+
destination[offset + 1] = value;
|
|
539
|
+
value >>>= 8;
|
|
540
|
+
destination[offset + 2] = value;
|
|
541
|
+
value >>>= 8;
|
|
542
|
+
destination[offset + 3] = value;
|
|
543
|
+
return 4;
|
|
544
|
+
},
|
|
545
|
+
setBigInt64LE(destination, offset, value) {
|
|
546
|
+
const mask32bits = BigInt(0xffff_ffff);
|
|
547
|
+
let lo = Number(value & mask32bits);
|
|
548
|
+
destination[offset] = lo;
|
|
549
|
+
lo >>= 8;
|
|
550
|
+
destination[offset + 1] = lo;
|
|
551
|
+
lo >>= 8;
|
|
552
|
+
destination[offset + 2] = lo;
|
|
553
|
+
lo >>= 8;
|
|
554
|
+
destination[offset + 3] = lo;
|
|
555
|
+
let hi = Number((value >> BigInt(32)) & mask32bits);
|
|
556
|
+
destination[offset + 4] = hi;
|
|
557
|
+
hi >>= 8;
|
|
558
|
+
destination[offset + 5] = hi;
|
|
559
|
+
hi >>= 8;
|
|
560
|
+
destination[offset + 6] = hi;
|
|
561
|
+
hi >>= 8;
|
|
562
|
+
destination[offset + 7] = hi;
|
|
563
|
+
return 8;
|
|
564
|
+
},
|
|
565
|
+
setFloat64LE: isBigEndian
|
|
566
|
+
? (destination, offset, value) => {
|
|
567
|
+
FLOAT[0] = value;
|
|
568
|
+
destination[offset] = FLOAT_BYTES[7];
|
|
569
|
+
destination[offset + 1] = FLOAT_BYTES[6];
|
|
570
|
+
destination[offset + 2] = FLOAT_BYTES[5];
|
|
571
|
+
destination[offset + 3] = FLOAT_BYTES[4];
|
|
572
|
+
destination[offset + 4] = FLOAT_BYTES[3];
|
|
573
|
+
destination[offset + 5] = FLOAT_BYTES[2];
|
|
574
|
+
destination[offset + 6] = FLOAT_BYTES[1];
|
|
575
|
+
destination[offset + 7] = FLOAT_BYTES[0];
|
|
576
|
+
return 8;
|
|
577
|
+
}
|
|
578
|
+
: (destination, offset, value) => {
|
|
579
|
+
FLOAT[0] = value;
|
|
580
|
+
destination[offset] = FLOAT_BYTES[0];
|
|
581
|
+
destination[offset + 1] = FLOAT_BYTES[1];
|
|
582
|
+
destination[offset + 2] = FLOAT_BYTES[2];
|
|
583
|
+
destination[offset + 3] = FLOAT_BYTES[3];
|
|
584
|
+
destination[offset + 4] = FLOAT_BYTES[4];
|
|
585
|
+
destination[offset + 5] = FLOAT_BYTES[5];
|
|
586
|
+
destination[offset + 6] = FLOAT_BYTES[6];
|
|
587
|
+
destination[offset + 7] = FLOAT_BYTES[7];
|
|
588
|
+
return 8;
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
|
|
468
592
|
class Binary extends BSONValue {
|
|
469
593
|
get _bsontype() {
|
|
470
594
|
return 'Binary';
|
|
@@ -537,7 +661,8 @@ class Binary extends BSONValue {
|
|
|
537
661
|
}
|
|
538
662
|
read(position, length) {
|
|
539
663
|
length = length && length > 0 ? length : this.position;
|
|
540
|
-
|
|
664
|
+
const end = position + length;
|
|
665
|
+
return this.buffer.subarray(position, end > this.position ? this.position : end);
|
|
541
666
|
}
|
|
542
667
|
value() {
|
|
543
668
|
return this.buffer.length === this.position
|
|
@@ -561,6 +686,9 @@ class Binary extends BSONValue {
|
|
|
561
686
|
}
|
|
562
687
|
toExtendedJSON(options) {
|
|
563
688
|
options = options || {};
|
|
689
|
+
if (this.sub_type === Binary.SUBTYPE_VECTOR) {
|
|
690
|
+
validateBinaryVector(this);
|
|
691
|
+
}
|
|
564
692
|
const base64String = ByteUtils.toBase64(this.buffer);
|
|
565
693
|
const subType = Number(this.sub_type).toString(16);
|
|
566
694
|
if (options.legacy) {
|
|
@@ -578,7 +706,7 @@ class Binary extends BSONValue {
|
|
|
578
706
|
}
|
|
579
707
|
toUUID() {
|
|
580
708
|
if (this.sub_type === Binary.SUBTYPE_UUID) {
|
|
581
|
-
return new UUID(this.buffer.
|
|
709
|
+
return new UUID(this.buffer.subarray(0, this.position));
|
|
582
710
|
}
|
|
583
711
|
throw new BSONError(`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only "${Binary.SUBTYPE_UUID}" is currently supported.`);
|
|
584
712
|
}
|
|
@@ -620,6 +748,99 @@ class Binary extends BSONValue {
|
|
|
620
748
|
const subTypeArg = inspect(this.sub_type, options);
|
|
621
749
|
return `Binary.createFromBase64(${base64Arg}, ${subTypeArg})`;
|
|
622
750
|
}
|
|
751
|
+
toInt8Array() {
|
|
752
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
753
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
754
|
+
}
|
|
755
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.Int8) {
|
|
756
|
+
throw new BSONError('Binary datatype field is not Int8');
|
|
757
|
+
}
|
|
758
|
+
return new Int8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
759
|
+
}
|
|
760
|
+
toFloat32Array() {
|
|
761
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
762
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
763
|
+
}
|
|
764
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.Float32) {
|
|
765
|
+
throw new BSONError('Binary datatype field is not Float32');
|
|
766
|
+
}
|
|
767
|
+
const floatBytes = new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
768
|
+
if (NumberUtils.isBigEndian)
|
|
769
|
+
ByteUtils.swap32(floatBytes);
|
|
770
|
+
return new Float32Array(floatBytes.buffer);
|
|
771
|
+
}
|
|
772
|
+
toPackedBits() {
|
|
773
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
774
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
775
|
+
}
|
|
776
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
|
|
777
|
+
throw new BSONError('Binary datatype field is not packed bit');
|
|
778
|
+
}
|
|
779
|
+
return new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
|
|
780
|
+
}
|
|
781
|
+
toBits() {
|
|
782
|
+
if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
|
|
783
|
+
throw new BSONError('Binary sub_type is not Vector');
|
|
784
|
+
}
|
|
785
|
+
if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
|
|
786
|
+
throw new BSONError('Binary datatype field is not packed bit');
|
|
787
|
+
}
|
|
788
|
+
const byteCount = this.length() - 2;
|
|
789
|
+
const bitCount = byteCount * 8 - this.buffer[1];
|
|
790
|
+
const bits = new Int8Array(bitCount);
|
|
791
|
+
for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
|
|
792
|
+
const byteOffset = (bitOffset / 8) | 0;
|
|
793
|
+
const byte = this.buffer[byteOffset + 2];
|
|
794
|
+
const shift = 7 - (bitOffset % 8);
|
|
795
|
+
const bit = (byte >> shift) & 1;
|
|
796
|
+
bits[bitOffset] = bit;
|
|
797
|
+
}
|
|
798
|
+
return bits;
|
|
799
|
+
}
|
|
800
|
+
static fromInt8Array(array) {
|
|
801
|
+
const buffer = ByteUtils.allocate(array.byteLength + 2);
|
|
802
|
+
buffer[0] = Binary.VECTOR_TYPE.Int8;
|
|
803
|
+
buffer[1] = 0;
|
|
804
|
+
const intBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
805
|
+
buffer.set(intBytes, 2);
|
|
806
|
+
return new this(buffer, this.SUBTYPE_VECTOR);
|
|
807
|
+
}
|
|
808
|
+
static fromFloat32Array(array) {
|
|
809
|
+
const binaryBytes = ByteUtils.allocate(array.byteLength + 2);
|
|
810
|
+
binaryBytes[0] = Binary.VECTOR_TYPE.Float32;
|
|
811
|
+
binaryBytes[1] = 0;
|
|
812
|
+
const floatBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
|
|
813
|
+
binaryBytes.set(floatBytes, 2);
|
|
814
|
+
if (NumberUtils.isBigEndian)
|
|
815
|
+
ByteUtils.swap32(new Uint8Array(binaryBytes.buffer, 2));
|
|
816
|
+
return new this(binaryBytes, this.SUBTYPE_VECTOR);
|
|
817
|
+
}
|
|
818
|
+
static fromPackedBits(array, padding = 0) {
|
|
819
|
+
const buffer = ByteUtils.allocate(array.byteLength + 2);
|
|
820
|
+
buffer[0] = Binary.VECTOR_TYPE.PackedBit;
|
|
821
|
+
buffer[1] = padding;
|
|
822
|
+
buffer.set(array, 2);
|
|
823
|
+
return new this(buffer, this.SUBTYPE_VECTOR);
|
|
824
|
+
}
|
|
825
|
+
static fromBits(bits) {
|
|
826
|
+
const byteLength = (bits.length + 7) >>> 3;
|
|
827
|
+
const bytes = new Uint8Array(byteLength + 2);
|
|
828
|
+
bytes[0] = Binary.VECTOR_TYPE.PackedBit;
|
|
829
|
+
const remainder = bits.length % 8;
|
|
830
|
+
bytes[1] = remainder === 0 ? 0 : 8 - remainder;
|
|
831
|
+
for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
|
|
832
|
+
const byteOffset = bitOffset >>> 3;
|
|
833
|
+
const bit = bits[bitOffset];
|
|
834
|
+
if (bit !== 0 && bit !== 1) {
|
|
835
|
+
throw new BSONError(`Invalid bit value at ${bitOffset}: must be 0 or 1, found ${bits[bitOffset]}`);
|
|
836
|
+
}
|
|
837
|
+
if (bit === 0)
|
|
838
|
+
continue;
|
|
839
|
+
const shift = 7 - (bitOffset % 8);
|
|
840
|
+
bytes[byteOffset + 2] |= bit << shift;
|
|
841
|
+
}
|
|
842
|
+
return new this(bytes, Binary.SUBTYPE_VECTOR);
|
|
843
|
+
}
|
|
623
844
|
}
|
|
624
845
|
Binary.BSON_BINARY_SUBTYPE_DEFAULT = 0;
|
|
625
846
|
Binary.BUFFER_SIZE = 256;
|
|
@@ -632,7 +853,30 @@ Binary.SUBTYPE_MD5 = 5;
|
|
|
632
853
|
Binary.SUBTYPE_ENCRYPTED = 6;
|
|
633
854
|
Binary.SUBTYPE_COLUMN = 7;
|
|
634
855
|
Binary.SUBTYPE_SENSITIVE = 8;
|
|
856
|
+
Binary.SUBTYPE_VECTOR = 9;
|
|
635
857
|
Binary.SUBTYPE_USER_DEFINED = 128;
|
|
858
|
+
Binary.VECTOR_TYPE = Object.freeze({
|
|
859
|
+
Int8: 0x03,
|
|
860
|
+
Float32: 0x27,
|
|
861
|
+
PackedBit: 0x10
|
|
862
|
+
});
|
|
863
|
+
function validateBinaryVector(vector) {
|
|
864
|
+
if (vector.sub_type !== Binary.SUBTYPE_VECTOR)
|
|
865
|
+
return;
|
|
866
|
+
const size = vector.position;
|
|
867
|
+
const datatype = vector.buffer[0];
|
|
868
|
+
const padding = vector.buffer[1];
|
|
869
|
+
if ((datatype === Binary.VECTOR_TYPE.Float32 || datatype === Binary.VECTOR_TYPE.Int8) &&
|
|
870
|
+
padding !== 0) {
|
|
871
|
+
throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');
|
|
872
|
+
}
|
|
873
|
+
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {
|
|
874
|
+
throw new BSONError('Invalid Vector: padding must be zero for packed bit vectors that are empty');
|
|
875
|
+
}
|
|
876
|
+
if (datatype === Binary.VECTOR_TYPE.PackedBit && padding > 7) {
|
|
877
|
+
throw new BSONError(`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
636
880
|
const UUID_BYTE_LENGTH = 16;
|
|
637
881
|
const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
|
|
638
882
|
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;
|
|
@@ -2244,134 +2488,8 @@ class MinKey extends BSONValue {
|
|
|
2244
2488
|
}
|
|
2245
2489
|
}
|
|
2246
2490
|
|
|
2247
|
-
const FLOAT = new Float64Array(1);
|
|
2248
|
-
const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
|
|
2249
|
-
FLOAT[0] = -1;
|
|
2250
|
-
const isBigEndian = FLOAT_BYTES[7] === 0;
|
|
2251
|
-
const NumberUtils = {
|
|
2252
|
-
getNonnegativeInt32LE(source, offset) {
|
|
2253
|
-
if (source[offset + 3] > 127) {
|
|
2254
|
-
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
|
2255
|
-
}
|
|
2256
|
-
return (source[offset] |
|
|
2257
|
-
(source[offset + 1] << 8) |
|
|
2258
|
-
(source[offset + 2] << 16) |
|
|
2259
|
-
(source[offset + 3] << 24));
|
|
2260
|
-
},
|
|
2261
|
-
getInt32LE(source, offset) {
|
|
2262
|
-
return (source[offset] |
|
|
2263
|
-
(source[offset + 1] << 8) |
|
|
2264
|
-
(source[offset + 2] << 16) |
|
|
2265
|
-
(source[offset + 3] << 24));
|
|
2266
|
-
},
|
|
2267
|
-
getUint32LE(source, offset) {
|
|
2268
|
-
return (source[offset] +
|
|
2269
|
-
source[offset + 1] * 256 +
|
|
2270
|
-
source[offset + 2] * 65536 +
|
|
2271
|
-
source[offset + 3] * 16777216);
|
|
2272
|
-
},
|
|
2273
|
-
getUint32BE(source, offset) {
|
|
2274
|
-
return (source[offset + 3] +
|
|
2275
|
-
source[offset + 2] * 256 +
|
|
2276
|
-
source[offset + 1] * 65536 +
|
|
2277
|
-
source[offset] * 16777216);
|
|
2278
|
-
},
|
|
2279
|
-
getBigInt64LE(source, offset) {
|
|
2280
|
-
const lo = NumberUtils.getUint32LE(source, offset);
|
|
2281
|
-
const hi = NumberUtils.getUint32LE(source, offset + 4);
|
|
2282
|
-
return (BigInt(hi) << BigInt(32)) + BigInt(lo);
|
|
2283
|
-
},
|
|
2284
|
-
getFloat64LE: isBigEndian
|
|
2285
|
-
? (source, offset) => {
|
|
2286
|
-
FLOAT_BYTES[7] = source[offset];
|
|
2287
|
-
FLOAT_BYTES[6] = source[offset + 1];
|
|
2288
|
-
FLOAT_BYTES[5] = source[offset + 2];
|
|
2289
|
-
FLOAT_BYTES[4] = source[offset + 3];
|
|
2290
|
-
FLOAT_BYTES[3] = source[offset + 4];
|
|
2291
|
-
FLOAT_BYTES[2] = source[offset + 5];
|
|
2292
|
-
FLOAT_BYTES[1] = source[offset + 6];
|
|
2293
|
-
FLOAT_BYTES[0] = source[offset + 7];
|
|
2294
|
-
return FLOAT[0];
|
|
2295
|
-
}
|
|
2296
|
-
: (source, offset) => {
|
|
2297
|
-
FLOAT_BYTES[0] = source[offset];
|
|
2298
|
-
FLOAT_BYTES[1] = source[offset + 1];
|
|
2299
|
-
FLOAT_BYTES[2] = source[offset + 2];
|
|
2300
|
-
FLOAT_BYTES[3] = source[offset + 3];
|
|
2301
|
-
FLOAT_BYTES[4] = source[offset + 4];
|
|
2302
|
-
FLOAT_BYTES[5] = source[offset + 5];
|
|
2303
|
-
FLOAT_BYTES[6] = source[offset + 6];
|
|
2304
|
-
FLOAT_BYTES[7] = source[offset + 7];
|
|
2305
|
-
return FLOAT[0];
|
|
2306
|
-
},
|
|
2307
|
-
setInt32BE(destination, offset, value) {
|
|
2308
|
-
destination[offset + 3] = value;
|
|
2309
|
-
value >>>= 8;
|
|
2310
|
-
destination[offset + 2] = value;
|
|
2311
|
-
value >>>= 8;
|
|
2312
|
-
destination[offset + 1] = value;
|
|
2313
|
-
value >>>= 8;
|
|
2314
|
-
destination[offset] = value;
|
|
2315
|
-
return 4;
|
|
2316
|
-
},
|
|
2317
|
-
setInt32LE(destination, offset, value) {
|
|
2318
|
-
destination[offset] = value;
|
|
2319
|
-
value >>>= 8;
|
|
2320
|
-
destination[offset + 1] = value;
|
|
2321
|
-
value >>>= 8;
|
|
2322
|
-
destination[offset + 2] = value;
|
|
2323
|
-
value >>>= 8;
|
|
2324
|
-
destination[offset + 3] = value;
|
|
2325
|
-
return 4;
|
|
2326
|
-
},
|
|
2327
|
-
setBigInt64LE(destination, offset, value) {
|
|
2328
|
-
const mask32bits = BigInt(0xffff_ffff);
|
|
2329
|
-
let lo = Number(value & mask32bits);
|
|
2330
|
-
destination[offset] = lo;
|
|
2331
|
-
lo >>= 8;
|
|
2332
|
-
destination[offset + 1] = lo;
|
|
2333
|
-
lo >>= 8;
|
|
2334
|
-
destination[offset + 2] = lo;
|
|
2335
|
-
lo >>= 8;
|
|
2336
|
-
destination[offset + 3] = lo;
|
|
2337
|
-
let hi = Number((value >> BigInt(32)) & mask32bits);
|
|
2338
|
-
destination[offset + 4] = hi;
|
|
2339
|
-
hi >>= 8;
|
|
2340
|
-
destination[offset + 5] = hi;
|
|
2341
|
-
hi >>= 8;
|
|
2342
|
-
destination[offset + 6] = hi;
|
|
2343
|
-
hi >>= 8;
|
|
2344
|
-
destination[offset + 7] = hi;
|
|
2345
|
-
return 8;
|
|
2346
|
-
},
|
|
2347
|
-
setFloat64LE: isBigEndian
|
|
2348
|
-
? (destination, offset, value) => {
|
|
2349
|
-
FLOAT[0] = value;
|
|
2350
|
-
destination[offset] = FLOAT_BYTES[7];
|
|
2351
|
-
destination[offset + 1] = FLOAT_BYTES[6];
|
|
2352
|
-
destination[offset + 2] = FLOAT_BYTES[5];
|
|
2353
|
-
destination[offset + 3] = FLOAT_BYTES[4];
|
|
2354
|
-
destination[offset + 4] = FLOAT_BYTES[3];
|
|
2355
|
-
destination[offset + 5] = FLOAT_BYTES[2];
|
|
2356
|
-
destination[offset + 6] = FLOAT_BYTES[1];
|
|
2357
|
-
destination[offset + 7] = FLOAT_BYTES[0];
|
|
2358
|
-
return 8;
|
|
2359
|
-
}
|
|
2360
|
-
: (destination, offset, value) => {
|
|
2361
|
-
FLOAT[0] = value;
|
|
2362
|
-
destination[offset] = FLOAT_BYTES[0];
|
|
2363
|
-
destination[offset + 1] = FLOAT_BYTES[1];
|
|
2364
|
-
destination[offset + 2] = FLOAT_BYTES[2];
|
|
2365
|
-
destination[offset + 3] = FLOAT_BYTES[3];
|
|
2366
|
-
destination[offset + 4] = FLOAT_BYTES[4];
|
|
2367
|
-
destination[offset + 5] = FLOAT_BYTES[5];
|
|
2368
|
-
destination[offset + 6] = FLOAT_BYTES[6];
|
|
2369
|
-
destination[offset + 7] = FLOAT_BYTES[7];
|
|
2370
|
-
return 8;
|
|
2371
|
-
}
|
|
2372
|
-
};
|
|
2373
|
-
|
|
2374
2491
|
let PROCESS_UNIQUE = null;
|
|
2492
|
+
const __idCache = new WeakMap();
|
|
2375
2493
|
class ObjectId extends BSONValue {
|
|
2376
2494
|
get _bsontype() {
|
|
2377
2495
|
return 'ObjectId';
|
|
@@ -2402,6 +2520,9 @@ class ObjectId extends BSONValue {
|
|
|
2402
2520
|
else if (typeof workingId === 'string') {
|
|
2403
2521
|
if (ObjectId.validateHexString(workingId)) {
|
|
2404
2522
|
this.buffer = ByteUtils.fromHex(workingId);
|
|
2523
|
+
if (ObjectId.cacheHexString) {
|
|
2524
|
+
__idCache.set(this, workingId);
|
|
2525
|
+
}
|
|
2405
2526
|
}
|
|
2406
2527
|
else {
|
|
2407
2528
|
throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
|
|
@@ -2410,9 +2531,6 @@ class ObjectId extends BSONValue {
|
|
|
2410
2531
|
else {
|
|
2411
2532
|
throw new BSONError('Argument passed in does not match the accepted types');
|
|
2412
2533
|
}
|
|
2413
|
-
if (ObjectId.cacheHexString) {
|
|
2414
|
-
this.__id = ByteUtils.toHex(this.id);
|
|
2415
|
-
}
|
|
2416
2534
|
}
|
|
2417
2535
|
get id() {
|
|
2418
2536
|
return this.buffer;
|
|
@@ -2420,7 +2538,7 @@ class ObjectId extends BSONValue {
|
|
|
2420
2538
|
set id(value) {
|
|
2421
2539
|
this.buffer = value;
|
|
2422
2540
|
if (ObjectId.cacheHexString) {
|
|
2423
|
-
this
|
|
2541
|
+
__idCache.set(this, ByteUtils.toHex(value));
|
|
2424
2542
|
}
|
|
2425
2543
|
}
|
|
2426
2544
|
static validateHexString(string) {
|
|
@@ -2438,12 +2556,14 @@ class ObjectId extends BSONValue {
|
|
|
2438
2556
|
return true;
|
|
2439
2557
|
}
|
|
2440
2558
|
toHexString() {
|
|
2441
|
-
if (ObjectId.cacheHexString
|
|
2442
|
-
|
|
2559
|
+
if (ObjectId.cacheHexString) {
|
|
2560
|
+
const __id = __idCache.get(this);
|
|
2561
|
+
if (__id)
|
|
2562
|
+
return __id;
|
|
2443
2563
|
}
|
|
2444
2564
|
const hexString = ByteUtils.toHex(this.id);
|
|
2445
|
-
if (ObjectId.cacheHexString
|
|
2446
|
-
this
|
|
2565
|
+
if (ObjectId.cacheHexString) {
|
|
2566
|
+
__idCache.set(this, hexString);
|
|
2447
2567
|
}
|
|
2448
2568
|
return hexString;
|
|
2449
2569
|
}
|
|
@@ -2567,6 +2687,9 @@ class ObjectId extends BSONValue {
|
|
|
2567
2687
|
static fromExtendedJSON(doc) {
|
|
2568
2688
|
return new ObjectId(doc.$oid);
|
|
2569
2689
|
}
|
|
2690
|
+
isCached() {
|
|
2691
|
+
return ObjectId.cacheHexString && __idCache.has(this);
|
|
2692
|
+
}
|
|
2570
2693
|
inspect(depth, options, inspect) {
|
|
2571
2694
|
inspect ??= defaultInspect;
|
|
2572
2695
|
return `new ObjectId(${inspect(this.toHexString(), options)})`;
|
|
@@ -3057,7 +3180,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3057
3180
|
if (objectSize <= 0 || objectSize > buffer.length - index)
|
|
3058
3181
|
throw new BSONError('bad embedded document length in bson');
|
|
3059
3182
|
if (raw) {
|
|
3060
|
-
value = buffer.
|
|
3183
|
+
value = buffer.subarray(index, index + objectSize);
|
|
3061
3184
|
}
|
|
3062
3185
|
else {
|
|
3063
3186
|
let objectOptions = options;
|
|
@@ -3129,49 +3252,23 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3129
3252
|
throw new BSONError('Negative binary type element size found');
|
|
3130
3253
|
if (binarySize > buffer.byteLength)
|
|
3131
3254
|
throw new BSONError('Binary type size larger than document size');
|
|
3132
|
-
if (
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
|
|
3145
|
-
}
|
|
3146
|
-
else {
|
|
3147
|
-
value = new Binary(buffer.slice(index, index + binarySize), subType);
|
|
3148
|
-
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3149
|
-
value = value.toUUID();
|
|
3150
|
-
}
|
|
3151
|
-
}
|
|
3255
|
+
if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
|
|
3256
|
+
binarySize = NumberUtils.getInt32LE(buffer, index);
|
|
3257
|
+
index += 4;
|
|
3258
|
+
if (binarySize < 0)
|
|
3259
|
+
throw new BSONError('Negative binary type element size found for subtype 0x02');
|
|
3260
|
+
if (binarySize > totalBinarySize - 4)
|
|
3261
|
+
throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
|
|
3262
|
+
if (binarySize < totalBinarySize - 4)
|
|
3263
|
+
throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
|
|
3264
|
+
}
|
|
3265
|
+
if (promoteBuffers && promoteValues) {
|
|
3266
|
+
value = ByteUtils.toLocalBufferType(buffer.subarray(index, index + binarySize));
|
|
3152
3267
|
}
|
|
3153
3268
|
else {
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
if (binarySize < 0)
|
|
3158
|
-
throw new BSONError('Negative binary type element size found for subtype 0x02');
|
|
3159
|
-
if (binarySize > totalBinarySize - 4)
|
|
3160
|
-
throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
|
|
3161
|
-
if (binarySize < totalBinarySize - 4)
|
|
3162
|
-
throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
|
|
3163
|
-
}
|
|
3164
|
-
if (promoteBuffers && promoteValues) {
|
|
3165
|
-
value = ByteUtils.allocateUnsafe(binarySize);
|
|
3166
|
-
for (i = 0; i < binarySize; i++) {
|
|
3167
|
-
value[i] = buffer[index + i];
|
|
3168
|
-
}
|
|
3169
|
-
}
|
|
3170
|
-
else {
|
|
3171
|
-
value = new Binary(buffer.slice(index, index + binarySize), subType);
|
|
3172
|
-
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3173
|
-
value = value.toUUID();
|
|
3174
|
-
}
|
|
3269
|
+
value = new Binary(buffer.subarray(index, index + binarySize), subType);
|
|
3270
|
+
if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
|
|
3271
|
+
value = value.toUUID();
|
|
3175
3272
|
}
|
|
3176
3273
|
}
|
|
3177
3274
|
index = index + binarySize;
|
|
@@ -3593,6 +3690,9 @@ function serializeBinary(buffer, key, value, index) {
|
|
|
3593
3690
|
size = size - 4;
|
|
3594
3691
|
index += NumberUtils.setInt32LE(buffer, index, size);
|
|
3595
3692
|
}
|
|
3693
|
+
if (value.sub_type === Binary.SUBTYPE_VECTOR) {
|
|
3694
|
+
validateBinaryVector(value);
|
|
3695
|
+
}
|
|
3596
3696
|
if (size <= 16) {
|
|
3597
3697
|
for (let i = 0; i < size; i++)
|
|
3598
3698
|
buffer[index + i] = data[i];
|