msgpackr 1.6.1 → 1.7.0-alpha2

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/package.json CHANGED
@@ -1,83 +1,83 @@
1
- {
2
- "name": "msgpackr",
3
- "author": "Kris Zyp",
4
- "version": "1.6.1",
5
- "description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
6
- "license": "MIT",
7
- "types": "./index.d.ts",
8
- "main": "./dist/node.cjs",
9
- "module": "./index.js",
10
- "keywords": [
11
- "MessagePack",
12
- "msgpack",
13
- "performance",
14
- "structured",
15
- "clone"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "http://github.com/kriszyp/msgpackr"
20
- },
21
- "scripts": {
22
- "benchmark": "node ./tests/benchmark.cjs",
23
- "build": "rollup -c",
24
- "dry-run": "npm publish --dry-run",
25
- "prepare": "npm run build",
26
- "test": "mocha tests/test**.*js -u tdd --experimental-json-modules"
27
- },
28
- "type": "module",
29
- "exports": {
30
- ".": {
31
- "node": {
32
- "require": "./dist/node.cjs",
33
- "import": "./node-index.js"
34
- },
35
- "bun": {
36
- "require": "./dist/node.cjs",
37
- "import": "./node-index.js"
38
- },
39
- "default": "./index.js"
40
- },
41
- "./pack": {
42
- "node": {
43
- "import": "./index.js",
44
- "require": "./dist/node.cjs"
45
- },
46
- "bun": {
47
- "import": "./index.js",
48
- "require": "./dist/node.cjs"
49
- },
50
- "default": "./pack.js"
51
- },
52
- "./unpack": {
53
- "node": {
54
- "import": "./index.js",
55
- "require": "./dist/node.cjs"
56
- },
57
- "bun": {
58
- "import": "./index.js",
59
- "require": "./dist/node.cjs"
60
- },
61
- "default": "./unpack.js"
62
- }
63
- },
64
- "files": [
65
- "/dist",
66
- "*.md",
67
- "/*.js",
68
- "/*.ts"
69
- ],
70
- "optionalDependencies": {
71
- "msgpackr-extract": "^2.0.2"
72
- },
73
- "devDependencies": {
74
- "@rollup/plugin-json": "^4.1.0",
75
- "@types/node": "latest",
76
- "async": "^3",
77
- "chai": "^4.3.4",
78
- "esm": "^3.2.25",
79
- "mocha": "^8.1.3",
80
- "rollup": "^1.20.3",
81
- "rollup-plugin-babel-minify": "^9.0.0"
82
- }
83
- }
1
+ {
2
+ "name": "msgpackr",
3
+ "author": "Kris Zyp",
4
+ "version": "1.7.0-alpha2",
5
+ "description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
6
+ "license": "MIT",
7
+ "types": "./index.d.ts",
8
+ "main": "./dist/node.cjs",
9
+ "module": "./index.js",
10
+ "keywords": [
11
+ "MessagePack",
12
+ "msgpack",
13
+ "performance",
14
+ "structured",
15
+ "clone"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "http://github.com/kriszyp/msgpackr"
20
+ },
21
+ "scripts": {
22
+ "benchmark": "node ./tests/benchmark.cjs",
23
+ "build": "rollup -c",
24
+ "dry-run": "npm publish --dry-run",
25
+ "prepare": "npm run build",
26
+ "test": "mocha tests/test**.*js -u tdd --experimental-json-modules"
27
+ },
28
+ "type": "module",
29
+ "exports": {
30
+ ".": {
31
+ "node": {
32
+ "require": "./dist/node.cjs",
33
+ "import": "./node-index.js"
34
+ },
35
+ "bun": {
36
+ "require": "./dist/node.cjs",
37
+ "import": "./node-index.js"
38
+ },
39
+ "default": "./index.js"
40
+ },
41
+ "./pack": {
42
+ "node": {
43
+ "import": "./index.js",
44
+ "require": "./dist/node.cjs"
45
+ },
46
+ "bun": {
47
+ "import": "./index.js",
48
+ "require": "./dist/node.cjs"
49
+ },
50
+ "default": "./pack.js"
51
+ },
52
+ "./unpack": {
53
+ "node": {
54
+ "import": "./index.js",
55
+ "require": "./dist/node.cjs"
56
+ },
57
+ "bun": {
58
+ "import": "./index.js",
59
+ "require": "./dist/node.cjs"
60
+ },
61
+ "default": "./unpack.js"
62
+ }
63
+ },
64
+ "files": [
65
+ "/dist",
66
+ "*.md",
67
+ "/*.js",
68
+ "/*.ts"
69
+ ],
70
+ "optionalDependencies": {
71
+ "msgpackr-extract": "^2.1.1"
72
+ },
73
+ "devDependencies": {
74
+ "@rollup/plugin-json": "^4.1.0",
75
+ "@types/node": "latest",
76
+ "async": "^3",
77
+ "chai": "^4.3.4",
78
+ "esm": "^3.2.25",
79
+ "mocha": "^8.1.3",
80
+ "rollup": "^1.20.3",
81
+ "rollup-plugin-babel-minify": "^9.0.0"
82
+ }
83
+ }
package/rollup.config.js CHANGED
@@ -7,7 +7,8 @@ export default [
7
7
  output: [
8
8
  {
9
9
  file: "dist/node.cjs",
10
- format: "cjs"
10
+ format: "cjs",
11
+ sourcemap: true
11
12
  }
12
13
  ]
13
14
  },
