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/LICENSE +21 -21
- package/README.md +335 -335
- package/SECURITY.md +11 -11
- package/benchmark.md +67 -67
- package/dist/index.js +125 -100
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +79 -77
- package/dist/index.min.js.map +1 -0
- package/dist/node.cjs +797 -313
- package/dist/node.cjs.map +1 -0
- package/dist/test.js +712 -182
- package/dist/test.js.map +1 -0
- package/index.js +5 -5
- package/iterators.js +86 -86
- package/pack.d.ts +9 -9
- package/pack.js +26 -13
- package/package.json +1 -1
- package/rollup.config.js +49 -45
- package/stream.js +57 -57
- package/struct.js +642 -186
- package/unpack.js +39 -12
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
|
-
|
|
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 ||
|
|
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
|
-
|
|
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
|
-
|
|
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 <
|
|
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
|
-
|
|
946
|
-
|
|
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
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
+
}
|