amqplib 0.10.8 → 1.0.0
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/.claude/commands/lint-disable.md +9 -0
- package/.claude/commands/lint-enable.md +12 -0
- package/.claude/settings.local.json +16 -0
- package/.github/workflows/publish.yml +1 -1
- package/.github/workflows/test.yml +1 -1
- package/CHANGELOG.md +34 -0
- package/CLAUDE.md +12 -0
- package/Makefile +5 -12
- package/bin/generate-defs.js +382 -369
- package/biome.json +51 -0
- package/callback_api.js +12 -8
- package/channel_api.js +5 -10
- package/examples/direct_reply_to_client.js +9 -5
- package/examples/direct_reply_to_server.js +8 -6
- package/examples/headers.js +13 -10
- package/examples/receive_generator.js +13 -20
- package/examples/send_generators.js +2 -9
- package/examples/ssl.js +2 -3
- package/examples/stream_queues/receive_stream.js +39 -36
- package/examples/stream_queues/send_stream.js +26 -29
- package/examples/tutorials/callback_api/emit_log.js +4 -3
- package/examples/tutorials/callback_api/emit_log_direct.js +5 -4
- package/examples/tutorials/callback_api/emit_log_topic.js +5 -4
- package/examples/tutorials/callback_api/new_task.js +5 -4
- package/examples/tutorials/callback_api/receive.js +16 -10
- package/examples/tutorials/callback_api/receive_logs.js +17 -11
- package/examples/tutorials/callback_api/receive_logs_direct.js +19 -13
- package/examples/tutorials/callback_api/receive_logs_topic.js +19 -14
- package/examples/tutorials/callback_api/rpc_client.js +20 -16
- package/examples/tutorials/callback_api/rpc_server.js +27 -21
- package/examples/tutorials/callback_api/send.js +4 -3
- package/examples/tutorials/callback_api/worker.js +18 -13
- package/examples/tutorials/emit_log.js +4 -6
- package/examples/tutorials/emit_log_direct.js +5 -7
- package/examples/tutorials/emit_log_topic.js +5 -7
- package/examples/tutorials/new_task.js +4 -6
- package/examples/tutorials/receive.js +8 -4
- package/examples/tutorials/receive_logs.js +10 -6
- package/examples/tutorials/receive_logs_direct.js +16 -10
- package/examples/tutorials/receive_logs_topic.js +16 -11
- package/examples/tutorials/rpc_client.js +17 -15
- package/examples/tutorials/rpc_server.js +9 -8
- package/examples/tutorials/send.js +4 -6
- package/examples/tutorials/worker.js +17 -14
- package/examples/waitForConfirms.js +2 -2
- package/lefthook.yml +14 -0
- package/lib/api_args.js +124 -149
- package/lib/bitset.js +28 -18
- package/lib/callback_model.js +134 -190
- package/lib/channel.js +175 -213
- package/lib/channel_model.js +41 -85
- package/lib/codec.js +257 -228
- package/lib/connect.js +74 -82
- package/lib/connection.js +204 -240
- package/lib/credentials.js +21 -29
- package/lib/defs.js +2559 -1927
- package/lib/error.js +5 -6
- package/lib/format.js +15 -33
- package/lib/frame.js +66 -66
- package/lib/heartbeat.js +17 -24
- package/lib/mux.js +32 -41
- package/package.json +8 -5
- package/test/bitset.test.js +65 -0
- package/test/callback_api.test.js +438 -0
- package/test/channel.test.js +592 -0
- package/test/channel_api.test.js +537 -0
- package/test/codec.test.js +172 -0
- package/test/connect.test.js +196 -0
- package/test/connection.test.js +330 -0
- package/test/data.test.js +33 -0
- package/test/frame.test.js +180 -0
- package/test/lib/data.js +249 -0
- package/test/lib/util.js +223 -0
- package/test/mux.test.js +215 -0
- package/test/bitset.js +0 -69
- package/test/callback_api.js +0 -379
- package/test/channel.js +0 -621
- package/test/channel_api.js +0 -606
- package/test/codec.js +0 -237
- package/test/connect.js +0 -197
- package/test/connection.js +0 -390
- package/test/data.js +0 -269
- package/test/frame.js +0 -191
- package/test/mux.js +0 -203
- package/test/util.js +0 -217
package/lib/codec.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
1
|
/*
|
|
6
|
-
|
|
7
2
|
The AMQP 0-9-1 is a mess when it comes to the types that can be
|
|
8
3
|
encoded on the wire.
|
|
9
4
|
|
|
@@ -48,12 +43,9 @@ except that they appear in content header frames, which include a
|
|
|
48
43
|
content size, and they carry a set of flags indicating which
|
|
49
44
|
properties are present. This scheme can save ones of bytes per message
|
|
50
45
|
(messages which take a minimum of three frames each to send).
|
|
51
|
-
|
|
52
46
|
*/
|
|
53
47
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
var ints = require('buffer-more-ints');
|
|
48
|
+
const ints = require('buffer-more-ints');
|
|
57
49
|
|
|
58
50
|
// JavaScript uses only doubles so what I'm testing for is whether
|
|
59
51
|
// it's *better* to encode a number as a float or double. This really
|
|
@@ -69,276 +61,313 @@ var ints = require('buffer-more-ints');
|
|
|
69
61
|
// as a 64-bit integer. Except that only signed integers are supported
|
|
70
62
|
// by RabbitMQ, so anything above 2^63 - 1 must be a double.
|
|
71
63
|
function isFloatingPoint(n) {
|
|
72
|
-
|
|
73
|
-
(Math.abs(n) < 0x4000000000000
|
|
74
|
-
&& Math.floor(n) !== n);
|
|
64
|
+
return n >= 0x8000000000000000 || (Math.abs(n) < 0x4000000000000 && Math.floor(n) !== n);
|
|
75
65
|
}
|
|
76
66
|
|
|
77
67
|
function encodeTable(buffer, val, offset) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
68
|
+
const start = offset;
|
|
69
|
+
offset += 4; // leave room for the table length
|
|
70
|
+
for (const key in val) {
|
|
71
|
+
if (val[key] !== undefined) {
|
|
72
|
+
const len = Buffer.byteLength(key);
|
|
73
|
+
buffer.writeUInt8(len, offset);
|
|
74
|
+
offset++;
|
|
75
|
+
buffer.write(key, offset, 'utf8');
|
|
76
|
+
offset += len;
|
|
77
|
+
offset += encodeFieldValue(buffer, val[key], offset);
|
|
87
78
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
}
|
|
80
|
+
const size = offset - start;
|
|
81
|
+
buffer.writeUInt32BE(size - 4, start);
|
|
82
|
+
return size;
|
|
91
83
|
}
|
|
92
84
|
|
|
93
85
|
function encodeArray(buffer, val, offset) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
const start = offset;
|
|
87
|
+
offset += 4;
|
|
88
|
+
for (let i = 0, num = val.length; i < num; i++) {
|
|
89
|
+
offset += encodeFieldValue(buffer, val[i], offset);
|
|
90
|
+
}
|
|
91
|
+
const size = offset - start;
|
|
92
|
+
buffer.writeUInt32BE(size - 4, start);
|
|
93
|
+
return size;
|
|
102
94
|
}
|
|
103
95
|
|
|
104
96
|
function encodeFieldValue(buffer, value, offset) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
97
|
+
const start = offset;
|
|
98
|
+
let type = typeof value;
|
|
99
|
+
let val = value;
|
|
100
|
+
// A trapdoor for specifying a type, e.g., timestamp
|
|
101
|
+
if (value && type === 'object' && Object.hasOwn(value, '!')) {
|
|
102
|
+
val = value.value;
|
|
103
|
+
type = value['!'];
|
|
104
|
+
}
|
|
112
105
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
else {
|
|
142
|
-
type = 'long';
|
|
143
|
-
}
|
|
144
|
-
}
|
|
106
|
+
// If it's a JS number, we'll have to guess what type to encode it
|
|
107
|
+
// as.
|
|
108
|
+
if (type === 'number') {
|
|
109
|
+
// Making assumptions about the kind of number (floating point
|
|
110
|
+
// v integer, signed, unsigned, size) desired is dangerous in
|
|
111
|
+
// general; however, in practice RabbitMQ uses only
|
|
112
|
+
// longstrings and unsigned integers in its arguments, and
|
|
113
|
+
// other clients generally conflate number types anyway. So
|
|
114
|
+
// the only distinction we care about is floating point vs
|
|
115
|
+
// integers, preferring integers since those can be promoted
|
|
116
|
+
// if necessary. If floating point is required, we may as well
|
|
117
|
+
// use double precision.
|
|
118
|
+
if (isFloatingPoint(val)) {
|
|
119
|
+
type = 'double';
|
|
120
|
+
} else {
|
|
121
|
+
// only signed values are used in tables by
|
|
122
|
+
// RabbitMQ. It *used* to (< v3.3.0) treat the byte 'b'
|
|
123
|
+
// type as unsigned, but most clients (and the spec)
|
|
124
|
+
// think it's signed, and now RabbitMQ does too.
|
|
125
|
+
if (val < 128 && val >= -128) {
|
|
126
|
+
type = 'byte';
|
|
127
|
+
} else if (val >= -0x8000 && val < 0x8000) {
|
|
128
|
+
type = 'short';
|
|
129
|
+
} else if (val >= -0x80000000 && val < 0x80000000) {
|
|
130
|
+
type = 'int';
|
|
131
|
+
} else {
|
|
132
|
+
type = 'long';
|
|
133
|
+
}
|
|
145
134
|
}
|
|
135
|
+
}
|
|
146
136
|
|
|
147
|
-
|
|
137
|
+
function tag(t) {
|
|
138
|
+
buffer.write(t, offset);
|
|
139
|
+
offset++;
|
|
140
|
+
}
|
|
148
141
|
|
|
149
|
-
|
|
150
|
-
case 'string':
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
142
|
+
switch (type) {
|
|
143
|
+
case 'string': {
|
|
144
|
+
// no shortstr in field tables
|
|
145
|
+
const len = Buffer.byteLength(val, 'utf8');
|
|
146
|
+
tag('S');
|
|
147
|
+
buffer.writeUInt32BE(len, offset);
|
|
148
|
+
offset += 4;
|
|
149
|
+
buffer.write(val, offset, 'utf8');
|
|
150
|
+
offset += len;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
156
153
|
case 'object':
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
break;
|
|
154
|
+
if (val === null) {
|
|
155
|
+
tag('V');
|
|
156
|
+
} else if (Array.isArray(val)) {
|
|
157
|
+
tag('A');
|
|
158
|
+
offset += encodeArray(buffer, val, offset);
|
|
159
|
+
} else if (Buffer.isBuffer(val)) {
|
|
160
|
+
tag('x');
|
|
161
|
+
buffer.writeUInt32BE(val.length, offset);
|
|
162
|
+
offset += 4;
|
|
163
|
+
val.copy(buffer, offset);
|
|
164
|
+
offset += val.length;
|
|
165
|
+
} else {
|
|
166
|
+
tag('F');
|
|
167
|
+
offset += encodeTable(buffer, val, offset);
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
174
170
|
case 'boolean':
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
171
|
+
tag('t');
|
|
172
|
+
buffer.writeUInt8(val ? 1 : 0, offset);
|
|
173
|
+
offset++;
|
|
174
|
+
break;
|
|
178
175
|
// These are the types that are either guessed above, or
|
|
179
176
|
// explicitly given using the {'!': type} notation.
|
|
180
177
|
case 'double':
|
|
181
178
|
case 'float64':
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
tag('d');
|
|
180
|
+
buffer.writeDoubleBE(val, offset);
|
|
181
|
+
offset += 8;
|
|
182
|
+
break;
|
|
186
183
|
case 'byte':
|
|
187
184
|
case 'int8':
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
185
|
+
tag('b');
|
|
186
|
+
buffer.writeInt8(val, offset);
|
|
187
|
+
offset++;
|
|
188
|
+
break;
|
|
191
189
|
case 'unsignedbyte':
|
|
192
190
|
case 'uint8':
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
191
|
+
tag('B');
|
|
192
|
+
buffer.writeUInt8(val, offset);
|
|
193
|
+
offset++;
|
|
194
|
+
break;
|
|
196
195
|
case 'short':
|
|
197
196
|
case 'int16':
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
tag('s');
|
|
198
|
+
buffer.writeInt16BE(val, offset);
|
|
199
|
+
offset += 2;
|
|
200
|
+
break;
|
|
201
201
|
case 'unsignedshort':
|
|
202
202
|
case 'uint16':
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
tag('u');
|
|
204
|
+
buffer.writeUInt16BE(val, offset);
|
|
205
|
+
offset += 2;
|
|
206
|
+
break;
|
|
206
207
|
case 'int':
|
|
207
208
|
case 'int32':
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
tag('I');
|
|
210
|
+
buffer.writeInt32BE(val, offset);
|
|
211
|
+
offset += 4;
|
|
212
|
+
break;
|
|
211
213
|
case 'unsignedint':
|
|
212
214
|
case 'uint32':
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
tag('i');
|
|
216
|
+
buffer.writeUInt32BE(val, offset);
|
|
217
|
+
offset += 4;
|
|
218
|
+
break;
|
|
216
219
|
case 'long':
|
|
217
220
|
case 'int64':
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
tag('l');
|
|
222
|
+
ints.writeInt64BE(buffer, val, offset);
|
|
223
|
+
offset += 8;
|
|
224
|
+
break;
|
|
221
225
|
|
|
222
226
|
// Now for exotic types, those can _only_ be denoted by using
|
|
223
227
|
// `{'!': type, value: val}
|
|
224
228
|
case 'timestamp':
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
229
|
+
tag('T');
|
|
230
|
+
ints.writeUInt64BE(buffer, val, offset);
|
|
231
|
+
offset += 8;
|
|
232
|
+
break;
|
|
228
233
|
case 'float':
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
tag('f');
|
|
235
|
+
buffer.writeFloatBE(val, offset);
|
|
236
|
+
offset += 4;
|
|
237
|
+
break;
|
|
232
238
|
case 'decimal':
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
"got " + JSON.stringify(val));
|
|
242
|
-
break;
|
|
239
|
+
tag('D');
|
|
240
|
+
if (Object.hasOwn(val, 'places') && Object.hasOwn(val, 'digits') && val.places >= 0 && val.places < 256) {
|
|
241
|
+
buffer[offset] = val.places;
|
|
242
|
+
offset++;
|
|
243
|
+
buffer.writeUInt32BE(val.digits, offset);
|
|
244
|
+
offset += 4;
|
|
245
|
+
} else throw new TypeError(`Decimal value must be {'places': 0..255, 'digits': uint32}, got ${JSON.stringify(val)}`);
|
|
246
|
+
break;
|
|
243
247
|
default:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
throw new TypeError(`Unknown type to encode: ${type}`);
|
|
249
|
+
}
|
|
250
|
+
return offset - start;
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
// Assume we're given a slice of the buffer that contains just the
|
|
250
254
|
// fields.
|
|
251
255
|
function decodeFields(slice) {
|
|
252
|
-
|
|
253
|
-
|
|
256
|
+
const fields = {};
|
|
257
|
+
let offset = 0;
|
|
258
|
+
const size = slice.length;
|
|
259
|
+
let len;
|
|
260
|
+
let key;
|
|
261
|
+
let val;
|
|
254
262
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
263
|
+
function decodeFieldValue() {
|
|
264
|
+
const tag = String.fromCharCode(slice[offset]);
|
|
265
|
+
offset++;
|
|
266
|
+
switch (tag) {
|
|
267
|
+
case 'b':
|
|
268
|
+
val = slice.readInt8(offset);
|
|
269
|
+
offset++;
|
|
270
|
+
break;
|
|
271
|
+
case 'B':
|
|
272
|
+
val = slice.readUInt8(offset);
|
|
273
|
+
offset++;
|
|
274
|
+
break;
|
|
275
|
+
case 'S':
|
|
276
|
+
len = slice.readUInt32BE(offset);
|
|
277
|
+
offset += 4;
|
|
278
|
+
val = slice.toString('utf8', offset, offset + len);
|
|
279
|
+
offset += len;
|
|
280
|
+
break;
|
|
281
|
+
case 'I':
|
|
282
|
+
val = slice.readInt32BE(offset);
|
|
283
|
+
offset += 4;
|
|
284
|
+
break;
|
|
285
|
+
case 'i':
|
|
286
|
+
val = slice.readUInt32BE(offset);
|
|
287
|
+
offset += 4;
|
|
288
|
+
break;
|
|
289
|
+
case 'D': {
|
|
290
|
+
// only positive decimals, apparently.
|
|
291
|
+
const places = slice[offset];
|
|
292
|
+
offset++;
|
|
293
|
+
const digits = slice.readUInt32BE(offset);
|
|
294
|
+
offset += 4;
|
|
295
|
+
val = { '!': 'decimal', value: { places: places, digits: digits } };
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
case 'T':
|
|
299
|
+
val = ints.readUInt64BE(slice, offset);
|
|
300
|
+
offset += 8;
|
|
301
|
+
val = { '!': 'timestamp', value: val };
|
|
302
|
+
break;
|
|
303
|
+
case 'F':
|
|
304
|
+
len = slice.readUInt32BE(offset);
|
|
305
|
+
offset += 4;
|
|
306
|
+
val = decodeFields(slice.subarray(offset, offset + len));
|
|
307
|
+
offset += len;
|
|
308
|
+
break;
|
|
309
|
+
case 'A':
|
|
310
|
+
len = slice.readUInt32BE(offset);
|
|
311
|
+
offset += 4;
|
|
312
|
+
decodeArray(offset + len);
|
|
313
|
+
// NB decodeArray will itself update offset and val
|
|
314
|
+
break;
|
|
315
|
+
case 'd':
|
|
316
|
+
val = slice.readDoubleBE(offset);
|
|
317
|
+
offset += 8;
|
|
318
|
+
break;
|
|
319
|
+
case 'f':
|
|
320
|
+
val = slice.readFloatBE(offset);
|
|
321
|
+
offset += 4;
|
|
322
|
+
break;
|
|
323
|
+
case 'l':
|
|
324
|
+
val = ints.readInt64BE(slice, offset);
|
|
325
|
+
offset += 8;
|
|
326
|
+
break;
|
|
327
|
+
case 's':
|
|
328
|
+
val = slice.readInt16BE(offset);
|
|
329
|
+
offset += 2;
|
|
330
|
+
break;
|
|
331
|
+
case 'u':
|
|
332
|
+
val = slice.readUInt16BE(offset);
|
|
333
|
+
offset += 2;
|
|
334
|
+
break;
|
|
335
|
+
case 't':
|
|
336
|
+
val = slice[offset] !== 0;
|
|
337
|
+
offset++;
|
|
338
|
+
break;
|
|
339
|
+
case 'V':
|
|
340
|
+
val = null;
|
|
341
|
+
break;
|
|
342
|
+
case 'x':
|
|
343
|
+
len = slice.readUInt32BE(offset);
|
|
344
|
+
offset += 4;
|
|
345
|
+
val = slice.subarray(offset, offset + len);
|
|
346
|
+
offset += len;
|
|
347
|
+
break;
|
|
348
|
+
default:
|
|
349
|
+
throw new TypeError(`Unexpected type tag "${tag}"`);
|
|
323
350
|
}
|
|
351
|
+
}
|
|
324
352
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
val = vals;
|
|
353
|
+
function decodeArray(until) {
|
|
354
|
+
const vals = [];
|
|
355
|
+
while (offset < until) {
|
|
356
|
+
decodeFieldValue();
|
|
357
|
+
vals.push(val);
|
|
332
358
|
}
|
|
359
|
+
val = vals;
|
|
360
|
+
}
|
|
333
361
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
362
|
+
while (offset < size) {
|
|
363
|
+
len = slice.readUInt8(offset);
|
|
364
|
+
offset++;
|
|
365
|
+
key = slice.toString('utf8', offset, offset + len);
|
|
366
|
+
offset += len;
|
|
367
|
+
decodeFieldValue();
|
|
368
|
+
fields[key] = val;
|
|
369
|
+
}
|
|
370
|
+
return fields;
|
|
342
371
|
}
|
|
343
372
|
|
|
344
373
|
module.exports.encodeTable = encodeTable;
|