@@ -16,7 +17,8 @@ export default [
16
17
  output: {
17
18
  file: "dist/index.js",
18
19
  format: "umd",
19
- name: "msgpackr"
20
+ name: "msgpackr",
21
+ sourcemap: true
20
22
  }
21
23
  },
22
24
  {
@@ -26,7 +28,8 @@ export default [
26
28
  output: {
27
29
  file: "dist/index.min.js",
28
30
  format: "umd",
29
- name: "msgpackr"
31
+ name: "msgpackr",
32
+ sourcemap: true
30
33
  }
31
34
  },
32
35
  {
@@ -36,6 +39,7 @@ export default [
36
39
  output: {
37
40
  file: "dist/test.js",
38
41
  format: "iife",
42
+ sourcemap: true,
39
43
  globals: {
40
44
  chai: 'chai',
41
45
  './index.js': 'msgpackr',
package/struct.js ADDED
@@ -0,0 +1,262 @@
1
+ // first four bits
2
+ // 0000 - unsigned int
3
+ // 0010 - float32
4
+ // 0011 - float32
5
+ // 0100 - float32
6
+ // 0101 - float32
7
+ // 0110 - latin string reference
8
+ // 0111 - plain reference
9
+ // 1000 - structure reference
10
+ // 1001 - random access structure reference
11
+ // 1010 - float32
12
+ // 1011 - float32
13
+ // 1100 - float32
14
+ // 1101 - float32
15
+ // 1110 - constants and 3-byte strings
16
+ // 1111 - negative int
17
+
18
+ // first three bits
19
+ // 000 - unsigned int
20
+ // 001 - float32
21
+ // 010 - float32
22
+ // 011 - latin string reference
23
+ // 100 - reference
24
+ // 101 - float32
25
+ // 110 - float32
26
+ // 111 - constants and 3-byte strings
27
+
28
+ import { setWriteStructSlots, RECORD_SYMBOL } from './pack.js'
29
+ import { setReadStruct, unpack, mult10 } from './unpack.js';
30
+ const hasNonLatin = /[\u0080-\uFFFF]/;
31
+ const float32Headers = [false, true, true, false, false, true, true, false]
32
+ setWriteStructSlots(writeStruct);
33
+ function writeStruct(object, target, position, structures, makeRoom, pack) {
34
+ let transition = structures.transitions || false
35
+ let newTransitions = 0
36
+ let keyCount = 0;
37
+ let start = position;
38
+ position += 4;
39
+ let queuedReferences = [];
40
+ let uint32 = target.uint32 || (target.uint32 = new Uint32Array(target.buffer));
41
+ let targetView = target.dataView;
42
+ let encoded;
43
+ let stringData = '';
44
+ let safeEnd = target.length - 10;
45
+ for (let key in object) {
46
+ let nextTransition = transition[key]
47
+ if (!nextTransition) {
48
+ return 0; // bail
49
+ //nextTransition = transition[key] = Object.create(null)
50
+ //newTransitions++
51
+ }
52
+ if (position > safeEnd) {
53
+ let newPosition = position - start;
54
+ target = makeRoom(position)
55
+ position = newPosition;
56
+ start = 0
57
+ safeEnd = target.length - 10
58
+ }
59
+ transition = nextTransition
60
+ let value = object[key];
61
+ switch (typeof value) {
62
+ case 'number':
63
+ if (value >>> 0 === value && value < 0x20000000) {
64
+ encoded = value;
65
+ break;
66
+ } else if (value < 0x100000000 && value >= -0x80000000) {
67
+ targetView.setFloat32(position, value, true)
68
+ if (float32Headers[target[position + 3] >>> 5]) {
69
+ let xShifted
70
+ // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
71
+ if (((xShifted = value * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
72
+ position += 4;
73
+ continue;
74
+ }
75
+ }
76
+ }
77
+ // fall back to msgpack encoding
78
+ queuedReferences.push(value, position - start);
79
+ position += 4;
80
+ continue;
81
+ case 'string':
82
+ if (hasNonLatin.test(value)) {
83
+ queuedReferences.push(value, position - start);
84
+ position += 4;
85
+ continue;
86
+ }
87
+ if (value.length < 4) { // we can inline really small strings
88
+ encoded = 0xf8000000 + (value.length << 24) + (value.charCodeAt(0) << 16) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) || 0)
89
+ // TODO: determining remaining and make max value be a ratio of that (probably 1/256th)
90
+ } else if (value.length < 256 && stringData.length < 61440) {
91
+ // bundle these strings
92
+ encoded = 0x60000000 | (value.length << 16) | stringData.length;
93
+ stringData += value;
94
+ } else { // else queue it
95
+ queuedReferences.push(value, position - start);
96
+ position += 4;
97
+ continue;
98
+ }
99
+ break;
100
+ case 'object':
101
+ if (value) {
102
+ queuedReferences.push(value, position - start);
103
+ position += 4;
104
+ continue;
105
+ } else { // null
106
+ encoded = 0xe0000000;
107
+ }
108
+ break;
109
+ case 'boolean':
110
+ encoded = value ? 0xe3000000 : 0xe2000000;
111
+ break;
112
+ case 'undefined':
113
+ encoded = 0xe1000000;
114
+ break;
115
+ }
116
+ targetView.setUint32(position, encoded, true);
117
+ position += 4;
118
+ }
119
+ let recordId = transition[RECORD_SYMBOL]
120
+ if (!(recordId < 1024)) {
121
+ // for now just punt and go back to writeObject
122
+ return 0;
123
+ // newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions, true)
124
+ }
125
+ let stringLength = stringData.length;
126
+ if (stringData) {
127
+ if (position + stringLength > safeEnd) {
128
+ target = makeRoom(position + stringLength);
129
+ }
130
+ position += target.latin1Write(stringData, position, 0xffffffff);
131
+ }
132
+ target[start] = recordId >> 8;
133
+ target[start + 1] = recordId & 0xff;
134
+ target[start + 2] = stringLength >> 8;
135
+ target[start + 3] = stringLength & 0xff;
136
+ let queued32BitReferences;
137
+ for (let i = 0, l = queuedReferences.length; i < l;) {
138
+ let value = queuedReferences[i++];
139
+ let slotOffset = queuedReferences[i++] + start;
140
+ let offset = position - slotOffset;
141
+ if (offset < 0x1f000000) {
142
+ targetView.setUint32(slotOffset, 0x80000000 | (offset), true);
143
+ } else {
144
+ if (!queued32BitReferences)
145
+ queued32BitReferences = [];
146
+ queued32BitReferences.push({slotOffset, offset: position - start});
147
+ }
148
+ let newPosition = pack(value, position);
149
+ if (typeof newPosition === 'object') {
150
+ // re-allocated
151
+ position = newPosition.position;
152
+ targetView = newPosition.targetView;
153
+ start = 0;
154
+ } else
155
+ position = newPosition;
156
+ }
157
+ if (queued32BitReferences) {
158
+ // TODO: makeRoom
159
+ for (let i = 0, l = queued32BitReferences.length; i < l; i++) {
160
+ let ref = queued32BitReferences[i];
161
+ targetView.setUint32(ref.slotOffset, 0xa0000000 - ((l - i) << 2), true);
162
+ targetView.setUint32(position, ref.offset, true);
163
+ position += 4;
164
+ }
165
+ }
166
+
167
+ return position;
168
+ }
169
+ var sourceSymbol = Symbol('source')
170
+ function readStruct(src, position, srcEnd, structure, unpackr) {
171
+ var stringLength = (src[position++] << 8) | src[position++];
172
+ var construct = structure.construct;
173
+ if (!construct) {
174
+ construct = structure.construct = function() {
175
+ }
176
+ var prototype = construct.prototype;
177
+ Object.defineProperty(prototype, 'toJSON', {
178
+ get() {
179
+ // return an enumerable object with own properties to JSON stringify
180
+ let resolved = {};
181
+ for (let i = 0, l = structure.length; i < l; i++) {
182
+ let key = structure[i];
183
+ resolved[key] = this[key];
184
+ }
185
+ return resolved;
186
+ },
187
+ // not enumerable or anything
188
+ });
189
+ for (let i = 0, l = structure.length; i < l; i++) {
190
+ let key = structure[i];
191
+ Object.defineProperty(prototype, key, {
192
+ get() {
193
+ let source = this[sourceSymbol];
194
+ let src = source.src;
195
+ //let uint32 = src.uint32 || (src.uint32 = new Uint32Array(src.buffer, src.byteOffset, src.byteLength));
196
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
197
+ let position = source.position + (i << 2);
198
+ let value = dataView.getUint32(position, true);
199
+ let start;
200
+ switch (value >>> 29) {
201
+ case 0:
202
+ return value;
203
+ case 3:
204
+ if (value & 0x10000000) {
205
+ start = (value & 0xffff) + position;
206
+ return src.toString('utf8', start, start + ((value >> 16) & 0x7ff));
207
+ } else {
208
+ if (!source.srcString) {
209
+ start = source.position + (l << 2);
210
+ source.srcString = src.toString('latin1', start, start + source.stringLength);
211
+ }
212
+ start = value & 0xffff;
213
+ return source.srcString.slice(start, start + ((value >> 16) & 0x7ff));
214
+ }
215
+ case 4:
216
+ start = (0x1fffffff & value) + position;
217
+ let end = source.srcEnd;
218
+ for (let next = i + 1; next < l; next++) {
219
+ position = source.position + (next << 2);
220
+ let nextValue = dataView.getUint32(position, true);;
221
+ if ((nextValue & 0xe0000000) == -0x80000000) {
222
+ end = (0x1fffffff & nextValue) + position;
223
+ break;
224
+ }
225
+ }
226
+ return unpackr.unpack(src.slice(start, end));
227
+ case 1: case 2: case 5: case 6:
228
+ let fValue = dataView.getFloat32(position, true);
229
+ // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
230
+ let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)]
231
+ return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
232
+ case 7:
233
+ switch((value >> 24) & 0x1f) {
234
+ case 0: return null;
235
+ case 1: return undefined;
236
+ case 2: return false;
237
+ case 3: return true;
238
+ case 8: return dataView.getFloat64(position + (value & 0x3ffffff), true);
239
+ case 0x18: return '';
240
+ case 0x19: return String.fromCharCode((value >> 16) & 0xff);
241
+ case 0x1a: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff);
242
+ case 0x1b: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
243
+ default: throw new Error('Unknown constant');
244
+ }
245
+ }
246
+ },
247
+ enumerable: true,
248
+ });
249
+ }
250
+ }
251
+ var instance = new construct();
252
+ instance[sourceSymbol] = {
253
+ src,
254
+ uint32: src.uint32,
255
+ position,
256
+ srcString: '',
257
+ srcEnd,
258
+ stringLength
259
+ }
260
+ return instance;
261
+ }
262
+ setReadStruct(readStruct)
package/unpack.d.ts CHANGED
@@ -1,51 +1,53 @@
1
- export enum FLOAT32_OPTIONS {
2
- NEVER = 0,
3
- ALWAYS = 1,
4
- DECIMAL_ROUND = 3,
5
- DECIMAL_FIT = 4
6
- }
7
-
8
- export interface Options {
9
- useFloat32?: FLOAT32_OPTIONS
10
- useRecords?: boolean
11
- structures?: {}[]
12
- moreTypes?: boolean
13
- structuredClone?: boolean
14
- mapsAsObjects?: boolean
15
- variableMapSize?: boolean
16
- copyBuffers?: boolean
17
- bundleStrings?: boolean
18
- useTimestamp32?: boolean
19
- largeBigIntToFloat?: boolean
20
- encodeUndefinedAsNil?: boolean
21
- maxSharedStructures?: number
22
- maxOwnStructures?: number
23
- int64AsNumber?: boolean
24
- shouldShareStructure?: (keys: string[]) => boolean
25
- getStructures?(): {}[]
26
- saveStructures?(structures: {}[]): boolean | void
27
- onInvalidDate?: () => any
28
- }
29
- interface Extension {
30
- Class: Function
31
- type: number
32
- pack?(value: any): Buffer | Uint8Array
33
- unpack?(messagePack: Buffer | Uint8Array): any
34
- read?(datum: any): any
35
- write?(instance: any): any
36
- }
37
- export class Unpackr {
38
- constructor(options?: Options)
39
- unpack(messagePack: Buffer | Uint8Array): any
40
- decode(messagePack: Buffer | Uint8Array): any
41
- unpackMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
42
- }
43
- export class Decoder extends Unpackr {}
44
- export function unpack(messagePack: Buffer | Uint8Array): any
45
- export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
46
- export function decode(messagePack: Buffer | Uint8Array): any
47
- export function addExtension(extension: Extension): void
48
- export function clearSource(): void
49
- export function roundFloat32(float32Number: number): number
50
- export const C1: {}
1
+ export enum FLOAT32_OPTIONS {
2
+ NEVER = 0,
3
+ ALWAYS = 1,
4
+ DECIMAL_ROUND = 3,
5
+ DECIMAL_FIT = 4
6
+ }
7
+
8
+ export interface Options {
9
+ useFloat32?: FLOAT32_OPTIONS
10
+ useRecords?: boolean
11
+ structures?: {}[]
12
+ moreTypes?: boolean
13
+ structuredClone?: boolean
14
+ mapsAsObjects?: boolean
15
+ variableMapSize?: boolean
16
+ copyBuffers?: boolean
17
+ bundleStrings?: boolean
18
+ useTimestamp32?: boolean
19
+ largeBigIntToFloat?: boolean
20
+ encodeUndefinedAsNil?: boolean
21
+ maxSharedStructures?: number
22
+ maxOwnStructures?: number
23
+ int64AsNumber?: boolean
24
+ shouldShareStructure?: (keys: string[]) => boolean
25
+ getStructures?(): {}[]
26
+ saveStructures?(structures: {}[]): boolean | void
27
+ onInvalidDate?: () => any
28
+ }
29
+ interface Extension {
30
+ Class: Function
31
+ type: number
32
+ pack?(value: any): Buffer | Uint8Array
33
+ unpack?(messagePack: Buffer | Uint8Array): any
34
+ read?(datum: any): any
35
+ write?(instance: any): any
36
+ }
37
+ export class Unpackr {
38
+ constructor(options?: Options)
39
+ unpack(messagePack: Buffer | Uint8Array): any
40
+ decode(messagePack: Buffer | Uint8Array): any
41
+ unpackMultiple(messagePack: Buffer | Uint8Array): any[]
42
+ unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
43
+ }
44
+ export class Decoder extends Unpackr {}
45
+ export function unpack(messagePack: Buffer | Uint8Array): any
46
+ export function unpackMultiple(messagePack: Buffer | Uint8Array): any[]
47
+ export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
48
+ export function decode(messagePack: Buffer | Uint8Array): any
49
+ export function addExtension(extension: Extension): void
50
+ export function clearSource(): void
51
+ export function roundFloat32(float32Number: number): number
52
+ export const C1: {}
51
53
  export let isNativeAccelerationEnabled: boolean