msgpackr 1.7.0-alpha1 → 1.7.0-alpha4

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/index.js CHANGED
@@ -1,5 +1,5 @@
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, isNativeAccelerationEnabled } from './unpack.js'
3
- export { decodeIter, encodeIter } from './iterators.js'
4
- export const useRecords = false
5
- export const mapsAsObjects = true
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, isNativeAccelerationEnabled } from './unpack.js'
3
+ export { decodeIter, encodeIter } from './iterators.js'
4
+ export const useRecords = false
5
+ export const mapsAsObjects = true
package/iterators.js CHANGED
@@ -1,87 +1,87 @@
1
- import { Packr } from './pack.js'
2
- import { Unpackr } from './unpack.js'
3
-
4
- /**
5
- * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
6
- * If the argument is only Async Iterable, the return value will be an Async Iterable.
7
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
8
- * @param {options} [options] - msgpackr pack options
9
- * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
10
- */
11
- export function packIter (objectIterator, options = {}) {
12
- if (!objectIterator || typeof objectIterator !== 'object') {
13
- throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
14
- } else if (typeof objectIterator[Symbol.iterator] === 'function') {
15
- return packIterSync(objectIterator, options)
16
- } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
17
- return packIterAsync(objectIterator, options)
18
- } else {
19
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
20
- }
21
- }
22
-
23
- function * packIterSync (objectIterator, options) {
24
- const packr = new Packr(options)
25
- for (const value of objectIterator) {
26
- yield packr.pack(value)
27
- }
28
- }
29
-
30
- async function * packIterAsync (objectIterator, options) {
31
- const packr = new Packr(options)
32
- for await (const value of objectIterator) {
33
- yield packr.pack(value)
34
- }
35
- }
36
-
37
- /**
38
- * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
39
- * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
40
- * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
41
- * @param {object} [options] - unpackr options
42
- * @returns {IterableIterator|Promise.<AsyncIterableIterator}
43
- */
44
- export function unpackIter (bufferIterator, options = {}) {
45
- if (!bufferIterator || typeof bufferIterator !== 'object') {
46
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
47
- }
48
-
49
- const unpackr = new Unpackr(options)
50
- let incomplete
51
- const parser = (chunk) => {
52
- let yields
53
- // if there's incomplete data from previous chunk, concatinate and try again
54
- if (incomplete) {
55
- chunk = Buffer.concat([incomplete, chunk])
56
- incomplete = undefined
57
- }
58
-
59
- try {
60
- yields = unpackr.unpackMultiple(chunk)
61
- } catch (err) {
62
- if (err.incomplete) {
63
- incomplete = chunk.slice(err.lastPosition)
64
- yields = err.values
65
- } else {
66
- throw err
67
- }
68
- }
69
- return yields
70
- }
71
-
72
- if (typeof bufferIterator[Symbol.iterator] === 'function') {
73
- return (function * iter () {
74
- for (const value of bufferIterator) {
75
- yield * parser(value)
76
- }
77
- })()
78
- } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
79
- return (async function * iter () {
80
- for await (const value of bufferIterator) {
81
- yield * parser(value)
82
- }
83
- })()
84
- }
85
- }
86
- export const decodeIter = unpackIter
1
+ import { Packr } from './pack.js'
2
+ import { Unpackr } from './unpack.js'
3
+
4
+ /**
5
+ * Given an Iterable first argument, returns an Iterable where each value is packed as a Buffer
6
+ * If the argument is only Async Iterable, the return value will be an Async Iterable.
7
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
8
+ * @param {options} [options] - msgpackr pack options
9
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
10
+ */
11
+ export function packIter (objectIterator, options = {}) {
12
+ if (!objectIterator || typeof objectIterator !== 'object') {
13
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
14
+ } else if (typeof objectIterator[Symbol.iterator] === 'function') {
15
+ return packIterSync(objectIterator, options)
16
+ } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
17
+ return packIterAsync(objectIterator, options)
18
+ } else {
19
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
20
+ }
21
+ }
22
+
23
+ function * packIterSync (objectIterator, options) {
24
+ const packr = new Packr(options)
25
+ for (const value of objectIterator) {
26
+ yield packr.pack(value)
27
+ }
28
+ }
29
+
30
+ async function * packIterAsync (objectIterator, options) {
31
+ const packr = new Packr(options)
32
+ for await (const value of objectIterator) {
33
+ yield packr.pack(value)
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
39
+ * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
40
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
41
+ * @param {object} [options] - unpackr options
42
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator}
43
+ */
44
+ export function unpackIter (bufferIterator, options = {}) {
45
+ if (!bufferIterator || typeof bufferIterator !== 'object') {
46
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
47
+ }
48
+
49
+ const unpackr = new Unpackr(options)
50
+ let incomplete
51
+ const parser = (chunk) => {
52
+ let yields
53
+ // if there's incomplete data from previous chunk, concatinate and try again
54
+ if (incomplete) {
55
+ chunk = Buffer.concat([incomplete, chunk])
56
+ incomplete = undefined
57
+ }
58
+
59
+ try {
60
+ yields = unpackr.unpackMultiple(chunk)
61
+ } catch (err) {
62
+ if (err.incomplete) {
63
+ incomplete = chunk.slice(err.lastPosition)
64
+ yields = err.values
65
+ } else {
66
+ throw err
67
+ }
68
+ }
69
+ return yields
70
+ }
71
+
72
+ if (typeof bufferIterator[Symbol.iterator] === 'function') {
73
+ return (function * iter () {
74
+ for (const value of bufferIterator) {
75
+ yield * parser(value)
76
+ }
77
+ })()
78
+ } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
79
+ return (async function * iter () {
80
+ for await (const value of bufferIterator) {
81
+ yield * parser(value)
82
+ }
83
+ })()
84
+ }
85
+ }
86
+ export const decodeIter = unpackIter
87
87
  export const encodeIter = packIter
