msgpackr 1.4.3 → 1.4.7
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 +3 -1
- package/SECURITY.md +11 -0
- package/dist/index.js +22 -5
- package/dist/index.min.js +22 -21
- package/dist/node.cjs +21 -5
- package/dist/test.js +13 -0
- package/index.d.ts +1 -1
- package/index.js +2 -2
- package/node-index.js +1 -1
- package/pack.js +11 -3
- package/package.json +5 -2
- package/tests/test-compatibility.cjs +18 -2
- package/tests/test.js +13 -0
- package/unpack.d.ts +5 -2
- package/unpack.js +7 -0
package/README.md
CHANGED
|
@@ -176,10 +176,12 @@ const { ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
|
176
176
|
|
|
177
177
|
* `ALWAYS` (1) - Always will encode non-integers (absolute less than 2147483648) as 32-bit float.
|
|
178
178
|
* `DECIMAL_ROUND` (3) - Always will encode non-integers as 32-bit float, and when decoding 32-bit float, round to the significant decimal digits (usually 7, but 6 or 8 digits for some ranges).
|
|
179
|
-
* `DECIMAL_FIT` (4) - Only encode non-integers as 32-bit float if all significant digits (usually up to 7) can be
|
|
179
|
+
* `DECIMAL_FIT` (4) - Only encode non-integers as 32-bit float if all significant digits (usually up to 7) can be unambiguously encoded as a 32-bit float, and decode/unpack with decimal rounding (same as above). This will ensure round-trip encoding/decoding without loss in precision and uses 32-bit when possible.
|
|
180
180
|
|
|
181
181
|
Note, that the performance is decreased with decimal rounding by about 20-25%, although if only 5% of your values are floating point, that will only have about a 1% impact overall.
|
|
182
182
|
|
|
183
|
+
In addition, msgpackr exports a `roundFloat32(number)` function that can be used to round floating point numbers to the maximum significant decimal digits that can be stored in 32-bit float, just as DECIMAL_ROUND does when decoding. This can be useful for determining how a number will be decoded prior to encoding it.
|
|
184
|
+
|
|
183
185
|
## Performance
|
|
184
186
|
Msgpackr is fast. Really fast. Here is comparison with the next fastest JS projects using the benchmark tool from `msgpack-lite` (and the sample data is from some clinical research data we use that has a good mix of different value types and structures). It also includes comparison to V8 native JSON functionality, and JavaScript Avro (`avsc`, a very optimized Avro implementation):
|
|
185
187
|
|
package/SECURITY.md
ADDED
package/dist/index.js
CHANGED
|
@@ -917,7 +917,14 @@
|
|
|
917
917
|
ALWAYS: 1,
|
|
918
918
|
DECIMAL_ROUND: 3,
|
|
919
919
|
DECIMAL_FIT: 4
|
|
920
|
-
};
|
|
920
|
+
};
|
|
921
|
+
let f32Array = new Float32Array(1);
|
|
922
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
923
|
+
function roundFloat32(float32Number) {
|
|
924
|
+
f32Array[0] = float32Number;
|
|
925
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
926
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
927
|
+
}
|
|
921
928
|
|
|
922
929
|
let textEncoder;
|
|
923
930
|
try {
|
|
@@ -976,7 +983,7 @@
|
|
|
976
983
|
let transitionsCount = 0;
|
|
977
984
|
let serializationsSinceTransitionRebuild = 0;
|
|
978
985
|
|
|
979
|
-
this.pack = this.encode = function(value) {
|
|
986
|
+
this.pack = this.encode = function(value, encodeOptions) {
|
|
980
987
|
if (!target) {
|
|
981
988
|
target = new ByteArrayAllocate(8192);
|
|
982
989
|
targetView = new DataView(target.buffer, 0, 8192);
|
|
@@ -1041,6 +1048,11 @@
|
|
|
1041
1048
|
referenceMap = null;
|
|
1042
1049
|
return serialized
|
|
1043
1050
|
}
|
|
1051
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
1052
|
+
target.start = start;
|
|
1053
|
+
target.end = position$1;
|
|
1054
|
+
return target
|
|
1055
|
+
}
|
|
1044
1056
|
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1045
1057
|
} finally {
|
|
1046
1058
|
if (sharedStructures) {
|
|
@@ -1064,13 +1076,15 @@
|
|
|
1064
1076
|
if (sharedStructures.length > sharedLength) {
|
|
1065
1077
|
sharedStructures = sharedStructures.slice(0, sharedLength);
|
|
1066
1078
|
}
|
|
1067
|
-
|
|
1079
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1080
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
1068
1081
|
if (packr.saveStructures(sharedStructures, lastSharedStructuresLength) === false) {
|
|
1069
1082
|
// get updated structures and try again if the update failed
|
|
1070
1083
|
packr._mergeStructures(packr.getStructures());
|
|
1071
1084
|
return packr.pack(value)
|
|
1072
1085
|
}
|
|
1073
1086
|
lastSharedStructuresLength = sharedLength;
|
|
1087
|
+
return returnBuffer
|
|
1074
1088
|
}
|
|
1075
1089
|
}
|
|
1076
1090
|
}
|
|
@@ -1191,7 +1205,7 @@
|
|
|
1191
1205
|
targetView.setFloat32(position$1, value);
|
|
1192
1206
|
let xShifted;
|
|
1193
1207
|
if (useFloat32 < 4 ||
|
|
1194
|
-
|
|
1208
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1195
1209
|
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1196
1210
|
position$1 += 4;
|
|
1197
1211
|
return
|
|
@@ -1726,7 +1740,8 @@
|
|
|
1726
1740
|
const pack = defaultPackr.pack;
|
|
1727
1741
|
const encode = defaultPackr.pack;
|
|
1728
1742
|
const Encoder = Packr;
|
|
1729
|
-
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1743
|
+
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1744
|
+
const REUSE_BUFFER_MODE = 1000;
|
|
1730
1745
|
|
|
1731
1746
|
/**
|
|
1732
1747
|
* Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
|
|
@@ -1825,6 +1840,7 @@
|
|
|
1825
1840
|
exports.FLOAT32_OPTIONS = FLOAT32_OPTIONS;
|
|
1826
1841
|
exports.NEVER = NEVER;
|
|
1827
1842
|
exports.Packr = Packr;
|
|
1843
|
+
exports.REUSE_BUFFER_MODE = REUSE_BUFFER_MODE;
|
|
1828
1844
|
exports.Unpackr = Unpackr;
|
|
1829
1845
|
exports.addExtension = addExtension$1;
|
|
1830
1846
|
exports.clearSource = clearSource;
|
|
@@ -1834,6 +1850,7 @@
|
|
|
1834
1850
|
exports.encodeIter = encodeIter;
|
|
1835
1851
|
exports.mapsAsObjects = mapsAsObjects;
|
|
1836
1852
|
exports.pack = pack;
|
|
1853
|
+
exports.roundFloat32 = roundFloat32;
|
|
1837
1854
|
exports.unpack = unpack;
|
|
1838
1855
|
exports.unpackMultiple = unpackMultiple;
|
|
1839
1856
|
exports.useRecords = useRecords;
|
package/dist/index.min.js
CHANGED
|
@@ -28,7 +28,7 @@ function p(a){let b=B,c=G,d=I,e=J,f=D,g=E,h=new Uint8Array(A.slice(0,B)),i=C,j=C
|
|
|
28
28
|
e[f++]=201,g.setUint32(f,d+1),f+=4}// "t" for typed array
|
|
29
29
|
e[f++]=116,e[f++]=b,e.set(new Uint8Array(a.buffer,a.byteOffset,a.byteLength),f)}function t(a,b){let c=a.byteLength;var d,e;if(256>c){var{target:d,position:e}=b(c+2);d[e++]=196,d[e++]=c}else if(65536>c){var{target:d,position:e}=b(c+3);d[e++]=197,d[e++]=c>>8,d[e++]=255&c}else{var{target:d,position:e,targetView:f}=b(c+5);d[e++]=198,f.setUint32(e,c),e+=4}d.set(a,e)}function u(a,b,c,d){let e=a.length;return 1===e?b[c++]=212:2===e?b[c++]=213:4===e?b[c++]=214:8===e?b[c++]=215:16===e?b[c++]=216:256>e?(b[c++]=199,b[c++]=e):65536>e?(b[c++]=200,b[c++]=e>>8,b[c++]=255&e):(b[c++]=201,b[c++]=e>>24,b[c++]=255&e>>16,b[c++]=255&e>>8,b[c++]=255&e),b[c++]=d,b.set(a,c),c+=e,c}function v(a,b){// insert the ids that need to be referenced for structured clones
|
|
30
30
|
let c,d=6*b.length,e=a.length-d;for(b.sort((c,a)=>c.offset>a.offset?1:-1);c=b.pop();){let b=c.offset,f=c.id;a.copyWithin(b+d,b,e),d-=6;let g=b+d;// 'i'
|
|
31
|
-
a[g++]=214,a[g++]=105,a[g++]=f>>24,a[g++]=255&f>>16,a[g++]=255&f>>8,a[g++]=255&f,e=b}return a}function w(a){if(a.Class){if(!a.pack&&!a.write)throw new Error("Extension has no pack or write function");if(a.pack&&!a.type)throw new Error("Extension has no type (numeric code to identify the extension)");
|
|
31
|
+
a[g++]=214,a[g++]=105,a[g++]=f>>24,a[g++]=255&f>>16,a[g++]=255&f>>8,a[g++]=255&f,e=b}return a}function w(a){if(a.Class){if(!a.pack&&!a.write)throw new Error("Extension has no pack or write function");if(a.pack&&!a.type)throw new Error("Extension has no type (numeric code to identify the extension)");ja.unshift(a.Class),ia.unshift(a)}r(a)}function*x(a,b){const c=new ta(b);for(const d of a)yield c.pack(d)}async function*y(a,b){const c=new ta(b);for await(const d of a)yield c.pack(d)}/**
|
|
32
32
|
* Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
|
|
33
33
|
* Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
|
|
34
34
|
* @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
|
|
@@ -44,17 +44,18 @@ let a=F.getUint32(G-4),b=E.get(a);return b.used=!0,b.target},K[115]=()=>new Set(
|
|
|
44
44
|
return new Z[c](Uint8Array.prototype.slice.call(a,1).buffer)},K[120]=()=>{let a=e();return new RegExp(a[0],a[1])},K[255]=a=>{// 32-bit date extension
|
|
45
45
|
if(4==a.length)return new Date(1e3*(16777216*a[0]+(a[1]<<16)+(a[2]<<8)+a[3]));if(8==a.length)return new Date(((a[0]<<22)+(a[1]<<14)+(a[2]<<6)+(a[3]>>2))/1e6+1e3*(4294967296*(3&a[3])+16777216*a[4]+(a[5]<<16)+(a[6]<<8)+a[7]));if(12==a.length)// TODO: Implement support for negative
|
|
46
46
|
return new Date(((a[0]<<24)+(a[1]<<16)+(a[2]<<8)+a[3])/1e6+1e3*((128&a[4]?-281474976710656:0)+1099511627776*a[6]+4294967296*a[7]+16777216*a[8]+(a[9]<<16)+(a[10]<<8)+a[11]));throw new Error("Invalid timestamp length")};const _=Array(147);// this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
47
|
-
for(let c=0;256>c;c++)_[c]=+("1e"+b(45.15-.30103*c));var aa=new P({useRecords:!1});const ba=aa.unpack,ca=aa.unpackMultiple,da=aa.unpack,ea={NEVER:0,ALWAYS:1,DECIMAL_ROUND:3,DECIMAL_FIT:4};let fa;try{fa=new TextEncoder}catch(a){}let
|
|
48
|
-
let n=32<l||64<m+l,o=l+64,p=l+m+64;if(8256<p)throw new Error("Maximum maxSharedStructure + maxOwnStructure is 8192");let q=[],r=0,s=0;this.pack=this.encode=function(a){if(
|
|
49
|
-
throw new Error("Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to "+c.sharedLength);if(!c.transitions){c.transitions=Object.create(null);for(let b,d=0;d<a;d++){if(b=c[d],!b)continue;let a,e=c.transitions;for(let c,d=0,f=b.length;d<f;d++)c=b[d],a=e[c],a||(a=e[c]=Object.create(null)),e=a;e[
|
|
50
|
-
if(t(a),i.offset=
|
|
51
|
-
}finally{if(c){if(10>s&&s++,1e4<r)c.transitions=null,s=0,r=0,0<q.length&&(q=[]);else if(0<q.length&&!j){for(let a=0,b=q.length;a<b;a++)q[a][
|
|
52
|
-
(c=a*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
let
|
|
47
|
+
for(let c=0;256>c;c++)_[c]=+("1e"+b(45.15-.30103*c));var aa=new P({useRecords:!1});const ba=aa.unpack,ca=aa.unpackMultiple,da=aa.unpack,ea={NEVER:0,ALWAYS:1,DECIMAL_ROUND:3,DECIMAL_FIT:4};let fa,ga=new Float32Array(1),ha=new Uint8Array(ga.buffer,0,4);try{fa=new TextEncoder}catch(a){}let ia,ja;const ka="undefined"!=typeof Buffer,la=ka?Buffer.allocUnsafeSlow:Uint8Array,ma=ka?Buffer:Uint8Array,na=ka?4294967296:2144337920;let oa,pa,qa,ra=0;const sa=Symbol("record-id");class ta extends P{constructor(a){super(a),this.offset=0;let b,c,d,e,f,g=0,h=ma.prototype.utf8Write?function(a,b,c){return oa.utf8Write(a,b,c)}:!!(fa&&fa.encodeInto)&&function(a,b){return fa.encodeInto(a,oa.subarray(b)).written},i=this;a||(a={});let j=a&&a.sequential,k=a.structures||a.saveStructures,l=a.maxSharedStructures;if(null==l&&(l=k?32:0),8160<l)throw new Error("Maximum maxSharedStructure is 8160");let m=a.maxOwnStructures;null==m&&(m=k?32:64),j&&!a.saveStructures&&(this.structures=[]);// two byte record ids for shared structures
|
|
48
|
+
let n=32<l||64<m+l,o=l+64,p=l+m+64;if(8256<p)throw new Error("Maximum maxSharedStructure + maxOwnStructure is 8192");let q=[],r=0,s=0;this.pack=this.encode=function(a,h){if(oa||(oa=new la(8192),pa=new DataView(oa.buffer,0,8192),ra=0),qa=oa.length-10,2048>qa-ra?(oa=new la(oa.length),pa=new DataView(oa.buffer,0,oa.length),qa=oa.length-10,ra=0):ra=2147483640&ra+7,b=ra,f=i.structuredClone?new Map:null,c=i.structures,c){c.uninitialized&&(c=i._mergeStructures(i.getStructures()));let a=c.sharedLength||0;if(a>l)//if (maxSharedStructures <= 32 && sharedStructures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
|
|
49
|
+
throw new Error("Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to "+c.sharedLength);if(!c.transitions){c.transitions=Object.create(null);for(let b,d=0;d<a;d++){if(b=c[d],!b)continue;let a,e=c.transitions;for(let c,d=0,f=b.length;d<f;d++)c=b[d],a=e[c],a||(a=e[c]=Object.create(null)),e=a;e[sa]=d+64}g=a}j||(c.nextId=a+64)}d&&(d=!1),e=c||[];try{// update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
50
|
+
if(t(a),i.offset=ra,f&&f.idsToInsert){ra+=6*f.idsToInsert.length,ra>qa&&x(ra),i.offset=ra;let a=v(oa.subarray(b,ra),f.idsToInsert);return f=null,a}return h===Ba?(oa.start=b,oa.end=ra,oa):oa.subarray(b,ra);// position can change if we call pack again in saveStructures, so we get the buffer now
|
|
51
|
+
}finally{if(c){if(10>s&&s++,1e4<r)c.transitions=null,s=0,r=0,0<q.length&&(q=[]);else if(0<q.length&&!j){for(let a=0,b=q.length;a<b;a++)q[a][sa]=0;q=[]}if(d&&i.saveStructures){let d=c.sharedLength||l;c.length>d&&(c=c.slice(0,d));// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
52
|
+
let e=oa.subarray(b,ra);return!1===i.saveStructures(c,g)?(i._mergeStructures(i.getStructures()),i.pack(a)):(g=d,e)}}}};const t=a=>{ra>qa&&(oa=x(ra));var c,d=typeof a;if("string"==d){let b,d=a.length;b=32>d?1:256>d?2:65536>d?3:5;let e=3*d;if(ra+e>qa&&(oa=x(ra+e)),64>d||!h){let e,f,g,h=ra+b;for(e=0;e<d;e++)f=a.charCodeAt(e),128>f?oa[h++]=f:2048>f?(oa[h++]=192|f>>6,oa[h++]=128|63&f):55296==(64512&f)&&56320==(64512&(g=a.charCodeAt(e+1)))?(f=65536+((1023&f)<<10)+(1023&g),e++,oa[h++]=240|f>>18,oa[h++]=128|63&f>>12,oa[h++]=128|63&f>>6,oa[h++]=128|63&f):(oa[h++]=224|f>>12,oa[h++]=128|63&f>>6,oa[h++]=128|63&f);c=h-ra-b}else c=h(a,ra+b,e);32>c?oa[ra++]=160|c:256>c?(2>b&&oa.copyWithin(ra+2,ra+1,ra+1+c),oa[ra++]=217,oa[ra++]=c):65536>c?(3>b&&oa.copyWithin(ra+3,ra+2,ra+2+c),oa[ra++]=218,oa[ra++]=c>>8,oa[ra++]=255&c):(5>b&&oa.copyWithin(ra+5,ra+3,ra+3+c),oa[ra++]=219,pa.setUint32(ra,c),ra+=4),ra+=c}else if("number"===d){if(a>>>0===a)64>a?oa[ra++]=a:256>a?(oa[ra++]=204,oa[ra++]=a):65536>a?(oa[ra++]=205,oa[ra++]=a>>8,oa[ra++]=255&a):(oa[ra++]=206,pa.setUint32(ra,a),ra+=4);else if(a>>0===a)-32<=a?oa[ra++]=256+a:-128<=a?(oa[ra++]=208,oa[ra++]=a+256):-32768<=a?(oa[ra++]=209,pa.setInt16(ra,a),ra+=2):(oa[ra++]=210,pa.setInt32(ra,a),ra+=4);else{let b;if(0<(b=this.useFloat32)&&4294967296>a&&-2147483648<=a){oa[ra++]=202,pa.setFloat32(ra,a);let c;if(4>b||// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
53
|
+
(c=a*_[(127&oa[ra])<<1|oa[ra+1]>>7])>>0===c)return void(ra+=4);// move back into position for writing a double
|
|
54
|
+
ra--}oa[ra++]=203,pa.setFloat64(ra,a),ra+=8}}else if("object"===d){if(!a)oa[ra++]=192;else{if(f){let c=f.get(a);if(c){if(!c.id){let a=f.idsToInsert||(f.idsToInsert=[]);c.id=a.push(c)}return oa[ra++]=214,oa[ra++]=112,pa.setUint32(ra,c.id),void(ra+=4)}f.set(a,{offset:ra-b})}let d=a.constructor;if(d===Object)w(a,!0);else if(d===Array){c=a.length,16>c?oa[ra++]=144|c:65536>c?(oa[ra++]=220,oa[ra++]=c>>8,oa[ra++]=255&c):(oa[ra++]=221,pa.setUint32(ra,c),ra+=4);for(let b=0;b<c;b++)t(a[b])}else if(d===Map){c=a.size,16>c?oa[ra++]=128|c:65536>c?(oa[ra++]=222,oa[ra++]=c>>8,oa[ra++]=255&c):(oa[ra++]=223,pa.setUint32(ra,c),ra+=4);for(let[b,c]of a)t(b),t(c)}else{for(let b,c=0,d=ia.length;c<d;c++)if(b=ja[c],a instanceof b){let b=ia[c];if(b.write)return b.type&&(oa[ra++]=212,oa[ra++]=b.type,oa[ra++]=0),void t(b.write.call(this,a));let d=oa,e=pa,f=ra;oa=null;let g;try{g=b.pack.call(this,a,a=>(oa=d,d=null,ra+=a,ra>qa&&x(ra),{target:oa,targetView:pa,position:ra-a}),t)}finally{d&&(oa=d,pa=e,ra=f,qa=oa.length-10)}return void(g&&(g.length+ra>qa&&x(g.length+ra),ra=u(g,oa,ra,b.type)))}// no extension found, write as object
|
|
55
|
+
w(a,!a.hasOwnProperty)}}}else if("boolean"===d)oa[ra++]=a?195:194;else if("bigint"===d){if(a<BigInt(1)<<BigInt(63)&&a>=-(BigInt(1)<<BigInt(63)))oa[ra++]=211,pa.setBigInt64(ra,a);else if(a<BigInt(1)<<BigInt(64)&&0<a)oa[ra++]=207,pa.setBigUint64(ra,a);else// overflow
|
|
56
|
+
if(this.largeBigIntToFloat)oa[ra++]=203,pa.setFloat64(ra,+a);else throw new RangeError(a+" was too large to fit in MessagePack 64-bit integer format, set largeBigIntToFloat to convert to float-64");ra+=8}else if("undefined"===d)this.encodeUndefinedAsNil?oa[ra++]=192:(oa[ra++]=212,oa[ra++]=0,oa[ra++]=0);else if("function"===d)t(this.writeFunction&&this.writeFunction());else throw new Error("Unknown type: "+d)},w=!1===this.useRecords?this.variableMapSize?a=>{// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
57
|
+
let b=Object.keys(a),c=b.length;16>c?oa[ra++]=128|c:65536>c?(oa[ra++]=222,oa[ra++]=c>>8,oa[ra++]=255&c):(oa[ra++]=223,pa.setUint32(ra,c),ra+=4);let d;for(let e=0;e<c;e++)t(d=b[e]),t(a[d])}:(a,c)=>{oa[ra++]=222;// always using map 16, so we can preallocate and set the length afterwards
|
|
58
|
+
let d=ra-b;ra+=2;let e=0;for(let b in a)(c||a.hasOwnProperty(b))&&(t(b),t(a[b]),e++);oa[d++ +b]=e>>8,oa[d+b]=255&e}:/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
|
|
58
59
|
(object, safePrototype) => {
|
|
59
60
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
60
61
|
let objectOffset = position++ - start
|
|
@@ -93,20 +94,20 @@ let d=pa-b;pa+=2;let e=0;for(let b in a)(c||a.hasOwnProperty(b))&&(t(b),t(a[b]),
|
|
|
93
94
|
sharedStructures.onUpdate(id, transition.__keys__)
|
|
94
95
|
}
|
|
95
96
|
target[objectOffset + start] = id
|
|
96
|
-
}*/a=>{let b,c=Object.keys(a),f=e.transitions||(e.transitions=Object.create(null)),g=0;for(let d,e=0,h=c.length;e<h;e++)d=c[e],b=f[d],b||(b=f[d]=Object.create(null),g++),f=b;let h=f[
|
|
97
|
-
h=o),e.nextId=h+1);let a=c.highByte=96<=h&&n?h-96>>5:-1;f[
|
|
97
|
+
}*/a=>{let b,c=Object.keys(a),f=e.transitions||(e.transitions=Object.create(null)),g=0;for(let d,e=0,h=c.length;e<h;e++)d=c[e],b=f[d],b||(b=f[d]=Object.create(null),g++),f=b;let h=f[sa];if(h)96<=h&&n?(oa[ra++]=(31&(h-=96))+96,oa[ra++]=h>>5):oa[ra++]=h;else{h=e.nextId,h||(h=64),h<o&&this.shouldShareStructure&&!this.shouldShareStructure(c)?(h=e.nextOwnId,!(h<p)&&(h=o),e.nextOwnId=h+1):(h>=p&&(// cycle back around
|
|
98
|
+
h=o),e.nextId=h+1);let a=c.highByte=96<=h&&n?h-96>>5:-1;f[sa]=h,e[h-64]=c,h<o?(c.isShared=!0,e.sharedLength=h-63,d=!0,0<=a?(oa[ra++]=(31&h)+96,oa[ra++]=a):oa[ra++]=h):(0<=a?(oa[ra++]=213,oa[ra++]=114,oa[ra++]=(31&h)+96,oa[ra++]=a):(oa[ra++]=212,oa[ra++]=114,oa[ra++]=h),g&&(r+=s*g),q.length>=m&&(q.shift()[sa]=0),q.push(f),t(c))}// now write the values
|
|
98
99
|
for(let b=0,d=c.length;b<d;b++)t(a[c[b]])},x=a=>{var c=Math.min,d=Math.round,e=Math.max;let f;if(16777216<a){// special handling for really large buffers
|
|
99
|
-
if(a-b>
|
|
100
|
-
f=(e(a-b<<2,
|
|
101
|
-
|
|
100
|
+
if(a-b>na)throw new Error("Packed buffer would be larger than maximum buffer size");f=c(na,4096*d(e((a-b)*(67108864<a?1.25:2),16777216)/4096))}else// faster handling for smaller buffers
|
|
101
|
+
f=(e(a-b<<2,oa.length-1)>>12)+1<<12;let g=new la(f);return pa=new DataView(g.buffer,0,f),oa.copy?oa.copy(g,0,b,a):g.set(oa.slice(b,a)),ra-=b,b=0,qa=g.length-10,oa=g}}useBuffer(a){// this means we are finished using our own buffer and we can write over it safely
|
|
102
|
+
oa=a,pa=new DataView(oa.buffer,oa.byteOffset,oa.byteLength),ra=0}}ja=[Date,Set,Error,RegExp,ArrayBuffer,Object.getPrototypeOf(Uint8Array.prototype).constructor/*TypedArray*/,M],ia=[{pack(a,c){let d=a.getTime()/1e3;if((this.useTimestamp32||0===a.getMilliseconds())&&0<=d&&4294967296>d){// Timestamp 32
|
|
102
103
|
let{target:a,targetView:b,position:e}=c(6);a[e++]=214,a[e++]=255,b.setUint32(e,d)}else if(0<d&&17179869184>d){// Timestamp 64
|
|
103
104
|
let{target:b,targetView:e,position:f}=c(10);b[f++]=215,b[f++]=255,e.setUint32(f,4e6*a.getMilliseconds()+(d/1e3/4294967296>>0)),e.setUint32(f+4,d)}else{// Timestamp 96
|
|
104
|
-
let{target:e,targetView:f,position:g}=c(15);e[g++]=199,e[g++]=12,e[g++]=255,f.setUint32(g,1e6*a.getMilliseconds()),f.setBigInt64(g+4,BigInt(b(d)))}}},{pack(a,b,c){let d=Array.from(a),{target:e,position:f}=b(this.structuredClone?3:0);this.structuredClone&&(e[f++]=212,e[f++]=115,e[f++]=0),c(d)}},{pack(a,b,c){let{target:d,position:e}=b(this.structuredClone?3:0);this.structuredClone&&(d[e++]=212,d[e++]=101,d[e++]=0),c([a.name,a.message])}},{pack(a,b,c){let{target:d,position:e}=b(this.structuredClone?3:0);this.structuredClone&&(d[e++]=212,d[e++]=120,d[e++]=0),c([a.source,a.flags])}},{pack(a,b){this.structuredClone?s(a,16,b):t(
|
|
105
|
-
let{target:c,position:d}=b(1);c[d]=193}}];let
|
|
106
|
-
d&&(a=Buffer.concat([d,a]),d=void 0);try{b=c.unpackMultiple(a)}catch(c){if(c.incomplete)d=a.slice(c.lastPosition),b=c.values;else throw c}return b};if("function"==typeof a[Symbol.iterator])return function*(){for(const b of a)yield*e(b)}();return"function"==typeof a[Symbol.asyncIterator]?async function*(){for await(const b of a)yield*e(b)}():void 0},a.encode=
|
|
105
|
+
let{target:e,targetView:f,position:g}=c(15);e[g++]=199,e[g++]=12,e[g++]=255,f.setUint32(g,1e6*a.getMilliseconds()),f.setBigInt64(g+4,BigInt(b(d)))}}},{pack(a,b,c){let d=Array.from(a),{target:e,position:f}=b(this.structuredClone?3:0);this.structuredClone&&(e[f++]=212,e[f++]=115,e[f++]=0),c(d)}},{pack(a,b,c){let{target:d,position:e}=b(this.structuredClone?3:0);this.structuredClone&&(d[e++]=212,d[e++]=101,d[e++]=0),c([a.name,a.message])}},{pack(a,b,c){let{target:d,position:e}=b(this.structuredClone?3:0);this.structuredClone&&(d[e++]=212,d[e++]=120,d[e++]=0),c([a.source,a.flags])}},{pack(a,b){this.structuredClone?s(a,16,b):t(ka?Buffer.from(a):new Uint8Array(a),b)}},{pack(a,b){let c=a.constructor;c!==ma&&this.structuredClone?s(a,$.indexOf(c.name),b):t(a,b)}},{pack(a,b){// specific 0xC1 object
|
|
106
|
+
let{target:c,position:d}=b(1);c[d]=193}}];let ua=new ta({useRecords:!1});const va=ua.pack,wa=ua.pack,{NEVER:xa,ALWAYS:ya,DECIMAL_ROUND:za,DECIMAL_FIT:Aa}=ea,Ba=1e3;a.ALWAYS=ya,a.C1=N,a.DECIMAL_FIT=Aa,a.DECIMAL_ROUND=za,a.Decoder=P,a.Encoder=ta,a.FLOAT32_OPTIONS=ea,a.NEVER=xa,a.Packr=ta,a.REUSE_BUFFER_MODE=Ba,a.Unpackr=P,a.addExtension=w,a.clearSource=q,a.decode=da,a.decodeIter=function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise");const c=new P(b);let d;const e=a=>{let b;// if there's incomplete data from previous chunk, concatinate and try again
|
|
107
|
+
d&&(a=Buffer.concat([d,a]),d=void 0);try{b=c.unpackMultiple(a)}catch(c){if(c.incomplete)d=a.slice(c.lastPosition),b=c.values;else throw c}return b};if("function"==typeof a[Symbol.iterator])return function*(){for(const b of a)yield*e(b)}();return"function"==typeof a[Symbol.asyncIterator]?async function*(){for await(const b of a)yield*e(b)}():void 0},a.encode=wa,a.encodeIter=/**
|
|
107
108
|
* Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
|
|
108
109
|
* If the argument is only Async Iterable, the return value will be an Async Iterable.
|
|
109
110
|
* @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
|
|
110
111
|
* @param {options} [options] - msgpackr pack options
|
|
111
112
|
* @returns {IterableIterator|Promise.<AsyncIterableIterator>}
|
|
112
|
-
*/function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable");else{if("function"==typeof a[Symbol.iterator])return x(a,b);if("function"==typeof a.then||"function"==typeof a[Symbol.asyncIterator])return y(a,b);throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise")}},a.mapsAsObjects=!0,a.pack=
|
|
113
|
+
*/function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable");else{if("function"==typeof a[Symbol.iterator])return x(a,b);if("function"==typeof a.then||"function"==typeof a[Symbol.asyncIterator])return y(a,b);throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise")}},a.mapsAsObjects=!0,a.pack=va,a.roundFloat32=function(a){ga[0]=a;let b=_[(127&ha[3])<<1|ha[2]>>7];return(b*a+(0<a?.5:-.5)>>0)/b},a.unpack=ba,a.unpackMultiple=ca,a.useRecords=!1,Object.defineProperty(a,"__esModule",{value:!0})});
|
package/dist/node.cjs
CHANGED
|
@@ -963,7 +963,14 @@ const FLOAT32_OPTIONS = {
|
|
|
963
963
|
ALWAYS: 1,
|
|
964
964
|
DECIMAL_ROUND: 3,
|
|
965
965
|
DECIMAL_FIT: 4
|
|
966
|
-
};
|
|
966
|
+
};
|
|
967
|
+
let f32Array = new Float32Array(1);
|
|
968
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
969
|
+
function roundFloat32(float32Number) {
|
|
970
|
+
f32Array[0] = float32Number;
|
|
971
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
972
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
973
|
+
}
|
|
967
974
|
|
|
968
975
|
let textEncoder;
|
|
969
976
|
try {
|
|
@@ -1022,7 +1029,7 @@ class Packr extends Unpackr {
|
|
|
1022
1029
|
let transitionsCount = 0;
|
|
1023
1030
|
let serializationsSinceTransitionRebuild = 0;
|
|
1024
1031
|
|
|
1025
|
-
this.pack = this.encode = function(value) {
|
|
1032
|
+
this.pack = this.encode = function(value, encodeOptions) {
|
|
1026
1033
|
if (!target) {
|
|
1027
1034
|
target = new ByteArrayAllocate(8192);
|
|
1028
1035
|
targetView = new DataView(target.buffer, 0, 8192);
|
|
@@ -1087,6 +1094,11 @@ class Packr extends Unpackr {
|
|
|
1087
1094
|
referenceMap = null;
|
|
1088
1095
|
return serialized
|
|
1089
1096
|
}
|
|
1097
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
1098
|
+
target.start = start;
|
|
1099
|
+
target.end = position$1;
|
|
1100
|
+
return target
|
|
1101
|
+
}
|
|
1090
1102
|
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1091
1103
|
} finally {
|
|
1092
1104
|
if (sharedStructures) {
|
|
@@ -1110,13 +1122,15 @@ class Packr extends Unpackr {
|
|
|
1110
1122
|
if (sharedStructures.length > sharedLength) {
|
|
1111
1123
|
sharedStructures = sharedStructures.slice(0, sharedLength);
|
|
1112
1124
|
}
|
|
1113
|
-
|
|
1125
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1126
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
1114
1127
|
if (packr.saveStructures(sharedStructures, lastSharedStructuresLength) === false) {
|
|
1115
1128
|
// get updated structures and try again if the update failed
|
|
1116
1129
|
packr._mergeStructures(packr.getStructures());
|
|
1117
1130
|
return packr.pack(value)
|
|
1118
1131
|
}
|
|
1119
1132
|
lastSharedStructuresLength = sharedLength;
|
|
1133
|
+
return returnBuffer
|
|
1120
1134
|
}
|
|
1121
1135
|
}
|
|
1122
1136
|
}
|
|
@@ -1237,7 +1251,7 @@ class Packr extends Unpackr {
|
|
|
1237
1251
|
targetView.setFloat32(position$1, value);
|
|
1238
1252
|
let xShifted;
|
|
1239
1253
|
if (useFloat32 < 4 ||
|
|
1240
|
-
|
|
1254
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1241
1255
|
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1242
1256
|
position$1 += 4;
|
|
1243
1257
|
return
|
|
@@ -1772,7 +1786,8 @@ let defaultPackr = new Packr({ useRecords: false });
|
|
|
1772
1786
|
const pack = defaultPackr.pack;
|
|
1773
1787
|
const encode = defaultPackr.pack;
|
|
1774
1788
|
const Encoder = Packr;
|
|
1775
|
-
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1789
|
+
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1790
|
+
const REUSE_BUFFER_MODE = 1000;
|
|
1776
1791
|
|
|
1777
1792
|
class PackrStream extends stream.Transform {
|
|
1778
1793
|
constructor(options) {
|
|
@@ -1953,6 +1968,7 @@ exports.encode = encode;
|
|
|
1953
1968
|
exports.encodeIter = encodeIter;
|
|
1954
1969
|
exports.mapsAsObjects = mapsAsObjects;
|
|
1955
1970
|
exports.pack = pack;
|
|
1971
|
+
exports.roundFloat32 = roundFloat32;
|
|
1956
1972
|
exports.unpack = unpack;
|
|
1957
1973
|
exports.unpackMultiple = unpackMultiple;
|
|
1958
1974
|
exports.useRecords = useRecords;
|
package/dist/test.js
CHANGED
|
@@ -594,6 +594,7 @@
|
|
|
594
594
|
var Packr = msgpackr.Packr;
|
|
595
595
|
var unpack = msgpackr.unpack;
|
|
596
596
|
var unpackMultiple = msgpackr.unpackMultiple;
|
|
597
|
+
var roundFloat32 = msgpackr.roundFloat32;
|
|
597
598
|
var pack = msgpackr.pack;
|
|
598
599
|
var DECIMAL_FIT = msgpackr.FLOAT32_OPTIONS.DECIMAL_FIT;
|
|
599
600
|
|
|
@@ -659,6 +660,13 @@
|
|
|
659
660
|
assert.deepEqual(deserialized, data);
|
|
660
661
|
});
|
|
661
662
|
|
|
663
|
+
test('255 chars', function() {
|
|
664
|
+
const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W';
|
|
665
|
+
var serialized = pack(data);
|
|
666
|
+
var deserialized = unpack(serialized);
|
|
667
|
+
assert.equal(deserialized, data);
|
|
668
|
+
});
|
|
669
|
+
|
|
662
670
|
test('pack/unpack sample data', function(){
|
|
663
671
|
var data = sampleData;
|
|
664
672
|
var serialized = pack(data);
|
|
@@ -1104,6 +1112,11 @@
|
|
|
1104
1112
|
assert.isTrue(deserialized.tooBig > 2n**65n);
|
|
1105
1113
|
});
|
|
1106
1114
|
|
|
1115
|
+
test('roundFloat32', function() {
|
|
1116
|
+
assert.equal(roundFloat32(0.00333000003), 0.00333);
|
|
1117
|
+
assert.equal(roundFloat32(43.29999999993), 43.3);
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1107
1120
|
test('buffers', function(){
|
|
1108
1121
|
var data = {
|
|
1109
1122
|
buffer1: new Uint8Array([2,3,4]),
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Unpackr, Decoder, unpack, decode, addExtension, FLOAT32_OPTIONS, clearSource } from './unpack'
|
|
1
|
+
export { Unpackr, Decoder, unpack, decode, addExtension, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './unpack'
|
|
2
2
|
import { Options } from './unpack'
|
|
3
3
|
export { Packr, Encoder, pack, encode } from './pack'
|
|
4
4
|
import { Transform, Readable } from 'stream'
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './pack.js'
|
|
2
|
-
export { Unpackr, Decoder, C1, unpack, unpackMultiple, decode, FLOAT32_OPTIONS, clearSource } from './unpack.js'
|
|
1
|
+
export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT, REUSE_BUFFER_MODE } from './pack.js'
|
|
2
|
+
export { Unpackr, Decoder, C1, unpack, unpackMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './unpack.js'
|
|
3
3
|
export { decodeIter, encodeIter } from './iterators.js'
|
|
4
4
|
export const useRecords = false
|
|
5
5
|
export const mapsAsObjects = true
|
package/node-index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './pack.js'
|
|
2
|
-
export { Unpackr, Decoder, C1, unpack, unpackMultiple, decode, FLOAT32_OPTIONS, clearSource} from './unpack.js'
|
|
2
|
+
export { Unpackr, Decoder, C1, unpack, unpackMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './unpack.js'
|
|
3
3
|
export { PackrStream, UnpackrStream, PackrStream as EncoderStream, UnpackrStream as DecoderStream } from './stream.js'
|
|
4
4
|
export { decodeIter, encodeIter } from './iterators.js'
|
|
5
5
|
export const useRecords = false
|
package/pack.js
CHANGED
|
@@ -58,7 +58,7 @@ export class Packr extends Unpackr {
|
|
|
58
58
|
let transitionsCount = 0
|
|
59
59
|
let serializationsSinceTransitionRebuild = 0
|
|
60
60
|
|
|
61
|
-
this.pack = this.encode = function(value) {
|
|
61
|
+
this.pack = this.encode = function(value, encodeOptions) {
|
|
62
62
|
if (!target) {
|
|
63
63
|
target = new ByteArrayAllocate(8192)
|
|
64
64
|
targetView = new DataView(target.buffer, 0, 8192)
|
|
@@ -123,6 +123,11 @@ export class Packr extends Unpackr {
|
|
|
123
123
|
referenceMap = null
|
|
124
124
|
return serialized
|
|
125
125
|
}
|
|
126
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
127
|
+
target.start = start
|
|
128
|
+
target.end = position
|
|
129
|
+
return target
|
|
130
|
+
}
|
|
126
131
|
return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
127
132
|
} finally {
|
|
128
133
|
if (sharedStructures) {
|
|
@@ -146,13 +151,15 @@ export class Packr extends Unpackr {
|
|
|
146
151
|
if (sharedStructures.length > sharedLength) {
|
|
147
152
|
sharedStructures = sharedStructures.slice(0, sharedLength)
|
|
148
153
|
}
|
|
149
|
-
|
|
154
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
155
|
+
let returnBuffer = target.subarray(start, position)
|
|
150
156
|
if (packr.saveStructures(sharedStructures, lastSharedStructuresLength) === false) {
|
|
151
157
|
// get updated structures and try again if the update failed
|
|
152
158
|
packr._mergeStructures(packr.getStructures())
|
|
153
159
|
return packr.pack(value)
|
|
154
160
|
}
|
|
155
161
|
lastSharedStructuresLength = sharedLength
|
|
162
|
+
return returnBuffer
|
|
156
163
|
}
|
|
157
164
|
}
|
|
158
165
|
}
|
|
@@ -273,7 +280,7 @@ export class Packr extends Unpackr {
|
|
|
273
280
|
targetView.setFloat32(position, value)
|
|
274
281
|
let xShifted
|
|
275
282
|
if (useFloat32 < 4 ||
|
|
276
|
-
|
|
283
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
277
284
|
((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
|
|
278
285
|
position += 4
|
|
279
286
|
return
|
|
@@ -817,3 +824,4 @@ export const Encoder = Packr
|
|
|
817
824
|
export { FLOAT32_OPTIONS } from './unpack.js'
|
|
818
825
|
import { FLOAT32_OPTIONS } from './unpack.js'
|
|
819
826
|
export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
|
|
827
|
+
export const REUSE_BUFFER_MODE = 1000
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msgpackr",
|
|
3
3
|
"author": "Kris Zyp",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.7",
|
|
5
5
|
"description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"types": "./index.d.ts",
|
|
8
|
+
"main": "./dist/node.cjs",
|
|
9
|
+
"module": "./index.js",
|
|
8
10
|
"keywords": [
|
|
9
11
|
"MessagePack",
|
|
10
12
|
"msgpack",
|
|
@@ -19,6 +21,7 @@
|
|
|
19
21
|
"scripts": {
|
|
20
22
|
"benchmark": "node ./tests/benchmark.cjs",
|
|
21
23
|
"build": "rollup -c",
|
|
24
|
+
"dry-run": "npm publish --dry-run",
|
|
22
25
|
"prepare": "npm run build",
|
|
23
26
|
"test": "mocha tests/test**.*js -u tdd --experimental-json-modules"
|
|
24
27
|
},
|
|
@@ -47,7 +50,7 @@
|
|
|
47
50
|
}
|
|
48
51
|
},
|
|
49
52
|
"optionalDependencies": {
|
|
50
|
-
"msgpackr-extract": "^1.0.
|
|
53
|
+
"msgpackr-extract": "^1.0.14"
|
|
51
54
|
},
|
|
52
55
|
"devDependencies": {
|
|
53
56
|
"@rollup/plugin-json": "^4.1.0",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
const data = require('./example4.json');
|
|
2
|
-
const { pack, unpack } = require('msgpackr/pack');
|
|
2
|
+
const { pack, unpack, Packr } = require('msgpackr/pack');
|
|
3
3
|
const chai = require('chai');
|
|
4
4
|
|
|
5
5
|
function tryRequire(module) {
|
|
6
6
|
try {
|
|
7
7
|
return require(module)
|
|
8
8
|
} catch(error) {
|
|
9
|
+
console.log(error)
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
//if (typeof chai === 'undefined') { chai = require('chai') }
|
|
@@ -13,6 +14,7 @@ const assert = chai.assert
|
|
|
13
14
|
//if (typeof msgpackr === 'undefined') { msgpackr = require('..') }
|
|
14
15
|
var msgpack_msgpack = tryRequire('@msgpack/msgpack');
|
|
15
16
|
var msgpack_lite = tryRequire('msgpack-lite');
|
|
17
|
+
var msgpack = tryRequire('msgpack');
|
|
16
18
|
|
|
17
19
|
const addCompatibilitySuite = (data) => () => {
|
|
18
20
|
if (msgpack_msgpack) {
|
|
@@ -41,8 +43,22 @@ const addCompatibilitySuite = (data) => () => {
|
|
|
41
43
|
assert.deepEqual(deserialized, data)
|
|
42
44
|
})
|
|
43
45
|
}
|
|
46
|
+
if (msgpack) {
|
|
47
|
+
test.skip('from msgpack', function(){
|
|
48
|
+
var serialized = msgpack.pack(data)
|
|
49
|
+
var deserialized = unpack(serialized)
|
|
50
|
+
assert.deepEqual(deserialized, data)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('to msgpack', function(){
|
|
54
|
+
var serialized = pack(data)
|
|
55
|
+
var deserialized = msgpack.unpack(serialized)
|
|
56
|
+
assert.deepEqual(deserialized, data)
|
|
57
|
+
})
|
|
58
|
+
}
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
suite('msgpackr compatibility tests (example)', addCompatibilitySuite(require('./example.json')))
|
|
47
62
|
suite('msgpackr compatibility tests (example4)', addCompatibilitySuite(require('./example4.json')))
|
|
48
|
-
suite('msgpackr compatibility tests (example5)', addCompatibilitySuite(require('./example5.json')))
|
|
63
|
+
suite('msgpackr compatibility tests (example5)', addCompatibilitySuite(require('./example5.json')))
|
|
64
|
+
suite.skip('msgpackr compatibility tests with dates', addCompatibilitySuite({ date: new Date() }))
|
package/tests/test.js
CHANGED
|
@@ -15,6 +15,7 @@ var assert = chai.assert
|
|
|
15
15
|
var Packr = msgpackr.Packr
|
|
16
16
|
var unpack = msgpackr.unpack
|
|
17
17
|
var unpackMultiple = msgpackr.unpackMultiple
|
|
18
|
+
var roundFloat32 = msgpackr.roundFloat32
|
|
18
19
|
var pack = msgpackr.pack
|
|
19
20
|
var DECIMAL_FIT = msgpackr.FLOAT32_OPTIONS.DECIMAL_FIT
|
|
20
21
|
|
|
@@ -83,6 +84,13 @@ suite('msgpackr basic tests', function(){
|
|
|
83
84
|
assert.deepEqual(deserialized, data)
|
|
84
85
|
})
|
|
85
86
|
|
|
87
|
+
test('255 chars', function() {
|
|
88
|
+
const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W'
|
|
89
|
+
var serialized = pack(data)
|
|
90
|
+
var deserialized = unpack(serialized)
|
|
91
|
+
assert.equal(deserialized, data)
|
|
92
|
+
})
|
|
93
|
+
|
|
86
94
|
test('pack/unpack sample data', function(){
|
|
87
95
|
var data = sampleData
|
|
88
96
|
let structures = []
|
|
@@ -531,6 +539,11 @@ suite('msgpackr basic tests', function(){
|
|
|
531
539
|
assert.isTrue(deserialized.tooBig > 2n**65n)
|
|
532
540
|
})
|
|
533
541
|
|
|
542
|
+
test('roundFloat32', function() {
|
|
543
|
+
assert.equal(roundFloat32(0.00333000003), 0.00333)
|
|
544
|
+
assert.equal(roundFloat32(43.29999999993), 43.3)
|
|
545
|
+
})
|
|
546
|
+
|
|
534
547
|
test('buffers', function(){
|
|
535
548
|
var data = {
|
|
536
549
|
buffer1: new Uint8Array([2,3,4]),
|
package/unpack.d.ts
CHANGED
|
@@ -25,8 +25,10 @@ export interface Options {
|
|
|
25
25
|
interface Extension {
|
|
26
26
|
Class: Function
|
|
27
27
|
type: number
|
|
28
|
-
pack(value: any): Buffer | Uint8Array
|
|
29
|
-
unpack(messagePack: Buffer | Uint8Array): any
|
|
28
|
+
pack?(value: any): Buffer | Uint8Array
|
|
29
|
+
unpack?(messagePack: Buffer | Uint8Array): any
|
|
30
|
+
read?(datum: any): any
|
|
31
|
+
write?(instance: any): any
|
|
30
32
|
}
|
|
31
33
|
export class Unpackr {
|
|
32
34
|
constructor(options?: Options)
|
|
@@ -40,4 +42,5 @@ export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach?: (valu
|
|
|
40
42
|
export function decode(messagePack: Buffer | Uint8Array): any
|
|
41
43
|
export function addExtension(extension: Extension): void
|
|
42
44
|
export function clearSource(): void
|
|
45
|
+
export function roundFloat32(float32Number: number): number
|
|
43
46
|
export const C1: {}
|
package/unpack.js
CHANGED
|
@@ -964,3 +964,10 @@ export const FLOAT32_OPTIONS = {
|
|
|
964
964
|
DECIMAL_ROUND: 3,
|
|
965
965
|
DECIMAL_FIT: 4
|
|
966
966
|
}
|
|
967
|
+
let f32Array = new Float32Array(1)
|
|
968
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4)
|
|
969
|
+
export function roundFloat32(float32Number) {
|
|
970
|
+
f32Array[0] = float32Number
|
|
971
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)]
|
|
972
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
973
|
+
}
|