cbor-x 1.3.3 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +347 -346
- package/SECURITY.md +11 -11
- package/benchmark.md +73 -73
- package/browser.js +11 -11
- package/decode.d.ts +2 -46
- package/decode.js +47 -29
- package/dist/index.js +1160 -1134
- package/dist/index.min.js +100 -85
- package/dist/node.cjs +1228 -1202
- package/dist/test.js +26 -1
- package/encode.d.ts +1 -6
- package/encode.js +1041 -1033
- package/index.d.ts +61 -12
- package/index.js +3 -3
- package/iterators.js +85 -85
- package/node-index.js +24 -24
- package/package.json +6 -1
- package/rollup.config.js +45 -45
- package/stream.js +57 -57
- package/webpack.config.js +19 -19
- package/dist/index.js.map +0 -1
- package/dist/node-index.js +0 -93
package/dist/index.js
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
}
|
|
86
86
|
let res = {};
|
|
87
87
|
//map.forEach((v,k) => res[Object.keys(this._keyMap)[Object.values(this._keyMap).indexOf(k)] || k] = v)
|
|
88
|
-
map.forEach((v,k) => res[this._mapKey.has(k) ? this._mapKey.get(k) : k] = v);
|
|
88
|
+
map.forEach((v,k) => res[safeKey(this._mapKey.has(k) ? this._mapKey.get(k) : k)] = v);
|
|
89
89
|
return res
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -285,8 +285,8 @@
|
|
|
285
285
|
let key;
|
|
286
286
|
if (currentDecoder.mapsAsObjects) {
|
|
287
287
|
let object = {};
|
|
288
|
-
if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) object[currentDecoder.decodeKey(key)] = read();
|
|
289
|
-
else while ((key = read()) != STOP_CODE) object[key] = read();
|
|
288
|
+
if (currentDecoder.keyMap) while((key = read()) != STOP_CODE) object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
289
|
+
else while ((key = read()) != STOP_CODE) object[safeKey(key)] = read();
|
|
290
290
|
return object
|
|
291
291
|
} else {
|
|
292
292
|
if (restoreMapsAsObject) {
|
|
@@ -334,8 +334,8 @@
|
|
|
334
334
|
case 5: // map
|
|
335
335
|
if (currentDecoder.mapsAsObjects) {
|
|
336
336
|
let object = {};
|
|
337
|
-
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[currentDecoder.decodeKey(read())] = read();
|
|
338
|
-
else for (let i = 0; i < token; i++) object[read()] = read();
|
|
337
|
+
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
338
|
+
else for (let i = 0; i < token; i++) object[safeKey(read())] = read();
|
|
339
339
|
return object
|
|
340
340
|
} else {
|
|
341
341
|
if (restoreMapsAsObject) {
|
|
@@ -451,8 +451,8 @@
|
|
|
451
451
|
if (this.slowReads++ >= 3) { // create a fast compiled reader
|
|
452
452
|
let array = this.length == length ? this : this.slice(0, length);
|
|
453
453
|
compiledReader = currentDecoder.keyMap
|
|
454
|
-
? new Function('r', 'return {' + array.map(k => currentDecoder.decodeKey(k)).map(k => validName.test(k) ? k + ':r()' : ('[' + JSON.stringify(k) + ']:r()')).join(',') + '}')
|
|
455
|
-
: new Function('r', 'return {' + array.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}');
|
|
454
|
+
? new Function('r', 'return {' + array.map(k => currentDecoder.decodeKey(k)).map(k => validName.test(k) ? safeKey(k) + ':r()' : ('[' + JSON.stringify(k) + ']:r()')).join(',') + '}')
|
|
455
|
+
: new Function('r', 'return {' + array.map(key => validName.test(key) ? safeKey(key) + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}');
|
|
456
456
|
if (this.compiledReader)
|
|
457
457
|
compiledReader.next = this.compiledReader; // if there is an existing one, we store multiple readers as a linked list because it is usually pretty rare to have multiple readers (of different length) for the same structure
|
|
458
458
|
compiledReader.propertyCount = length;
|
|
@@ -460,14 +460,20 @@
|
|
|
460
460
|
return compiledReader(read)
|
|
461
461
|
}
|
|
462
462
|
let object = {};
|
|
463
|
-
if (currentDecoder.keyMap) for (let i = 0; i < length; i++) object[currentDecoder.decodeKey(this[i])] = read();
|
|
464
|
-
else for (let i = 0; i < length; i++)
|
|
463
|
+
if (currentDecoder.keyMap) for (let i = 0; i < length; i++) object[safeKey(currentDecoder.decodeKey(this[i]))] = read();
|
|
464
|
+
else for (let i = 0; i < length; i++) {
|
|
465
|
+
object[safeKey(this[i])] = read();
|
|
466
|
+
}
|
|
465
467
|
return object
|
|
466
468
|
}
|
|
467
469
|
structure.slowReads = 0;
|
|
468
470
|
return readObject
|
|
469
471
|
}
|
|
470
472
|
|
|
473
|
+
function safeKey(key) {
|
|
474
|
+
return key === '__proto__' ? '__proto_' : key
|
|
475
|
+
}
|
|
476
|
+
|
|
471
477
|
let readFixedString = readStringJS;
|
|
472
478
|
|
|
473
479
|
let isNativeAccelerationEnabled = false;
|
|
@@ -684,18 +690,30 @@
|
|
|
684
690
|
Uint8Array.prototype.slice.call(src, position, position += length) :
|
|
685
691
|
src.subarray(position, position += length)
|
|
686
692
|
}
|
|
687
|
-
|
|
693
|
+
let f32Array = new Float32Array(1);
|
|
694
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
688
695
|
function getFloat16() {
|
|
689
696
|
let byte0 = src[position++];
|
|
690
697
|
let byte1 = src[position++];
|
|
691
|
-
let
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
698
|
+
let exponent = (byte0 & 0x7f) >> 2;
|
|
699
|
+
if (exponent === 0x1f) { // specials
|
|
700
|
+
if (byte1 || (byte0 & 3))
|
|
701
|
+
return NaN;
|
|
702
|
+
return (byte0 & 0x80) ? -Infinity : Infinity;
|
|
703
|
+
}
|
|
704
|
+
if (exponent === 0) { // sub-normals
|
|
705
|
+
// significand with 10 fractional bits and divided by 2^14
|
|
706
|
+
let abs = (((byte0 & 3) << 8) | byte1) / (1 << 24);
|
|
707
|
+
return (byte0 & 0x80) ? -abs : abs
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
u8Array[3] = (byte0 & 0x80) | // sign bit
|
|
711
|
+
((exponent >> 1) + 56); // 4 of 5 of the exponent bits, re-offset-ed
|
|
712
|
+
u8Array[2] = ((byte0 & 7) << 5) | // last exponent bit and first two mantissa bits
|
|
713
|
+
(byte1 >> 3); // next 5 bits of mantissa
|
|
714
|
+
u8Array[1] = byte1 << 5; // last three bits of mantissa
|
|
715
|
+
u8Array[0] = 0;
|
|
716
|
+
return f32Array[0];
|
|
699
717
|
}
|
|
700
718
|
|
|
701
719
|
let keyCache = new Array(4096);
|
|
@@ -707,8 +725,6 @@
|
|
|
707
725
|
}
|
|
708
726
|
}
|
|
709
727
|
|
|
710
|
-
let glbl = typeof self == 'object' ? self : global;
|
|
711
|
-
|
|
712
728
|
currentExtensions[0] = (dateString) => {
|
|
713
729
|
// string date extension
|
|
714
730
|
return new Date(dateString)
|
|
@@ -756,11 +772,11 @@
|
|
|
756
772
|
let object = {};
|
|
757
773
|
if (currentDecoder.keyMap) for (let i = 2,l = definition.length; i < l; i++) {
|
|
758
774
|
let key = currentDecoder.decodeKey(structure[i - 2]);
|
|
759
|
-
object[key] = definition[i];
|
|
775
|
+
object[safeKey(key)] = definition[i];
|
|
760
776
|
}
|
|
761
777
|
else for (let i = 2,l = definition.length; i < l; i++) {
|
|
762
778
|
let key = structure[i - 2];
|
|
763
|
-
object[key] = definition[i];
|
|
779
|
+
object[safeKey(key)] = definition[i];
|
|
764
780
|
}
|
|
765
781
|
return object
|
|
766
782
|
};
|
|
@@ -775,7 +791,7 @@
|
|
|
775
791
|
return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
|
|
776
792
|
return new Tag(value, 15)
|
|
777
793
|
};
|
|
778
|
-
|
|
794
|
+
let glbl = { Error, RegExp };
|
|
779
795
|
currentExtensions[27] = (data) => { // http://cbor.schmorp.de/generic-object
|
|
780
796
|
return (glbl[data[0]] || Error)(data[1], data[2])
|
|
781
797
|
};
|
|
@@ -900,13 +916,17 @@
|
|
|
900
916
|
});
|
|
901
917
|
|
|
902
918
|
const isLittleEndianMachine = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1;
|
|
903
|
-
const typedArrays = [
|
|
919
|
+
const typedArrays = [Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
|
|
920
|
+
typeof BigUint64Array == 'undefined' ? { name:'BigUint64Array' } : BigUint64Array, Int8Array, Int16Array, Int32Array,
|
|
921
|
+
typeof BigInt64Array == 'undefined' ? { name:'BigInt64Array' } : BigInt64Array, Float32Array, Float64Array];
|
|
904
922
|
const typedArrayTags = [64, 68, 69, 70, 71, 72, 77, 78, 79, 85, 86];
|
|
905
923
|
for (let i = 0; i < typedArrays.length; i++) {
|
|
906
924
|
registerTypedArray(typedArrays[i], typedArrayTags[i]);
|
|
907
925
|
}
|
|
908
|
-
function registerTypedArray(
|
|
909
|
-
let
|
|
926
|
+
function registerTypedArray(TypedArray, tag) {
|
|
927
|
+
let dvMethod = 'get' + TypedArray.name.slice(0, -5);
|
|
928
|
+
if (typeof TypedArray !== 'function')
|
|
929
|
+
TypedArray = null;
|
|
910
930
|
let bytesPerElement = TypedArray.BYTES_PER_ELEMENT;
|
|
911
931
|
for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
|
|
912
932
|
if (!littleEndian && bytesPerElement == 1)
|
|
@@ -923,7 +943,7 @@
|
|
|
923
943
|
let dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
924
944
|
let elements = buffer.length >> sizeShift;
|
|
925
945
|
let ta = new TypedArray(elements);
|
|
926
|
-
let method = dv[
|
|
946
|
+
let method = dv[dvMethod];
|
|
927
947
|
for (let i = 0; i < elements; i++) {
|
|
928
948
|
ta[i] = method.call(dv, i << sizeShift, littleEndian);
|
|
929
949
|
}
|
|
@@ -1039,1121 +1059,1127 @@
|
|
|
1039
1059
|
DECIMAL_ROUND: 3,
|
|
1040
1060
|
DECIMAL_FIT: 4
|
|
1041
1061
|
};
|
|
1042
|
-
let f32Array = new Float32Array(1);
|
|
1043
|
-
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
1044
1062
|
function roundFloat32(float32Number) {
|
|
1045
1063
|
f32Array[0] = float32Number;
|
|
1046
1064
|
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
1047
1065
|
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
1048
1066
|
}
|
|
1049
1067
|
|
|
1050
|
-
let textEncoder;
|
|
1051
|
-
try {
|
|
1052
|
-
textEncoder = new TextEncoder();
|
|
1053
|
-
} catch (error) {}
|
|
1054
|
-
let extensions, extensionClasses;
|
|
1055
|
-
const hasNodeBuffer = typeof Buffer !== 'undefined';
|
|
1056
|
-
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array;
|
|
1057
|
-
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
1058
|
-
const MAX_STRUCTURES = 0x100;
|
|
1059
|
-
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
1060
|
-
let target;
|
|
1061
|
-
let targetView;
|
|
1062
|
-
let position$1 = 0;
|
|
1063
|
-
let safeEnd;
|
|
1064
|
-
let bundledStrings$1 = null;
|
|
1065
|
-
const MAX_BUNDLE_SIZE = 0xf000;
|
|
1066
|
-
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
1067
|
-
const RECORD_SYMBOL = Symbol('record-id');
|
|
1068
|
-
class Encoder extends Decoder {
|
|
1069
|
-
constructor(options) {
|
|
1070
|
-
super(options);
|
|
1071
|
-
this.offset = 0;
|
|
1072
|
-
let start;
|
|
1073
|
-
let sharedStructures;
|
|
1074
|
-
let hasSharedUpdate;
|
|
1075
|
-
let structures;
|
|
1076
|
-
let referenceMap;
|
|
1077
|
-
options = options || {};
|
|
1078
|
-
let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
|
|
1079
|
-
return target.utf8Write(string, position, maxBytes)
|
|
1080
|
-
} : (textEncoder && textEncoder.encodeInto) ?
|
|
1081
|
-
function(string, position) {
|
|
1082
|
-
return textEncoder.encodeInto(string, target.subarray(position)).written
|
|
1083
|
-
} : false;
|
|
1084
|
-
|
|
1085
|
-
let encoder = this;
|
|
1086
|
-
let hasSharedStructures = options.structures || options.saveStructures;
|
|
1087
|
-
let maxSharedStructures = options.maxSharedStructures;
|
|
1088
|
-
if (maxSharedStructures == null)
|
|
1089
|
-
maxSharedStructures = hasSharedStructures ? 128 : 0;
|
|
1090
|
-
if (maxSharedStructures > 8190)
|
|
1091
|
-
throw new Error('Maximum maxSharedStructure is 8190')
|
|
1092
|
-
let isSequential = options.sequential;
|
|
1093
|
-
if (isSequential) {
|
|
1094
|
-
maxSharedStructures = 0;
|
|
1095
|
-
}
|
|
1096
|
-
if (!this.structures)
|
|
1097
|
-
this.structures = [];
|
|
1098
|
-
if (this.saveStructures)
|
|
1099
|
-
this.saveShared = this.saveStructures;
|
|
1100
|
-
let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues;
|
|
1101
|
-
let sharedPackedObjectMap;
|
|
1102
|
-
if (sharedValues) {
|
|
1103
|
-
sharedPackedObjectMap = Object.create(null);
|
|
1104
|
-
for (let i = 0, l = sharedValues.length; i < l; i++) {
|
|
1105
|
-
sharedPackedObjectMap[sharedValues[i]] = i;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
let recordIdsToRemove = [];
|
|
1109
|
-
let transitionsCount = 0;
|
|
1110
|
-
let serializationsSinceTransitionRebuild = 0;
|
|
1111
|
-
|
|
1112
|
-
this.mapEncode = function(value, encodeOptions) {
|
|
1113
|
-
// Experimental support for premapping keys using _keyMap instad of keyMap - not optiimised yet)
|
|
1114
|
-
if (this._keyMap && !this._mapped) {
|
|
1115
|
-
//console.log('encoding ', value)
|
|
1116
|
-
switch (value.constructor.name) {
|
|
1117
|
-
case 'Array':
|
|
1118
|
-
value = value.map(r => this.encodeKeys(r));
|
|
1119
|
-
break
|
|
1120
|
-
//case 'Map':
|
|
1121
|
-
// value = this.encodeKeys(value)
|
|
1122
|
-
// break
|
|
1123
|
-
}
|
|
1124
|
-
//this._mapped = true
|
|
1125
|
-
}
|
|
1126
|
-
return this.encode(value, encodeOptions)
|
|
1127
|
-
};
|
|
1128
|
-
|
|
1129
|
-
this.encode = function(value, encodeOptions) {
|
|
1130
|
-
if (!target) {
|
|
1131
|
-
target = new ByteArrayAllocate(8192);
|
|
1132
|
-
targetView = new DataView(target.buffer, 0, 8192);
|
|
1133
|
-
position$1 = 0;
|
|
1134
|
-
}
|
|
1135
|
-
safeEnd = target.length - 10;
|
|
1136
|
-
if (safeEnd - position$1 < 0x800) {
|
|
1137
|
-
// don't start too close to the end,
|
|
1138
|
-
target = new ByteArrayAllocate(target.length);
|
|
1139
|
-
targetView = new DataView(target.buffer, 0, target.length);
|
|
1140
|
-
safeEnd = target.length - 10;
|
|
1141
|
-
position$1 = 0;
|
|
1142
|
-
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
1143
|
-
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1144
|
-
start = position$1;
|
|
1145
|
-
if (encoder.useSelfDescribedHeader) {
|
|
1146
|
-
targetView.setUint32(position$1, 0xd9d9f700); // tag two byte, then self-descriptive tag
|
|
1147
|
-
position$1 += 3;
|
|
1148
|
-
}
|
|
1149
|
-
referenceMap = encoder.structuredClone ? new Map() : null;
|
|
1150
|
-
if (encoder.bundleStrings && typeof value !== 'string') {
|
|
1151
|
-
bundledStrings$1 = [];
|
|
1152
|
-
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1153
|
-
} else
|
|
1154
|
-
bundledStrings$1 = null;
|
|
1155
|
-
|
|
1156
|
-
sharedStructures = encoder.structures;
|
|
1157
|
-
if (sharedStructures) {
|
|
1158
|
-
if (sharedStructures.uninitialized) {
|
|
1159
|
-
let sharedData = encoder.getShared() || {};
|
|
1160
|
-
encoder.structures = sharedStructures = sharedData.structures || [];
|
|
1161
|
-
encoder.sharedVersion = sharedData.version;
|
|
1162
|
-
let sharedValues = encoder.sharedValues = sharedData.packedValues;
|
|
1163
|
-
if (sharedValues) {
|
|
1164
|
-
sharedPackedObjectMap = {};
|
|
1165
|
-
for (let i = 0, l = sharedValues.length; i < l; i++)
|
|
1166
|
-
sharedPackedObjectMap[sharedValues[i]] = i;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
let sharedStructuresLength = sharedStructures.length;
|
|
1170
|
-
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
1171
|
-
sharedStructuresLength = maxSharedStructures;
|
|
1172
|
-
if (!sharedStructures.transitions) {
|
|
1173
|
-
// rebuild our structure transitions
|
|
1174
|
-
sharedStructures.transitions = Object.create(null);
|
|
1175
|
-
for (let i = 0; i < sharedStructuresLength; i++) {
|
|
1176
|
-
let keys = sharedStructures[i];
|
|
1177
|
-
//console.log('shared struct keys:', keys)
|
|
1178
|
-
if (!keys)
|
|
1179
|
-
continue
|
|
1180
|
-
let nextTransition, transition = sharedStructures.transitions;
|
|
1181
|
-
for (let j = 0, l = keys.length; j < l; j++) {
|
|
1182
|
-
if (transition[RECORD_SYMBOL] === undefined)
|
|
1183
|
-
transition[RECORD_SYMBOL] = i;
|
|
1184
|
-
let key = keys[j];
|
|
1185
|
-
nextTransition = transition[key];
|
|
1186
|
-
if (!nextTransition) {
|
|
1187
|
-
nextTransition = transition[key] = Object.create(null);
|
|
1188
|
-
}
|
|
1189
|
-
transition = nextTransition;
|
|
1190
|
-
}
|
|
1191
|
-
transition[RECORD_SYMBOL] = i | 0x100000;
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
if (!isSequential)
|
|
1195
|
-
sharedStructures.nextId = sharedStructuresLength;
|
|
1196
|
-
}
|
|
1197
|
-
if (hasSharedUpdate)
|
|
1198
|
-
hasSharedUpdate = false;
|
|
1199
|
-
structures = sharedStructures || [];
|
|
1200
|
-
packedObjectMap = sharedPackedObjectMap;
|
|
1201
|
-
if (options.pack) {
|
|
1202
|
-
let packedValues = new Map();
|
|
1203
|
-
packedValues.values = [];
|
|
1204
|
-
packedValues.encoder = encoder;
|
|
1205
|
-
packedValues.maxValues = options.maxPrivatePackedValues || (sharedPackedObjectMap ? 16 : Infinity);
|
|
1206
|
-
packedValues.objectMap = sharedPackedObjectMap || false;
|
|
1207
|
-
packedValues.samplingPackedValues = samplingPackedValues;
|
|
1208
|
-
findRepetitiveStrings(value, packedValues);
|
|
1209
|
-
if (packedValues.values.length > 0) {
|
|
1210
|
-
target[position$1++] = 0xd8; // one-byte tag
|
|
1211
|
-
target[position$1++] = 51; // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1212
|
-
writeArrayHeader(4);
|
|
1213
|
-
let valuesArray = packedValues.values;
|
|
1214
|
-
encode(valuesArray);
|
|
1215
|
-
writeArrayHeader(0); // prefixes
|
|
1216
|
-
writeArrayHeader(0); // suffixes
|
|
1217
|
-
packedObjectMap = Object.create(sharedPackedObjectMap || null);
|
|
1218
|
-
for (let i = 0, l = valuesArray.length; i < l; i++) {
|
|
1219
|
-
packedObjectMap[valuesArray[i]] = i;
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
try {
|
|
1224
|
-
encode(value);
|
|
1225
|
-
if (bundledStrings$1) {
|
|
1226
|
-
writeBundles(start, encode);
|
|
1227
|
-
}
|
|
1228
|
-
encoder.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1229
|
-
if (referenceMap && referenceMap.idsToInsert) {
|
|
1230
|
-
position$1 += referenceMap.idsToInsert.length * 2;
|
|
1231
|
-
if (position$1 > safeEnd)
|
|
1232
|
-
makeRoom(position$1);
|
|
1233
|
-
encoder.offset = position$1;
|
|
1234
|
-
let serialized = insertIds(target.subarray(start, position$1), referenceMap.idsToInsert);
|
|
1235
|
-
referenceMap = null;
|
|
1236
|
-
return serialized
|
|
1237
|
-
}
|
|
1238
|
-
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
1239
|
-
target.start = start;
|
|
1240
|
-
target.end = position$1;
|
|
1241
|
-
return target
|
|
1242
|
-
}
|
|
1243
|
-
return target.subarray(start, position$1) // position can change if we call encode again in saveShared, so we get the buffer now
|
|
1244
|
-
} finally {
|
|
1245
|
-
if (sharedStructures) {
|
|
1246
|
-
if (serializationsSinceTransitionRebuild < 10)
|
|
1247
|
-
serializationsSinceTransitionRebuild++;
|
|
1248
|
-
if (sharedStructures.length > maxSharedStructures)
|
|
1249
|
-
sharedStructures.length = maxSharedStructures;
|
|
1250
|
-
if (transitionsCount > 10000) {
|
|
1251
|
-
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1252
|
-
sharedStructures.transitions = null;
|
|
1253
|
-
serializationsSinceTransitionRebuild = 0;
|
|
1254
|
-
transitionsCount = 0;
|
|
1255
|
-
if (recordIdsToRemove.length > 0)
|
|
1256
|
-
recordIdsToRemove = [];
|
|
1257
|
-
} else if (recordIdsToRemove.length > 0 && !isSequential) {
|
|
1258
|
-
for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
|
|
1259
|
-
recordIdsToRemove[i][RECORD_SYMBOL] = undefined;
|
|
1260
|
-
}
|
|
1261
|
-
recordIdsToRemove = [];
|
|
1262
|
-
//sharedStructures.nextId = maxSharedStructures
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
if (hasSharedUpdate && encoder.saveShared) {
|
|
1266
|
-
if (encoder.structures.length > maxSharedStructures) {
|
|
1267
|
-
encoder.structures = encoder.structures.slice(0, maxSharedStructures);
|
|
1268
|
-
}
|
|
1269
|
-
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1270
|
-
let returnBuffer = target.subarray(start, position$1);
|
|
1271
|
-
if (encoder.updateSharedData() === false)
|
|
1272
|
-
return encoder.encode(value) // re-encode if it fails
|
|
1273
|
-
return returnBuffer
|
|
1274
|
-
}
|
|
1275
|
-
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1276
|
-
position$1 = start;
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
this.findCommonStringsToPack = () => {
|
|
1280
|
-
samplingPackedValues = new Map();
|
|
1281
|
-
if (!sharedPackedObjectMap)
|
|
1282
|
-
sharedPackedObjectMap = Object.create(null);
|
|
1283
|
-
return (options) => {
|
|
1284
|
-
let threshold = options && options.threshold || 4;
|
|
1285
|
-
let position = this.pack ? options.maxPrivatePackedValues || 16 : 0;
|
|
1286
|
-
if (!sharedValues)
|
|
1287
|
-
sharedValues = this.sharedValues = [];
|
|
1288
|
-
for (let [ key, status ] of samplingPackedValues) {
|
|
1289
|
-
if (status.count > threshold) {
|
|
1290
|
-
sharedPackedObjectMap[key] = position++;
|
|
1291
|
-
sharedValues.push(key);
|
|
1292
|
-
hasSharedUpdate = true;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
while (this.saveShared && this.updateSharedData() === false) {}
|
|
1296
|
-
samplingPackedValues = null;
|
|
1297
|
-
}
|
|
1298
|
-
};
|
|
1299
|
-
const encode = (value) => {
|
|
1300
|
-
if (position$1 > safeEnd)
|
|
1301
|
-
target = makeRoom(position$1);
|
|
1302
|
-
|
|
1303
|
-
var type = typeof value;
|
|
1304
|
-
var length;
|
|
1305
|
-
if (type === 'string') {
|
|
1306
|
-
if (packedObjectMap) {
|
|
1307
|
-
let packedPosition = packedObjectMap[value];
|
|
1308
|
-
if (packedPosition >= 0) {
|
|
1309
|
-
if (packedPosition < 16)
|
|
1310
|
-
target[position$1++] = packedPosition + 0xe0; // simple values, defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1311
|
-
else {
|
|
1312
|
-
target[position$1++] = 0xc6; // tag 6 defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1313
|
-
if (packedPosition & 1)
|
|
1314
|
-
encode((15 - packedPosition) >> 1);
|
|
1315
|
-
else
|
|
1316
|
-
encode((packedPosition - 16) >> 1);
|
|
1317
|
-
}
|
|
1318
|
-
return
|
|
1319
|
-
/* } else if (packedStatus.serializationId != serializationId) {
|
|
1320
|
-
packedStatus.serializationId = serializationId
|
|
1321
|
-
packedStatus.count = 1
|
|
1322
|
-
if (options.sharedPack) {
|
|
1323
|
-
let sharedCount = packedStatus.sharedCount = (packedStatus.sharedCount || 0) + 1
|
|
1324
|
-
if (shareCount > (options.sharedPack.threshold || 5)) {
|
|
1325
|
-
let sharedPosition = packedStatus.position = packedStatus.nextSharedPosition
|
|
1326
|
-
hasSharedUpdate = true
|
|
1327
|
-
if (sharedPosition < 16)
|
|
1328
|
-
target[position++] = sharedPosition + 0xc0
|
|
1329
|
-
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
} // else any in-doc incrementation?*/
|
|
1333
|
-
} else if (samplingPackedValues && !options.pack) {
|
|
1334
|
-
let status = samplingPackedValues.get(value);
|
|
1335
|
-
if (status)
|
|
1336
|
-
status.count++;
|
|
1337
|
-
else
|
|
1338
|
-
samplingPackedValues.set(value, {
|
|
1339
|
-
count: 1,
|
|
1340
|
-
});
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
let strLength = value.length;
|
|
1344
|
-
if (bundledStrings$1 && strLength >= 4 && strLength < 0x400) {
|
|
1345
|
-
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1346
|
-
let extStart;
|
|
1347
|
-
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1348
|
-
if (position$1 + maxBytes > safeEnd)
|
|
1349
|
-
target = makeRoom(position$1 + maxBytes);
|
|
1350
|
-
target[position$1++] = 0xd9; // tag 16-bit
|
|
1351
|
-
target[position$1++] = 0xdf; // tag 0xdff9
|
|
1352
|
-
target[position$1++] = 0xf9;
|
|
1353
|
-
// TODO: If we only have one bundle with any string data, only write one string bundle
|
|
1354
|
-
target[position$1++] = bundledStrings$1.position ? 0x84 : 0x82; // array of 4 or 2 elements depending on if we write bundles
|
|
1355
|
-
target[position$1++] = 0x1a; // 32-bit unsigned int
|
|
1356
|
-
extStart = position$1 - start;
|
|
1357
|
-
position$1 += 4; // reserve for writing bundle reference
|
|
1358
|
-
if (bundledStrings$1.position) {
|
|
1359
|
-
writeBundles(start, encode); // write the last bundles
|
|
1360
|
-
}
|
|
1361
|
-
bundledStrings$1 = ['', '']; // create new ones
|
|
1362
|
-
bundledStrings$1.size = 0;
|
|
1363
|
-
bundledStrings$1.position = extStart;
|
|
1364
|
-
}
|
|
1365
|
-
let twoByte = hasNonLatin.test(value);
|
|
1366
|
-
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1367
|
-
target[position$1++] = twoByte ? 0xce : 0xcf;
|
|
1368
|
-
encode(strLength);
|
|
1369
|
-
return
|
|
1370
|
-
}
|
|
1371
|
-
let headerSize;
|
|
1372
|
-
// first we estimate the header size, so we can write to the correct location
|
|
1373
|
-
if (strLength < 0x20) {
|
|
1374
|
-
headerSize = 1;
|
|
1375
|
-
} else if (strLength < 0x100) {
|
|
1376
|
-
headerSize = 2;
|
|
1377
|
-
} else if (strLength < 0x10000) {
|
|
1378
|
-
headerSize = 3;
|
|
1379
|
-
} else {
|
|
1380
|
-
headerSize = 5;
|
|
1381
|
-
}
|
|
1382
|
-
let maxBytes = strLength * 3;
|
|
1383
|
-
if (position$1 + maxBytes > safeEnd)
|
|
1384
|
-
target = makeRoom(position$1 + maxBytes);
|
|
1385
|
-
|
|
1386
|
-
if (strLength < 0x40 || !encodeUtf8) {
|
|
1387
|
-
let i, c1, c2, strPosition = position$1 + headerSize;
|
|
1388
|
-
for (i = 0; i < strLength; i++) {
|
|
1389
|
-
c1 = value.charCodeAt(i);
|
|
1390
|
-
if (c1 < 0x80) {
|
|
1391
|
-
target[strPosition++] = c1;
|
|
1392
|
-
} else if (c1 < 0x800) {
|
|
1393
|
-
target[strPosition++] = c1 >> 6 | 0xc0;
|
|
1394
|
-
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1395
|
-
} else if (
|
|
1396
|
-
(c1 & 0xfc00) === 0xd800 &&
|
|
1397
|
-
((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
|
|
1398
|
-
) {
|
|
1399
|
-
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
|
|
1400
|
-
i++;
|
|
1401
|
-
target[strPosition++] = c1 >> 18 | 0xf0;
|
|
1402
|
-
target[strPosition++] = c1 >> 12 & 0x3f | 0x80;
|
|
1403
|
-
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1404
|
-
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1405
|
-
} else {
|
|
1406
|
-
target[strPosition++] = c1 >> 12 | 0xe0;
|
|
1407
|
-
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1408
|
-
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
length = strPosition - position$1 - headerSize;
|
|
1412
|
-
} else {
|
|
1413
|
-
length = encodeUtf8(value, position$1 + headerSize, maxBytes);
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
if (length < 0x18) {
|
|
1417
|
-
target[position$1++] = 0x60 | length;
|
|
1418
|
-
} else if (length < 0x100) {
|
|
1419
|
-
if (headerSize < 2) {
|
|
1420
|
-
target.copyWithin(position$1 + 2, position$1 + 1, position$1 + 1 + length);
|
|
1421
|
-
}
|
|
1422
|
-
target[position$1++] = 0x78;
|
|
1423
|
-
target[position$1++] = length;
|
|
1424
|
-
} else if (length < 0x10000) {
|
|
1425
|
-
if (headerSize < 3) {
|
|
1426
|
-
target.copyWithin(position$1 + 3, position$1 + 2, position$1 + 2 + length);
|
|
1427
|
-
}
|
|
1428
|
-
target[position$1++] = 0x79;
|
|
1429
|
-
target[position$1++] = length >> 8;
|
|
1430
|
-
target[position$1++] = length & 0xff;
|
|
1431
|
-
} else {
|
|
1432
|
-
if (headerSize < 5) {
|
|
1433
|
-
target.copyWithin(position$1 + 5, position$1 + 3, position$1 + 3 + length);
|
|
1434
|
-
}
|
|
1435
|
-
target[position$1++] = 0x7a;
|
|
1436
|
-
targetView.setUint32(position$1, length);
|
|
1437
|
-
position$1 += 4;
|
|
1438
|
-
}
|
|
1439
|
-
position$1 += length;
|
|
1440
|
-
} else if (type === 'number') {
|
|
1441
|
-
if (value >>> 0 === value) {// positive integer, 32-bit or less
|
|
1442
|
-
// positive uint
|
|
1443
|
-
if (value < 0x18) {
|
|
1444
|
-
target[position$1++] = value;
|
|
1445
|
-
} else if (value < 0x100) {
|
|
1446
|
-
target[position$1++] = 0x18;
|
|
1447
|
-
target[position$1++] = value;
|
|
1448
|
-
} else if (value < 0x10000) {
|
|
1449
|
-
target[position$1++] = 0x19;
|
|
1450
|
-
target[position$1++] = value >> 8;
|
|
1451
|
-
target[position$1++] = value & 0xff;
|
|
1452
|
-
} else {
|
|
1453
|
-
target[position$1++] = 0x1a;
|
|
1454
|
-
targetView.setUint32(position$1, value);
|
|
1455
|
-
position$1 += 4;
|
|
1456
|
-
}
|
|
1457
|
-
} else if (value >> 0 === value) { // negative integer
|
|
1458
|
-
if (value >= -0x18) {
|
|
1459
|
-
target[position$1++] = 0x1f - value;
|
|
1460
|
-
} else if (value >= -0x100) {
|
|
1461
|
-
target[position$1++] = 0x38;
|
|
1462
|
-
target[position$1++] = ~value;
|
|
1463
|
-
} else if (value >= -0x10000) {
|
|
1464
|
-
target[position$1++] = 0x39;
|
|
1465
|
-
targetView.setUint16(position$1, ~value);
|
|
1466
|
-
position$1 += 2;
|
|
1467
|
-
} else {
|
|
1468
|
-
target[position$1++] = 0x3a;
|
|
1469
|
-
targetView.setUint32(position$1, ~value);
|
|
1470
|
-
position$1 += 4;
|
|
1471
|
-
}
|
|
1472
|
-
} else {
|
|
1473
|
-
let useFloat32;
|
|
1474
|
-
if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
|
|
1475
|
-
target[position$1++] = 0xfa;
|
|
1476
|
-
targetView.setFloat32(position$1, value);
|
|
1477
|
-
let xShifted;
|
|
1478
|
-
if (useFloat32 < 4 ||
|
|
1479
|
-
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1480
|
-
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1481
|
-
position$1 += 4;
|
|
1482
|
-
return
|
|
1483
|
-
} else
|
|
1484
|
-
position$1--; // move back into position for writing a double
|
|
1485
|
-
}
|
|
1486
|
-
target[position$1++] = 0xfb;
|
|
1487
|
-
targetView.setFloat64(position$1, value);
|
|
1488
|
-
position$1 += 8;
|
|
1489
|
-
}
|
|
1490
|
-
} else if (type === 'object') {
|
|
1491
|
-
if (!value)
|
|
1492
|
-
target[position$1++] = 0xf6;
|
|
1493
|
-
else {
|
|
1494
|
-
if (referenceMap) {
|
|
1495
|
-
let referee = referenceMap.get(value);
|
|
1496
|
-
if (referee) {
|
|
1497
|
-
target[position$1++] = 0xd8;
|
|
1498
|
-
target[position$1++] = 29; // http://cbor.schmorp.de/value-sharing
|
|
1499
|
-
target[position$1++] = 0x19; // 16-bit uint
|
|
1500
|
-
if (!referee.references) {
|
|
1501
|
-
let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = []);
|
|
1502
|
-
referee.references = [];
|
|
1503
|
-
idsToInsert.push(referee);
|
|
1504
|
-
}
|
|
1505
|
-
referee.references.push(position$1 - start);
|
|
1506
|
-
position$1 += 2; // TODO: also support 32-bit
|
|
1507
|
-
return
|
|
1508
|
-
} else
|
|
1509
|
-
referenceMap.set(value, { offset: position$1 - start });
|
|
1510
|
-
}
|
|
1511
|
-
let constructor = value.constructor;
|
|
1512
|
-
if (constructor === Object) {
|
|
1513
|
-
writeObject(value, true);
|
|
1514
|
-
} else if (constructor === Array) {
|
|
1515
|
-
length = value.length;
|
|
1516
|
-
if (length < 0x18) {
|
|
1517
|
-
target[position$1++] = 0x80 | length;
|
|
1518
|
-
} else {
|
|
1519
|
-
writeArrayHeader(length);
|
|
1520
|
-
}
|
|
1521
|
-
for (let i = 0; i < length; i++) {
|
|
1522
|
-
encode(value[i]);
|
|
1523
|
-
}
|
|
1524
|
-
} else if (constructor === Map) {
|
|
1525
|
-
if (this.mapsAsObjects ? this.useTag259ForMaps !== false : this.useTag259ForMaps) {
|
|
1526
|
-
// use Tag 259 (https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md) for maps if the user wants it that way
|
|
1527
|
-
target[position$1++] = 0xd9;
|
|
1528
|
-
target[position$1++] = 1;
|
|
1529
|
-
target[position$1++] = 3;
|
|
1530
|
-
}
|
|
1531
|
-
length = value.size;
|
|
1532
|
-
if (length < 0x18) {
|
|
1533
|
-
target[position$1++] = 0xa0 | length;
|
|
1534
|
-
} else if (length < 0x100) {
|
|
1535
|
-
target[position$1++] = 0xb8;
|
|
1536
|
-
target[position$1++] = length;
|
|
1537
|
-
} else if (length < 0x10000) {
|
|
1538
|
-
target[position$1++] = 0xb9;
|
|
1539
|
-
target[position$1++] = length >> 8;
|
|
1540
|
-
target[position$1++] = length & 0xff;
|
|
1541
|
-
} else {
|
|
1542
|
-
target[position$1++] = 0xba;
|
|
1543
|
-
targetView.setUint32(position$1, length);
|
|
1544
|
-
position$1 += 4;
|
|
1545
|
-
}
|
|
1546
|
-
if (encoder.keyMap) {
|
|
1547
|
-
for (let [ key, entryValue ] of value) {
|
|
1548
|
-
encode(encoder.encodeKey(key));
|
|
1549
|
-
encode(entryValue);
|
|
1550
|
-
}
|
|
1551
|
-
} else {
|
|
1552
|
-
for (let [ key, entryValue ] of value) {
|
|
1553
|
-
encode(key);
|
|
1554
|
-
encode(entryValue);
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
} else {
|
|
1558
|
-
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
1559
|
-
let extensionClass = extensionClasses[i];
|
|
1560
|
-
if (value instanceof extensionClass) {
|
|
1561
|
-
let extension = extensions[i];
|
|
1562
|
-
let tag = extension.tag;
|
|
1563
|
-
if (tag == undefined)
|
|
1564
|
-
tag = extension.getTag && extension.getTag(value);
|
|
1565
|
-
if (tag < 0x18) {
|
|
1566
|
-
target[position$1++] = 0xc0 | tag;
|
|
1567
|
-
} else if (tag < 0x100) {
|
|
1568
|
-
target[position$1++] = 0xd8;
|
|
1569
|
-
target[position$1++] = tag;
|
|
1570
|
-
} else if (tag < 0x10000) {
|
|
1571
|
-
target[position$1++] = 0xd9;
|
|
1572
|
-
target[position$1++] = tag >> 8;
|
|
1573
|
-
target[position$1++] = tag & 0xff;
|
|
1574
|
-
} else if (tag > -1) {
|
|
1575
|
-
target[position$1++] = 0xda;
|
|
1576
|
-
targetView.setUint32(position$1, tag);
|
|
1577
|
-
position$1 += 4;
|
|
1578
|
-
} // else undefined, don't write tag
|
|
1579
|
-
extension.encode.call(this, value, encode, makeRoom);
|
|
1580
|
-
return
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
if (value[Symbol.iterator]) {
|
|
1584
|
-
target[position$1++] = 0x9f; // indefinite length array
|
|
1585
|
-
for (let entry of value) {
|
|
1586
|
-
encode(entry);
|
|
1587
|
-
}
|
|
1588
|
-
target[position$1++] = 0xff; // stop-code
|
|
1589
|
-
return
|
|
1590
|
-
}
|
|
1591
|
-
// no extension found, write as object
|
|
1592
|
-
writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
} else if (type === 'boolean') {
|
|
1596
|
-
target[position$1++] = value ? 0xf5 : 0xf4;
|
|
1597
|
-
} else if (type === 'bigint') {
|
|
1598
|
-
if (value < (BigInt(1)<<BigInt(64)) && value >= 0) {
|
|
1599
|
-
// use an unsigned int as long as it fits
|
|
1600
|
-
target[position$1++] = 0x1b;
|
|
1601
|
-
targetView.setBigUint64(position$1, value);
|
|
1602
|
-
} else if (value > -(BigInt(1)<<BigInt(64)) && value < 0) {
|
|
1603
|
-
// if we can fit an unsigned int, use that
|
|
1604
|
-
target[position$1++] = 0x3b;
|
|
1605
|
-
targetView.setBigUint64(position$1, -value - BigInt(1));
|
|
1606
|
-
} else {
|
|
1607
|
-
// overflow
|
|
1608
|
-
if (this.largeBigIntToFloat) {
|
|
1609
|
-
target[position$1++] = 0xfb;
|
|
1610
|
-
targetView.setFloat64(position$1, Number(value));
|
|
1611
|
-
} else {
|
|
1612
|
-
throw new RangeError(value + ' was too large to fit in CBOR 64-bit integer format, set largeBigIntToFloat to convert to float-64')
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
position$1 += 8;
|
|
1616
|
-
} else if (type === 'undefined') {
|
|
1617
|
-
target[position$1++] = 0xf7;
|
|
1618
|
-
} else {
|
|
1619
|
-
throw new Error('Unknown type: ' + type)
|
|
1620
|
-
}
|
|
1621
|
-
};
|
|
1622
|
-
|
|
1623
|
-
const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
|
|
1624
|
-
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1625
|
-
let keys = Object.keys(object);
|
|
1626
|
-
let vals = Object.values(object);
|
|
1627
|
-
let length = keys.length;
|
|
1628
|
-
if (length < 0x18) {
|
|
1629
|
-
target[position$1++] = 0xa0 | length;
|
|
1630
|
-
} else if (length < 0x100) {
|
|
1631
|
-
target[position$1++] = 0xb8;
|
|
1632
|
-
target[position$1++] = length;
|
|
1633
|
-
} else if (length < 0x10000) {
|
|
1634
|
-
target[position$1++] = 0xb9;
|
|
1635
|
-
target[position$1++] = length >> 8;
|
|
1636
|
-
target[position$1++] = length & 0xff;
|
|
1637
|
-
} else {
|
|
1638
|
-
target[position$1++] = 0xba;
|
|
1639
|
-
targetView.setUint32(position$1, length);
|
|
1640
|
-
position$1 += 4;
|
|
1641
|
-
}
|
|
1642
|
-
if (encoder.keyMap) {
|
|
1643
|
-
for (let i = 0; i < length; i++) {
|
|
1644
|
-
encode(encodeKey(keys[i]));
|
|
1645
|
-
encode(vals[i]);
|
|
1646
|
-
}
|
|
1647
|
-
} else {
|
|
1648
|
-
for (let i = 0; i < length; i++) {
|
|
1649
|
-
encode(keys[i]);
|
|
1650
|
-
encode(vals[i]);
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
} :
|
|
1654
|
-
(object, safePrototype) => {
|
|
1655
|
-
target[position$1++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
|
|
1656
|
-
let objectOffset = position$1 - start;
|
|
1657
|
-
position$1 += 2;
|
|
1658
|
-
let size = 0;
|
|
1659
|
-
if (encoder.keyMap) {
|
|
1660
|
-
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1661
|
-
encode(encoder.encodeKey(key));
|
|
1662
|
-
encode(object[key]);
|
|
1663
|
-
size++;
|
|
1664
|
-
}
|
|
1665
|
-
} else {
|
|
1666
|
-
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1667
|
-
encode(key);
|
|
1668
|
-
encode(object[key]);
|
|
1669
|
-
size++;
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
target[objectOffset++ + start] = size >> 8;
|
|
1673
|
-
target[objectOffset + start] = size & 0xff;
|
|
1674
|
-
} :
|
|
1675
|
-
(object, safePrototype) => {
|
|
1676
|
-
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1677
|
-
let newTransitions = 0;
|
|
1678
|
-
let length = 0;
|
|
1679
|
-
let parentRecordId;
|
|
1680
|
-
let keys;
|
|
1681
|
-
if (this.keyMap) {
|
|
1682
|
-
keys = Object.keys(object).map(k => this.encodeKey(k));
|
|
1683
|
-
length = keys.length;
|
|
1684
|
-
for (let i = 0; i < length; i++) {
|
|
1685
|
-
let key = keys[i];
|
|
1686
|
-
nextTransition = transition[key];
|
|
1687
|
-
if (!nextTransition) {
|
|
1688
|
-
nextTransition = transition[key] = Object.create(null);
|
|
1689
|
-
newTransitions++;
|
|
1690
|
-
}
|
|
1691
|
-
transition = nextTransition;
|
|
1692
|
-
}
|
|
1693
|
-
} else {
|
|
1694
|
-
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1695
|
-
nextTransition = transition[key];
|
|
1696
|
-
if (!nextTransition) {
|
|
1697
|
-
if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
|
|
1698
|
-
parentRecordId = transition[RECORD_SYMBOL] & 0xffff;
|
|
1699
|
-
}
|
|
1700
|
-
nextTransition = transition[key] = Object.create(null);
|
|
1701
|
-
newTransitions++;
|
|
1702
|
-
}
|
|
1703
|
-
transition = nextTransition;
|
|
1704
|
-
length++;
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
let recordId = transition[RECORD_SYMBOL];
|
|
1708
|
-
if (recordId !== undefined) {
|
|
1709
|
-
recordId &= 0xffff;
|
|
1710
|
-
target[position$1++] = 0xd9;
|
|
1711
|
-
target[position$1++] = (recordId >> 8) | 0xe0;
|
|
1712
|
-
target[position$1++] = recordId & 0xff;
|
|
1713
|
-
} else {
|
|
1714
|
-
if (!keys)
|
|
1715
|
-
keys = transition.__keys__ || (transition.__keys__ = Object.keys(object));
|
|
1716
|
-
if (parentRecordId === undefined) {
|
|
1717
|
-
recordId = structures.nextId++;
|
|
1718
|
-
if (!recordId) {
|
|
1719
|
-
recordId = 0;
|
|
1720
|
-
structures.nextId = 1;
|
|
1721
|
-
}
|
|
1722
|
-
if (recordId >= MAX_STRUCTURES) {// cycle back around
|
|
1723
|
-
structures.nextId = (recordId = maxSharedStructures) + 1;
|
|
1724
|
-
}
|
|
1725
|
-
} else {
|
|
1726
|
-
recordId = parentRecordId;
|
|
1727
|
-
}
|
|
1728
|
-
structures[recordId] = keys;
|
|
1729
|
-
if (recordId < maxSharedStructures) {
|
|
1730
|
-
target[position$1++] = 0xd9;
|
|
1731
|
-
target[position$1++] = (recordId >> 8) | 0xe0;
|
|
1732
|
-
target[position$1++] = recordId & 0xff;
|
|
1733
|
-
transition = structures.transitions;
|
|
1734
|
-
for (let i = 0; i < length; i++) {
|
|
1735
|
-
if (transition[RECORD_SYMBOL] === undefined || (transition[RECORD_SYMBOL] & 0x100000))
|
|
1736
|
-
transition[RECORD_SYMBOL] = recordId;
|
|
1737
|
-
transition = transition[keys[i]];
|
|
1738
|
-
}
|
|
1739
|
-
transition[RECORD_SYMBOL] = recordId | 0x100000; // indicates it is a extendable terminal
|
|
1740
|
-
hasSharedUpdate = true;
|
|
1741
|
-
} else {
|
|
1742
|
-
transition[RECORD_SYMBOL] = recordId;
|
|
1743
|
-
targetView.setUint32(position$1, 0xd9dfff00); // tag two byte, then record definition id
|
|
1744
|
-
position$1 += 3;
|
|
1745
|
-
if (newTransitions)
|
|
1746
|
-
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1747
|
-
// record the removal of the id, we can maintain our shared structure
|
|
1748
|
-
if (recordIdsToRemove.length >= MAX_STRUCTURES - maxSharedStructures)
|
|
1749
|
-
recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined; // we are cycling back through, and have to remove old ones
|
|
1750
|
-
recordIdsToRemove.push(transition);
|
|
1751
|
-
writeArrayHeader(length + 2);
|
|
1752
|
-
encode(0xe000 + recordId);
|
|
1753
|
-
encode(keys);
|
|
1754
|
-
for (let v of Object.values(object)) encode(v);
|
|
1755
|
-
return
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
if (length < 0x18) { // write the array header
|
|
1759
|
-
target[position$1++] = 0x80 | length;
|
|
1760
|
-
} else {
|
|
1761
|
-
writeArrayHeader(length);
|
|
1762
|
-
}
|
|
1763
|
-
for (let key in object)
|
|
1764
|
-
if (safePrototype || object.hasOwnProperty(key))
|
|
1765
|
-
encode(object[key]);
|
|
1766
|
-
};
|
|
1767
|
-
const makeRoom = (end) => {
|
|
1768
|
-
let newSize;
|
|
1769
|
-
if (end > 0x1000000) {
|
|
1770
|
-
// special handling for really large buffers
|
|
1771
|
-
if ((end - start) > MAX_BUFFER_SIZE)
|
|
1772
|
-
throw new Error('Encoded buffer would be larger than maximum buffer size')
|
|
1773
|
-
newSize = Math.min(MAX_BUFFER_SIZE,
|
|
1774
|
-
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
|
|
1775
|
-
} else // faster handling for smaller buffers
|
|
1776
|
-
newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
|
|
1777
|
-
let newBuffer = new ByteArrayAllocate(newSize);
|
|
1778
|
-
targetView = new DataView(newBuffer.buffer, 0, newSize);
|
|
1779
|
-
if (target.copy)
|
|
1780
|
-
target.copy(newBuffer, 0, start, end);
|
|
1781
|
-
else
|
|
1782
|
-
newBuffer.set(target.slice(start, end));
|
|
1783
|
-
position$1 -= start;
|
|
1784
|
-
start = 0;
|
|
1785
|
-
safeEnd = newBuffer.length - 10;
|
|
1786
|
-
return target = newBuffer
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1789
|
-
useBuffer(buffer) {
|
|
1790
|
-
// this means we are finished using our own buffer and we can write over it safely
|
|
1791
|
-
target = buffer;
|
|
1792
|
-
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1793
|
-
position$1 = 0;
|
|
1794
|
-
}
|
|
1795
|
-
clearSharedData() {
|
|
1796
|
-
if (this.structures)
|
|
1797
|
-
this.structures = [];
|
|
1798
|
-
if (this.sharedValues)
|
|
1799
|
-
this.sharedValues = undefined;
|
|
1800
|
-
}
|
|
1801
|
-
updateSharedData() {
|
|
1802
|
-
let lastVersion = this.sharedVersion || 0;
|
|
1803
|
-
this.sharedVersion = lastVersion + 1;
|
|
1804
|
-
let structuresCopy = this.structures.slice(0);
|
|
1805
|
-
let sharedData = new SharedData(structuresCopy, this.sharedValues, this.sharedVersion);
|
|
1806
|
-
let saveResults = this.saveShared(sharedData,
|
|
1807
|
-
existingShared => (existingShared && existingShared.version || 0) == lastVersion);
|
|
1808
|
-
if (saveResults === false) {
|
|
1809
|
-
// get updated structures and try again if the update failed
|
|
1810
|
-
sharedData = this.getShared() || {};
|
|
1811
|
-
this.structures = sharedData.structures || [];
|
|
1812
|
-
this.sharedValues = sharedData.packedValues;
|
|
1813
|
-
this.sharedVersion = sharedData.version;
|
|
1814
|
-
this.structures.nextId = this.structures.length;
|
|
1815
|
-
} else {
|
|
1816
|
-
// restore structures
|
|
1817
|
-
structuresCopy.forEach((structure, i) => this.structures[i] = structure);
|
|
1818
|
-
}
|
|
1819
|
-
// saveShared may fail to write and reload, or may have reloaded to check compatibility and overwrite saved data, either way load the correct shared data
|
|
1820
|
-
return saveResults
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
class SharedData {
|
|
1824
|
-
constructor(structures, values, version) {
|
|
1825
|
-
this.structures = structures;
|
|
1826
|
-
this.packedValues = values;
|
|
1827
|
-
this.version = version;
|
|
1828
|
-
}
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
function writeArrayHeader(length) {
|
|
1832
|
-
if (length < 0x18)
|
|
1833
|
-
target[position$1++] = 0x80 | length;
|
|
1834
|
-
else if (length < 0x100) {
|
|
1835
|
-
target[position$1++] = 0x98;
|
|
1836
|
-
target[position$1++] = length;
|
|
1837
|
-
} else if (length < 0x10000) {
|
|
1838
|
-
target[position$1++] = 0x99;
|
|
1839
|
-
target[position$1++] = length >> 8;
|
|
1840
|
-
target[position$1++] = length & 0xff;
|
|
1841
|
-
} else {
|
|
1842
|
-
target[position$1++] = 0x9a;
|
|
1843
|
-
targetView.setUint32(position$1, length);
|
|
1844
|
-
position$1 += 4;
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
function findRepetitiveStrings(value, packedValues) {
|
|
1849
|
-
switch(typeof value) {
|
|
1850
|
-
case 'string':
|
|
1851
|
-
if (value.length > 3) {
|
|
1852
|
-
if (packedValues.objectMap[value] > -1 || packedValues.values.length >= packedValues.maxValues)
|
|
1853
|
-
return
|
|
1854
|
-
let packedStatus = packedValues.get(value);
|
|
1855
|
-
if (packedStatus) {
|
|
1856
|
-
if (++packedStatus.count == 2) {
|
|
1857
|
-
packedValues.values.push(value);
|
|
1858
|
-
}
|
|
1859
|
-
} else {
|
|
1860
|
-
packedValues.set(value, {
|
|
1861
|
-
count: 1,
|
|
1862
|
-
});
|
|
1863
|
-
if (packedValues.samplingPackedValues) {
|
|
1864
|
-
let status = packedValues.samplingPackedValues.get(value);
|
|
1865
|
-
if (status)
|
|
1866
|
-
status.count++;
|
|
1867
|
-
else
|
|
1868
|
-
packedValues.samplingPackedValues.set(value, {
|
|
1869
|
-
count: 1,
|
|
1870
|
-
});
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
break
|
|
1875
|
-
case 'object':
|
|
1876
|
-
if (value) {
|
|
1877
|
-
if (value instanceof Array) {
|
|
1878
|
-
for (let i = 0, l = value.length; i < l; i++) {
|
|
1879
|
-
findRepetitiveStrings(value[i], packedValues);
|
|
1880
|
-
}
|
|
1881
|
-
|
|
1882
|
-
} else {
|
|
1883
|
-
let includeKeys = !packedValues.encoder.useRecords;
|
|
1884
|
-
for (var key in value) {
|
|
1885
|
-
if (value.hasOwnProperty(key)) {
|
|
1886
|
-
if (includeKeys)
|
|
1887
|
-
findRepetitiveStrings(key, packedValues);
|
|
1888
|
-
findRepetitiveStrings(value[key], packedValues);
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
break
|
|
1894
|
-
case 'function': console.log(value);
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
const isLittleEndianMachine$1 = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1;
|
|
1898
|
-
extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer,
|
|
1899
|
-
Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
|
|
1900
|
-
typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
|
|
1901
|
-
typeof BigInt64Array == 'undefined' ? function() {} : BigInt64Array,
|
|
1902
|
-
Float32Array, Float64Array, SharedData];
|
|
1903
|
-
|
|
1904
|
-
//Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/
|
|
1905
|
-
extensions = [{
|
|
1906
|
-
tag: 1,
|
|
1907
|
-
encode(date, encode) {
|
|
1908
|
-
let seconds = date.getTime() / 1000;
|
|
1909
|
-
if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
|
|
1910
|
-
// Timestamp 32
|
|
1911
|
-
target[position$1++] = 0x1a;
|
|
1912
|
-
targetView.setUint32(position$1, seconds);
|
|
1913
|
-
position$1 += 4;
|
|
1914
|
-
} else {
|
|
1915
|
-
// Timestamp float64
|
|
1916
|
-
target[position$1++] = 0xfb;
|
|
1917
|
-
targetView.setFloat64(position$1, seconds);
|
|
1918
|
-
position$1 += 8;
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
}, {
|
|
1922
|
-
tag: 258, // https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
1923
|
-
encode(set, encode) {
|
|
1924
|
-
let array = Array.from(set);
|
|
1925
|
-
encode(array);
|
|
1926
|
-
}
|
|
1927
|
-
}, {
|
|
1928
|
-
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1929
|
-
encode(error, encode) {
|
|
1930
|
-
encode([ error.name, error.message ]);
|
|
1931
|
-
}
|
|
1932
|
-
}, {
|
|
1933
|
-
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1934
|
-
encode(regex, encode) {
|
|
1935
|
-
encode([ 'RegExp', regex.source, regex.flags ]);
|
|
1936
|
-
}
|
|
1937
|
-
}, {
|
|
1938
|
-
getTag(tag) {
|
|
1939
|
-
return tag.tag
|
|
1940
|
-
},
|
|
1941
|
-
encode(tag, encode) {
|
|
1942
|
-
encode(tag.value);
|
|
1943
|
-
}
|
|
1944
|
-
}, {
|
|
1945
|
-
encode(arrayBuffer, encode, makeRoom) {
|
|
1946
|
-
writeBuffer(arrayBuffer, makeRoom);
|
|
1947
|
-
}
|
|
1948
|
-
}, {
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
typedArrayEncoder(
|
|
1960
|
-
typedArrayEncoder(
|
|
1961
|
-
typedArrayEncoder(
|
|
1962
|
-
typedArrayEncoder(
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
}
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
target[position$1++] =
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
target[position$1++] =
|
|
2018
|
-
|
|
2019
|
-
position$1
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
let
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
function
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
1068
|
+
let textEncoder;
|
|
1069
|
+
try {
|
|
1070
|
+
textEncoder = new TextEncoder();
|
|
1071
|
+
} catch (error) {}
|
|
1072
|
+
let extensions, extensionClasses;
|
|
1073
|
+
const hasNodeBuffer = typeof Buffer !== 'undefined';
|
|
1074
|
+
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array;
|
|
1075
|
+
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
1076
|
+
const MAX_STRUCTURES = 0x100;
|
|
1077
|
+
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
1078
|
+
let target;
|
|
1079
|
+
let targetView;
|
|
1080
|
+
let position$1 = 0;
|
|
1081
|
+
let safeEnd;
|
|
1082
|
+
let bundledStrings$1 = null;
|
|
1083
|
+
const MAX_BUNDLE_SIZE = 0xf000;
|
|
1084
|
+
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
1085
|
+
const RECORD_SYMBOL = Symbol('record-id');
|
|
1086
|
+
class Encoder extends Decoder {
|
|
1087
|
+
constructor(options) {
|
|
1088
|
+
super(options);
|
|
1089
|
+
this.offset = 0;
|
|
1090
|
+
let start;
|
|
1091
|
+
let sharedStructures;
|
|
1092
|
+
let hasSharedUpdate;
|
|
1093
|
+
let structures;
|
|
1094
|
+
let referenceMap;
|
|
1095
|
+
options = options || {};
|
|
1096
|
+
let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
|
|
1097
|
+
return target.utf8Write(string, position, maxBytes)
|
|
1098
|
+
} : (textEncoder && textEncoder.encodeInto) ?
|
|
1099
|
+
function(string, position) {
|
|
1100
|
+
return textEncoder.encodeInto(string, target.subarray(position)).written
|
|
1101
|
+
} : false;
|
|
1102
|
+
|
|
1103
|
+
let encoder = this;
|
|
1104
|
+
let hasSharedStructures = options.structures || options.saveStructures;
|
|
1105
|
+
let maxSharedStructures = options.maxSharedStructures;
|
|
1106
|
+
if (maxSharedStructures == null)
|
|
1107
|
+
maxSharedStructures = hasSharedStructures ? 128 : 0;
|
|
1108
|
+
if (maxSharedStructures > 8190)
|
|
1109
|
+
throw new Error('Maximum maxSharedStructure is 8190')
|
|
1110
|
+
let isSequential = options.sequential;
|
|
1111
|
+
if (isSequential) {
|
|
1112
|
+
maxSharedStructures = 0;
|
|
1113
|
+
}
|
|
1114
|
+
if (!this.structures)
|
|
1115
|
+
this.structures = [];
|
|
1116
|
+
if (this.saveStructures)
|
|
1117
|
+
this.saveShared = this.saveStructures;
|
|
1118
|
+
let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues;
|
|
1119
|
+
let sharedPackedObjectMap;
|
|
1120
|
+
if (sharedValues) {
|
|
1121
|
+
sharedPackedObjectMap = Object.create(null);
|
|
1122
|
+
for (let i = 0, l = sharedValues.length; i < l; i++) {
|
|
1123
|
+
sharedPackedObjectMap[sharedValues[i]] = i;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
let recordIdsToRemove = [];
|
|
1127
|
+
let transitionsCount = 0;
|
|
1128
|
+
let serializationsSinceTransitionRebuild = 0;
|
|
1129
|
+
|
|
1130
|
+
this.mapEncode = function(value, encodeOptions) {
|
|
1131
|
+
// Experimental support for premapping keys using _keyMap instad of keyMap - not optiimised yet)
|
|
1132
|
+
if (this._keyMap && !this._mapped) {
|
|
1133
|
+
//console.log('encoding ', value)
|
|
1134
|
+
switch (value.constructor.name) {
|
|
1135
|
+
case 'Array':
|
|
1136
|
+
value = value.map(r => this.encodeKeys(r));
|
|
1137
|
+
break
|
|
1138
|
+
//case 'Map':
|
|
1139
|
+
// value = this.encodeKeys(value)
|
|
1140
|
+
// break
|
|
1141
|
+
}
|
|
1142
|
+
//this._mapped = true
|
|
1143
|
+
}
|
|
1144
|
+
return this.encode(value, encodeOptions)
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
this.encode = function(value, encodeOptions) {
|
|
1148
|
+
if (!target) {
|
|
1149
|
+
target = new ByteArrayAllocate(8192);
|
|
1150
|
+
targetView = new DataView(target.buffer, 0, 8192);
|
|
1151
|
+
position$1 = 0;
|
|
1152
|
+
}
|
|
1153
|
+
safeEnd = target.length - 10;
|
|
1154
|
+
if (safeEnd - position$1 < 0x800) {
|
|
1155
|
+
// don't start too close to the end,
|
|
1156
|
+
target = new ByteArrayAllocate(target.length);
|
|
1157
|
+
targetView = new DataView(target.buffer, 0, target.length);
|
|
1158
|
+
safeEnd = target.length - 10;
|
|
1159
|
+
position$1 = 0;
|
|
1160
|
+
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
1161
|
+
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1162
|
+
start = position$1;
|
|
1163
|
+
if (encoder.useSelfDescribedHeader) {
|
|
1164
|
+
targetView.setUint32(position$1, 0xd9d9f700); // tag two byte, then self-descriptive tag
|
|
1165
|
+
position$1 += 3;
|
|
1166
|
+
}
|
|
1167
|
+
referenceMap = encoder.structuredClone ? new Map() : null;
|
|
1168
|
+
if (encoder.bundleStrings && typeof value !== 'string') {
|
|
1169
|
+
bundledStrings$1 = [];
|
|
1170
|
+
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1171
|
+
} else
|
|
1172
|
+
bundledStrings$1 = null;
|
|
1173
|
+
|
|
1174
|
+
sharedStructures = encoder.structures;
|
|
1175
|
+
if (sharedStructures) {
|
|
1176
|
+
if (sharedStructures.uninitialized) {
|
|
1177
|
+
let sharedData = encoder.getShared() || {};
|
|
1178
|
+
encoder.structures = sharedStructures = sharedData.structures || [];
|
|
1179
|
+
encoder.sharedVersion = sharedData.version;
|
|
1180
|
+
let sharedValues = encoder.sharedValues = sharedData.packedValues;
|
|
1181
|
+
if (sharedValues) {
|
|
1182
|
+
sharedPackedObjectMap = {};
|
|
1183
|
+
for (let i = 0, l = sharedValues.length; i < l; i++)
|
|
1184
|
+
sharedPackedObjectMap[sharedValues[i]] = i;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
let sharedStructuresLength = sharedStructures.length;
|
|
1188
|
+
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
1189
|
+
sharedStructuresLength = maxSharedStructures;
|
|
1190
|
+
if (!sharedStructures.transitions) {
|
|
1191
|
+
// rebuild our structure transitions
|
|
1192
|
+
sharedStructures.transitions = Object.create(null);
|
|
1193
|
+
for (let i = 0; i < sharedStructuresLength; i++) {
|
|
1194
|
+
let keys = sharedStructures[i];
|
|
1195
|
+
//console.log('shared struct keys:', keys)
|
|
1196
|
+
if (!keys)
|
|
1197
|
+
continue
|
|
1198
|
+
let nextTransition, transition = sharedStructures.transitions;
|
|
1199
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
1200
|
+
if (transition[RECORD_SYMBOL] === undefined)
|
|
1201
|
+
transition[RECORD_SYMBOL] = i;
|
|
1202
|
+
let key = keys[j];
|
|
1203
|
+
nextTransition = transition[key];
|
|
1204
|
+
if (!nextTransition) {
|
|
1205
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1206
|
+
}
|
|
1207
|
+
transition = nextTransition;
|
|
1208
|
+
}
|
|
1209
|
+
transition[RECORD_SYMBOL] = i | 0x100000;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (!isSequential)
|
|
1213
|
+
sharedStructures.nextId = sharedStructuresLength;
|
|
1214
|
+
}
|
|
1215
|
+
if (hasSharedUpdate)
|
|
1216
|
+
hasSharedUpdate = false;
|
|
1217
|
+
structures = sharedStructures || [];
|
|
1218
|
+
packedObjectMap = sharedPackedObjectMap;
|
|
1219
|
+
if (options.pack) {
|
|
1220
|
+
let packedValues = new Map();
|
|
1221
|
+
packedValues.values = [];
|
|
1222
|
+
packedValues.encoder = encoder;
|
|
1223
|
+
packedValues.maxValues = options.maxPrivatePackedValues || (sharedPackedObjectMap ? 16 : Infinity);
|
|
1224
|
+
packedValues.objectMap = sharedPackedObjectMap || false;
|
|
1225
|
+
packedValues.samplingPackedValues = samplingPackedValues;
|
|
1226
|
+
findRepetitiveStrings(value, packedValues);
|
|
1227
|
+
if (packedValues.values.length > 0) {
|
|
1228
|
+
target[position$1++] = 0xd8; // one-byte tag
|
|
1229
|
+
target[position$1++] = 51; // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1230
|
+
writeArrayHeader(4);
|
|
1231
|
+
let valuesArray = packedValues.values;
|
|
1232
|
+
encode(valuesArray);
|
|
1233
|
+
writeArrayHeader(0); // prefixes
|
|
1234
|
+
writeArrayHeader(0); // suffixes
|
|
1235
|
+
packedObjectMap = Object.create(sharedPackedObjectMap || null);
|
|
1236
|
+
for (let i = 0, l = valuesArray.length; i < l; i++) {
|
|
1237
|
+
packedObjectMap[valuesArray[i]] = i;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
try {
|
|
1242
|
+
encode(value);
|
|
1243
|
+
if (bundledStrings$1) {
|
|
1244
|
+
writeBundles(start, encode);
|
|
1245
|
+
}
|
|
1246
|
+
encoder.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1247
|
+
if (referenceMap && referenceMap.idsToInsert) {
|
|
1248
|
+
position$1 += referenceMap.idsToInsert.length * 2;
|
|
1249
|
+
if (position$1 > safeEnd)
|
|
1250
|
+
makeRoom(position$1);
|
|
1251
|
+
encoder.offset = position$1;
|
|
1252
|
+
let serialized = insertIds(target.subarray(start, position$1), referenceMap.idsToInsert);
|
|
1253
|
+
referenceMap = null;
|
|
1254
|
+
return serialized
|
|
1255
|
+
}
|
|
1256
|
+
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
1257
|
+
target.start = start;
|
|
1258
|
+
target.end = position$1;
|
|
1259
|
+
return target
|
|
1260
|
+
}
|
|
1261
|
+
return target.subarray(start, position$1) // position can change if we call encode again in saveShared, so we get the buffer now
|
|
1262
|
+
} finally {
|
|
1263
|
+
if (sharedStructures) {
|
|
1264
|
+
if (serializationsSinceTransitionRebuild < 10)
|
|
1265
|
+
serializationsSinceTransitionRebuild++;
|
|
1266
|
+
if (sharedStructures.length > maxSharedStructures)
|
|
1267
|
+
sharedStructures.length = maxSharedStructures;
|
|
1268
|
+
if (transitionsCount > 10000) {
|
|
1269
|
+
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1270
|
+
sharedStructures.transitions = null;
|
|
1271
|
+
serializationsSinceTransitionRebuild = 0;
|
|
1272
|
+
transitionsCount = 0;
|
|
1273
|
+
if (recordIdsToRemove.length > 0)
|
|
1274
|
+
recordIdsToRemove = [];
|
|
1275
|
+
} else if (recordIdsToRemove.length > 0 && !isSequential) {
|
|
1276
|
+
for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
|
|
1277
|
+
recordIdsToRemove[i][RECORD_SYMBOL] = undefined;
|
|
1278
|
+
}
|
|
1279
|
+
recordIdsToRemove = [];
|
|
1280
|
+
//sharedStructures.nextId = maxSharedStructures
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (hasSharedUpdate && encoder.saveShared) {
|
|
1284
|
+
if (encoder.structures.length > maxSharedStructures) {
|
|
1285
|
+
encoder.structures = encoder.structures.slice(0, maxSharedStructures);
|
|
1286
|
+
}
|
|
1287
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1288
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
1289
|
+
if (encoder.updateSharedData() === false)
|
|
1290
|
+
return encoder.encode(value) // re-encode if it fails
|
|
1291
|
+
return returnBuffer
|
|
1292
|
+
}
|
|
1293
|
+
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1294
|
+
position$1 = start;
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
1297
|
+
this.findCommonStringsToPack = () => {
|
|
1298
|
+
samplingPackedValues = new Map();
|
|
1299
|
+
if (!sharedPackedObjectMap)
|
|
1300
|
+
sharedPackedObjectMap = Object.create(null);
|
|
1301
|
+
return (options) => {
|
|
1302
|
+
let threshold = options && options.threshold || 4;
|
|
1303
|
+
let position = this.pack ? options.maxPrivatePackedValues || 16 : 0;
|
|
1304
|
+
if (!sharedValues)
|
|
1305
|
+
sharedValues = this.sharedValues = [];
|
|
1306
|
+
for (let [ key, status ] of samplingPackedValues) {
|
|
1307
|
+
if (status.count > threshold) {
|
|
1308
|
+
sharedPackedObjectMap[key] = position++;
|
|
1309
|
+
sharedValues.push(key);
|
|
1310
|
+
hasSharedUpdate = true;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
while (this.saveShared && this.updateSharedData() === false) {}
|
|
1314
|
+
samplingPackedValues = null;
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
const encode = (value) => {
|
|
1318
|
+
if (position$1 > safeEnd)
|
|
1319
|
+
target = makeRoom(position$1);
|
|
1320
|
+
|
|
1321
|
+
var type = typeof value;
|
|
1322
|
+
var length;
|
|
1323
|
+
if (type === 'string') {
|
|
1324
|
+
if (packedObjectMap) {
|
|
1325
|
+
let packedPosition = packedObjectMap[value];
|
|
1326
|
+
if (packedPosition >= 0) {
|
|
1327
|
+
if (packedPosition < 16)
|
|
1328
|
+
target[position$1++] = packedPosition + 0xe0; // simple values, defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1329
|
+
else {
|
|
1330
|
+
target[position$1++] = 0xc6; // tag 6 defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1331
|
+
if (packedPosition & 1)
|
|
1332
|
+
encode((15 - packedPosition) >> 1);
|
|
1333
|
+
else
|
|
1334
|
+
encode((packedPosition - 16) >> 1);
|
|
1335
|
+
}
|
|
1336
|
+
return
|
|
1337
|
+
/* } else if (packedStatus.serializationId != serializationId) {
|
|
1338
|
+
packedStatus.serializationId = serializationId
|
|
1339
|
+
packedStatus.count = 1
|
|
1340
|
+
if (options.sharedPack) {
|
|
1341
|
+
let sharedCount = packedStatus.sharedCount = (packedStatus.sharedCount || 0) + 1
|
|
1342
|
+
if (shareCount > (options.sharedPack.threshold || 5)) {
|
|
1343
|
+
let sharedPosition = packedStatus.position = packedStatus.nextSharedPosition
|
|
1344
|
+
hasSharedUpdate = true
|
|
1345
|
+
if (sharedPosition < 16)
|
|
1346
|
+
target[position++] = sharedPosition + 0xc0
|
|
1347
|
+
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
} // else any in-doc incrementation?*/
|
|
1351
|
+
} else if (samplingPackedValues && !options.pack) {
|
|
1352
|
+
let status = samplingPackedValues.get(value);
|
|
1353
|
+
if (status)
|
|
1354
|
+
status.count++;
|
|
1355
|
+
else
|
|
1356
|
+
samplingPackedValues.set(value, {
|
|
1357
|
+
count: 1,
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
let strLength = value.length;
|
|
1362
|
+
if (bundledStrings$1 && strLength >= 4 && strLength < 0x400) {
|
|
1363
|
+
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1364
|
+
let extStart;
|
|
1365
|
+
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1366
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1367
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1368
|
+
target[position$1++] = 0xd9; // tag 16-bit
|
|
1369
|
+
target[position$1++] = 0xdf; // tag 0xdff9
|
|
1370
|
+
target[position$1++] = 0xf9;
|
|
1371
|
+
// TODO: If we only have one bundle with any string data, only write one string bundle
|
|
1372
|
+
target[position$1++] = bundledStrings$1.position ? 0x84 : 0x82; // array of 4 or 2 elements depending on if we write bundles
|
|
1373
|
+
target[position$1++] = 0x1a; // 32-bit unsigned int
|
|
1374
|
+
extStart = position$1 - start;
|
|
1375
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1376
|
+
if (bundledStrings$1.position) {
|
|
1377
|
+
writeBundles(start, encode); // write the last bundles
|
|
1378
|
+
}
|
|
1379
|
+
bundledStrings$1 = ['', '']; // create new ones
|
|
1380
|
+
bundledStrings$1.size = 0;
|
|
1381
|
+
bundledStrings$1.position = extStart;
|
|
1382
|
+
}
|
|
1383
|
+
let twoByte = hasNonLatin.test(value);
|
|
1384
|
+
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1385
|
+
target[position$1++] = twoByte ? 0xce : 0xcf;
|
|
1386
|
+
encode(strLength);
|
|
1387
|
+
return
|
|
1388
|
+
}
|
|
1389
|
+
let headerSize;
|
|
1390
|
+
// first we estimate the header size, so we can write to the correct location
|
|
1391
|
+
if (strLength < 0x20) {
|
|
1392
|
+
headerSize = 1;
|
|
1393
|
+
} else if (strLength < 0x100) {
|
|
1394
|
+
headerSize = 2;
|
|
1395
|
+
} else if (strLength < 0x10000) {
|
|
1396
|
+
headerSize = 3;
|
|
1397
|
+
} else {
|
|
1398
|
+
headerSize = 5;
|
|
1399
|
+
}
|
|
1400
|
+
let maxBytes = strLength * 3;
|
|
1401
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1402
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1403
|
+
|
|
1404
|
+
if (strLength < 0x40 || !encodeUtf8) {
|
|
1405
|
+
let i, c1, c2, strPosition = position$1 + headerSize;
|
|
1406
|
+
for (i = 0; i < strLength; i++) {
|
|
1407
|
+
c1 = value.charCodeAt(i);
|
|
1408
|
+
if (c1 < 0x80) {
|
|
1409
|
+
target[strPosition++] = c1;
|
|
1410
|
+
} else if (c1 < 0x800) {
|
|
1411
|
+
target[strPosition++] = c1 >> 6 | 0xc0;
|
|
1412
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1413
|
+
} else if (
|
|
1414
|
+
(c1 & 0xfc00) === 0xd800 &&
|
|
1415
|
+
((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
|
|
1416
|
+
) {
|
|
1417
|
+
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
|
|
1418
|
+
i++;
|
|
1419
|
+
target[strPosition++] = c1 >> 18 | 0xf0;
|
|
1420
|
+
target[strPosition++] = c1 >> 12 & 0x3f | 0x80;
|
|
1421
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1422
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1423
|
+
} else {
|
|
1424
|
+
target[strPosition++] = c1 >> 12 | 0xe0;
|
|
1425
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1426
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
length = strPosition - position$1 - headerSize;
|
|
1430
|
+
} else {
|
|
1431
|
+
length = encodeUtf8(value, position$1 + headerSize, maxBytes);
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
if (length < 0x18) {
|
|
1435
|
+
target[position$1++] = 0x60 | length;
|
|
1436
|
+
} else if (length < 0x100) {
|
|
1437
|
+
if (headerSize < 2) {
|
|
1438
|
+
target.copyWithin(position$1 + 2, position$1 + 1, position$1 + 1 + length);
|
|
1439
|
+
}
|
|
1440
|
+
target[position$1++] = 0x78;
|
|
1441
|
+
target[position$1++] = length;
|
|
1442
|
+
} else if (length < 0x10000) {
|
|
1443
|
+
if (headerSize < 3) {
|
|
1444
|
+
target.copyWithin(position$1 + 3, position$1 + 2, position$1 + 2 + length);
|
|
1445
|
+
}
|
|
1446
|
+
target[position$1++] = 0x79;
|
|
1447
|
+
target[position$1++] = length >> 8;
|
|
1448
|
+
target[position$1++] = length & 0xff;
|
|
1449
|
+
} else {
|
|
1450
|
+
if (headerSize < 5) {
|
|
1451
|
+
target.copyWithin(position$1 + 5, position$1 + 3, position$1 + 3 + length);
|
|
1452
|
+
}
|
|
1453
|
+
target[position$1++] = 0x7a;
|
|
1454
|
+
targetView.setUint32(position$1, length);
|
|
1455
|
+
position$1 += 4;
|
|
1456
|
+
}
|
|
1457
|
+
position$1 += length;
|
|
1458
|
+
} else if (type === 'number') {
|
|
1459
|
+
if (value >>> 0 === value) {// positive integer, 32-bit or less
|
|
1460
|
+
// positive uint
|
|
1461
|
+
if (value < 0x18) {
|
|
1462
|
+
target[position$1++] = value;
|
|
1463
|
+
} else if (value < 0x100) {
|
|
1464
|
+
target[position$1++] = 0x18;
|
|
1465
|
+
target[position$1++] = value;
|
|
1466
|
+
} else if (value < 0x10000) {
|
|
1467
|
+
target[position$1++] = 0x19;
|
|
1468
|
+
target[position$1++] = value >> 8;
|
|
1469
|
+
target[position$1++] = value & 0xff;
|
|
1470
|
+
} else {
|
|
1471
|
+
target[position$1++] = 0x1a;
|
|
1472
|
+
targetView.setUint32(position$1, value);
|
|
1473
|
+
position$1 += 4;
|
|
1474
|
+
}
|
|
1475
|
+
} else if (value >> 0 === value) { // negative integer
|
|
1476
|
+
if (value >= -0x18) {
|
|
1477
|
+
target[position$1++] = 0x1f - value;
|
|
1478
|
+
} else if (value >= -0x100) {
|
|
1479
|
+
target[position$1++] = 0x38;
|
|
1480
|
+
target[position$1++] = ~value;
|
|
1481
|
+
} else if (value >= -0x10000) {
|
|
1482
|
+
target[position$1++] = 0x39;
|
|
1483
|
+
targetView.setUint16(position$1, ~value);
|
|
1484
|
+
position$1 += 2;
|
|
1485
|
+
} else {
|
|
1486
|
+
target[position$1++] = 0x3a;
|
|
1487
|
+
targetView.setUint32(position$1, ~value);
|
|
1488
|
+
position$1 += 4;
|
|
1489
|
+
}
|
|
1490
|
+
} else {
|
|
1491
|
+
let useFloat32;
|
|
1492
|
+
if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
|
|
1493
|
+
target[position$1++] = 0xfa;
|
|
1494
|
+
targetView.setFloat32(position$1, value);
|
|
1495
|
+
let xShifted;
|
|
1496
|
+
if (useFloat32 < 4 ||
|
|
1497
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1498
|
+
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1499
|
+
position$1 += 4;
|
|
1500
|
+
return
|
|
1501
|
+
} else
|
|
1502
|
+
position$1--; // move back into position for writing a double
|
|
1503
|
+
}
|
|
1504
|
+
target[position$1++] = 0xfb;
|
|
1505
|
+
targetView.setFloat64(position$1, value);
|
|
1506
|
+
position$1 += 8;
|
|
1507
|
+
}
|
|
1508
|
+
} else if (type === 'object') {
|
|
1509
|
+
if (!value)
|
|
1510
|
+
target[position$1++] = 0xf6;
|
|
1511
|
+
else {
|
|
1512
|
+
if (referenceMap) {
|
|
1513
|
+
let referee = referenceMap.get(value);
|
|
1514
|
+
if (referee) {
|
|
1515
|
+
target[position$1++] = 0xd8;
|
|
1516
|
+
target[position$1++] = 29; // http://cbor.schmorp.de/value-sharing
|
|
1517
|
+
target[position$1++] = 0x19; // 16-bit uint
|
|
1518
|
+
if (!referee.references) {
|
|
1519
|
+
let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = []);
|
|
1520
|
+
referee.references = [];
|
|
1521
|
+
idsToInsert.push(referee);
|
|
1522
|
+
}
|
|
1523
|
+
referee.references.push(position$1 - start);
|
|
1524
|
+
position$1 += 2; // TODO: also support 32-bit
|
|
1525
|
+
return
|
|
1526
|
+
} else
|
|
1527
|
+
referenceMap.set(value, { offset: position$1 - start });
|
|
1528
|
+
}
|
|
1529
|
+
let constructor = value.constructor;
|
|
1530
|
+
if (constructor === Object) {
|
|
1531
|
+
writeObject(value, true);
|
|
1532
|
+
} else if (constructor === Array) {
|
|
1533
|
+
length = value.length;
|
|
1534
|
+
if (length < 0x18) {
|
|
1535
|
+
target[position$1++] = 0x80 | length;
|
|
1536
|
+
} else {
|
|
1537
|
+
writeArrayHeader(length);
|
|
1538
|
+
}
|
|
1539
|
+
for (let i = 0; i < length; i++) {
|
|
1540
|
+
encode(value[i]);
|
|
1541
|
+
}
|
|
1542
|
+
} else if (constructor === Map) {
|
|
1543
|
+
if (this.mapsAsObjects ? this.useTag259ForMaps !== false : this.useTag259ForMaps) {
|
|
1544
|
+
// use Tag 259 (https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md) for maps if the user wants it that way
|
|
1545
|
+
target[position$1++] = 0xd9;
|
|
1546
|
+
target[position$1++] = 1;
|
|
1547
|
+
target[position$1++] = 3;
|
|
1548
|
+
}
|
|
1549
|
+
length = value.size;
|
|
1550
|
+
if (length < 0x18) {
|
|
1551
|
+
target[position$1++] = 0xa0 | length;
|
|
1552
|
+
} else if (length < 0x100) {
|
|
1553
|
+
target[position$1++] = 0xb8;
|
|
1554
|
+
target[position$1++] = length;
|
|
1555
|
+
} else if (length < 0x10000) {
|
|
1556
|
+
target[position$1++] = 0xb9;
|
|
1557
|
+
target[position$1++] = length >> 8;
|
|
1558
|
+
target[position$1++] = length & 0xff;
|
|
1559
|
+
} else {
|
|
1560
|
+
target[position$1++] = 0xba;
|
|
1561
|
+
targetView.setUint32(position$1, length);
|
|
1562
|
+
position$1 += 4;
|
|
1563
|
+
}
|
|
1564
|
+
if (encoder.keyMap) {
|
|
1565
|
+
for (let [ key, entryValue ] of value) {
|
|
1566
|
+
encode(encoder.encodeKey(key));
|
|
1567
|
+
encode(entryValue);
|
|
1568
|
+
}
|
|
1569
|
+
} else {
|
|
1570
|
+
for (let [ key, entryValue ] of value) {
|
|
1571
|
+
encode(key);
|
|
1572
|
+
encode(entryValue);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
} else {
|
|
1576
|
+
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
1577
|
+
let extensionClass = extensionClasses[i];
|
|
1578
|
+
if (value instanceof extensionClass) {
|
|
1579
|
+
let extension = extensions[i];
|
|
1580
|
+
let tag = extension.tag;
|
|
1581
|
+
if (tag == undefined)
|
|
1582
|
+
tag = extension.getTag && extension.getTag.call(this, value);
|
|
1583
|
+
if (tag < 0x18) {
|
|
1584
|
+
target[position$1++] = 0xc0 | tag;
|
|
1585
|
+
} else if (tag < 0x100) {
|
|
1586
|
+
target[position$1++] = 0xd8;
|
|
1587
|
+
target[position$1++] = tag;
|
|
1588
|
+
} else if (tag < 0x10000) {
|
|
1589
|
+
target[position$1++] = 0xd9;
|
|
1590
|
+
target[position$1++] = tag >> 8;
|
|
1591
|
+
target[position$1++] = tag & 0xff;
|
|
1592
|
+
} else if (tag > -1) {
|
|
1593
|
+
target[position$1++] = 0xda;
|
|
1594
|
+
targetView.setUint32(position$1, tag);
|
|
1595
|
+
position$1 += 4;
|
|
1596
|
+
} // else undefined, don't write tag
|
|
1597
|
+
extension.encode.call(this, value, encode, makeRoom);
|
|
1598
|
+
return
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
if (value[Symbol.iterator]) {
|
|
1602
|
+
target[position$1++] = 0x9f; // indefinite length array
|
|
1603
|
+
for (let entry of value) {
|
|
1604
|
+
encode(entry);
|
|
1605
|
+
}
|
|
1606
|
+
target[position$1++] = 0xff; // stop-code
|
|
1607
|
+
return
|
|
1608
|
+
}
|
|
1609
|
+
// no extension found, write as object
|
|
1610
|
+
writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
} else if (type === 'boolean') {
|
|
1614
|
+
target[position$1++] = value ? 0xf5 : 0xf4;
|
|
1615
|
+
} else if (type === 'bigint') {
|
|
1616
|
+
if (value < (BigInt(1)<<BigInt(64)) && value >= 0) {
|
|
1617
|
+
// use an unsigned int as long as it fits
|
|
1618
|
+
target[position$1++] = 0x1b;
|
|
1619
|
+
targetView.setBigUint64(position$1, value);
|
|
1620
|
+
} else if (value > -(BigInt(1)<<BigInt(64)) && value < 0) {
|
|
1621
|
+
// if we can fit an unsigned int, use that
|
|
1622
|
+
target[position$1++] = 0x3b;
|
|
1623
|
+
targetView.setBigUint64(position$1, -value - BigInt(1));
|
|
1624
|
+
} else {
|
|
1625
|
+
// overflow
|
|
1626
|
+
if (this.largeBigIntToFloat) {
|
|
1627
|
+
target[position$1++] = 0xfb;
|
|
1628
|
+
targetView.setFloat64(position$1, Number(value));
|
|
1629
|
+
} else {
|
|
1630
|
+
throw new RangeError(value + ' was too large to fit in CBOR 64-bit integer format, set largeBigIntToFloat to convert to float-64')
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
position$1 += 8;
|
|
1634
|
+
} else if (type === 'undefined') {
|
|
1635
|
+
target[position$1++] = 0xf7;
|
|
1636
|
+
} else {
|
|
1637
|
+
throw new Error('Unknown type: ' + type)
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
|
|
1641
|
+
const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
|
|
1642
|
+
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1643
|
+
let keys = Object.keys(object);
|
|
1644
|
+
let vals = Object.values(object);
|
|
1645
|
+
let length = keys.length;
|
|
1646
|
+
if (length < 0x18) {
|
|
1647
|
+
target[position$1++] = 0xa0 | length;
|
|
1648
|
+
} else if (length < 0x100) {
|
|
1649
|
+
target[position$1++] = 0xb8;
|
|
1650
|
+
target[position$1++] = length;
|
|
1651
|
+
} else if (length < 0x10000) {
|
|
1652
|
+
target[position$1++] = 0xb9;
|
|
1653
|
+
target[position$1++] = length >> 8;
|
|
1654
|
+
target[position$1++] = length & 0xff;
|
|
1655
|
+
} else {
|
|
1656
|
+
target[position$1++] = 0xba;
|
|
1657
|
+
targetView.setUint32(position$1, length);
|
|
1658
|
+
position$1 += 4;
|
|
1659
|
+
}
|
|
1660
|
+
if (encoder.keyMap) {
|
|
1661
|
+
for (let i = 0; i < length; i++) {
|
|
1662
|
+
encode(encodeKey(keys[i]));
|
|
1663
|
+
encode(vals[i]);
|
|
1664
|
+
}
|
|
1665
|
+
} else {
|
|
1666
|
+
for (let i = 0; i < length; i++) {
|
|
1667
|
+
encode(keys[i]);
|
|
1668
|
+
encode(vals[i]);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
} :
|
|
1672
|
+
(object, safePrototype) => {
|
|
1673
|
+
target[position$1++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
|
|
1674
|
+
let objectOffset = position$1 - start;
|
|
1675
|
+
position$1 += 2;
|
|
1676
|
+
let size = 0;
|
|
1677
|
+
if (encoder.keyMap) {
|
|
1678
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1679
|
+
encode(encoder.encodeKey(key));
|
|
1680
|
+
encode(object[key]);
|
|
1681
|
+
size++;
|
|
1682
|
+
}
|
|
1683
|
+
} else {
|
|
1684
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1685
|
+
encode(key);
|
|
1686
|
+
encode(object[key]);
|
|
1687
|
+
size++;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
target[objectOffset++ + start] = size >> 8;
|
|
1691
|
+
target[objectOffset + start] = size & 0xff;
|
|
1692
|
+
} :
|
|
1693
|
+
(object, safePrototype) => {
|
|
1694
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1695
|
+
let newTransitions = 0;
|
|
1696
|
+
let length = 0;
|
|
1697
|
+
let parentRecordId;
|
|
1698
|
+
let keys;
|
|
1699
|
+
if (this.keyMap) {
|
|
1700
|
+
keys = Object.keys(object).map(k => this.encodeKey(k));
|
|
1701
|
+
length = keys.length;
|
|
1702
|
+
for (let i = 0; i < length; i++) {
|
|
1703
|
+
let key = keys[i];
|
|
1704
|
+
nextTransition = transition[key];
|
|
1705
|
+
if (!nextTransition) {
|
|
1706
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1707
|
+
newTransitions++;
|
|
1708
|
+
}
|
|
1709
|
+
transition = nextTransition;
|
|
1710
|
+
}
|
|
1711
|
+
} else {
|
|
1712
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1713
|
+
nextTransition = transition[key];
|
|
1714
|
+
if (!nextTransition) {
|
|
1715
|
+
if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
|
|
1716
|
+
parentRecordId = transition[RECORD_SYMBOL] & 0xffff;
|
|
1717
|
+
}
|
|
1718
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1719
|
+
newTransitions++;
|
|
1720
|
+
}
|
|
1721
|
+
transition = nextTransition;
|
|
1722
|
+
length++;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1726
|
+
if (recordId !== undefined) {
|
|
1727
|
+
recordId &= 0xffff;
|
|
1728
|
+
target[position$1++] = 0xd9;
|
|
1729
|
+
target[position$1++] = (recordId >> 8) | 0xe0;
|
|
1730
|
+
target[position$1++] = recordId & 0xff;
|
|
1731
|
+
} else {
|
|
1732
|
+
if (!keys)
|
|
1733
|
+
keys = transition.__keys__ || (transition.__keys__ = Object.keys(object));
|
|
1734
|
+
if (parentRecordId === undefined) {
|
|
1735
|
+
recordId = structures.nextId++;
|
|
1736
|
+
if (!recordId) {
|
|
1737
|
+
recordId = 0;
|
|
1738
|
+
structures.nextId = 1;
|
|
1739
|
+
}
|
|
1740
|
+
if (recordId >= MAX_STRUCTURES) {// cycle back around
|
|
1741
|
+
structures.nextId = (recordId = maxSharedStructures) + 1;
|
|
1742
|
+
}
|
|
1743
|
+
} else {
|
|
1744
|
+
recordId = parentRecordId;
|
|
1745
|
+
}
|
|
1746
|
+
structures[recordId] = keys;
|
|
1747
|
+
if (recordId < maxSharedStructures) {
|
|
1748
|
+
target[position$1++] = 0xd9;
|
|
1749
|
+
target[position$1++] = (recordId >> 8) | 0xe0;
|
|
1750
|
+
target[position$1++] = recordId & 0xff;
|
|
1751
|
+
transition = structures.transitions;
|
|
1752
|
+
for (let i = 0; i < length; i++) {
|
|
1753
|
+
if (transition[RECORD_SYMBOL] === undefined || (transition[RECORD_SYMBOL] & 0x100000))
|
|
1754
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1755
|
+
transition = transition[keys[i]];
|
|
1756
|
+
}
|
|
1757
|
+
transition[RECORD_SYMBOL] = recordId | 0x100000; // indicates it is a extendable terminal
|
|
1758
|
+
hasSharedUpdate = true;
|
|
1759
|
+
} else {
|
|
1760
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1761
|
+
targetView.setUint32(position$1, 0xd9dfff00); // tag two byte, then record definition id
|
|
1762
|
+
position$1 += 3;
|
|
1763
|
+
if (newTransitions)
|
|
1764
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1765
|
+
// record the removal of the id, we can maintain our shared structure
|
|
1766
|
+
if (recordIdsToRemove.length >= MAX_STRUCTURES - maxSharedStructures)
|
|
1767
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined; // we are cycling back through, and have to remove old ones
|
|
1768
|
+
recordIdsToRemove.push(transition);
|
|
1769
|
+
writeArrayHeader(length + 2);
|
|
1770
|
+
encode(0xe000 + recordId);
|
|
1771
|
+
encode(keys);
|
|
1772
|
+
for (let v of Object.values(object)) encode(v);
|
|
1773
|
+
return
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
if (length < 0x18) { // write the array header
|
|
1777
|
+
target[position$1++] = 0x80 | length;
|
|
1778
|
+
} else {
|
|
1779
|
+
writeArrayHeader(length);
|
|
1780
|
+
}
|
|
1781
|
+
for (let key in object)
|
|
1782
|
+
if (safePrototype || object.hasOwnProperty(key))
|
|
1783
|
+
encode(object[key]);
|
|
1784
|
+
};
|
|
1785
|
+
const makeRoom = (end) => {
|
|
1786
|
+
let newSize;
|
|
1787
|
+
if (end > 0x1000000) {
|
|
1788
|
+
// special handling for really large buffers
|
|
1789
|
+
if ((end - start) > MAX_BUFFER_SIZE)
|
|
1790
|
+
throw new Error('Encoded buffer would be larger than maximum buffer size')
|
|
1791
|
+
newSize = Math.min(MAX_BUFFER_SIZE,
|
|
1792
|
+
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
|
|
1793
|
+
} else // faster handling for smaller buffers
|
|
1794
|
+
newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
|
|
1795
|
+
let newBuffer = new ByteArrayAllocate(newSize);
|
|
1796
|
+
targetView = new DataView(newBuffer.buffer, 0, newSize);
|
|
1797
|
+
if (target.copy)
|
|
1798
|
+
target.copy(newBuffer, 0, start, end);
|
|
1799
|
+
else
|
|
1800
|
+
newBuffer.set(target.slice(start, end));
|
|
1801
|
+
position$1 -= start;
|
|
1802
|
+
start = 0;
|
|
1803
|
+
safeEnd = newBuffer.length - 10;
|
|
1804
|
+
return target = newBuffer
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1807
|
+
useBuffer(buffer) {
|
|
1808
|
+
// this means we are finished using our own buffer and we can write over it safely
|
|
1809
|
+
target = buffer;
|
|
1810
|
+
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1811
|
+
position$1 = 0;
|
|
1812
|
+
}
|
|
1813
|
+
clearSharedData() {
|
|
1814
|
+
if (this.structures)
|
|
1815
|
+
this.structures = [];
|
|
1816
|
+
if (this.sharedValues)
|
|
1817
|
+
this.sharedValues = undefined;
|
|
1818
|
+
}
|
|
1819
|
+
updateSharedData() {
|
|
1820
|
+
let lastVersion = this.sharedVersion || 0;
|
|
1821
|
+
this.sharedVersion = lastVersion + 1;
|
|
1822
|
+
let structuresCopy = this.structures.slice(0);
|
|
1823
|
+
let sharedData = new SharedData(structuresCopy, this.sharedValues, this.sharedVersion);
|
|
1824
|
+
let saveResults = this.saveShared(sharedData,
|
|
1825
|
+
existingShared => (existingShared && existingShared.version || 0) == lastVersion);
|
|
1826
|
+
if (saveResults === false) {
|
|
1827
|
+
// get updated structures and try again if the update failed
|
|
1828
|
+
sharedData = this.getShared() || {};
|
|
1829
|
+
this.structures = sharedData.structures || [];
|
|
1830
|
+
this.sharedValues = sharedData.packedValues;
|
|
1831
|
+
this.sharedVersion = sharedData.version;
|
|
1832
|
+
this.structures.nextId = this.structures.length;
|
|
1833
|
+
} else {
|
|
1834
|
+
// restore structures
|
|
1835
|
+
structuresCopy.forEach((structure, i) => this.structures[i] = structure);
|
|
1836
|
+
}
|
|
1837
|
+
// saveShared may fail to write and reload, or may have reloaded to check compatibility and overwrite saved data, either way load the correct shared data
|
|
1838
|
+
return saveResults
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
class SharedData {
|
|
1842
|
+
constructor(structures, values, version) {
|
|
1843
|
+
this.structures = structures;
|
|
1844
|
+
this.packedValues = values;
|
|
1845
|
+
this.version = version;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
function writeArrayHeader(length) {
|
|
1850
|
+
if (length < 0x18)
|
|
1851
|
+
target[position$1++] = 0x80 | length;
|
|
1852
|
+
else if (length < 0x100) {
|
|
1853
|
+
target[position$1++] = 0x98;
|
|
1854
|
+
target[position$1++] = length;
|
|
1855
|
+
} else if (length < 0x10000) {
|
|
1856
|
+
target[position$1++] = 0x99;
|
|
1857
|
+
target[position$1++] = length >> 8;
|
|
1858
|
+
target[position$1++] = length & 0xff;
|
|
1859
|
+
} else {
|
|
1860
|
+
target[position$1++] = 0x9a;
|
|
1861
|
+
targetView.setUint32(position$1, length);
|
|
1862
|
+
position$1 += 4;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
function findRepetitiveStrings(value, packedValues) {
|
|
1867
|
+
switch(typeof value) {
|
|
1868
|
+
case 'string':
|
|
1869
|
+
if (value.length > 3) {
|
|
1870
|
+
if (packedValues.objectMap[value] > -1 || packedValues.values.length >= packedValues.maxValues)
|
|
1871
|
+
return
|
|
1872
|
+
let packedStatus = packedValues.get(value);
|
|
1873
|
+
if (packedStatus) {
|
|
1874
|
+
if (++packedStatus.count == 2) {
|
|
1875
|
+
packedValues.values.push(value);
|
|
1876
|
+
}
|
|
1877
|
+
} else {
|
|
1878
|
+
packedValues.set(value, {
|
|
1879
|
+
count: 1,
|
|
1880
|
+
});
|
|
1881
|
+
if (packedValues.samplingPackedValues) {
|
|
1882
|
+
let status = packedValues.samplingPackedValues.get(value);
|
|
1883
|
+
if (status)
|
|
1884
|
+
status.count++;
|
|
1885
|
+
else
|
|
1886
|
+
packedValues.samplingPackedValues.set(value, {
|
|
1887
|
+
count: 1,
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
break
|
|
1893
|
+
case 'object':
|
|
1894
|
+
if (value) {
|
|
1895
|
+
if (value instanceof Array) {
|
|
1896
|
+
for (let i = 0, l = value.length; i < l; i++) {
|
|
1897
|
+
findRepetitiveStrings(value[i], packedValues);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
} else {
|
|
1901
|
+
let includeKeys = !packedValues.encoder.useRecords;
|
|
1902
|
+
for (var key in value) {
|
|
1903
|
+
if (value.hasOwnProperty(key)) {
|
|
1904
|
+
if (includeKeys)
|
|
1905
|
+
findRepetitiveStrings(key, packedValues);
|
|
1906
|
+
findRepetitiveStrings(value[key], packedValues);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
break
|
|
1912
|
+
case 'function': console.log(value);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
const isLittleEndianMachine$1 = new Uint8Array(new Uint16Array([1]).buffer)[0] == 1;
|
|
1916
|
+
extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer,
|
|
1917
|
+
Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
|
|
1918
|
+
typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
|
|
1919
|
+
typeof BigInt64Array == 'undefined' ? function() {} : BigInt64Array,
|
|
1920
|
+
Float32Array, Float64Array, SharedData ];
|
|
1921
|
+
|
|
1922
|
+
//Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/
|
|
1923
|
+
extensions = [{ // Date
|
|
1924
|
+
tag: 1,
|
|
1925
|
+
encode(date, encode) {
|
|
1926
|
+
let seconds = date.getTime() / 1000;
|
|
1927
|
+
if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
|
|
1928
|
+
// Timestamp 32
|
|
1929
|
+
target[position$1++] = 0x1a;
|
|
1930
|
+
targetView.setUint32(position$1, seconds);
|
|
1931
|
+
position$1 += 4;
|
|
1932
|
+
} else {
|
|
1933
|
+
// Timestamp float64
|
|
1934
|
+
target[position$1++] = 0xfb;
|
|
1935
|
+
targetView.setFloat64(position$1, seconds);
|
|
1936
|
+
position$1 += 8;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}, { // Set
|
|
1940
|
+
tag: 258, // https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
1941
|
+
encode(set, encode) {
|
|
1942
|
+
let array = Array.from(set);
|
|
1943
|
+
encode(array);
|
|
1944
|
+
}
|
|
1945
|
+
}, { // Error
|
|
1946
|
+
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1947
|
+
encode(error, encode) {
|
|
1948
|
+
encode([ error.name, error.message ]);
|
|
1949
|
+
}
|
|
1950
|
+
}, { // RegExp
|
|
1951
|
+
tag: 27, // http://cbor.schmorp.de/generic-object
|
|
1952
|
+
encode(regex, encode) {
|
|
1953
|
+
encode([ 'RegExp', regex.source, regex.flags ]);
|
|
1954
|
+
}
|
|
1955
|
+
}, { // Tag
|
|
1956
|
+
getTag(tag) {
|
|
1957
|
+
return tag.tag
|
|
1958
|
+
},
|
|
1959
|
+
encode(tag, encode) {
|
|
1960
|
+
encode(tag.value);
|
|
1961
|
+
}
|
|
1962
|
+
}, { // ArrayBuffer
|
|
1963
|
+
encode(arrayBuffer, encode, makeRoom) {
|
|
1964
|
+
writeBuffer(arrayBuffer, makeRoom);
|
|
1965
|
+
}
|
|
1966
|
+
}, { // Uint8Array
|
|
1967
|
+
getTag(typedArray) {
|
|
1968
|
+
if (typedArray.constructor === Uint8Array) {
|
|
1969
|
+
if (this.tagUint8Array || hasNodeBuffer && this.tagUint8Array !== false)
|
|
1970
|
+
return 64;
|
|
1971
|
+
} // else no tag
|
|
1972
|
+
},
|
|
1973
|
+
encode(typedArray, encode, makeRoom) {
|
|
1974
|
+
writeBuffer(typedArray, makeRoom);
|
|
1975
|
+
}
|
|
1976
|
+
},
|
|
1977
|
+
typedArrayEncoder(68, 1),
|
|
1978
|
+
typedArrayEncoder(69, 2),
|
|
1979
|
+
typedArrayEncoder(70, 4),
|
|
1980
|
+
typedArrayEncoder(71, 8),
|
|
1981
|
+
typedArrayEncoder(72, 1),
|
|
1982
|
+
typedArrayEncoder(77, 2),
|
|
1983
|
+
typedArrayEncoder(78, 4),
|
|
1984
|
+
typedArrayEncoder(79, 8),
|
|
1985
|
+
typedArrayEncoder(85, 4),
|
|
1986
|
+
typedArrayEncoder(86, 8),
|
|
1987
|
+
{
|
|
1988
|
+
encode(sharedData, encode) { // write SharedData
|
|
1989
|
+
let packedValues = sharedData.packedValues || [];
|
|
1990
|
+
let sharedStructures = sharedData.structures || [];
|
|
1991
|
+
if (packedValues.values.length > 0) {
|
|
1992
|
+
target[position$1++] = 0xd8; // one-byte tag
|
|
1993
|
+
target[position$1++] = 51; // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
|
|
1994
|
+
writeArrayHeader(4);
|
|
1995
|
+
let valuesArray = packedValues.values;
|
|
1996
|
+
encode(valuesArray);
|
|
1997
|
+
writeArrayHeader(0); // prefixes
|
|
1998
|
+
writeArrayHeader(0); // suffixes
|
|
1999
|
+
packedObjectMap = Object.create(sharedPackedObjectMap || null);
|
|
2000
|
+
for (let i = 0, l = valuesArray.length; i < l; i++) {
|
|
2001
|
+
packedObjectMap[valuesArray[i]] = i;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
if (sharedStructures) {
|
|
2005
|
+
targetView.setUint32(position$1, 0xd9dffe00);
|
|
2006
|
+
position$1 += 3;
|
|
2007
|
+
let definitions = sharedStructures.slice(0);
|
|
2008
|
+
definitions.unshift(0xe000);
|
|
2009
|
+
definitions.push(new Tag(sharedData.version, 0x53687264));
|
|
2010
|
+
encode(definitions);
|
|
2011
|
+
} else
|
|
2012
|
+
encode(new Tag(sharedData.version, 0x53687264));
|
|
2013
|
+
}
|
|
2014
|
+
}];
|
|
2015
|
+
function typedArrayEncoder(tag, size) {
|
|
2016
|
+
if (!isLittleEndianMachine$1 && size > 1)
|
|
2017
|
+
tag -= 4; // the big endian equivalents are 4 less
|
|
2018
|
+
return {
|
|
2019
|
+
tag: tag,
|
|
2020
|
+
encode: function writeExtBuffer(typedArray, encode) {
|
|
2021
|
+
let length = typedArray.byteLength;
|
|
2022
|
+
let offset = typedArray.byteOffset || 0;
|
|
2023
|
+
let buffer = typedArray.buffer || typedArray;
|
|
2024
|
+
encode(hasNodeBuffer ? Buffer.from(buffer, offset, length) :
|
|
2025
|
+
new Uint8Array(buffer, offset, length));
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
function writeBuffer(buffer, makeRoom) {
|
|
2030
|
+
let length = buffer.byteLength;
|
|
2031
|
+
if (length < 0x18) {
|
|
2032
|
+
target[position$1++] = 0x40 + length;
|
|
2033
|
+
} else if (length < 0x100) {
|
|
2034
|
+
target[position$1++] = 0x58;
|
|
2035
|
+
target[position$1++] = length;
|
|
2036
|
+
} else if (length < 0x10000) {
|
|
2037
|
+
target[position$1++] = 0x59;
|
|
2038
|
+
target[position$1++] = length >> 8;
|
|
2039
|
+
target[position$1++] = length & 0xff;
|
|
2040
|
+
} else {
|
|
2041
|
+
target[position$1++] = 0x5a;
|
|
2042
|
+
targetView.setUint32(position$1, length);
|
|
2043
|
+
position$1 += 4;
|
|
2044
|
+
}
|
|
2045
|
+
if (position$1 + length >= target.length) {
|
|
2046
|
+
makeRoom(position$1 + length);
|
|
2047
|
+
}
|
|
2048
|
+
// if it is already a typed array (has an ArrayBuffer), use that, but if it is an ArrayBuffer itself,
|
|
2049
|
+
// must wrap it to set it.
|
|
2050
|
+
target.set(buffer.buffer ? buffer : new Uint8Array(buffer), position$1);
|
|
2051
|
+
position$1 += length;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
function insertIds(serialized, idsToInsert) {
|
|
2055
|
+
// insert the ids that need to be referenced for structured clones
|
|
2056
|
+
let nextId;
|
|
2057
|
+
let distanceToMove = idsToInsert.length * 2;
|
|
2058
|
+
let lastEnd = serialized.length - distanceToMove;
|
|
2059
|
+
idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1);
|
|
2060
|
+
for (let id = 0; id < idsToInsert.length; id++) {
|
|
2061
|
+
let referee = idsToInsert[id];
|
|
2062
|
+
referee.id = id;
|
|
2063
|
+
for (let position of referee.references) {
|
|
2064
|
+
serialized[position++] = id >> 8;
|
|
2065
|
+
serialized[position] = id & 0xff;
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
while (nextId = idsToInsert.pop()) {
|
|
2069
|
+
let offset = nextId.offset;
|
|
2070
|
+
serialized.copyWithin(offset + distanceToMove, offset, lastEnd);
|
|
2071
|
+
distanceToMove -= 2;
|
|
2072
|
+
let position = offset + distanceToMove;
|
|
2073
|
+
serialized[position++] = 0xd8;
|
|
2074
|
+
serialized[position++] = 28; // http://cbor.schmorp.de/value-sharing
|
|
2075
|
+
lastEnd = offset;
|
|
2076
|
+
}
|
|
2077
|
+
return serialized
|
|
2078
|
+
}
|
|
2079
|
+
function writeBundles(start, encode) {
|
|
2080
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start + 1); // the offset to bundle
|
|
2081
|
+
let writeStrings = bundledStrings$1;
|
|
2082
|
+
bundledStrings$1 = null;
|
|
2083
|
+
encode(writeStrings[0]);
|
|
2084
|
+
encode(writeStrings[1]);
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
function addExtension$1(extension) {
|
|
2088
|
+
if (extension.Class) {
|
|
2089
|
+
if (!extension.encode)
|
|
2090
|
+
throw new Error('Extension has no encode function')
|
|
2091
|
+
extensionClasses.unshift(extension.Class);
|
|
2092
|
+
extensions.unshift(extension);
|
|
2093
|
+
}
|
|
2094
|
+
addExtension(extension);
|
|
2095
|
+
}
|
|
2096
|
+
let defaultEncoder = new Encoder({ useRecords: false });
|
|
2097
|
+
const encode = defaultEncoder.encode;
|
|
2098
|
+
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
2099
|
+
const REUSE_BUFFER_MODE = 512;
|
|
2074
2100
|
const RESET_BUFFER_MODE = 1024;
|
|
2075
2101
|
|
|
2076
|
-
/**
|
|
2077
|
-
* Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
|
|
2078
|
-
* If the argument is only Async Iterable, the return value will be an Async Iterable.
|
|
2079
|
-
* @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
|
|
2080
|
-
* @param {options} [options] - cbor-x Encoder options
|
|
2081
|
-
* @returns {IterableIterator|Promise.<AsyncIterableIterator>}
|
|
2082
|
-
*/
|
|
2083
|
-
function encodeIter (objectIterator, options = {}) {
|
|
2084
|
-
if (!objectIterator || typeof objectIterator !== 'object') {
|
|
2085
|
-
throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
|
|
2086
|
-
} else if (typeof objectIterator[Symbol.iterator] === 'function') {
|
|
2087
|
-
return encodeIterSync(objectIterator, options)
|
|
2088
|
-
} else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
|
|
2089
|
-
return encodeIterAsync(objectIterator, options)
|
|
2090
|
-
} else {
|
|
2091
|
-
throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
function * encodeIterSync (objectIterator, options) {
|
|
2096
|
-
const encoder = new Encoder(options);
|
|
2097
|
-
for (const value of objectIterator) {
|
|
2098
|
-
yield encoder.encode(value);
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
|
|
2102
|
-
async function * encodeIterAsync (objectIterator, options) {
|
|
2103
|
-
const encoder = new Encoder(options);
|
|
2104
|
-
for await (const value of objectIterator) {
|
|
2105
|
-
yield encoder.encode(value);
|
|
2106
|
-
}
|
|
2107
|
-
}
|
|
2108
|
-
|
|
2109
|
-
/**
|
|
2110
|
-
* Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
|
|
2111
|
-
* Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
|
|
2112
|
-
* @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
|
|
2113
|
-
* @param {object} [options] - Decoder options
|
|
2114
|
-
* @returns {IterableIterator|Promise.<AsyncIterableIterator}
|
|
2115
|
-
*/
|
|
2116
|
-
function decodeIter (bufferIterator, options = {}) {
|
|
2117
|
-
if (!bufferIterator || typeof bufferIterator !== 'object') {
|
|
2118
|
-
throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
const decoder = new Decoder(options);
|
|
2122
|
-
let incomplete;
|
|
2123
|
-
const parser = (chunk) => {
|
|
2124
|
-
let yields;
|
|
2125
|
-
// if there's incomplete data from previous chunk, concatinate and try again
|
|
2126
|
-
if (incomplete) {
|
|
2127
|
-
chunk = Buffer.concat([incomplete, chunk]);
|
|
2128
|
-
incomplete = undefined;
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
try {
|
|
2132
|
-
yields = decoder.decodeMultiple(chunk);
|
|
2133
|
-
} catch (err) {
|
|
2134
|
-
if (err.incomplete) {
|
|
2135
|
-
incomplete = chunk.slice(err.lastPosition);
|
|
2136
|
-
yields = err.values;
|
|
2137
|
-
} else {
|
|
2138
|
-
throw err
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
return yields
|
|
2142
|
-
};
|
|
2143
|
-
|
|
2144
|
-
if (typeof bufferIterator[Symbol.iterator] === 'function') {
|
|
2145
|
-
return (function * iter () {
|
|
2146
|
-
for (const value of bufferIterator) {
|
|
2147
|
-
yield * parser(value);
|
|
2148
|
-
}
|
|
2149
|
-
})()
|
|
2150
|
-
} else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
|
|
2151
|
-
return (async function * iter () {
|
|
2152
|
-
for await (const value of bufferIterator) {
|
|
2153
|
-
yield * parser(value);
|
|
2154
|
-
}
|
|
2155
|
-
})()
|
|
2156
|
-
}
|
|
2102
|
+
/**
|
|
2103
|
+
* Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
|
|
2104
|
+
* If the argument is only Async Iterable, the return value will be an Async Iterable.
|
|
2105
|
+
* @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
|
|
2106
|
+
* @param {options} [options] - cbor-x Encoder options
|
|
2107
|
+
* @returns {IterableIterator|Promise.<AsyncIterableIterator>}
|
|
2108
|
+
*/
|
|
2109
|
+
function encodeIter (objectIterator, options = {}) {
|
|
2110
|
+
if (!objectIterator || typeof objectIterator !== 'object') {
|
|
2111
|
+
throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
|
|
2112
|
+
} else if (typeof objectIterator[Symbol.iterator] === 'function') {
|
|
2113
|
+
return encodeIterSync(objectIterator, options)
|
|
2114
|
+
} else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
|
|
2115
|
+
return encodeIterAsync(objectIterator, options)
|
|
2116
|
+
} else {
|
|
2117
|
+
throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
function * encodeIterSync (objectIterator, options) {
|
|
2122
|
+
const encoder = new Encoder(options);
|
|
2123
|
+
for (const value of objectIterator) {
|
|
2124
|
+
yield encoder.encode(value);
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
async function * encodeIterAsync (objectIterator, options) {
|
|
2129
|
+
const encoder = new Encoder(options);
|
|
2130
|
+
for await (const value of objectIterator) {
|
|
2131
|
+
yield encoder.encode(value);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
/**
|
|
2136
|
+
* Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
|
|
2137
|
+
* Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
|
|
2138
|
+
* @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
|
|
2139
|
+
* @param {object} [options] - Decoder options
|
|
2140
|
+
* @returns {IterableIterator|Promise.<AsyncIterableIterator}
|
|
2141
|
+
*/
|
|
2142
|
+
function decodeIter (bufferIterator, options = {}) {
|
|
2143
|
+
if (!bufferIterator || typeof bufferIterator !== 'object') {
|
|
2144
|
+
throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
const decoder = new Decoder(options);
|
|
2148
|
+
let incomplete;
|
|
2149
|
+
const parser = (chunk) => {
|
|
2150
|
+
let yields;
|
|
2151
|
+
// if there's incomplete data from previous chunk, concatinate and try again
|
|
2152
|
+
if (incomplete) {
|
|
2153
|
+
chunk = Buffer.concat([incomplete, chunk]);
|
|
2154
|
+
incomplete = undefined;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
try {
|
|
2158
|
+
yields = decoder.decodeMultiple(chunk);
|
|
2159
|
+
} catch (err) {
|
|
2160
|
+
if (err.incomplete) {
|
|
2161
|
+
incomplete = chunk.slice(err.lastPosition);
|
|
2162
|
+
yields = err.values;
|
|
2163
|
+
} else {
|
|
2164
|
+
throw err
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
return yields
|
|
2168
|
+
};
|
|
2169
|
+
|
|
2170
|
+
if (typeof bufferIterator[Symbol.iterator] === 'function') {
|
|
2171
|
+
return (function * iter () {
|
|
2172
|
+
for (const value of bufferIterator) {
|
|
2173
|
+
yield * parser(value);
|
|
2174
|
+
}
|
|
2175
|
+
})()
|
|
2176
|
+
} else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
|
|
2177
|
+
return (async function * iter () {
|
|
2178
|
+
for await (const value of bufferIterator) {
|
|
2179
|
+
yield * parser(value);
|
|
2180
|
+
}
|
|
2181
|
+
})()
|
|
2182
|
+
}
|
|
2157
2183
|
}
|
|
2158
2184
|
|
|
2159
2185
|
exports.ALWAYS = ALWAYS;
|