amqplib 0.10.9 → 1.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/.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/README.md +0 -5
- 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 +76 -83
- 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 -204
- 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/bin/generate-defs.js
CHANGED
|
@@ -1,41 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
var format = require('util').format;
|
|
1
|
+
const format = require('node:util').format;
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
const defs = require('./amqp-rabbitmq-0.9.1.json');
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
const FRAME_OVERHEAD = 8; // type + channel + size + frame-end
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
const METHOD_OVERHEAD = FRAME_OVERHEAD + 4;
|
|
9
8
|
// F_O + classId + methodId
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
const PROPERTIES_OVERHEAD = FRAME_OVERHEAD + 4 + 8 + 2;
|
|
12
11
|
// F_O + classId + weight + content size + flags
|
|
13
12
|
|
|
13
|
+
const out = process.stdout;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function printf() {
|
|
18
|
-
out.write(format.apply(format, arguments), 'utf8');
|
|
15
|
+
function printf(...args) {
|
|
16
|
+
out.write(format.apply(format, args), 'utf8');
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
function nl() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function isEmptyObject(val) {
|
|
25
|
-
return (val != null && typeof val === 'object' &&
|
|
26
|
-
Object.keys(val).length === 0);
|
|
19
|
+
function nl() {
|
|
20
|
+
out.write('\n');
|
|
27
21
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
JSON.stringify(val);
|
|
22
|
+
function println(...args) {
|
|
23
|
+
printf.apply(printf, args);
|
|
24
|
+
nl();
|
|
32
25
|
}
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
const constants = {};
|
|
28
|
+
const constant_strs = {};
|
|
36
29
|
|
|
37
|
-
for (
|
|
38
|
-
|
|
30
|
+
for (let i = 0, len = defs.constants.length; i < len; i++) {
|
|
31
|
+
const cdef = defs.constants[i];
|
|
39
32
|
constants[constantName(cdef)] = cdef.value;
|
|
40
33
|
constant_strs[cdef.value] = cdef.name;
|
|
41
34
|
}
|
|
@@ -49,7 +42,7 @@ function methodName(clazz, method) {
|
|
|
49
42
|
}
|
|
50
43
|
|
|
51
44
|
function propertyName(dashed) {
|
|
52
|
-
|
|
45
|
+
const parts = dashed.split('-');
|
|
53
46
|
return parts[0] + parts.slice(1).map(initial).join('');
|
|
54
47
|
}
|
|
55
48
|
|
|
@@ -58,26 +51,26 @@ function initial(part) {
|
|
|
58
51
|
}
|
|
59
52
|
|
|
60
53
|
function argument(a) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return {type: type, name: friendlyName, default: a['default-value']};
|
|
54
|
+
const type = a.type || domains[a.domain];
|
|
55
|
+
const friendlyName = propertyName(a.name);
|
|
56
|
+
return { type: type, name: friendlyName, default: a['default-value'] };
|
|
64
57
|
}
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
for (
|
|
68
|
-
|
|
59
|
+
const domains = {};
|
|
60
|
+
for (let i = 0, len = defs.domains.length; i < len; i++) {
|
|
61
|
+
const dom = defs.domains[i];
|
|
69
62
|
domains[dom[0]] = dom[1];
|
|
70
63
|
}
|
|
71
64
|
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
const methods = {};
|
|
66
|
+
const propertieses = {};
|
|
74
67
|
|
|
75
|
-
for (
|
|
76
|
-
|
|
77
|
-
for (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
for (let i = 0, len = defs.classes.length; i < len; i++) {
|
|
69
|
+
const clazz = defs.classes[i];
|
|
70
|
+
for (let j = 0, num = clazz.methods.length; j < num; j++) {
|
|
71
|
+
const method = clazz.methods[j];
|
|
72
|
+
const name = methodName(clazz, method);
|
|
73
|
+
const info = `methodInfo${name}`;
|
|
81
74
|
|
|
82
75
|
methods[name] = {
|
|
83
76
|
id: methodId(clazz, method),
|
|
@@ -87,20 +80,20 @@ for (var i = 0, len = defs.classes.length; i < len; i++) {
|
|
|
87
80
|
clazz: clazz.name,
|
|
88
81
|
args: method['arguments'].map(argument),
|
|
89
82
|
isReply: method.answer,
|
|
90
|
-
encoder:
|
|
91
|
-
decoder:
|
|
92
|
-
info: info
|
|
83
|
+
encoder: `encode${name}`,
|
|
84
|
+
decoder: `decode${name}`,
|
|
85
|
+
info: info,
|
|
93
86
|
};
|
|
94
87
|
}
|
|
95
88
|
if (clazz.properties && clazz.properties.length > 0) {
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
const name = propertiesName(clazz);
|
|
90
|
+
const props = clazz.properties;
|
|
98
91
|
propertieses[name] = {
|
|
99
92
|
id: clazz.id,
|
|
100
93
|
name: name,
|
|
101
|
-
encoder:
|
|
102
|
-
decoder:
|
|
103
|
-
info:
|
|
94
|
+
encoder: `encode${name}`,
|
|
95
|
+
decoder: `decode${name}`,
|
|
96
|
+
info: `propertiesInfo${name}`,
|
|
104
97
|
args: props.map(argument),
|
|
105
98
|
};
|
|
106
99
|
}
|
|
@@ -109,14 +102,16 @@ for (var i = 0, len = defs.classes.length; i < len; i++) {
|
|
|
109
102
|
// OK let's get emitting
|
|
110
103
|
|
|
111
104
|
println(
|
|
112
|
-
'/** @preserve This file is generated by the script\n',
|
|
113
|
-
'* ../bin/generate-defs.js, which is not in general included in a\n',
|
|
114
|
-
'* distribution, but is available in the source repository e.g. at\n',
|
|
115
|
-
'* https://github.com/amqp-node/amqplib/\n',
|
|
116
|
-
'*/'
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
'/** @preserve This file is generated by the script\n',
|
|
106
|
+
'* ../bin/generate-defs.js, which is not in general included in a\n',
|
|
107
|
+
'* distribution, but is available in the source repository e.g. at\n',
|
|
108
|
+
'* https://github.com/amqp-node/amqplib/\n',
|
|
109
|
+
'*/',
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
println("'use strict';");
|
|
113
|
+
nl();
|
|
114
|
+
nl();
|
|
120
115
|
println('var codec = require("./codec");');
|
|
121
116
|
println('var ints = require("buffer-more-ints");');
|
|
122
117
|
println('var encodeTable = codec.encodeTable;');
|
|
@@ -126,77 +121,81 @@ nl();
|
|
|
126
121
|
println('var SCRATCH = Buffer.alloc(65536);');
|
|
127
122
|
println('var EMPTY_OBJECT = Object.freeze({});');
|
|
128
123
|
|
|
129
|
-
println('module.exports.constants = %s',
|
|
130
|
-
JSON.stringify(constants));
|
|
124
|
+
println('module.exports.constants = %s', JSON.stringify(constants));
|
|
131
125
|
nl();
|
|
132
|
-
println('module.exports.constant_strs = %s',
|
|
133
|
-
JSON.stringify(constant_strs));
|
|
126
|
+
println('module.exports.constant_strs = %s', JSON.stringify(constant_strs));
|
|
134
127
|
nl();
|
|
135
128
|
println('module.exports.FRAME_OVERHEAD = %d;', FRAME_OVERHEAD);
|
|
136
129
|
nl();
|
|
137
130
|
|
|
138
131
|
println('module.exports.decode = function(id, buf) {');
|
|
139
132
|
println('switch (id) {');
|
|
140
|
-
for (
|
|
141
|
-
|
|
133
|
+
for (const m in methods) {
|
|
134
|
+
const method = methods[m];
|
|
142
135
|
println('case %d: return %s(buf);', method.id, method.decoder);
|
|
143
136
|
}
|
|
144
|
-
for (
|
|
145
|
-
|
|
146
|
-
println('case %d: return %s(buf);', props.id,
|
|
137
|
+
for (const p in propertieses) {
|
|
138
|
+
const props = propertieses[p];
|
|
139
|
+
println('case %d: return %s(buf);', props.id, props.decoder);
|
|
147
140
|
}
|
|
148
141
|
println('default: throw new Error("Unknown class/method ID");');
|
|
149
|
-
println('}}');
|
|
142
|
+
println('}}');
|
|
143
|
+
nl();
|
|
150
144
|
|
|
151
|
-
println('module.exports.encodeMethod =',
|
|
152
|
-
'function(id, channel, fields) {');
|
|
145
|
+
println('module.exports.encodeMethod =', 'function(id, channel, fields) {');
|
|
153
146
|
println('switch (id) {');
|
|
154
|
-
for (
|
|
155
|
-
|
|
156
|
-
println('case %d: return %s(channel, fields);',
|
|
157
|
-
method.id, method.encoder);
|
|
147
|
+
for (const m in methods) {
|
|
148
|
+
const method = methods[m];
|
|
149
|
+
println('case %d: return %s(channel, fields);', method.id, method.encoder);
|
|
158
150
|
}
|
|
159
151
|
println('default: throw new Error("Unknown class/method ID");');
|
|
160
|
-
println('}}');
|
|
152
|
+
println('}}');
|
|
153
|
+
nl();
|
|
161
154
|
|
|
162
|
-
println('module.exports.encodeProperties ='
|
|
163
|
-
, 'function(id, channel, size, fields) {');
|
|
155
|
+
println('module.exports.encodeProperties =', 'function(id, channel, size, fields) {');
|
|
164
156
|
println('switch (id) {');
|
|
165
|
-
for (
|
|
166
|
-
|
|
167
|
-
println('case %d: return %s(channel, size, fields);',
|
|
168
|
-
props.id, props.encoder);
|
|
157
|
+
for (const p in propertieses) {
|
|
158
|
+
const props = propertieses[p];
|
|
159
|
+
println('case %d: return %s(channel, size, fields);', props.id, props.encoder);
|
|
169
160
|
}
|
|
170
161
|
println('default: throw new Error("Unknown class/properties ID");');
|
|
171
|
-
println('}}');
|
|
162
|
+
println('}}');
|
|
163
|
+
nl();
|
|
172
164
|
|
|
173
165
|
println('module.exports.info = function(id) {');
|
|
174
166
|
println('switch(id) {');
|
|
175
|
-
for (
|
|
176
|
-
|
|
167
|
+
for (const m in methods) {
|
|
168
|
+
const method = methods[m];
|
|
177
169
|
println('case %d: return %s; ', method.id, method.info);
|
|
178
170
|
}
|
|
179
|
-
for (
|
|
180
|
-
|
|
171
|
+
for (const p in propertieses) {
|
|
172
|
+
const properties = propertieses[p];
|
|
181
173
|
println('case %d: return %s', properties.id, properties.info);
|
|
182
174
|
}
|
|
183
175
|
println('default: throw new Error("Unknown class/method ID");');
|
|
184
|
-
println('}}');
|
|
176
|
+
println('}}');
|
|
177
|
+
nl();
|
|
185
178
|
|
|
186
|
-
for (
|
|
187
|
-
|
|
179
|
+
for (const m in methods) {
|
|
180
|
+
const method = methods[m];
|
|
188
181
|
println('module.exports.%s = %d;', m, method.id);
|
|
189
|
-
decoderFn(method);
|
|
190
|
-
|
|
191
|
-
|
|
182
|
+
decoderFn(method);
|
|
183
|
+
nl();
|
|
184
|
+
encoderFn(method);
|
|
185
|
+
nl();
|
|
186
|
+
infoObj(method);
|
|
187
|
+
nl();
|
|
192
188
|
}
|
|
193
189
|
|
|
194
|
-
for (
|
|
195
|
-
|
|
190
|
+
for (const p in propertieses) {
|
|
191
|
+
const properties = propertieses[p];
|
|
196
192
|
println('module.exports.%s = %d;', p, properties.id);
|
|
197
|
-
encodePropsFn(properties);
|
|
198
|
-
|
|
199
|
-
|
|
193
|
+
encodePropsFn(properties);
|
|
194
|
+
nl();
|
|
195
|
+
decodePropsFn(properties);
|
|
196
|
+
nl();
|
|
197
|
+
infoObj(properties);
|
|
198
|
+
nl();
|
|
200
199
|
}
|
|
201
200
|
|
|
202
201
|
function methodId(clazz, method) {
|
|
@@ -204,46 +203,55 @@ function methodId(clazz, method) {
|
|
|
204
203
|
}
|
|
205
204
|
|
|
206
205
|
function propertiesName(clazz) {
|
|
207
|
-
return initial(clazz.name)
|
|
206
|
+
return `${initial(clazz.name)}Properties`;
|
|
208
207
|
}
|
|
209
208
|
|
|
210
209
|
function valTypeTest(arg) {
|
|
211
210
|
switch (arg.type) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
"
|
|
221
|
-
|
|
222
|
-
|
|
211
|
+
// everything is booleany
|
|
212
|
+
case 'bit':
|
|
213
|
+
return 'true';
|
|
214
|
+
case 'octet':
|
|
215
|
+
case 'short':
|
|
216
|
+
case 'long':
|
|
217
|
+
case 'longlong':
|
|
218
|
+
case 'timestamp':
|
|
219
|
+
return "typeof val === 'number' && !isNaN(val)";
|
|
220
|
+
case 'shortstr':
|
|
221
|
+
return "typeof val === 'string' &&" + ' Buffer.byteLength(val) < 256';
|
|
222
|
+
case 'longstr':
|
|
223
|
+
return 'Buffer.isBuffer(val)';
|
|
224
|
+
case 'table':
|
|
225
|
+
return "typeof val === 'object'";
|
|
223
226
|
}
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
function typeDesc(t) {
|
|
227
230
|
switch (t) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
231
|
+
case 'bit':
|
|
232
|
+
return 'booleany';
|
|
233
|
+
case 'octet':
|
|
234
|
+
case 'short':
|
|
235
|
+
case 'long':
|
|
236
|
+
case 'longlong':
|
|
237
|
+
case 'timestamp':
|
|
238
|
+
return 'a number (but not NaN)';
|
|
239
|
+
case 'shortstr':
|
|
240
|
+
return 'a string (up to 255 chars)';
|
|
241
|
+
case 'longstr':
|
|
242
|
+
return 'a Buffer';
|
|
243
|
+
case 'table':
|
|
244
|
+
return 'an object';
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
function defaultValueRepr(arg) {
|
|
241
249
|
switch (arg.type) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
250
|
+
case 'longstr':
|
|
251
|
+
return format('Buffer.from(%s)', JSON.stringify(arg.default));
|
|
252
|
+
default:
|
|
253
|
+
// assumes no tables as defaults
|
|
254
|
+
return JSON.stringify(arg.default);
|
|
247
255
|
}
|
|
248
256
|
}
|
|
249
257
|
|
|
@@ -254,7 +262,7 @@ function assignArg(a) {
|
|
|
254
262
|
|
|
255
263
|
function assignOrDefault(a) {
|
|
256
264
|
println("val = fields['%s'];", a.name);
|
|
257
|
-
println(
|
|
265
|
+
println('if (val === undefined) val = %s;', defaultValueRepr(a));
|
|
258
266
|
}
|
|
259
267
|
|
|
260
268
|
// Emit code for assigning an argument value to `val`, checking that
|
|
@@ -265,15 +273,13 @@ function checkAssignArg(a) {
|
|
|
265
273
|
println('if (val === undefined) {');
|
|
266
274
|
if (a.default !== undefined) {
|
|
267
275
|
println('val = %s;', defaultValueRepr(a));
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
276
|
+
} else {
|
|
270
277
|
println('throw new Error("Missing value for mandatory field \'%s\'");', a.name);
|
|
271
278
|
}
|
|
272
279
|
println('}'); // undefined test
|
|
273
280
|
println('else if (!(%s)) {', valTypeTest(a));
|
|
274
281
|
println('throw new TypeError(');
|
|
275
|
-
println('"Field \'%s\' is the wrong type; must be %s");',
|
|
276
|
-
a.name, typeDesc(a.type));
|
|
282
|
+
println('"Field \'%s\' is the wrong type; must be %s");', a.name, typeDesc(a.type));
|
|
277
283
|
println('}'); // type test
|
|
278
284
|
}
|
|
279
285
|
|
|
@@ -285,30 +291,28 @@ function checkAssignArg(a) {
|
|
|
285
291
|
// another buffer before returning. `scratchOffset`, `val`, `len` are
|
|
286
292
|
// expected to have been declared.
|
|
287
293
|
function assignTable(a) {
|
|
288
|
-
|
|
289
|
-
println(
|
|
290
|
-
"len = encodeTable(SCRATCH, val, scratchOffset);");
|
|
294
|
+
const varname = tableVar(a);
|
|
295
|
+
println('len = encodeTable(SCRATCH, val, scratchOffset);');
|
|
291
296
|
println('var %s = SCRATCH.slice(scratchOffset, scratchOffset + len);', varname);
|
|
292
297
|
println('scratchOffset += len;');
|
|
293
298
|
}
|
|
294
299
|
|
|
295
300
|
function tableVar(a) {
|
|
296
|
-
return a.name
|
|
301
|
+
return `${a.name}_encoded`;
|
|
297
302
|
}
|
|
298
303
|
|
|
299
304
|
function stringLenVar(a) {
|
|
300
|
-
return a.name
|
|
305
|
+
return `${a.name}_len`;
|
|
301
306
|
}
|
|
302
307
|
|
|
303
308
|
function assignStringLen(a) {
|
|
304
|
-
|
|
309
|
+
const v = stringLenVar(a);
|
|
305
310
|
// Assumes the value or default is in val
|
|
306
311
|
println("var %s = Buffer.byteLength(val, 'utf8');", v);
|
|
307
312
|
}
|
|
308
313
|
|
|
309
|
-
|
|
310
314
|
function encoderFn(method) {
|
|
311
|
-
|
|
315
|
+
const args = method['args'];
|
|
312
316
|
println('function %s(channel, fields) {', method.encoder);
|
|
313
317
|
println('var offset = 0, val = null, bits = 0, varyingSize = 0;');
|
|
314
318
|
println('var len, scratchOffset = 0;');
|
|
@@ -319,50 +323,57 @@ function encoderFn(method) {
|
|
|
319
323
|
// either 1. contribute to the fixed size; or 2. emit code to
|
|
320
324
|
// calculate the size (and possibly the encoded value, in the case
|
|
321
325
|
// of tables).
|
|
322
|
-
|
|
326
|
+
let fixedSize = METHOD_OVERHEAD;
|
|
323
327
|
|
|
324
|
-
|
|
328
|
+
let bitsInARow = 0;
|
|
325
329
|
|
|
326
|
-
for (
|
|
327
|
-
|
|
330
|
+
for (let i = 0, len = args.length; i < len; i++) {
|
|
331
|
+
const arg = args[i];
|
|
328
332
|
|
|
329
|
-
if (arg.type
|
|
333
|
+
if (arg.type !== 'bit') bitsInARow = 0;
|
|
330
334
|
|
|
331
335
|
switch (arg.type) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
336
|
+
// varying size
|
|
337
|
+
case 'shortstr':
|
|
338
|
+
checkAssignArg(arg);
|
|
339
|
+
assignStringLen(arg);
|
|
340
|
+
println('varyingSize += %s;', stringLenVar(arg));
|
|
341
|
+
fixedSize += 1;
|
|
342
|
+
break;
|
|
343
|
+
case 'longstr':
|
|
344
|
+
checkAssignArg(arg);
|
|
345
|
+
println('varyingSize += val.length;');
|
|
346
|
+
fixedSize += 4;
|
|
347
|
+
break;
|
|
348
|
+
case 'table':
|
|
349
|
+
// For a table we have to encode the table before we can see its
|
|
350
|
+
// length.
|
|
351
|
+
checkAssignArg(arg);
|
|
352
|
+
assignTable(arg);
|
|
353
|
+
println('varyingSize += %s.length;', tableVar(arg));
|
|
354
|
+
break;
|
|
355
|
+
|
|
356
|
+
// fixed size
|
|
357
|
+
case 'octet':
|
|
358
|
+
fixedSize += 1;
|
|
359
|
+
break;
|
|
360
|
+
case 'short':
|
|
361
|
+
fixedSize += 2;
|
|
362
|
+
break;
|
|
363
|
+
case 'long':
|
|
364
|
+
fixedSize += 4;
|
|
365
|
+
break;
|
|
366
|
+
case 'longlong': //fall through
|
|
367
|
+
case 'timestamp':
|
|
368
|
+
fixedSize += 8;
|
|
369
|
+
break;
|
|
370
|
+
case 'bit':
|
|
371
|
+
bitsInARow++;
|
|
372
|
+
// open a fresh pack o' bits
|
|
373
|
+
if (bitsInARow === 1) fixedSize += 1;
|
|
374
|
+
// just used a pack; reset
|
|
375
|
+
else if (bitsInARow === 8) bitsInARow = 0;
|
|
376
|
+
break;
|
|
366
377
|
}
|
|
367
378
|
}
|
|
368
379
|
|
|
@@ -376,58 +387,58 @@ function encoderFn(method) {
|
|
|
376
387
|
|
|
377
388
|
bitsInARow = 0;
|
|
378
389
|
|
|
379
|
-
for (
|
|
380
|
-
|
|
390
|
+
for (let i = 0, len = args.length; i < len; i++) {
|
|
391
|
+
const a = args[i];
|
|
381
392
|
|
|
382
393
|
// Flush any collected bits before doing a new field
|
|
383
|
-
if (a.type
|
|
394
|
+
if (a.type !== 'bit' && bitsInARow > 0) {
|
|
384
395
|
bitsInARow = 0;
|
|
385
396
|
println('buffer[offset] = bits; offset++; bits = 0;');
|
|
386
397
|
}
|
|
387
398
|
|
|
388
399
|
switch (a.type) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
400
|
+
case 'octet':
|
|
401
|
+
checkAssignArg(a);
|
|
402
|
+
println('buffer.writeUInt8(val, offset); offset++;');
|
|
403
|
+
break;
|
|
404
|
+
case 'short':
|
|
405
|
+
checkAssignArg(a);
|
|
406
|
+
println('buffer.writeUInt16BE(val, offset); offset += 2;');
|
|
407
|
+
break;
|
|
408
|
+
case 'long':
|
|
409
|
+
checkAssignArg(a);
|
|
410
|
+
println('buffer.writeUInt32BE(val, offset); offset += 4;');
|
|
411
|
+
break;
|
|
412
|
+
case 'longlong':
|
|
413
|
+
case 'timestamp':
|
|
414
|
+
checkAssignArg(a);
|
|
415
|
+
println('ints.writeUInt64BE(buffer, val, offset); offset += 8;');
|
|
416
|
+
break;
|
|
417
|
+
case 'bit':
|
|
418
|
+
checkAssignArg(a);
|
|
419
|
+
println('if (val) bits += %d;', 1 << bitsInARow);
|
|
420
|
+
if (bitsInARow === 7) {
|
|
421
|
+
// I don't think this ever happens, but whatever
|
|
422
|
+
println('buffer[offset] = bits; offset++; bits = 0;');
|
|
423
|
+
bitsInARow = 0;
|
|
424
|
+
} else bitsInARow++;
|
|
425
|
+
break;
|
|
426
|
+
case 'shortstr':
|
|
427
|
+
assignOrDefault(a);
|
|
428
|
+
println('buffer[offset] = %s; offset++;', stringLenVar(a));
|
|
429
|
+
println('buffer.write(val, offset, "utf8"); offset += %s;', stringLenVar(a));
|
|
430
|
+
break;
|
|
431
|
+
case 'longstr':
|
|
432
|
+
assignOrDefault(a);
|
|
433
|
+
println('len = val.length;');
|
|
434
|
+
println('buffer.writeUInt32BE(len, offset); offset += 4;');
|
|
435
|
+
println('val.copy(buffer, offset); offset += len;');
|
|
436
|
+
break;
|
|
437
|
+
case 'table':
|
|
438
|
+
println('offset += %s.copy(buffer, offset);', tableVar(a));
|
|
439
|
+
break;
|
|
440
|
+
default:
|
|
441
|
+
throw new Error(`Unexpected argument type: ${a.type}`);
|
|
431
442
|
}
|
|
432
443
|
}
|
|
433
444
|
|
|
@@ -446,70 +457,70 @@ function encoderFn(method) {
|
|
|
446
457
|
|
|
447
458
|
function fieldsDecl(args) {
|
|
448
459
|
println('var fields = {');
|
|
449
|
-
for (
|
|
460
|
+
for (let i = 0, num = args.length; i < num; i++) {
|
|
450
461
|
println('%s: undefined,', args[i].name);
|
|
451
462
|
}
|
|
452
463
|
println('};');
|
|
453
464
|
}
|
|
454
465
|
|
|
455
466
|
function decoderFn(method) {
|
|
456
|
-
|
|
467
|
+
const args = method.args;
|
|
457
468
|
println('function %s(buffer) {', method.decoder);
|
|
458
469
|
println('var offset = 0, val, len;');
|
|
459
470
|
fieldsDecl(args);
|
|
460
471
|
|
|
461
|
-
|
|
472
|
+
let bitsInARow = 0;
|
|
462
473
|
|
|
463
|
-
for (
|
|
464
|
-
|
|
465
|
-
|
|
474
|
+
for (let i = 0, num = args.length; i < num; i++) {
|
|
475
|
+
const a = args[i];
|
|
476
|
+
const field = `fields['${a.name}']`;
|
|
466
477
|
|
|
467
478
|
// Flush any collected bits before doing a new field
|
|
468
|
-
if (a.type
|
|
479
|
+
if (a.type !== 'bit' && bitsInARow > 0) {
|
|
469
480
|
bitsInARow = 0;
|
|
470
481
|
println('offset++;');
|
|
471
482
|
}
|
|
472
483
|
|
|
473
484
|
switch (a.type) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
485
|
+
case 'octet':
|
|
486
|
+
println('val = buffer[offset]; offset++;');
|
|
487
|
+
break;
|
|
488
|
+
case 'short':
|
|
489
|
+
println('val = buffer.readUInt16BE(offset); offset += 2;');
|
|
490
|
+
break;
|
|
491
|
+
case 'long':
|
|
492
|
+
println('val = buffer.readUInt32BE(offset); offset += 4;');
|
|
493
|
+
break;
|
|
494
|
+
case 'longlong':
|
|
495
|
+
case 'timestamp':
|
|
496
|
+
println('val = ints.readUInt64BE(buffer, offset); offset += 8;');
|
|
497
|
+
break;
|
|
498
|
+
case 'bit': {
|
|
499
|
+
const bit = 1 << bitsInARow;
|
|
500
|
+
println('val = !!(buffer[offset] & %d);', bit);
|
|
501
|
+
if (bitsInARow === 7) {
|
|
502
|
+
println('offset++;');
|
|
503
|
+
bitsInARow = 0;
|
|
504
|
+
} else bitsInARow++;
|
|
505
|
+
break;
|
|
493
506
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
default:
|
|
512
|
-
throw new TypeError("Unexpected type in argument list: " + a.type);
|
|
507
|
+
case 'longstr':
|
|
508
|
+
println('len = buffer.readUInt32BE(offset); offset += 4;');
|
|
509
|
+
println('val = buffer.subarray(offset, offset + len);');
|
|
510
|
+
println('offset += len;');
|
|
511
|
+
break;
|
|
512
|
+
case 'shortstr':
|
|
513
|
+
println('len = buffer.readUInt8(offset); offset++;');
|
|
514
|
+
println('val = buffer.toString("utf8", offset, offset + len);');
|
|
515
|
+
println('offset += len;');
|
|
516
|
+
break;
|
|
517
|
+
case 'table':
|
|
518
|
+
println('len = buffer.readUInt32BE(offset); offset += 4;');
|
|
519
|
+
println('val = decodeFields(buffer.subarray(offset, offset + len));');
|
|
520
|
+
println('offset += len;');
|
|
521
|
+
break;
|
|
522
|
+
default:
|
|
523
|
+
throw new TypeError(`Unexpected type in argument list: ${a.type}`);
|
|
513
524
|
}
|
|
514
525
|
println('%s = val;', field);
|
|
515
526
|
}
|
|
@@ -518,13 +529,8 @@ function decoderFn(method) {
|
|
|
518
529
|
}
|
|
519
530
|
|
|
520
531
|
function infoObj(thing) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
methodId: thing.methodId,
|
|
524
|
-
name: thing.name,
|
|
525
|
-
args: thing.args});
|
|
526
|
-
println('var %s = module.exports.%s = %s;',
|
|
527
|
-
thing.info, thing.info, info);
|
|
532
|
+
const info = JSON.stringify({ id: thing.id, classId: thing.clazzId, methodId: thing.methodId, name: thing.name, args: thing.args });
|
|
533
|
+
println('var %s = module.exports.%s = %s;', thing.info, thing.info, info);
|
|
528
534
|
}
|
|
529
535
|
|
|
530
536
|
// The flags are laid out in groups of fifteen in a short (high to
|
|
@@ -546,47 +552,53 @@ function encodePropsFn(props) {
|
|
|
546
552
|
println('var offset = 0, flags = 0, val, len;');
|
|
547
553
|
println('var scratchOffset = 0, varyingSize = 0;');
|
|
548
554
|
|
|
549
|
-
|
|
555
|
+
const fixedSize = PROPERTIES_OVERHEAD;
|
|
550
556
|
|
|
551
|
-
|
|
557
|
+
const args = props.args;
|
|
552
558
|
|
|
553
559
|
function incVarying(by) {
|
|
554
|
-
println(
|
|
560
|
+
println('varyingSize += %d;', by);
|
|
555
561
|
}
|
|
556
562
|
|
|
557
|
-
for (
|
|
558
|
-
|
|
563
|
+
for (let i = 0, num = args.length; i < num; i++) {
|
|
564
|
+
const p = args[i];
|
|
559
565
|
|
|
560
566
|
assignArg(p);
|
|
561
|
-
println(
|
|
567
|
+
println('if (val != undefined) {');
|
|
562
568
|
|
|
563
|
-
println(
|
|
569
|
+
println('if (%s) {', valTypeTest(p));
|
|
564
570
|
switch (p.type) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
571
|
+
case 'shortstr':
|
|
572
|
+
assignStringLen(p);
|
|
573
|
+
incVarying(1);
|
|
574
|
+
println('varyingSize += %s;', stringLenVar(p));
|
|
575
|
+
break;
|
|
576
|
+
case 'longstr':
|
|
577
|
+
incVarying(4);
|
|
578
|
+
println('varyingSize += val.length;');
|
|
579
|
+
break;
|
|
580
|
+
case 'table':
|
|
581
|
+
assignTable(p);
|
|
582
|
+
println('varyingSize += %s.length;', tableVar(p));
|
|
583
|
+
break;
|
|
584
|
+
case 'octet':
|
|
585
|
+
incVarying(1);
|
|
586
|
+
break;
|
|
587
|
+
case 'short':
|
|
588
|
+
incVarying(2);
|
|
589
|
+
break;
|
|
590
|
+
case 'long':
|
|
591
|
+
incVarying(4);
|
|
592
|
+
break;
|
|
593
|
+
case 'longlong': // fall through
|
|
594
|
+
case 'timestamp':
|
|
595
|
+
incVarying(8);
|
|
596
|
+
break;
|
|
584
597
|
// no case for bit, as they are accounted for in the flags
|
|
585
598
|
}
|
|
586
599
|
println('} else {');
|
|
587
600
|
println('throw new TypeError(');
|
|
588
|
-
println('"Field \'%s\' is the wrong type; must be %s");',
|
|
589
|
-
p.name, typeDesc(p.type));
|
|
601
|
+
println('"Field \'%s\' is the wrong type; must be %s");', p.name, typeDesc(p.type));
|
|
590
602
|
println('}');
|
|
591
603
|
println('}');
|
|
592
604
|
}
|
|
@@ -606,48 +618,50 @@ function encodePropsFn(props) {
|
|
|
606
618
|
// we'll write the flags later too
|
|
607
619
|
println('offset = 21;');
|
|
608
620
|
|
|
609
|
-
for (
|
|
610
|
-
|
|
611
|
-
|
|
621
|
+
for (let i = 0, num = args.length; i < num; i++) {
|
|
622
|
+
const p = args[i];
|
|
623
|
+
const flag = flagAt(i);
|
|
612
624
|
|
|
613
625
|
assignArg(p);
|
|
614
|
-
println(
|
|
615
|
-
if (p.type === 'bit') {
|
|
626
|
+
println('if (val != undefined) {');
|
|
627
|
+
if (p.type === 'bit') {
|
|
628
|
+
// which none of them are ..
|
|
616
629
|
println('if (val) flags += %d;', flag);
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
630
|
+
} else {
|
|
619
631
|
println('flags += %d;', flag);
|
|
620
632
|
// %%% FIXME only slightly different to the method args encoding
|
|
621
633
|
switch (p.type) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
634
|
+
case 'octet':
|
|
635
|
+
println('buffer.writeUInt8(val, offset); offset++;');
|
|
636
|
+
break;
|
|
637
|
+
case 'short':
|
|
638
|
+
println('buffer.writeUInt16BE(val, offset); offset += 2;');
|
|
639
|
+
break;
|
|
640
|
+
case 'long':
|
|
641
|
+
println('buffer.writeUInt32BE(val, offset); offset += 4;');
|
|
642
|
+
break;
|
|
643
|
+
case 'longlong':
|
|
644
|
+
case 'timestamp':
|
|
645
|
+
println('ints.writeUInt64BE(buffer, val, offset);');
|
|
646
|
+
println('offset += 8;');
|
|
647
|
+
break;
|
|
648
|
+
case 'shortstr': {
|
|
649
|
+
const v = stringLenVar(p);
|
|
650
|
+
println('buffer[offset] = %s; offset++;', v);
|
|
651
|
+
println("buffer.write(val, offset, 'utf8');");
|
|
652
|
+
println('offset += %s;', v);
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
case 'longstr':
|
|
656
|
+
println('buffer.writeUInt32BE(val.length, offset);');
|
|
657
|
+
println('offset += 4;');
|
|
658
|
+
println('offset += val.copy(buffer, offset);');
|
|
659
|
+
break;
|
|
660
|
+
case 'table':
|
|
661
|
+
println('offset += %s.copy(buffer, offset);', tableVar(p));
|
|
662
|
+
break;
|
|
663
|
+
default:
|
|
664
|
+
throw new Error(`Unexpected argument type: ${p.type}`);
|
|
651
665
|
}
|
|
652
666
|
}
|
|
653
667
|
println('}'); // != undefined
|
|
@@ -662,7 +676,7 @@ function encodePropsFn(props) {
|
|
|
662
676
|
}
|
|
663
677
|
|
|
664
678
|
function decodePropsFn(props) {
|
|
665
|
-
|
|
679
|
+
const args = props.args;
|
|
666
680
|
|
|
667
681
|
println('function %s(buffer) {', props.decoder);
|
|
668
682
|
println('var flags, offset = 2, val, len;');
|
|
@@ -672,46 +686,45 @@ function decodePropsFn(props) {
|
|
|
672
686
|
|
|
673
687
|
fieldsDecl(args);
|
|
674
688
|
|
|
675
|
-
for (
|
|
676
|
-
|
|
677
|
-
|
|
689
|
+
for (let i = 0, num = args.length; i < num; i++) {
|
|
690
|
+
const p = argument(args[i]);
|
|
691
|
+
const field = `fields['${p.name}']`;
|
|
678
692
|
|
|
679
693
|
println('if (flags & %d) {', flagAt(i));
|
|
680
694
|
if (p.type === 'bit') {
|
|
681
695
|
println('%d = true;', field);
|
|
682
|
-
}
|
|
683
|
-
else {
|
|
696
|
+
} else {
|
|
684
697
|
switch (p.type) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
698
|
+
case 'octet':
|
|
699
|
+
println('val = buffer[offset]; offset++;');
|
|
700
|
+
break;
|
|
701
|
+
case 'short':
|
|
702
|
+
println('val = buffer.readUInt16BE(offset); offset += 2;');
|
|
703
|
+
break;
|
|
704
|
+
case 'long':
|
|
705
|
+
println('val = buffer.readUInt32BE(offset); offset += 4;');
|
|
706
|
+
break;
|
|
707
|
+
case 'longlong':
|
|
708
|
+
case 'timestamp':
|
|
709
|
+
println('val = ints.readUInt64BE(buffer, offset); offset += 8;');
|
|
710
|
+
break;
|
|
711
|
+
case 'longstr':
|
|
712
|
+
println('len = buffer.readUInt32BE(offset); offset += 4;');
|
|
713
|
+
println('val = buffer.subarray(offset, offset + len);');
|
|
714
|
+
println('offset += len;');
|
|
715
|
+
break;
|
|
716
|
+
case 'shortstr':
|
|
717
|
+
println('len = buffer.readUInt8(offset); offset++;');
|
|
718
|
+
println('val = buffer.toString("utf8", offset, offset + len);');
|
|
719
|
+
println('offset += len;');
|
|
720
|
+
break;
|
|
721
|
+
case 'table':
|
|
722
|
+
println('len = buffer.readUInt32BE(offset); offset += 4;');
|
|
723
|
+
println('val = decodeFields(buffer.subarray(offset, offset + len));');
|
|
724
|
+
println('offset += len;');
|
|
725
|
+
break;
|
|
726
|
+
default:
|
|
727
|
+
throw new TypeError(`Unexpected type in argument list: ${p.type}`);
|
|
715
728
|
}
|
|
716
729
|
println('%s = val;', field);
|
|
717
730
|
}
|