package/pack.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Unpackr } from './unpack'
2
- export { addExtension, FLOAT32_OPTIONS } from './unpack'
3
- export class Packr extends Unpackr {
4
- pack(value: any): Buffer
5
- encode(value: any): Buffer
6
- }
7
- export class Encoder extends Packr {}
8
- export function pack(value: any): Buffer
9
- export function encode(value: any): Buffer
1
+ import { Unpackr } from './unpack'
2
+ export { addExtension, FLOAT32_OPTIONS } from './unpack'
3
+ export class Packr extends Unpackr {
4
+ pack(value: any): Buffer
5
+ encode(value: any): Buffer
6
+ }
7
+ export class Encoder extends Packr {}
8
+ export function pack(value: any): Buffer
9
+ export function encode(value: any): Buffer
package/pack.js CHANGED
@@ -28,7 +28,6 @@ export class Packr extends Unpackr {
28
28
  let hasSharedUpdate
29
29
  let structures
30
30
  let referenceMap
31
- let lastSharedStructuresLength = 0
32
31
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
33
32
  return target.utf8Write(string, position, 0xffffffff)
34
33
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -114,7 +113,7 @@ export class Packr extends Unpackr {
114
113
  }
115
114
  transition[RECORD_SYMBOL] = i + 0x40
116
115
  }
117
- lastSharedStructuresLength = sharedLength
116
+ this.lastNamedStructuresLength = sharedLength
118
117
  }
