msgpackr 1.4.7 → 1.5.3

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/unpack.d.ts CHANGED
@@ -13,6 +13,7 @@ export interface Options {
13
13
  mapsAsObjects?: boolean
14
14
  variableMapSize?: boolean
15
15
  copyBuffers?: boolean
16
+ bundleStrings?: boolean
16
17
  useTimestamp32?: boolean
17
18
  largeBigIntToFloat?: boolean
18
19
  encodeUndefinedAsNil?: boolean
@@ -21,6 +22,7 @@ export interface Options {
21
22
  shouldShareStructure?: (keys: string[]) => boolean
22
23
  getStructures?(): {}[]
23
24
  saveStructures?(structures: {}[]): boolean | void
25
+ onInvalidDate?: () => any
24
26
  }
25
27
  interface Extension {
26
28
  Class: Function
@@ -44,3 +46,4 @@ export function addExtension(extension: Extension): void
44
46
  export function clearSource(): void
45
47
  export function roundFloat32(float32Number: number): number
46
48
  export const C1: {}
49
+ export let isNativeAccelerationEnabled: boolean
package/unpack.js CHANGED
@@ -15,6 +15,7 @@ var currentStructures
15
15
  var srcString
16
16
  var srcStringStart = 0
17
17
  var srcStringEnd = 0
18
+ var bundledStrings
18
19
  var referenceMap
19
20
  var currentExtensions = []
20
21
  var dataView
@@ -55,12 +56,21 @@ export class Unpackr {
55
56
  srcStringEnd = 0
56
57
  srcString = null
57
58
  strings = EMPTY_ARRAY
59
+ bundledStrings = null
58
60
  src = source
59
61
  // this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
60
62
  // technique for getting data from a database where it can be copied into an existing buffer instead of creating
61
63
  // new ones
62
- dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength))
63
- if (this) {
64
+ try {
65
+ dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength))
66
+ } catch(error) {
67
+ // if it doesn't have a buffer, maybe it is the wrong type of object
68
+ src = null
69
+ if (source instanceof Uint8Array)
70
+ throw error
71
+ throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
72
+ }
73
+ if (this instanceof Unpackr) {
64
74
  currentUnpackr = this
65
75
  if (this.structures) {
66
76
  currentStructures = this.structures
@@ -146,6 +156,9 @@ export function checkedRead() {
146
156
  currentStructures.length = sharedLength
147
157
  }
148
158
  let result = read()
159
+ if (bundledStrings) // bundled strings to skip past
160
+ position = bundledStrings.postBundlePosition
161
+
149
162
  if (position == srcEnd) {
150
163
  // finished reading this source, cleanup references
151
164
  if (currentStructures.restoreStructures)
@@ -240,7 +253,15 @@ export function read() {
240
253
  let value
241
254
  switch (token) {
242
255
  case 0xc0: return null
243
- case 0xc1: return C1; // "never-used", return special object to denote that
256
+ case 0xc1:
257
+ if (bundledStrings) {
258
+ value = read() // followed by the length of the string in characters (not bytes!)
259
+ if (value > 0)
260
+ return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
261
+ else
262
+ return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value)
263
+ }
264
+ return C1; // "never-used", return special object to denote that
244
265
  case 0xc2: return false
245
266
  case 0xc3: return true
246
267
  case 0xc4:
@@ -295,10 +316,11 @@ export function read() {
295
316
  position += 4
296
317
  return value
297
318
  case 0xcf:
298
- if (currentUnpackr.uint64AsNumber)
299
- return src[position++] * 0x100000000000000 + src[position++] * 0x1000000000000 + src[position++] * 0x10000000000 + src[position++] * 0x100000000 +
300
- src[position++] * 0x1000000 + (src[position++] << 16) + (src[position++] << 8) + src[position++]
301
- value = dataView.getBigUint64(position)
319
+ if (currentUnpackr.int64AsNumber) {
320
+ value = dataView.getUint32(position) * 0x100000000
321
+ value += dataView.getUint32(position + 4)
322
+ } else
323
+ value = dataView.getBigUint64(position)
302
324
  position += 8
303
325
  return value
304
326
 
@@ -314,7 +336,11 @@ export function read() {
314
336
  position += 4
315
337
  return value
316
338
  case 0xd3:
317
- value = dataView.getBigInt64(position)
339
+ if (currentUnpackr.int64AsNumber) {
340
+ value = dataView.getInt32(position) * 0x100000000
341
+ value += dataView.getUint32(position + 4)
342
+ } else
343
+ value = dataView.getBigInt64(position)
318
344
  position += 8
319
345
  return value
320
346
 
@@ -463,8 +489,10 @@ var readFixedString = readStringJS
463
489
  var readString8 = readStringJS
464
490
  var readString16 = readStringJS
465
491
  var readString32 = readStringJS
492
+ export let isNativeAccelerationEnabled = false
466
493
 
467
494
  export function setExtractor(extractStrings) {
495
+ isNativeAccelerationEnabled = true
468
496
  readFixedString = readString(1)
469
497
  readString8 = readString(2)
470
498
  readString16 = readString(3)
@@ -473,6 +501,8 @@ export function setExtractor(extractStrings) {
473
501
  return function readString(length) {
474
502
  let string = strings[stringPosition++]
475
503
  if (string == null) {
504
+ if (bundledStrings)
505
+ return readStringJS(length)
476
506
  let extraction = extractStrings(position - headerLength, srcEnd, src)
477
507
  if (typeof extraction == 'string') {
478
508
  string = extraction
@@ -731,6 +761,36 @@ function shortStringInJS(length) {
731
761
  }
732
762
  }
733
763
 
764
+ function readOnlyJSString() {
765
+ let token = src[position++]
766
+ let length
767
+ if (token < 0xc0) {
768
+ // fixstr
769
+ length = token - 0xa0
770
+ } else {
771
+ switch(token) {
772
+ case 0xd9:
773
+ // str 8
774
+ length = src[position++]
775
+ break
776
+ case 0xda:
777
+ // str 16
778
+ length = dataView.getUint16(position)
779
+ position += 2
780
+ break
781
+ case 0xdb:
782
+ // str 32
783
+ length = dataView.getUint32(position)
784
+ position += 4
785
+ break
786
+ default:
787
+ throw new Error('Expected string')
788
+ }
789
+ }
790
+ return readStringJS(length)
791
+ }
792
+
793
+
734
794
  function readBin(length) {
735
795
  return currentUnpackr.copyBuffers ?
736
796
  // specifically use the copying slice (not the node one)
@@ -882,6 +942,19 @@ currentExtensions[0x78] = () => {
882
942
  let data = read()
883
943
  return new RegExp(data[0], data[1])
884
944
  }
945
+ const TEMP_BUNDLE = []
946
+ currentExtensions[0x62] = (data) => {
947
+ let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]
948
+ let dataPosition = position
949
+ position += dataSize - data.length
950
+ bundledStrings = TEMP_BUNDLE
951
+ bundledStrings = [readOnlyJSString(), readOnlyJSString()]
952
+ bundledStrings.position0 = 0
953
+ bundledStrings.position1 = 0
954
+ bundledStrings.postBundlePosition = position
955
+ position = dataPosition
956
+ return read()
957
+ }
885
958
 
886
959
  currentExtensions[0xff] = (data) => {
887
960
  // 32-bit date extension
@@ -896,7 +969,7 @@ currentExtensions[0xff] = (data) => {
896
969
  ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
897
970
  (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
898
971
  else
899
- throw new Error('Invalid timestamp length')
972
+ return new Date('invalid')
900
973
  } // notepack defines extension 0 to mean undefined, so use that as the default here
901
974
  // registration of bulk record definition?
902
975
  // currentExtensions[0x52] = () =>
@@ -910,6 +983,7 @@ function saveState(callback) {
910
983
  let savedSrcString = srcString
911
984
  let savedStrings = strings
912
985
  let savedReferenceMap = referenceMap
986
+ let savedBundledStrings = bundledStrings
913
987
 
914
988
  // TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
915
989
  let savedSrc = new Uint8Array(src.slice(0, srcEnd)) // we copy the data in case it changes while external data is processed
@@ -926,6 +1000,7 @@ function saveState(callback) {
926
1000
  srcString = savedSrcString
927
1001
  strings = savedStrings
928
1002
  referenceMap = savedReferenceMap
1003
+ bundledStrings = savedBundledStrings
929
1004
  src = savedSrc
930
1005
  sequentialMode = savedSequentialMode
931
1006
  currentStructures = savedStructures
@@ -951,8 +1026,6 @@ export const mult10 = new Array(147) // this is a table matching binary exponent
951
1026
  for (let i = 0; i < 256; i++) {
952
1027
  mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103))
953
1028
  }
954
- export const useRecords = false
955
- export const mapsAsObjects = true
956
1029
  export const Decoder = Unpackr
957
1030
  var defaultUnpackr = new Unpackr({ useRecords: false })
958
1031
  export const unpack = defaultUnpackr.unpack
@@ -1,23 +0,0 @@
1
- {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
- "version": "0.2.0",
6
- "configurations": [
7
- {
8
- "type": "pwa-node",
9
- "request": "launch",
10
- "name": "Run msgpackr tests",
11
- "runtimeArgs": [
12
- "test"
13
- ],
14
- "runtimeExecutable": "npm",
15
- "skipFiles": [
16
- "<node_internals>/**"
17
- ],
18
- "type": "pwa-node",
19
- "console": "internalConsole",
20
- "outputCapture": "std"
21
- }
22
- ]
23
- }
@@ -1,282 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- var PassThrough = require("stream").PassThrough;
4
- var async = require("async");
5
-
6
- let { PackrStream, UnpackrStream } = require("..");
7
- var msgpack = require("msgpack-lite");
8
- var Encoder = require("msgpack-lite/lib/encoder").Encoder;
9
- var Decoder = require("msgpack-lite/lib/decoder").Decoder;
10
- var notepack = require("notepack");
11
-
12
- var pkg = require("../package.json");
13
-
14
- // a sample fluentd message
15
- var data = ["tag", [[1440949922, {"message": "hi there"}]]];
16
- var packed = msgpack.encode(data); // 30 bytes per message
17
- var packsize = packed.length;
18
- var opcount = 1000000;
19
- var joincount = 100;
20
- var packjoin = repeatbuf(packed, joincount); // 3KB per chunk
21
- var limit = 2;
22
-
23
- var blocksToJoin = []
24
- var streamForJoin = new PackrStream();
25
- streamForJoin.on("data", data => blocksToJoin.push(data));
26
- for (var j = 0; j < joincount; j++) {
27
- streamForJoin.write(data);
28
- }
29
- var packjoinWithRecords = Buffer.concat(blocksToJoin)
30
-
31
- var argv = Array.prototype.slice.call(process.argv, 2);
32
-
33
- if (argv[0] === "-v") {
34
- console.warn(pkg.name + " " + pkg.version);
35
- process.exit(0);
36
- }
37
-
38
- if (argv[0] - 0) limit = argv.shift() - 0;
39
-
40
- var list = [
41
- ['new PackrStream().write(obj);', encode5],
42
- ['new UnpackrStream().write(buf);', decode5],
43
- ['stream.write(msgpack.encode(obj));', encode1],
44
- ['stream.write(msgpack.decode(buf));', decode1],
45
- ['stream.write(notepack.encode(obj));', encode4],
46
- ['stream.write(notepack.decode(buf));', decode4],
47
- ['msgpack.Encoder().on("data",ondata).encode(obj);', encode2],
48
- ['msgpack.createDecodeStream().write(buf);', decode3],
49
- ['msgpack.createEncodeStream().write(obj);', encode3],
50
- ['msgpack.Decoder().on("data",ondata).decode(buf);', decode2],
51
- // ['stream.write(Buffer.from(JSON.stringify(obj)));', stringify],
52
- // ['stream.write(JSON.parse(buf));', parse]
53
- ];
54
-
55
- function encode5(callback) {
56
- var stream = new PackrStream();
57
- var cnt = counter(callback);
58
- stream.on("data", cnt.inc);
59
- stream.on("end", cnt.end);
60
- for (var j = 0; j < opcount; j++) {
61
- stream.write(data);
62
- }
63
- stream.end();
64
- }
65
-
66
- function encode1(callback) {
67
- var stream = new PassThrough();
68
- var cnt = counter(callback);
69
- stream.on("data", cnt.buf);
70
- stream.on("end", cnt.end);
71
- for (var j = 0; j < opcount; j++) {
72
- stream.write(msgpack.encode(data));
73
- }
74
- stream.end();
75
- }
76
-
77
- function encode2(callback) {
78
- var stream = new PassThrough();
79
- var cnt = counter(callback);
80
- stream.on("data", cnt.buf);
81
- stream.on("end", cnt.end);
82
- var encoder = Encoder();
83
- encoder.on("data", function(chunk) {
84
- stream.write(chunk);
85
- });
86
- encoder.on("end", function() {
87
- stream.end();
88
- });
89
- for (var j = 0; j < opcount; j++) {
90
- encoder.encode(data);
91
- }
92
- encoder.end();
93
- }
94
-
95
- function encode3(callback) {
96
- var stream = msgpack.createEncodeStream();
97
- var cnt = counter(callback);
98
- stream.on("data", cnt.buf);
99
- stream.on("end", cnt.end);
100
- for (var j = 0; j < opcount; j++) {
101
- stream.write(data);
102
- }
103
- stream.end();
104
- }
105
-
106
- function encode4(callback) {
107
- var stream = new PassThrough();
108
- var cnt = counter(callback);
109
- stream.on("data", cnt.buf);
110
- stream.on("end", cnt.end);
111
- for (var j = 0; j < opcount; j++) {
112
- stream.write(notepack.encode(data));
113
- }
114
- stream.end();
115
- }
116
-
117
- function decode5(callback) {
118
- var stream = new UnpackrStream();
119
- var cnt = counter(callback);
120
- stream.on("data", cnt.inc);
121
- stream.on("end", cnt.end);
122
- for (var j = 0; j < opcount / joincount; j++) {
123
- stream.write(packjoinWithRecords);
124
- }
125
- stream.end();
126
- }
127
-
128
- function decode1(callback) {
129
- var stream = new PassThrough({objectMode: true});
130
- var cnt = counter(callback);
131
- stream.on("data", cnt.inc);
132
- stream.on("end", cnt.end);
133
- for (var j = 0; j < opcount; j++) {
134
- stream.write(msgpack.decode(packed));
135
- }
136
- stream.end();
137
- }
138
-
139
- function decode2(callback) {
140
- var stream = new PassThrough({objectMode: true});
141
- var cnt = counter(callback);
142
- stream.on("data", cnt.inc);
143
- stream.on("end", cnt.end);
144
- var decoder = Decoder();
145
- decoder.on("data", function(chunk) {
146
- stream.write(chunk);
147
- });
148
- decoder.on("end", function() {
149
- stream.end();
150
- });
151
- for (var j = 0; j < opcount / joincount; j++) {
152
- decoder.decode(packjoin);
153
- }
154
- decoder.end();
155
- }
156
-
157
- function decode3(callback) {
158
- var stream = msgpack.createDecodeStream();
159
- var cnt = counter(callback);
160
- stream.on("data", cnt.inc);
161
- stream.on("end", cnt.end);
162
- for (var j = 0; j < opcount / joincount; j++) {
163
- stream.write(packjoin);
164
- }
165
- stream.end();
166
- }
167
-
168
- function decode4(callback) {
169
- var stream = new PassThrough({objectMode: true});
170
- var cnt = counter(callback);
171
- stream.on("data", cnt.inc);
172
- stream.on("end", cnt.end);
173
- for (var j = 0; j < opcount; j++) {
174
- stream.write(notepack.decode(packed));
175
- }
176
- stream.end();
177
- }
178
-
179
- function rpad(str, len, chr) {
180
- if (!chr) chr = " ";
181
- str += "";
182
- while (str.length < len) str += chr;
183
- return str;
184
- }
185
-
186
- function lpad(str, len, chr) {
187
- if (!chr) chr = " ";
188
- str += "";
189
- while (str.length < len) str = chr + str;
190
- return str;
191
- }
192
-
193
- function repeatbuf(buf, cnt) {
194
- var array = [];
195
- for (var i = 0; i < cnt; i++) {
196
- array.push(buf);
197
- }
198
- return Buffer.concat(array);
199
- }
200
-
201
- function counter(callback) {
202
- var cnt = 0;
203
- return {buf: b, inc: i, end: e};
204
-
205
- function b(buf) {
206
- cnt += buf.length / packsize;
207
- }
208
-
209
- function i() {
210
- cnt++;
211
- }
212
-
213
- function e() {
214
- cnt = Math.round(cnt);
215
- callback(null, cnt);
216
- }
217
- }
218
-
219
- function run() {
220
- // task filter
221
- if (argv.length) {
222
- list = list.filter(function(pair) {
223
- var name = pair[0];
224
- var match = argv.filter(function(grep) {
225
- return (name.indexOf(grep) > -1);
226
- });
227
- return match.length;
228
- });
229
- }
230
-
231
- // run tasks repeatedly
232
- var tasks = [];
233
- for (var i = 0; i < limit; i++) {
234
- tasks.push(oneset);
235
- }
236
- async.series(tasks, end);
237
-
238
- // run a series of tasks
239
- function oneset(callback) {
240
- async.eachSeries(list, bench, callback);
241
- }
242
-
243
- // run a single benchmark
244
- function bench(pair, callback) {
245
- process.stdout.write(".");
246
- var func = pair[1];
247
- var start = new Date() - 0;
248
- func(function(err, cnt) {
249
- var end = new Date() - 0;
250
- var array = pair[2] || (pair[2] = []);
251
- array.push(end - start);
252
- pair[3] = cnt;
253
- setTimeout(callback, 100);
254
- });
255
- }
256
-
257
- // show result
258
- function end() {
259
- var title = "operation (" + opcount + " x " + limit + ")";
260
- process.stdout.write("\n");
261
-
262
- // table header
263
- var COL1 = 48;
264
- console.log(rpad(title, COL1), "|", " op ", "|", " ms ", "|", " op/s ");
265
- console.log(rpad("", COL1, "-"), "|", "------:", "|", "----:", "|", "-----:");
266
-
267
- // table body
268
- list.forEach(function(pair) {
269
- var name = pair[0];
270
- var op = pair[3];
271
- var array = pair[2];
272
- array = array.sort(function(a, b) {
273
- return a > b;
274
- });
275
- var fastest = array[0];
276
- var score = Math.floor(opcount / fastest * 1000);
277
- console.log(rpad(name, COL1), "|", lpad(op, 7), "|", lpad(fastest, 5), "|", lpad(score, 6));
278
- });
279
- }
280
- }
281
-
282
- run();