msgpackr 1.11.2 → 1.11.4
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/README.md +1 -0
- package/dist/index-no-eval.cjs +42 -21
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +42 -21
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +49 -24
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +105 -26
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +31 -17
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +1 -0
- package/index.d.ts +1 -0
- package/pack.js +11 -4
- package/package.json +5 -1
- package/struct.js +7 -3
- package/unpack.js +31 -17
package/README.md
CHANGED
|
@@ -193,6 +193,7 @@ The following options properties can be provided to the Packr or Unpackr constru
|
|
|
193
193
|
* `writeFunction` - This can be provided as function that will be called when a function is encountered. The function can throw an error, or return a value that will be encoded in place of the function. If not provided, a function will be encoded as undefined (similar to `JSON.stringify`).
|
|
194
194
|
* `mapAsEmptyObject` - Encodes JS `Map`s as empty objects (for back-compat with older libraries).
|
|
195
195
|
* `setAsEmptyObject` - Encodes JS `Set`s as empty objects (for back-compat with older libraries).
|
|
196
|
+
* `allowArraysInMapKeys` - Allows arrays to be used as keys in Maps, as long as all elements are strings, numbers, booleans, or bigints. When enabled, such arrays are flattened and converted to a string representation.
|
|
196
197
|
|
|
197
198
|
### 32-bit Float Options
|
|
198
199
|
By default all non-integer numbers are serialized as 64-bit float (double). This is fast, and ensures maximum precision. However, often real-world data doesn't not need 64-bits of precision, and using 32-bit encoding can be much more space efficient. There are several options that provide more efficient encodings. Using the decimal rounding options for encoding and decoding provides lossless storage of common decimal representations like 7.99, in more efficient 32-bit format (rather than 64-bit). The `useFloat32` property has several possible options, available from the module as constants:
|
package/dist/index-no-eval.cjs
CHANGED
|
@@ -916,7 +916,10 @@
|
|
|
916
916
|
if (typeof property === 'string') return property;
|
|
917
917
|
if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
|
|
918
918
|
if (property == null) return property + '';
|
|
919
|
-
|
|
919
|
+
if (currentUnpackr.allowArraysInMapKeys && Array.isArray(property) && property.flat().every(item => ['string', 'number', 'boolean', 'bigint'].includes(typeof item))) {
|
|
920
|
+
return property.flat().toString();
|
|
921
|
+
}
|
|
922
|
+
throw new Error(`Invalid property type for record: ${typeof property}`);
|
|
920
923
|
}
|
|
921
924
|
// the registration of the record definition extension (as "r")
|
|
922
925
|
const recordDefinition = (id, highByte) => {
|
|
@@ -966,20 +969,33 @@
|
|
|
966
969
|
referenceMap = new Map();
|
|
967
970
|
let token = src[position$1];
|
|
968
971
|
let target;
|
|
969
|
-
// TODO: handle
|
|
970
|
-
// ahead past references to record structure definitions
|
|
972
|
+
// TODO: handle any other types that can cycle and make the code more robust if there are other extensions
|
|
971
973
|
if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
|
|
972
974
|
target = [];
|
|
975
|
+
else if (token >= 0x80 && token < 0x90 || token == 0xde || token == 0xdf)
|
|
976
|
+
target = new Map();
|
|
977
|
+
else if ((token >= 0xc7 && token <= 0xc9 || token >= 0xd4 && token <= 0xd8) && src[position$1 + 1] === 0x73)
|
|
978
|
+
target = new Set();
|
|
973
979
|
else
|
|
974
980
|
target = {};
|
|
975
981
|
|
|
976
982
|
let refEntry = { target }; // a placeholder object
|
|
977
983
|
referenceMap.set(id, refEntry);
|
|
978
984
|
let targetProperties = read(); // read the next value as the target object to id
|
|
979
|
-
if (refEntry.used)
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
985
|
+
if (!refEntry.used) {
|
|
986
|
+
// no cycle, can just use the returned read object
|
|
987
|
+
return refEntry.target = targetProperties // replace the placeholder with the real one
|
|
988
|
+
} else {
|
|
989
|
+
// there is a cycle, so we have to assign properties to original target
|
|
990
|
+
Object.assign(target, targetProperties);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// copy over map/set entries if we're able to
|
|
994
|
+
if (target instanceof Map)
|
|
995
|
+
for (let [k, v] of targetProperties.entries()) target.set(k, v);
|
|
996
|
+
if (target instanceof Set)
|
|
997
|
+
for (let i of Array.from(targetProperties)) target.add(i);
|
|
998
|
+
return target
|
|
983
999
|
};
|
|
984
1000
|
|
|
985
1001
|
currentExtensions[0x70] = (data) => {
|
|
@@ -998,18 +1014,16 @@
|
|
|
998
1014
|
let glbl = typeof globalThis === 'object' ? globalThis : window;
|
|
999
1015
|
currentExtensions[0x74] = (data) => {
|
|
1000
1016
|
let typeCode = data[0];
|
|
1017
|
+
// we always have to slice to get a new ArrayBuffer that is aligned
|
|
1018
|
+
let buffer = Uint8Array.prototype.slice.call(data, 1).buffer;
|
|
1019
|
+
|
|
1001
1020
|
let typedArrayName = typedArrays[typeCode];
|
|
1002
1021
|
if (!typedArrayName) {
|
|
1003
|
-
if (typeCode === 16)
|
|
1004
|
-
|
|
1005
|
-
let u8 = new Uint8Array(ab);
|
|
1006
|
-
u8.set(data.subarray(1));
|
|
1007
|
-
return ab;
|
|
1008
|
-
}
|
|
1022
|
+
if (typeCode === 16) return buffer
|
|
1023
|
+
if (typeCode === 17) return new DataView(buffer)
|
|
1009
1024
|
throw new Error('Could not find typed array for code ' + typeCode)
|
|
1010
1025
|
}
|
|
1011
|
-
|
|
1012
|
-
return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
1026
|
+
return new glbl[typedArrayName](buffer)
|
|
1013
1027
|
};
|
|
1014
1028
|
currentExtensions[0x78] = () => {
|
|
1015
1029
|
let data = read();
|
|
@@ -1037,13 +1051,13 @@
|
|
|
1037
1051
|
return new Date(
|
|
1038
1052
|
((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
|
|
1039
1053
|
((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
|
|
1040
|
-
else if (data.length == 12)
|
|
1054
|
+
else if (data.length == 12)
|
|
1041
1055
|
return new Date(
|
|
1042
1056
|
((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
|
|
1043
1057
|
(((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
|
|
1044
1058
|
else
|
|
1045
1059
|
return new Date('invalid')
|
|
1046
|
-
};
|
|
1060
|
+
};
|
|
1047
1061
|
// registration of bulk record definition?
|
|
1048
1062
|
// currentExtensions[0x52] = () =>
|
|
1049
1063
|
|
|
@@ -1637,11 +1651,11 @@
|
|
|
1637
1651
|
} else if (type === 'boolean') {
|
|
1638
1652
|
target[position++] = value ? 0xc3 : 0xc2;
|
|
1639
1653
|
} else if (type === 'bigint') {
|
|
1640
|
-
if (value <
|
|
1654
|
+
if (value < 0x8000000000000000 && value >= -0x8000000000000000) {
|
|
1641
1655
|
// use a signed int as long as it fits
|
|
1642
1656
|
target[position++] = 0xd3;
|
|
1643
1657
|
targetView.setBigInt64(position, value);
|
|
1644
|
-
} else if (value <
|
|
1658
|
+
} else if (value < 0x10000000000000000 && value > 0) {
|
|
1645
1659
|
// if we can fit an unsigned int, use that
|
|
1646
1660
|
target[position++] = 0xcf;
|
|
1647
1661
|
targetView.setBigUint64(position, value);
|
|
@@ -1652,7 +1666,7 @@
|
|
|
1652
1666
|
targetView.setFloat64(position, Number(value));
|
|
1653
1667
|
} else if (this.largeBigIntToString) {
|
|
1654
1668
|
return pack(value.toString());
|
|
1655
|
-
} else if (this.useBigIntExtension && value < BigInt(2)**BigInt(1023) && value > -(BigInt(2)**BigInt(1023))) {
|
|
1669
|
+
} else if ((this.useBigIntExtension || this.moreTypes) && value < BigInt(2)**BigInt(1023) && value > -(BigInt(2)**BigInt(1023))) {
|
|
1656
1670
|
target[position++] = 0xc7;
|
|
1657
1671
|
position++;
|
|
1658
1672
|
target[position++] = 0x42; // "B" for BigInt
|
|
@@ -1971,7 +1985,7 @@
|
|
|
1971
1985
|
}
|
|
1972
1986
|
}
|
|
1973
1987
|
|
|
1974
|
-
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
|
|
1988
|
+
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, DataView, C1Type ];
|
|
1975
1989
|
extensions = [{
|
|
1976
1990
|
pack(date, allocateForWrite, pack) {
|
|
1977
1991
|
let seconds = date.getTime() / 1000;
|
|
@@ -2058,6 +2072,13 @@
|
|
|
2058
2072
|
else
|
|
2059
2073
|
writeBuffer(typedArray, allocateForWrite);
|
|
2060
2074
|
}
|
|
2075
|
+
}, {
|
|
2076
|
+
pack(arrayBuffer, allocateForWrite) {
|
|
2077
|
+
if (this.moreTypes)
|
|
2078
|
+
writeExtBuffer(arrayBuffer, 0x11, allocateForWrite);
|
|
2079
|
+
else
|
|
2080
|
+
writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
|
|
2081
|
+
}
|
|
2061
2082
|
}, {
|
|
2062
2083
|
pack(c1, allocateForWrite) { // specific 0xC1 object
|
|
2063
2084
|
let { target, position} = allocateForWrite(1);
|