119
118
  if (!isSequential) {
120
119
  structures.nextId = sharedLength + 0x40
@@ -123,7 +122,7 @@ export class Packr extends Unpackr {
123
122
  if (hasSharedUpdate)
124
123
  hasSharedUpdate = false
125
124
  try {
126
- if (packr.randomAccessStructure)
125
+ if (packr.randomAccessStructure && value.constructor && value.constructor === Object)
127
126
  writeStruct(value);
128
127
  else
129
128
  pack(value)
@@ -150,7 +149,7 @@ export class Packr extends Unpackr {
150
149
  if (structures) {
151
150
  if (serializationsSinceTransitionRebuild < 10)
152
151
  serializationsSinceTransitionRebuild++
153
- let sharedLength = structures.sharedLength || maxSharedStructures
152
+ let sharedLength = structures.sharedLength || 0
154
153
  if (structures.length > sharedLength)
155
154
  structures.length = sharedLength
156
155
  if (transitionsCount > 10000) {
@@ -169,12 +168,12 @@ export class Packr extends Unpackr {
169
168
  if (hasSharedUpdate && packr.saveStructures) {
170
169
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
171
170
  let returnBuffer = target.subarray(start, position)
172
- if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
171
+ let newSharedData = prepareStructures(structures, packr);
172
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
173
173
  // get updated structures and try again if the update failed
174
- packr._mergeStructures(packr.getStructures())
175
174
  return packr.pack(value)
176
175
  }
177
- lastSharedStructuresLength = sharedLength
176
+ packr.lastNamedStructuresLength = sharedLength
178
177
  return returnBuffer
179
178
  }
180
179
  }
@@ -292,7 +291,7 @@ export class Packr extends Unpackr {
292
291
  } else if (type === 'number') {
293
292
  if (value >>> 0 === value) {// positive integer, 32-bit or less
294
293
  // positive uint
295
- if (value < 0x40 || (value < 0x80 && this.useRecords === false)) {
294
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
296
295
  target[position++] = value
297
296
  } else if (value < 0x100) {
298
297
  target[position++] = 0xcc
@@ -692,16 +691,18 @@ export class Packr extends Unpackr {
692
691
  }
693
692
  }
694
693
  const writeStruct = (object, safePrototype) => {
695
- let newPosition = writeStructSlots(object, target, position, structures, makeRoom, (value, newPosition) => {
694
+ let newPosition = writeStructSlots(object, target, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
695
+ if (notifySharedUpdate)
696
+ return hasSharedUpdate = true;
696
697
  position = newPosition;
697
698
  if (start > 0) {
698
699
  pack(value);
699
700
  if (start == 0)
700
- return { position, targetView }; // indicate the buffer was re-allocated
701
+ return { position, targetView, target }; // indicate the buffer was re-allocated
701
702
  } else
702
703
  pack(value);
703
704
  return position;
704
- })
705
+ }, this);
705
706
  if (newPosition === 0) // bail and go to a msgpack object
706
707
  return writeObject(object, true);
707
708
  position = newPosition;
@@ -716,6 +717,8 @@ export class Packr extends Unpackr {
716
717
  clearSharedData() {
717
718
  if (this.structures)
718
719
  this.structures = []
720
+ if (this.typedStructs)
721
+ this.typedStructs = []
719
722
  }
720
723
  }
721
724
 
@@ -942,8 +945,18 @@ export function addExtension(extension) {
942
945
  }
943
946
  unpackAddExtension(extension)
944
947
  }
945
- export function setWriteStructSlots(func) {
946
- writeStructSlots = func;
948
+ function prepareStructures(structures, packr) {
949
+ structures.isCompatible = (existingStructures) => {
950
+ let compatible = !existingStructures || ((packr.lastNamedStructuresLength || 0) === existingStructures.length)
951
+ if (!compatible) // we want to merge these existing structures immediately since we already have it and we are in the right transaction
952
+ packr._mergeStructures(existingStructures);
953
+ return compatible;
954
+ }
955
+ return structures
956
+ }
957
+ export function setWriteStructSlots(writeSlots, makeStructures) {
958
+ writeStructSlots = writeSlots;
959
+ prepareStructures = makeStructures;
947
960
  }
948
961
 
949
962
  let defaultPackr = new Packr({ useRecords: false })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "msgpackr",
3
3
  "author": "Kris Zyp",
4
- "version": "1.7.0-alpha1",
4
+ "version": "1.7.0-alpha4",
5
5
  "description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
6
6
  "license": "MIT",
7
7
  "types": "./index.d.ts",
package/rollup.config.js CHANGED
@@ -1,45 +1,49 @@
1
- import minify from "rollup-plugin-babel-minify";
2
- import json from "@rollup/plugin-json";
3
-
4
- export default [
5
- {
6
- input: "node-index.js",
7
- output: [
8
- {
9
- file: "dist/node.cjs",
10
- format: "cjs"
11
- }
12
- ]
13
- },
14
- {
15
- input: "index.js",
16
- output: {
17
- file: "dist/index.js",
18
- format: "umd",
19
- name: "msgpackr"
20
- }
21
- },
22
- {
23
- input: "index.js",
24
- plugins: [minify({
25
- })],
26
- output: {
27
- file: "dist/index.min.js",
28
- format: "umd",
29
- name: "msgpackr"
30
- }
31
- },
32
- {
33
- input: "tests/test.js",
34
- plugins: [json()],
35
- external: ['chai', '../index.js'],
36
- output: {
37
- file: "dist/test.js",
38
- format: "iife",
39
- globals: {
40
- chai: 'chai',
41
- './index.js': 'msgpackr',
42
- },
43
- }
44
- }
45
- ];
1
+ import minify from "rollup-plugin-babel-minify";
2
+ import json from "@rollup/plugin-json";
3
+
4
+ export default [
5
+ {
6
+ input: "node-index.js",
7
+ output: [
8
+ {
9
+ file: "dist/node.cjs",
10
+ format: "cjs",
11
+ sourcemap: true
12
+ }
13
+ ]
14
+ },
15
+ {
16
+ input: "index.js",
17
+ output: {
18
+ file: "dist/index.js",
19
+ format: "umd",
20
+ name: "msgpackr",
21
+ sourcemap: true
22
+ }
23
+ },
24
+ {
25
+ input: "index.js",
26
+ plugins: [minify({
27
+ })],
28
+ output: {
29
+ file: "dist/index.min.js",
30
+ format: "umd",
31
+ name: "msgpackr",
32
+ sourcemap: true
33
+ }
34
+ },
35
+ {
36
+ input: "tests/test.js",
37
+ plugins: [json()],
38
+ external: ['chai', '../index.js'],
39
+ output: {
40
+ file: "dist/test.js",
41
+ format: "iife",
42
+ sourcemap: true,
43
+ globals: {
44
+ chai: 'chai',
45
+ './index.js': 'msgpackr',
46
+ },
47
+ }
48
+ }
49
+ ];
package/stream.js CHANGED
@@ -1,57 +1,57 @@
1
- import { Transform } from 'stream'
2
- import { Packr } from './pack.js'
3
- import { Unpackr } from './unpack.js'
4
- var DEFAULT_OPTIONS = {objectMode: true}
5
-
6
- export class PackrStream extends Transform {
7
- constructor(options) {
8
- if (!options)
9
- options = {}
10
- options.writableObjectMode = true
11
- super(options)
12
- options.sequential = true
13
- this.packr = options.packr || new Packr(options)
14
- }
15
- _transform(value, encoding, callback) {
16
- this.push(this.packr.pack(value))
17
- callback()
18
- }
19
- }
20
-
21
- export class UnpackrStream extends Transform {
22
- constructor(options) {
23
- if (!options)
24
- options = {}
25
- options.objectMode = true
26
- super(options)
27
- options.structures = []
28
- this.unpackr = options.unpackr || new Unpackr(options)
29
- }
30
- _transform(chunk, encoding, callback) {
31
- if (this.incompleteBuffer) {
32
- chunk = Buffer.concat([this.incompleteBuffer, chunk])
33
- this.incompleteBuffer = null
34
- }
35
- let values
36
- try {
37
- values = this.unpackr.unpackMultiple(chunk)
38
- } catch(error) {
39
- if (error.incomplete) {
40
- this.incompleteBuffer = chunk.slice(error.lastPosition)
41
- values = error.values
42
- }
43
- else
44
- throw error
45
- } finally {
46
- for (let value of values || []) {
47
- if (value === null)
48
- value = this.getNullValue()
49
- this.push(value)
50
- }
51
- }
52
- if (callback) callback()
53
- }
54
- getNullValue() {
55
- return Symbol.for(null)
56
- }
57
- }
1
+ import { Transform } from 'stream'
2
+ import { Packr } from './pack.js'
3
+ import { Unpackr } from './unpack.js'
4
+ var DEFAULT_OPTIONS = {objectMode: true}
5
+
6
+ export class PackrStream extends Transform {
7
+ constructor(options) {
8
+ if (!options)
9
+ options = {}
10
+ options.writableObjectMode = true
11
+ super(options)
12
+ options.sequential = true
13
+ this.packr = options.packr || new Packr(options)
14
+ }
15
+ _transform(value, encoding, callback) {
16
+ this.push(this.packr.pack(value))
17
+ callback()
18
+ }
19
+ }
20
+
21
+ export class UnpackrStream extends Transform {
22
+ constructor(options) {
23
+ if (!options)
24
+ options = {}
25
+ options.objectMode = true
26
+ super(options)
27
+ options.structures = []
28
+ this.unpackr = options.unpackr || new Unpackr(options)
29
+ }
30
+ _transform(chunk, encoding, callback) {
31
+ if (this.incompleteBuffer) {
32
+ chunk = Buffer.concat([this.incompleteBuffer, chunk])
33
+ this.incompleteBuffer = null
34
+ }
35
+ let values
36
+ try {
37
+ values = this.unpackr.unpackMultiple(chunk)
38
+ } catch(error) {
39
+ if (error.incomplete) {
40
+ this.incompleteBuffer = chunk.slice(error.lastPosition)
41
+ values = error.values
42
+ }
43
+ else
44
+ throw error
45
+ } finally {
46
+ for (let value of values || []) {
47
+ if (value === null)
48
+ value = this.getNullValue()
49
+ this.push(value)
50
+ }
51
+ }
52
+ if (callback) callback()
53
+ }
54
+ getNullValue() {
55
+ return Symbol.for(null)
56
+ }
57
+ }