msgpack5 5.3.1 → 6.0.1
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/.github/workflows/ci.yml +1 -1
- package/dist/msgpack5.js +458 -350
- package/dist/msgpack5.min.js +1 -1
- package/lib/decoder.js +179 -181
- package/package.json +2 -2
- package/test/nested-containers.js +44 -0
package/lib/decoder.js
CHANGED
|
@@ -38,233 +38,231 @@ function isValidDataSize (dataLength, bufLength, headerLength) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
module.exports = function buildDecode (decodingTypes, options) {
|
|
41
|
+
const context = { decodingTypes, options, decode }
|
|
41
42
|
return decode
|
|
42
43
|
|
|
43
44
|
function decode (buf) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
buf = bl().append(buf)
|
|
45
|
+
if (!bl.isBufferList(buf)) {
|
|
46
|
+
buf = bl(buf)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const result = tryDecode(buf, 0)
|
|
49
|
+
const result = tryDecode(buf, 0, context)
|
|
50
50
|
// Handle worst case ASAP and keep code flat
|
|
51
51
|
if (!result) throw new IncompleteBufferError()
|
|
52
52
|
|
|
53
53
|
buf.consume(result[1])
|
|
54
54
|
return result[0]
|
|
55
55
|
}
|
|
56
|
+
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let offset = initialOffset
|
|
58
|
+
function decodeArray (buf, initialOffset, length, headerLength, context) {
|
|
59
|
+
let offset = initialOffset
|
|
60
|
+
const result = []
|
|
61
|
+
let i = 0
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
offset
|
|
63
|
+
while (i++ < length) {
|
|
64
|
+
const decodeResult = tryDecode(buf, offset, context)
|
|
65
|
+
if (!decodeResult) return null
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
result.push(decodeResult[0])
|
|
68
|
+
offset += decodeResult[1]
|
|
69
|
+
}
|
|
70
|
+
return [result, headerLength + offset - initialOffset]
|
|
71
|
+
}
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
function decodeMap (buf, offset, length, headerLength, context) {
|
|
74
|
+
const _temp = decodeArray(buf, offset, 2 * length, headerLength, context)
|
|
75
|
+
if (!_temp) return null
|
|
76
|
+
const [result, consumedBytes] = _temp
|
|
70
77
|
|
|
71
|
-
|
|
72
|
-
if ((first & 0xf0) === 0x80) {
|
|
73
|
-
const length = first & 0x0f
|
|
74
|
-
const headerSize = offset - initialOffset
|
|
75
|
-
// we have a map with less than 15 elements
|
|
76
|
-
return decodeMap(buf, offset, length, headerSize, options)
|
|
77
|
-
}
|
|
78
|
-
if ((first & 0xf0) === 0x90) {
|
|
79
|
-
const length = first & 0x0f
|
|
80
|
-
const headerSize = offset - initialOffset
|
|
81
|
-
// we have an array with less than 15 elements
|
|
82
|
-
return decodeArray(buf, offset, length, headerSize)
|
|
83
|
-
}
|
|
78
|
+
let isPlainObject = !context.options.preferMap
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (inRange(0xc0, 0xc3)) return decodeConstants(first)
|
|
93
|
-
if (inRange(0xc4, 0xc6)) {
|
|
94
|
-
const length = buf.readUIntBE(offset, size - 1)
|
|
95
|
-
offset += size - 1
|
|
96
|
-
|
|
97
|
-
if (!isValidDataSize(length, bufLength, size)) return null
|
|
98
|
-
const result = buf.slice(offset, offset + length)
|
|
99
|
-
return [result, size + length]
|
|
80
|
+
if (isPlainObject) {
|
|
81
|
+
for (let i = 0; i < 2 * length; i += 2) {
|
|
82
|
+
if (typeof result[i] !== 'string') {
|
|
83
|
+
isPlainObject = false
|
|
84
|
+
break
|
|
85
|
+
}
|
|
100
86
|
}
|
|
101
|
-
|
|
102
|
-
const length = buf.readUIntBE(offset, size - 2)
|
|
103
|
-
offset += size - 2
|
|
87
|
+
}
|
|
104
88
|
|
|
105
|
-
|
|
106
|
-
|
|
89
|
+
if (isPlainObject) {
|
|
90
|
+
const object = {}
|
|
91
|
+
for (let i = 0; i < 2 * length; i += 2) {
|
|
92
|
+
const key = result[i]
|
|
93
|
+
const val = result[i + 1]
|
|
107
94
|
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (inRange(0xcc, 0xcf)) return decodeUnsignedInt(buf, offset, size - 1)
|
|
113
|
-
if (inRange(0xd0, 0xd3)) return decodeSigned(buf, offset, size - 1)
|
|
114
|
-
if (inRange(0xd4, 0xd8)) {
|
|
115
|
-
const type = buf.readInt8(offset) // Signed
|
|
116
|
-
offset += 1
|
|
117
|
-
return decodeExt(buf, offset, type, size - 2, 2)
|
|
118
|
-
}
|
|
95
|
+
if (key === '__proto__') {
|
|
96
|
+
if (context.options.protoAction === 'error') {
|
|
97
|
+
throw new SyntaxError('Object contains forbidden prototype property')
|
|
98
|
+
}
|
|
119
99
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
100
|
+
if (context.options.protoAction === 'remove') {
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
}
|
|
123
104
|
|
|
124
|
-
|
|
125
|
-
const result = buf.toString('utf8', offset, offset + length)
|
|
126
|
-
return [result, size + length]
|
|
105
|
+
object[key] = val
|
|
127
106
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
switch (first) {
|
|
136
|
-
case 0xde:
|
|
137
|
-
// maps up to 2^16 elements - 2 bytes
|
|
138
|
-
length = buf.readUInt16BE(offset)
|
|
139
|
-
offset += 2
|
|
140
|
-
// console.log(offset - initialOffset)
|
|
141
|
-
return decodeMap(buf, offset, length, 3, options)
|
|
142
|
-
|
|
143
|
-
case 0xdf:
|
|
144
|
-
length = buf.readUInt32BE(offset)
|
|
145
|
-
offset += 4
|
|
146
|
-
return decodeMap(buf, offset, length, 5, options)
|
|
147
|
-
}
|
|
107
|
+
return [object, consumedBytes]
|
|
108
|
+
} else {
|
|
109
|
+
const mapping = new Map()
|
|
110
|
+
for (let i = 0; i < 2 * length; i += 2) {
|
|
111
|
+
const key = result[i]
|
|
112
|
+
const val = result[i + 1]
|
|
113
|
+
mapping.set(key, val)
|
|
148
114
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
throw new Error('not implemented yet')
|
|
115
|
+
return [mapping, consumedBytes]
|
|
152
116
|
}
|
|
117
|
+
}
|
|
153
118
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const result = []
|
|
157
|
-
let i = 0
|
|
119
|
+
function tryDecode (buf, initialOffset, context) {
|
|
120
|
+
if (buf.length <= initialOffset) return null
|
|
158
121
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!decodeResult) return null
|
|
122
|
+
const bufLength = buf.length - initialOffset
|
|
123
|
+
let offset = initialOffset
|
|
162
124
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
return [result, headerLength + offset - initialOffset]
|
|
167
|
-
}
|
|
125
|
+
const first = buf.readUInt8(offset)
|
|
126
|
+
offset += 1
|
|
168
127
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (!_temp) return null
|
|
172
|
-
const [result, consumedBytes] = _temp
|
|
128
|
+
const size = SIZES[first] || -1
|
|
129
|
+
if (bufLength < size) return null
|
|
173
130
|
|
|
174
|
-
|
|
131
|
+
if (first < 0x80) return [first, 1] // 7-bits positive ints
|
|
132
|
+
if ((first & 0xf0) === 0x80) {
|
|
133
|
+
const length = first & 0x0f
|
|
134
|
+
const headerSize = offset - initialOffset
|
|
135
|
+
// we have a map with less than 15 elements
|
|
136
|
+
return decodeMap(buf, offset, length, headerSize, context)
|
|
137
|
+
}
|
|
138
|
+
if ((first & 0xf0) === 0x90) {
|
|
139
|
+
const length = first & 0x0f
|
|
140
|
+
const headerSize = offset - initialOffset
|
|
141
|
+
// we have an array with less than 15 elements
|
|
142
|
+
return decodeArray(buf, offset, length, headerSize, context)
|
|
143
|
+
}
|
|
175
144
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
145
|
+
if ((first & 0xe0) === 0xa0) {
|
|
146
|
+
// fixstr up to 31 bytes
|
|
147
|
+
const length = first & 0x1f
|
|
148
|
+
if (!isValidDataSize(length, bufLength, 1)) return null
|
|
149
|
+
const result = buf.toString('utf8', offset, offset + length)
|
|
150
|
+
return [result, length + 1]
|
|
151
|
+
}
|
|
152
|
+
if (first >= 0xc0 && first <= 0xc3) return decodeConstants(first)
|
|
153
|
+
if (first >= 0xc4 && first <= 0xc6) {
|
|
154
|
+
const length = buf.readUIntBE(offset, size - 1)
|
|
155
|
+
offset += size - 1
|
|
156
|
+
|
|
157
|
+
if (!isValidDataSize(length, bufLength, size)) return null
|
|
158
|
+
const result = buf.slice(offset, offset + length)
|
|
159
|
+
return [result, size + length]
|
|
160
|
+
}
|
|
161
|
+
if (first >= 0xc7 && first <= 0xc9) {
|
|
162
|
+
const length = buf.readUIntBE(offset, size - 2)
|
|
163
|
+
offset += size - 2
|
|
184
164
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
for (let i = 0; i < 2 * length; i += 2) {
|
|
188
|
-
const key = result[i]
|
|
189
|
-
const val = result[i + 1]
|
|
165
|
+
const type = buf.readInt8(offset)
|
|
166
|
+
offset += 1
|
|
190
167
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
168
|
+
if (!isValidDataSize(length, bufLength, size)) return null
|
|
169
|
+
return decodeExt(buf, offset, type, length, size, context)
|
|
170
|
+
}
|
|
171
|
+
if (first >= 0xca && first <= 0xcb) return decodeFloat(buf, offset, size - 1)
|
|
172
|
+
if (first >= 0xcc && first <= 0xcf) return decodeUnsignedInt(buf, offset, size - 1)
|
|
173
|
+
if (first >= 0xd0 && first <= 0xd3) return decodeSigned(buf, offset, size - 1)
|
|
174
|
+
if (first >= 0xd4 && first <= 0xd8) {
|
|
175
|
+
const type = buf.readInt8(offset) // Signed
|
|
176
|
+
offset += 1
|
|
177
|
+
return decodeExt(buf, offset, type, size - 2, 2, context)
|
|
178
|
+
}
|
|
195
179
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
180
|
+
if (first >= 0xd9 && first <= 0xdb) {
|
|
181
|
+
const length = buf.readUIntBE(offset, size - 1)
|
|
182
|
+
offset += size - 1
|
|
200
183
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
184
|
+
if (!isValidDataSize(length, bufLength, size)) return null
|
|
185
|
+
const result = buf.toString('utf8', offset, offset + length)
|
|
186
|
+
return [result, size + length]
|
|
187
|
+
}
|
|
188
|
+
if (first >= 0xdc && first <= 0xdd) {
|
|
189
|
+
const length = buf.readUIntBE(offset, size - 1)
|
|
190
|
+
offset += size - 1
|
|
191
|
+
return decodeArray(buf, offset, length, size, context)
|
|
192
|
+
}
|
|
193
|
+
if (first >= 0xde && first <= 0xdf) {
|
|
194
|
+
let length
|
|
195
|
+
switch (first) {
|
|
196
|
+
case 0xde:
|
|
197
|
+
// maps up to 2^16 elements - 2 bytes
|
|
198
|
+
length = buf.readUInt16BE(offset)
|
|
199
|
+
offset += 2
|
|
200
|
+
// console.log(offset - initialOffset)
|
|
201
|
+
return decodeMap(buf, offset, length, 3, context)
|
|
202
|
+
|
|
203
|
+
case 0xdf:
|
|
204
|
+
length = buf.readUInt32BE(offset)
|
|
205
|
+
offset += 4
|
|
206
|
+
return decodeMap(buf, offset, length, 5, context)
|
|
212
207
|
}
|
|
213
208
|
}
|
|
209
|
+
if (first >= 0xe0) return [first - 0x100, 1] // 5 bits negative ints
|
|
214
210
|
|
|
215
|
-
|
|
216
|
-
|
|
211
|
+
throw new Error('not implemented yet')
|
|
212
|
+
}
|
|
217
213
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
214
|
+
function decodeSigned (buf, offset, size) {
|
|
215
|
+
let result
|
|
216
|
+
if (size === 1) result = buf.readInt8(offset)
|
|
217
|
+
if (size === 2) result = buf.readInt16BE(offset)
|
|
218
|
+
if (size === 4) result = buf.readInt32BE(offset)
|
|
219
|
+
if (size === 8) result = readInt64BE(buf.slice(offset, offset + 8), 0)
|
|
220
|
+
return [result, size + 1]
|
|
221
|
+
}
|
|
226
222
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return (hi * 4294967296 + lo) * (negate ? -1 : +1)
|
|
230
|
-
}
|
|
223
|
+
function decodeExt (buf, offset, type, size, headerSize, context) {
|
|
224
|
+
const toDecode = buf.slice(offset, offset + size)
|
|
231
225
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
let result = 0
|
|
235
|
-
while (offset < maxOffset) { result += buf.readUInt8(offset++) * Math.pow(256, maxOffset - offset) }
|
|
236
|
-
return [result, size + 1]
|
|
237
|
-
}
|
|
226
|
+
const decode = context.decodingTypes.get(type)
|
|
227
|
+
if (!decode) throw new Error('unable to find ext type ' + type)
|
|
238
228
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (first === 0xc3) return [true, 1]
|
|
243
|
-
}
|
|
229
|
+
const value = decode(toDecode)
|
|
230
|
+
return [value, headerSize + size]
|
|
231
|
+
}
|
|
244
232
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
return [result, size + 1]
|
|
252
|
-
}
|
|
233
|
+
function decodeUnsignedInt (buf, offset, size) {
|
|
234
|
+
const maxOffset = offset + size
|
|
235
|
+
let result = 0
|
|
236
|
+
while (offset < maxOffset) { result += buf.readUInt8(offset++) * Math.pow(256, maxOffset - offset) }
|
|
237
|
+
return [result, size + 1]
|
|
238
|
+
}
|
|
253
239
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
240
|
+
function decodeConstants (first) {
|
|
241
|
+
if (first === 0xc0) return [null, 1]
|
|
242
|
+
if (first === 0xc2) return [false, 1]
|
|
243
|
+
if (first === 0xc3) return [true, 1]
|
|
244
|
+
}
|
|
260
245
|
|
|
261
|
-
|
|
262
|
-
|
|
246
|
+
function decodeFloat (buf, offset, size) {
|
|
247
|
+
let result
|
|
248
|
+
if (size === 4) result = buf.readFloatBE(offset)
|
|
249
|
+
if (size === 8) result = buf.readDoubleBE(offset)
|
|
250
|
+
return [result, size + 1]
|
|
251
|
+
}
|
|
263
252
|
|
|
264
|
-
|
|
265
|
-
|
|
253
|
+
function readInt64BE (buf, offset) {
|
|
254
|
+
var negate = (buf[offset] & 0x80) == 0x80; // eslint-disable-line
|
|
266
255
|
|
|
267
|
-
|
|
268
|
-
|
|
256
|
+
if (negate) {
|
|
257
|
+
let carry = 1
|
|
258
|
+
for (let i = offset + 7; i >= offset; i--) {
|
|
259
|
+
const v = (buf[i] ^ 0xff) + carry
|
|
260
|
+
buf[i] = v & 0xff
|
|
261
|
+
carry = v >> 8
|
|
262
|
+
}
|
|
269
263
|
}
|
|
264
|
+
|
|
265
|
+
const hi = buf.readUInt32BE(offset + 0)
|
|
266
|
+
const lo = buf.readUInt32BE(offset + 4)
|
|
267
|
+
return (hi * 4294967296 + lo) * (negate ? -1 : +1)
|
|
270
268
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msgpack5",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"description": "A msgpack v5 implementation for node.js and the browser, with extension points",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"bl": "^
|
|
47
|
+
"bl": "^5.0.0",
|
|
48
48
|
"inherits": "^2.0.3",
|
|
49
49
|
"readable-stream": "^3.0.0",
|
|
50
50
|
"safe-buffer": "^5.1.2"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tape').test
|
|
4
|
+
const msgpack = require('../')
|
|
5
|
+
|
|
6
|
+
test('encode/decode nested containers (map/array)', function (t) {
|
|
7
|
+
const encoder = msgpack()
|
|
8
|
+
|
|
9
|
+
function doEncodeDecode (value) {
|
|
10
|
+
return encoder.decode(encoder.encode(value))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function preserveTest (A, message = 'works') {
|
|
14
|
+
const B = doEncodeDecode(A)
|
|
15
|
+
t.deepEqual(A, B, message)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
preserveTest({
|
|
19
|
+
hello: 'world',
|
|
20
|
+
digit: 111,
|
|
21
|
+
array: [1, 2, 3, 4, 'string', { hello: 'world' }]
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
preserveTest([
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
hello: 'world',
|
|
28
|
+
array: [1, 2, 3, 4, 'string', { hello: 'world' }]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
digit: 111
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
{
|
|
36
|
+
hello: 'world',
|
|
37
|
+
digit: 111,
|
|
38
|
+
array: [1, 2, 3, 4, 'string', { hello: 'world' }]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
t.end()
|
|
44
|
+
})
|