u8-mqtt 0.6.2 → 0.6.4

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.
Files changed (108) hide show
  1. package/cjs/basic-v4.cjs +194 -243
  2. package/cjs/basic-v4.cjs.map +1 -1
  3. package/cjs/basic-v5.cjs +247 -368
  4. package/cjs/basic-v5.cjs.map +1 -1
  5. package/cjs/full-v4.cjs +342 -384
  6. package/cjs/full-v4.cjs.map +1 -1
  7. package/cjs/full-v5.cjs +395 -507
  8. package/cjs/full-v5.cjs.map +1 -1
  9. package/cjs/index.cjs +292 -399
  10. package/cjs/index.cjs.map +1 -1
  11. package/cjs/v4.cjs +239 -274
  12. package/cjs/v4.cjs.map +1 -1
  13. package/cjs/v5.cjs +292 -399
  14. package/cjs/v5.cjs.map +1 -1
  15. package/code/router_path.jsy +39 -28
  16. package/code/with_topic_router.jsy +4 -1
  17. package/esm/basic-v4.js +194 -243
  18. package/esm/basic-v4.js.map +1 -1
  19. package/esm/basic-v5.js +247 -368
  20. package/esm/basic-v5.js.map +1 -1
  21. package/esm/deno/basic-v4.js +194 -243
  22. package/esm/deno/basic-v4.js.map +1 -1
  23. package/esm/deno/basic-v5.js +247 -368
  24. package/esm/deno/basic-v5.js.map +1 -1
  25. package/esm/deno/full-v4.js +342 -384
  26. package/esm/deno/full-v4.js.map +1 -1
  27. package/esm/deno/full-v5.js +395 -507
  28. package/esm/deno/full-v5.js.map +1 -1
  29. package/esm/deno/index.js +292 -399
  30. package/esm/deno/index.js.map +1 -1
  31. package/esm/deno/v4.js +239 -274
  32. package/esm/deno/v4.js.map +1 -1
  33. package/esm/deno/v5.js +292 -399
  34. package/esm/deno/v5.js.map +1 -1
  35. package/esm/full-v4.js +342 -384
  36. package/esm/full-v4.js.map +1 -1
  37. package/esm/full-v5.js +395 -507
  38. package/esm/full-v5.js.map +1 -1
  39. package/esm/index.js +292 -399
  40. package/esm/index.js.map +1 -1
  41. package/esm/node/basic-v4.js +194 -243
  42. package/esm/node/basic-v4.js.map +1 -1
  43. package/esm/node/basic-v4.mjs +194 -243
  44. package/esm/node/basic-v4.mjs.map +1 -1
  45. package/esm/node/basic-v5.js +247 -368
  46. package/esm/node/basic-v5.js.map +1 -1
  47. package/esm/node/basic-v5.mjs +247 -368
  48. package/esm/node/basic-v5.mjs.map +1 -1
  49. package/esm/node/full-v4.js +342 -384
  50. package/esm/node/full-v4.js.map +1 -1
  51. package/esm/node/full-v4.mjs +342 -384
  52. package/esm/node/full-v4.mjs.map +1 -1
  53. package/esm/node/full-v5.js +395 -507
  54. package/esm/node/full-v5.js.map +1 -1
  55. package/esm/node/full-v5.mjs +395 -507
  56. package/esm/node/full-v5.mjs.map +1 -1
  57. package/esm/node/index.js +292 -399
  58. package/esm/node/index.js.map +1 -1
  59. package/esm/node/index.mjs +292 -399
  60. package/esm/node/index.mjs.map +1 -1
  61. package/esm/node/v4.js +239 -274
  62. package/esm/node/v4.js.map +1 -1
  63. package/esm/node/v4.mjs +239 -274
  64. package/esm/node/v4.mjs.map +1 -1
  65. package/esm/node/v5.js +292 -399
  66. package/esm/node/v5.js.map +1 -1
  67. package/esm/node/v5.mjs +292 -399
  68. package/esm/node/v5.mjs.map +1 -1
  69. package/esm/v4.js +239 -274
  70. package/esm/v4.js.map +1 -1
  71. package/esm/v5.js +292 -399
  72. package/esm/v5.js.map +1 -1
  73. package/esm/web/basic-v4.js +194 -243
  74. package/esm/web/basic-v4.js.map +1 -1
  75. package/esm/web/basic-v4.min.js +1 -1
  76. package/esm/web/basic-v4.min.js.br +0 -0
  77. package/esm/web/basic-v4.min.js.gz +0 -0
  78. package/esm/web/basic-v5.js +247 -368
  79. package/esm/web/basic-v5.js.map +1 -1
  80. package/esm/web/basic-v5.min.js +1 -1
  81. package/esm/web/basic-v5.min.js.br +0 -0
  82. package/esm/web/basic-v5.min.js.gz +0 -0
  83. package/esm/web/full-v4.js +342 -384
  84. package/esm/web/full-v4.js.map +1 -1
  85. package/esm/web/full-v4.min.js +1 -1
  86. package/esm/web/full-v4.min.js.br +0 -0
  87. package/esm/web/full-v4.min.js.gz +0 -0
  88. package/esm/web/full-v5.js +395 -507
  89. package/esm/web/full-v5.js.map +1 -1
  90. package/esm/web/full-v5.min.js +1 -1
  91. package/esm/web/full-v5.min.js.br +0 -0
  92. package/esm/web/full-v5.min.js.gz +0 -0
  93. package/esm/web/index.js +292 -399
  94. package/esm/web/index.js.map +1 -1
  95. package/esm/web/index.min.js +1 -1
  96. package/esm/web/index.min.js.br +0 -0
  97. package/esm/web/index.min.js.gz +0 -0
  98. package/esm/web/v4.js +239 -274
  99. package/esm/web/v4.js.map +1 -1
  100. package/esm/web/v4.min.js +1 -1
  101. package/esm/web/v4.min.js.br +0 -0
  102. package/esm/web/v4.min.js.gz +0 -0
  103. package/esm/web/v5.js +292 -399
  104. package/esm/web/v5.js.map +1 -1
  105. package/esm/web/v5.min.js +1 -1
  106. package/esm/web/v5.min.js.br +0 -0
  107. package/esm/web/v5.min.js.gz +0 -0
  108. package/package.json +5 -5
package/cjs/full-v5.cjs CHANGED
@@ -6,41 +6,20 @@ var node_net = require('node:net');
6
6
  var node_tls = require('node:tls');
7
7
 
8
8
  function encode_varint(n, a=[]) {
9
- do {
10
- const ni = n & 0x7f;
11
- n >>>= 7;
12
- a.push( ni | (0===n ? 0 : 0x80) );
13
- } while (n > 0)
9
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
10
+ for(; ( n>>>=7 ) > 0 ;)
11
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
14
12
  return a
15
13
  }
16
14
 
15
+ function decode_varint$1(u8, i0=0, invalid) {
16
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
17
+ for(; b & 0x80;)
18
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
17
19
 
18
- /*
19
- export function decode_varint_loop(u8, i=0) {
20
- let i0 = i
21
- let shift = 0, n = (u8[i] & 0x7f)
22
- while ( 0x80 & u8[i++] )
23
- n |= (u8[i] & 0x7f) << (shift += 7)
24
-
25
- return [n, i, i0]
26
- }
27
- */
28
-
29
-
30
- function decode_varint$1(u8, i=0) {
31
- let i0 = i;
32
- // unrolled for a max of 4 chains
33
- let n = (u8[i] & 0x7f) << 0;
34
- if ( 0x80 & u8[i++] ) {
35
- n |= (u8[i] & 0x7f) << 7;
36
- if ( 0x80 & u8[i++] ) {
37
- n |= (u8[i] & 0x7f) << 14;
38
- if ( 0x80 & u8[i++] ) {
39
- n |= (u8[i] & 0x7f) << 21;
40
- }
41
- }
42
- }
43
- return [n, i, i0]
20
+ return (u8.length < i)
21
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
22
+ : [n, i, i0] // successful value
44
23
  }
45
24
 
46
25
  function add_mqtt_props(mqtt_props, entries) {
@@ -87,19 +66,18 @@ const init_mqtt_props = () =>
87
66
  const mqtt_props = /* #__PURE__ */
88
67
  init_mqtt_props();
89
68
 
90
- class U8_Reason extends Number {
91
- static of(v, pkt_kind, by_kind) {
92
- let self = new this(v);
93
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
94
- return self
69
+ class mqtt_reason extends Number {
70
+ constructor(v, reason) {
71
+ super(v);
72
+ this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
95
73
  }
96
74
  }
97
75
 
98
76
  class mqtt_reader_v4 {
99
- static of(buf) { return this.prototype.of(buf) }
100
- of(buf) {
77
+ static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
78
+ of(buf, opt) {
101
79
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
102
- return {__proto__: this, buf, step}
80
+ return {__proto__: this, buf, step, ...opt}
103
81
  }
104
82
 
105
83
  has_more() {
@@ -142,7 +120,7 @@ class mqtt_reader_v4 {
142
120
  reason(pkt_kind) {
143
121
  let v = this.buf[this.step(1)];
144
122
  if (null != v)
145
- return U8_Reason.of(v, pkt_kind, this._reasons_by)
123
+ return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
146
124
  }
147
125
 
148
126
  flush() {
@@ -156,7 +134,7 @@ class mqtt_reader_v4 {
156
134
  let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
157
135
  props() {
158
136
  let {buf, step} = this;
159
- let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
137
+ let [n, vi, vi0] = decode_varint$1(buf, step.k|0, 0);
160
138
  step(n + vi - vi0);
161
139
  if (0 === n) return null
162
140
 
@@ -165,7 +143,7 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
165
143
  let v, pk = fork.u8(), pt = mqtt_props.get( pk );
166
144
  if (!pt) {
167
145
  res._unknown_ = pk;
168
- this.warn(`unknown property: ${pk}`);
146
+ this.warn?.(`unknown property: ${pk}`);
169
147
  break
170
148
  }
171
149
 
@@ -185,8 +163,6 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
185
163
  return vec
186
164
  }
187
165
 
188
- warn(msg) { console.warn('[u8-mqtt-packet] '+msg); }
189
-
190
166
  /*
191
167
  vbuf() {
192
168
  let {buf, step} = this
@@ -198,28 +174,99 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
198
174
  */
199
175
  };
200
176
 
201
- function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
202
- mqtt_reader = class extends mqtt_reader {
203
- static reasons(pkt_type, ...reason_entries) {
204
- let proto = this.prototype;
205
- proto._reasons_by = {... proto._reasons_by};
177
+ function with_reasons(mqtt_reader, by_kind) {
178
+ for (let [k,lut] of Object.entries(by_kind))
179
+ by_kind[k] = new Map(lut);
206
180
 
207
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
208
- for (let [u8, reason] of reason_entries)
209
- lut.set( u8, reason );
210
-
211
- return this
181
+ return class extends mqtt_reader {
182
+ _reason_for(v, pkt_kind) {
183
+ return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
184
+ }
185
+ warn(msg) {
186
+ let pkt = this.pkt;
187
+ pkt.warn ? pkt.warn(msg, pkt)
188
+ : console.warn('[u8-mqtt-packet] '+msg);
212
189
  }
213
- };
190
+ }
191
+ }
214
192
 
215
- for (let fn_info of info_fn_list)
216
- fn_info(mqtt_reader);
217
193
 
218
- return mqtt_reader
219
- }
194
+ const reasons_v4 = {
195
+ connack: [
196
+ [ 0x01, 'conn refused: unacceptable protocol version'],
197
+ [ 0x02, 'conn refused: identifier rejected'],
198
+ [ 0x03, 'conn refused: server unavailable'],
199
+ [ 0x04, 'conn refused: bad user name or password'],
200
+ [ 0x05, 'conn refused: not authorized'],
201
+ ],
202
+ suback: [
203
+ [ 0x00, 'qos=0'],
204
+ [ 0x01, 'qos=1'],
205
+ [ 0x02, 'qos=2'],
206
+ ],
207
+ unsuback: [
208
+ [ 0x11, 'no subscription existed'],
209
+ ],
210
+ puback: [
211
+ [ 0x10, 'no matching subscribers'],
212
+ ],
213
+ all: [
214
+ [ 0, ''], // Success
215
+ [ 0x80, 'unspecified error'], // disconnect puback suback unsuback
216
+ [ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
217
+ [ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
218
+ [ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
219
+ [ 0x91, 'packet identifier in use'], // puback suback unsuback
220
+ [ 0x92, 'packet identifier not found' ], // pubxxx
221
+ ]};
222
+
223
+ const reasons_v5 = {
224
+ ... reasons_v4,
225
+ auth: [
226
+ [ 0x18, 'continue authentication' ],
227
+ [ 0x19, 're-authenticate' ],
228
+ ],
229
+ disconnect: [
230
+ [ 0x04, 'disconnect with will message'],
231
+ ],
232
+ all: [
233
+ ... reasons_v4.all,
234
+ [ 0x81, 'malformed packet'], // connack disconnect
235
+ [ 0x82, 'protocol error'], // connack disconnect
236
+ [ 0x84, 'unsupported protocol version'], // connack
237
+ [ 0x85, 'client identifier not valid'], // connack
238
+ [ 0x86, 'bad user name or password'], // connack
239
+ [ 0x88, 'server unavailable'], // connack
240
+ [ 0x89, 'server busy'], // connack disconnect
241
+ [ 0x8A, 'banned'], // connack
242
+ [ 0x8B, 'server shutting down'], // disconnect
243
+ [ 0x8C, 'bad authentication method'], // connack
244
+ [ 0x8D, 'keep alive timeout'], // disconnect
245
+ [ 0x8E, 'session taken over'], // disconnect
246
+ [ 0x90, 'topic name invalid'], // connack disconnect puback
247
+ [ 0x93, 'receive maximum exceeded'], // disconnect
248
+ [ 0x94, 'topic alias invalid'], // disconnect
249
+ [ 0x95, 'packet too large'], // connack disconnect
250
+ [ 0x96, 'message rate too high'], // disconnect
251
+ [ 0x97, 'quota exceeded'], // connack disconnect puback suback
252
+ [ 0x98, 'administrative action'], // disconnect
253
+ [ 0x99, 'payload format invalid'], // connack disconnect puback
254
+ [ 0x9A, 'retain not supported'], // connack disconnect
255
+ [ 0x9B, 'qoS not supported'], // connack disconnect
256
+ [ 0x9C, 'use another server'], // connack disconnect
257
+ [ 0x9D, 'server moved'], // connack disconnect
258
+ [ 0x9E, 'shared subscriptions not supported'], // disconnect suback
259
+ [ 0x9F, 'connection rate exceeded'], // connack disconnect
260
+ [ 0xA0, 'maximum connect time'], // disconnect
261
+ [ 0xA1, 'subscription identifiers not supported'], // disconnect suback
262
+ [ 0xA2, 'wildcard subscriptions not supported'], // disconnect suback
263
+ ]};
264
+
265
+ const mqtt_reader_v5 = /* #__PURE__ */
266
+ with_reasons(mqtt_reader_v5$1, reasons_v5);
220
267
 
221
268
  class mqtt_writer_v4 {
222
- static of() { return this.prototype.of() }
269
+ static for(pkt) { return new this().of() }
223
270
  of() { return {__proto__: this, $:[]} }
224
271
 
225
272
  static init() { return this }
@@ -333,351 +380,6 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
333
380
  }
334
381
  }
335
382
 
336
- function mqtt_decode_connect(ns, mqtt_reader) {
337
- class _connect_flags_ extends Number {
338
- get reserved() { return this & 0x01 !== 0 }
339
- get clean_start() { return this & 0x02 !== 0 }
340
- get will_flag() { return this & 0x04 !== 0 }
341
- get will_qos() { return (this >>> 3) & 0x3 }
342
- get will_retain() { return this & 0x20 !== 0 }
343
- get password() { return this & 0x40 !== 0 }
344
- get username() { return this & 0x80 !== 0 }
345
- }
346
-
347
- return ns[0x1] = (pkt, u8_body) => {
348
- let rdr = mqtt_reader.of(u8_body);
349
- if ('MQTT' !== rdr.utf8())
350
- throw new Error('Invalid mqtt_connect packet')
351
-
352
- pkt._base_.mqtt_level = pkt.mqtt_level = rdr.u8();
353
-
354
- let flags = pkt.flags =
355
- rdr.flags(_connect_flags_);
356
-
357
- pkt.keep_alive = rdr.u16();
358
-
359
- if (5 <= pkt.mqtt_level)
360
- pkt.props = rdr.props();
361
-
362
-
363
-
364
- pkt.client_id = rdr.utf8();
365
- if (flags.will_flag) {
366
- let will = pkt.will = {};
367
- if (5 <= pkt.mqtt_level)
368
- will.props = rdr.props();
369
-
370
- will.topic = rdr.utf8();
371
- will.payload = rdr.bin();
372
- will.qos = flags.will_qos;
373
- will.retain = flags.will_retain;
374
- }
375
-
376
- if (flags.username)
377
- pkt.username = rdr.utf8();
378
-
379
- if (flags.password)
380
- pkt.password = rdr.bin();
381
- return pkt }
382
- }
383
-
384
- function mqtt_decode_connack(ns, mqtt_reader) {
385
- class _connack_flags_ extends Number {
386
- get session_present() { return this & 0x01 !== 0 }
387
- }
388
-
389
- return ns[0x2] = (pkt, u8_body) => {
390
- let rdr = mqtt_reader.of(u8_body);
391
-
392
- pkt.flags =
393
- rdr.flags(_connack_flags_);
394
-
395
- pkt.reason = rdr.reason(pkt.type);
396
- if (5 <= pkt.mqtt_level)
397
- pkt.props = rdr.props();
398
- return pkt }
399
- }
400
-
401
-
402
- function _connack_v4(mqtt_reader) {
403
- mqtt_reader.reasons('connack',
404
- // MQTT 3.1.1
405
- [ 0x00, 'Success'],
406
- [ 0x01, 'Connection refused, unacceptable protocol version'],
407
- [ 0x02, 'Connection refused, identifier rejected'],
408
- [ 0x03, 'Connection refused, server unavailable'],
409
- [ 0x04, 'Connection refused, bad user name or password'],
410
- [ 0x05, 'Connection refused, not authorized'],
411
- );
412
- }
413
-
414
- function _connack_v5(mqtt_reader) {
415
- _connack_v4(mqtt_reader);
416
-
417
- mqtt_reader.reasons('connack',
418
- // MQTT 5.0
419
- [ 0x81, 'Malformed Packet'],
420
- [ 0x82, 'Protocol Error'],
421
- [ 0x83, 'Implementation specific error'],
422
- [ 0x84, 'Unsupported Protocol Version'],
423
- [ 0x85, 'Client Identifier not valid'],
424
- [ 0x86, 'Bad User Name or Password'],
425
- [ 0x87, 'Not authorized'],
426
- [ 0x88, 'Server unavailable'],
427
- [ 0x89, 'Server busy'],
428
- [ 0x8A, 'Banned'],
429
- [ 0x8C, 'Bad authentication method'],
430
- [ 0x90, 'Topic Name invalid'],
431
- [ 0x95, 'Packet too large'],
432
- [ 0x97, 'Quota exceeded'],
433
- [ 0x99, 'Payload format invalid'],
434
- [ 0x9A, 'Retain not supported'],
435
- [ 0x9B, 'QoS not supported'],
436
- [ 0x9C, 'Use another server'],
437
- [ 0x9D, 'Server moved'],
438
- [ 0x9F, 'Connection rate exceeded'],
439
- );
440
- }
441
-
442
- function mqtt_decode_publish(ns, mqtt_reader) {
443
- return ns[0x3] = (pkt, u8_body) => {
444
- let {hdr} = pkt;
445
- pkt.dup = Boolean(hdr & 0x8);
446
- pkt.retain = Boolean(hdr & 0x1);
447
- let qos = pkt.qos = (hdr>>1) & 0x3;
448
-
449
- let rdr = mqtt_reader.of(u8_body);
450
- pkt.topic = rdr.utf8();
451
- if (0 !== qos)
452
- pkt.pkt_id = rdr.u16();
453
-
454
- if (5 <= pkt.mqtt_level)
455
- pkt.props = rdr.props();
456
-
457
- pkt.payload = rdr.flush();
458
- return pkt }
459
- }
460
-
461
- function mqtt_decode_puback(ns, mqtt_reader) {
462
- return ns[0x4] = (pkt, u8_body) => {
463
- let rdr = mqtt_reader.of(u8_body);
464
-
465
- pkt.pkt_id = rdr.u16();
466
- if (5 <= pkt.mqtt_level) {
467
- pkt.reason = rdr.reason(pkt.type);
468
- pkt.props = rdr.props();
469
- }
470
-
471
- return pkt }
472
- }
473
-
474
-
475
- function _puback_v5(mqtt_reader) {
476
- mqtt_reader.reasons('puback',
477
- // MQTT 5.0
478
- [ 0x00, 'Success'],
479
- [ 0x10, 'No matching subscribers'],
480
- [ 0x80, 'Unspecified error'],
481
- [ 0x83, 'Implementation specific error'],
482
- [ 0x87, 'Not authorized'],
483
- [ 0x90, 'Topic Name invalid'],
484
- [ 0x91, 'Packet identifier in use'],
485
- [ 0x97, 'Quota exceeded'],
486
- [ 0x99, 'Payload format invalid'],
487
- );
488
- }
489
-
490
- function mqtt_decode_pubxxx(ns, mqtt_reader) {
491
- return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
492
- let rdr = mqtt_reader.of(u8_body);
493
-
494
- pkt.pkt_id = rdr.u16();
495
- pkt.reason = rdr.reason('pubxxx', mqtt_reader);
496
- if (5 <= pkt.mqtt_level)
497
- pkt.props = rdr.props();
498
- return pkt }
499
- }
500
-
501
- function _pubxxx_v4(mqtt_reader) {
502
- mqtt_reader.reasons('pubxxx',
503
- // MQTT 3.1.1
504
- [ 0x00, 'Success' ],
505
- [ 0x92, 'Packet Identifier not found' ],
506
- );
507
- }
508
-
509
- function mqtt_decode_subscribe(ns, mqtt_reader) {
510
- class _subscription_options_ extends Number {
511
- get qos() { return this & 0x3 }
512
- get retain() { return this & 0x4 !== 0 }
513
- get retain_handling() { return (this >> 2) & 0x3 }
514
- }
515
-
516
- return ns[0x8] = (pkt, u8_body) => {
517
- let rdr = mqtt_reader.of(u8_body);
518
-
519
- pkt.pkt_id = rdr.u16();
520
- if (5 <= pkt.mqtt_level)
521
- pkt.props = rdr.props();
522
-
523
- let topic, opts, topic_list = pkt.topics = [];
524
- while (rdr.has_more()) {
525
- topic = rdr.utf8();
526
- opts = rdr.flags(_subscription_options_);
527
- topic_list.push({topic, opts});
528
- }
529
-
530
- return pkt }
531
- }
532
-
533
- function _mqtt_decode_suback(mqtt_reader) {
534
- return (pkt, u8_body) => {
535
- let rdr = mqtt_reader.of(u8_body);
536
-
537
- pkt.pkt_id = rdr.u16();
538
- if (5 <= pkt.mqtt_level)
539
- pkt.props = rdr.props();
540
-
541
- let answers = pkt.answers = [];
542
- while (rdr.has_more())
543
- answers.push(
544
- rdr.reason(pkt.type) );
545
-
546
- return pkt }
547
- }
548
-
549
- function mqtt_decode_suback(ns, mqtt_reader) {
550
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
551
- }
552
-
553
- function _suback_v4(mqtt_reader) {
554
- mqtt_reader.reasons('suback',
555
- // MQTT 3.1.1
556
- [ 0x00, 'Granted QoS 0'],
557
- [ 0x01, 'Granted QoS 1'],
558
- [ 0x02, 'Granted QoS 2'],
559
- );
560
- }
561
-
562
- function _suback_v5(mqtt_reader) {
563
- _suback_v4(mqtt_reader);
564
-
565
- mqtt_reader.reasons('suback',
566
- // MQTT 5.0
567
- [ 0x80, 'Unspecified error'],
568
- [ 0x83, 'Implementation specific error'],
569
- [ 0x87, 'Not authorized'],
570
- [ 0x8F, 'Topic Filter invalid'],
571
- [ 0x91, 'Packet Identifier in use'],
572
- [ 0x97, 'Quota exceeded'],
573
- [ 0x9E, 'Shared Subscriptions not supported'],
574
- [ 0xA1, 'Subscription Identifiers not supported'],
575
- [ 0xA2, 'Wildcard Subscriptions not supported'],
576
- );
577
- }
578
-
579
- function mqtt_decode_unsubscribe(ns, mqtt_reader) {
580
- return ns[0xa] = (pkt, u8_body) => {
581
- let rdr = mqtt_reader.of(u8_body);
582
-
583
- pkt.pkt_id = rdr.u16();
584
- if (5 <= pkt.mqtt_level)
585
- pkt.props = rdr.props();
586
-
587
- let topic_list = pkt.topics = [];
588
- while (rdr.has_more())
589
- topic_list.push(rdr.utf8());
590
-
591
- return pkt }
592
- }
593
-
594
- function mqtt_decode_unsuback(ns, mqtt_reader) {
595
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
596
- }
597
-
598
- function _unsuback_v4(mqtt_reader) {
599
- mqtt_reader.reasons('unsuback',
600
- // MQTT 3.1.1
601
- [ 0x00, 'Success'],
602
- [ 0x11, 'No subscription existed'],
603
- [ 0x80, 'Unspecified error'],
604
- [ 0x83, 'Implementation specific error'],
605
- [ 0x87, 'Not authorized'],
606
- [ 0x8F, 'Topic Filter invalid'],
607
- [ 0x91, 'Packet Identifier in use'],
608
- );
609
- }
610
-
611
- function mqtt_decode_pingxxx(ns) {
612
- return ns[0xc] = ns[0xd] = pkt => pkt
613
- }
614
-
615
- function mqtt_decode_disconnect(ns, mqtt_reader) {
616
- return ns[0xe] = (pkt, u8_body) => {
617
- if (u8_body && 5 <= pkt.mqtt_level) {
618
- let rdr = mqtt_reader.of(u8_body);
619
- pkt.reason = rdr.reason(pkt.type);
620
- pkt.props = rdr.props();
621
- }
622
- return pkt }
623
- }
624
-
625
-
626
- function _disconnect_v5(mqtt_reader) {
627
- mqtt_reader.reasons('disconnect',
628
- // MQTT 5.0
629
- [ 0x00, 'Normal disconnection'],
630
- [ 0x04, 'Disconnect with Will Message'],
631
- [ 0x80, 'Unspecified error'],
632
- [ 0x81, 'Malformed Packet'],
633
- [ 0x82, 'Protocol Error'],
634
- [ 0x83, 'Implementation specific error'],
635
- [ 0x87, 'Not authorized'],
636
- [ 0x89, 'Server busy'],
637
- [ 0x8B, 'Server shutting down'],
638
- [ 0x8D, 'Keep Alive timeout'],
639
- [ 0x8E, 'Session taken over'],
640
- [ 0x8F, 'Topic Filter invalid'],
641
- [ 0x90, 'Topic Name invalid'],
642
- [ 0x93, 'Receive Maximum exceeded'],
643
- [ 0x94, 'Topic Alias invalid'],
644
- [ 0x95, 'Packet too large'],
645
- [ 0x96, 'Message rate too high'],
646
- [ 0x97, 'Quota exceeded'],
647
- [ 0x98, 'Administrative action'],
648
- [ 0x99, 'Payload format invalid'],
649
- [ 0x9A, 'Retain not supported'],
650
- [ 0x9B, 'QoS not supported'],
651
- [ 0x9C, 'Use another server'],
652
- [ 0x9D, 'Server moved'],
653
- [ 0x9E, 'Shared Subscriptions not supported'],
654
- [ 0x9F, 'Connection rate exceeded'],
655
- [ 0xA0, 'Maximum connect time'],
656
- [ 0xA1, 'Subscription Identifiers not supported'],
657
- [ 0xA2, 'Wildcard Subscriptions not supported'],
658
- );
659
- }
660
-
661
- function mqtt_decode_auth(ns, mqtt_reader) {
662
- return ns[0xf] = (pkt, u8_body) => {
663
- if ( 5 <= pkt.mqtt_level ) {
664
- let rdr = mqtt_reader.of(u8_body);
665
- pkt.reason = rdr.reason(pkt.type);
666
- pkt.props = rdr.props();
667
- }
668
- return pkt }
669
- }
670
-
671
-
672
- function _auth_v5(mqtt_reader) {
673
- mqtt_reader.reasons('auth',
674
- // MQTT 5.0
675
- [ 0x00, 'Success' ],
676
- [ 0x18, 'Continue authentication' ],
677
- [ 0x19, 'Re-authenticate' ],
678
- );
679
- }
680
-
681
383
  function mqtt_encode_connect(ns, mqtt_writer) {
682
384
  const _c_mqtt_proto = new Uint8Array([
683
385
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -696,7 +398,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
696
398
  | ( will.retain ? 0x20 : 0 );
697
399
 
698
400
  return ns.connect = ( mqtt_level, pkt ) => {
699
- let wrt = mqtt_writer.of(pkt);
401
+ let wrt = mqtt_writer.for(pkt);
700
402
 
701
403
  wrt.push(_c_mqtt_proto);
702
404
  wrt.u8( mqtt_level );
@@ -734,12 +436,61 @@ function mqtt_encode_connect(ns, mqtt_writer) {
734
436
  }
735
437
  }
736
438
 
439
+ function mqtt_decode_connect(ns, mqtt_reader) {
440
+ class _connect_flags_ extends Number {
441
+ get reserved() { return this & 0x01 !== 0 }
442
+ get clean_start() { return this & 0x02 !== 0 }
443
+ get will_flag() { return this & 0x04 !== 0 }
444
+ get will_qos() { return (this >>> 3) & 0x3 }
445
+ get will_retain() { return this & 0x20 !== 0 }
446
+ get password() { return this & 0x40 !== 0 }
447
+ get username() { return this & 0x80 !== 0 }
448
+ }
449
+
450
+ return ns[0x1] = (pkt, u8_body) => {
451
+ let rdr = mqtt_reader.for(pkt, u8_body);
452
+ if ('MQTT' !== rdr.utf8())
453
+ throw new Error('Invalid mqtt_connect packet')
454
+
455
+ pkt.__proto__.mqtt_level =
456
+ pkt.mqtt_level = rdr.u8();
457
+
458
+ let flags = pkt.flags =
459
+ rdr.flags(_connect_flags_);
460
+
461
+ pkt.keep_alive = rdr.u16();
462
+
463
+ if (5 <= pkt.mqtt_level)
464
+ pkt.props = rdr.props();
465
+
466
+
467
+
468
+ pkt.client_id = rdr.utf8();
469
+ if (flags.will_flag) {
470
+ let will = pkt.will = {};
471
+ if (5 <= pkt.mqtt_level)
472
+ will.props = rdr.props();
473
+
474
+ will.topic = rdr.utf8();
475
+ will.payload = rdr.bin();
476
+ will.qos = flags.will_qos;
477
+ will.retain = flags.will_retain;
478
+ }
479
+
480
+ if (flags.username)
481
+ pkt.username = rdr.utf8();
482
+
483
+ if (flags.password)
484
+ pkt.password = rdr.bin();
485
+ return pkt }
486
+ }
487
+
737
488
  function mqtt_encode_connack(ns, mqtt_writer) {
738
489
  const _enc_flags_connack = flags =>
739
490
  flags.session_present ? 1 : 0;
740
491
 
741
492
  return ns.connack = (mqtt_level, pkt) => {
742
- let wrt = mqtt_writer.of(pkt);
493
+ let wrt = mqtt_writer.for(pkt);
743
494
 
744
495
  wrt.flags( pkt.flags, _enc_flags_connack );
745
496
 
@@ -755,10 +506,28 @@ function mqtt_encode_connack(ns, mqtt_writer) {
755
506
  }
756
507
  }
757
508
 
509
+
510
+ function mqtt_decode_connack(ns, mqtt_reader) {
511
+ class _connack_flags_ extends Number {
512
+ get session_present() { return this & 0x01 !== 0 }
513
+ }
514
+
515
+ return ns[0x2] = (pkt, u8_body) => {
516
+ let rdr = mqtt_reader.for(pkt, u8_body);
517
+
518
+ pkt.flags =
519
+ rdr.flags(_connack_flags_);
520
+
521
+ pkt.reason = rdr.reason(pkt.type);
522
+ if (5 <= pkt.mqtt_level)
523
+ pkt.props = rdr.props();
524
+ return pkt }
525
+ }
526
+
758
527
  function mqtt_encode_publish(ns, mqtt_writer) {
759
528
  return ns.publish = ( mqtt_level, pkt ) => {
760
529
  let qos = (pkt.qos & 0x3) << 1;
761
- let wrt = mqtt_writer.of(pkt);
530
+ let wrt = mqtt_writer.for(pkt);
762
531
 
763
532
  wrt.utf8(pkt.topic);
764
533
  if (0 !== qos)
@@ -776,9 +545,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
776
545
  }
777
546
  }
778
547
 
548
+ function mqtt_decode_publish(ns, mqtt_reader) {
549
+ return ns[0x3] = (pkt, u8_body) => {
550
+ let {hdr} = pkt;
551
+ pkt.dup = Boolean(hdr & 0x8);
552
+ pkt.retain = Boolean(hdr & 0x1);
553
+ let qos = pkt.qos = (hdr>>1) & 0x3;
554
+
555
+ let rdr = mqtt_reader.for(pkt, u8_body);
556
+ pkt.topic = rdr.utf8();
557
+ if (0 !== qos)
558
+ pkt.pkt_id = rdr.u16();
559
+
560
+ if (5 <= pkt.mqtt_level)
561
+ pkt.props = rdr.props();
562
+
563
+ pkt.payload = rdr.flush();
564
+ return pkt }
565
+ }
566
+
779
567
  function mqtt_encode_puback(ns, mqtt_writer) {
780
568
  return ns.puback = ( mqtt_level, pkt ) => {
781
- let wrt = mqtt_writer.of(pkt);
569
+ let wrt = mqtt_writer.for(pkt);
782
570
 
783
571
  wrt.u16(pkt.pkt_id);
784
572
  if (5 <= mqtt_level) {
@@ -790,6 +578,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
790
578
  }
791
579
  }
792
580
 
581
+
582
+ function mqtt_decode_puback(ns, mqtt_reader) {
583
+ return ns[0x4] = (pkt, u8_body) => {
584
+ let rdr = mqtt_reader.for(pkt, u8_body);
585
+
586
+ pkt.pkt_id = rdr.u16();
587
+ if (5 <= pkt.mqtt_level) {
588
+ pkt.reason = rdr.reason(pkt.type);
589
+ pkt.props = rdr.props();
590
+ }
591
+
592
+ return pkt }
593
+ }
594
+
793
595
  function mqtt_encode_pubxxx(ns, mqtt_writer) {
794
596
  ns.pubrec = _enc_pubxxx(0x50);
795
597
  ns.pubrel = _enc_pubxxx(0x62);
@@ -798,7 +600,7 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
798
600
 
799
601
  function _enc_pubxxx(hdr) {
800
602
  return ( mqtt_level, pkt ) => {
801
- let wrt = mqtt_writer.of(pkt);
603
+ let wrt = mqtt_writer.for(pkt);
802
604
 
803
605
  wrt.u16(pkt.pkt_id);
804
606
  if (5 <= mqtt_level) {
@@ -814,6 +616,17 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
814
616
  }
815
617
  }
816
618
 
619
+ function mqtt_decode_pubxxx(ns, mqtt_reader) {
620
+ return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
621
+ let rdr = mqtt_reader.for(pkt, u8_body);
622
+
623
+ pkt.pkt_id = rdr.u16();
624
+ pkt.reason = rdr.reason('pubxxx', mqtt_reader);
625
+ if (5 <= pkt.mqtt_level)
626
+ pkt.props = rdr.props();
627
+ return pkt }
628
+ }
629
+
817
630
  function mqtt_encode_subscribe(ns, mqtt_writer) {
818
631
  const _enc_subscribe_flags = opts => 0
819
632
  | ( opts.qos & 0x3 )
@@ -821,7 +634,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
821
634
  | ( (opts.retain_handling & 0x3) << 2 );
822
635
 
823
636
  return ns.subscribe = ( mqtt_level, pkt ) => {
824
- let wrt = mqtt_writer.of(pkt);
637
+ let wrt = mqtt_writer.for(pkt);
825
638
 
826
639
  wrt.u16(pkt.pkt_id);
827
640
  if (5 <= mqtt_level)
@@ -847,6 +660,30 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
847
660
  }
848
661
  }
849
662
 
663
+ function mqtt_decode_subscribe(ns, mqtt_reader) {
664
+ class _subscription_options_ extends Number {
665
+ get qos() { return this & 0x3 }
666
+ get retain() { return this & 0x4 !== 0 }
667
+ get retain_handling() { return (this >> 2) & 0x3 }
668
+ }
669
+
670
+ return ns[0x8] = (pkt, u8_body) => {
671
+ let rdr = mqtt_reader.for(pkt, u8_body);
672
+
673
+ pkt.pkt_id = rdr.u16();
674
+ if (5 <= pkt.mqtt_level)
675
+ pkt.props = rdr.props();
676
+
677
+ let topic, opts, topic_list = pkt.topics = [];
678
+ while (rdr.has_more()) {
679
+ topic = rdr.utf8();
680
+ opts = rdr.flags(_subscription_options_);
681
+ topic_list.push({topic, opts});
682
+ }
683
+
684
+ return pkt }
685
+ }
686
+
850
687
  function mqtt_encode_xxsuback(ns, mqtt_writer) {
851
688
  ns.suback = _enc_xxsuback(0x90);
852
689
  ns.unsuback = _enc_xxsuback(0xb0);
@@ -854,7 +691,7 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
854
691
 
855
692
  function _enc_xxsuback(hdr) {
856
693
  return ( mqtt_level, pkt ) => {
857
- let wrt = mqtt_writer.of(pkt);
694
+ let wrt = mqtt_writer.for(pkt);
858
695
 
859
696
  wrt.u16(pkt.pkt_id);
860
697
  if (5 <= mqtt_level)
@@ -868,9 +705,26 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
868
705
  }
869
706
  }
870
707
 
708
+
709
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
710
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
711
+ let rdr = mqtt_reader.for(pkt, u8_body);
712
+
713
+ pkt.pkt_id = rdr.u16();
714
+ if (5 <= pkt.mqtt_level)
715
+ pkt.props = rdr.props();
716
+
717
+ let answers = pkt.answers = [];
718
+ while (rdr.has_more())
719
+ answers.push(
720
+ rdr.reason(pkt.type) );
721
+
722
+ return pkt }
723
+ }
724
+
871
725
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
872
726
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
873
- let wrt = mqtt_writer.of(pkt);
727
+ let wrt = mqtt_writer.for(pkt);
874
728
 
875
729
  wrt.u16(pkt.pkt_id);
876
730
  if (5 <= mqtt_level)
@@ -883,14 +737,34 @@ function mqtt_encode_unsubscribe(ns, mqtt_writer) {
883
737
  }
884
738
  }
885
739
 
740
+ function mqtt_decode_unsubscribe(ns, mqtt_reader) {
741
+ return ns[0xa] = (pkt, u8_body) => {
742
+ let rdr = mqtt_reader.for(pkt, u8_body);
743
+
744
+ pkt.pkt_id = rdr.u16();
745
+ if (5 <= pkt.mqtt_level)
746
+ pkt.props = rdr.props();
747
+
748
+ let topic_list = pkt.topics = [];
749
+ while (rdr.has_more())
750
+ topic_list.push(rdr.utf8());
751
+
752
+ return pkt }
753
+ }
754
+
886
755
  function mqtt_encode_pingxxx(ns) {
887
756
  ns.pingreq = () => new Uint8Array([ 0xc0, 0 ]);
888
757
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
889
758
  }
890
759
 
760
+
761
+ function mqtt_decode_pingxxx(ns) {
762
+ return ns[0xc] = ns[0xd] = pkt => pkt
763
+ }
764
+
891
765
  function mqtt_encode_disconnect(ns, mqtt_writer) {
892
766
  return ns.disconnect = ( mqtt_level, pkt ) => {
893
- let wrt = mqtt_writer.of(pkt);
767
+ let wrt = mqtt_writer.for(pkt);
894
768
 
895
769
  if (pkt && 5 <= mqtt_level) {
896
770
  if (pkt.reason || pkt.props) {
@@ -903,6 +777,17 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
903
777
  }
904
778
  }
905
779
 
780
+
781
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
782
+ return ns[0xe] = (pkt, u8_body) => {
783
+ if (u8_body && 5 <= pkt.mqtt_level) {
784
+ let rdr = mqtt_reader.for(pkt, u8_body);
785
+ pkt.reason = rdr.reason(pkt.type);
786
+ pkt.props = rdr.props();
787
+ }
788
+ return pkt }
789
+ }
790
+
906
791
  function mqtt_encode_auth(ns, mqtt_writer) {
907
792
  return ns.auth = ( mqtt_level, pkt ) => {
908
793
  if (5 > mqtt_level)
@@ -917,17 +802,15 @@ function mqtt_encode_auth(ns, mqtt_writer) {
917
802
  }
918
803
  }
919
804
 
920
- const mqtt_reader_v5 = /* #__PURE__ */
921
- mqtt_reader_info(
922
- mqtt_reader_v5$1,
923
- _connack_v5,
924
- _puback_v5,
925
- _pubxxx_v4,
926
- _suback_v5,
927
- _unsuback_v4,
928
- _disconnect_v5,
929
- _auth_v5,
930
- );
805
+ function mqtt_decode_auth(ns, mqtt_reader) {
806
+ return ns[0xf] = (pkt, u8_body) => {
807
+ if ( 5 <= pkt.mqtt_level ) {
808
+ let rdr = mqtt_reader.of(u8_body);
809
+ pkt.reason = rdr.reason(pkt.type);
810
+ pkt.props = rdr.props();
811
+ }
812
+ return pkt }
813
+ }
931
814
 
932
815
  const mqtt_decode_v5 = [
933
816
  mqtt_decode_connect,
@@ -936,9 +819,8 @@ const mqtt_decode_v5 = [
936
819
  mqtt_decode_puback,
937
820
  mqtt_decode_pubxxx,
938
821
  mqtt_decode_subscribe,
939
- mqtt_decode_suback,
822
+ mqtt_decode_xxsuback,
940
823
  mqtt_decode_unsubscribe,
941
- mqtt_decode_unsuback,
942
824
  mqtt_decode_pingxxx,
943
825
  mqtt_decode_disconnect,
944
826
  mqtt_decode_auth,
@@ -1051,7 +933,10 @@ const with_topic_router = mqtt_topic_router =>
1051
933
  // alias: unsub_topic
1052
934
  unsubscribe_topic(topic_route, ...args) {
1053
935
  let router = this.router;
1054
- router.remove(topic_route, true);
936
+
937
+ let fn = args.at(-1)?.call ? args.pop() : null;
938
+ router.remove(topic_route, true, fn);
939
+
1055
940
  let topic = router.mqtt_topic(topic_route);
1056
941
  return this.unsubscribe(topic, ...args ) }// topic_prefix
1057
942
 
@@ -1104,34 +989,38 @@ function mqtt_topic_path_router() {
1104
989
  if (fn) {throw new TypeError()}
1105
990
  fn = _ignore;}
1106
991
 
1107
- let rte = parse(as_topic_path(topic_route));
1108
-
1109
- rte.key = topic_route;
1110
- rte.tgt = fn;
1111
- pri_lsts[priority ? 0 : 1].push(rte);
992
+ let route = parse(as_topic_path(topic_route));
993
+ route.topic = topic_route;
994
+ route.tgt = fn;
995
+ pri_lsts[priority ? 0 : 1].push(route);
1112
996
  return this}
1113
997
 
1114
- , remove(topic_route, priority) {
1115
- let lst = pri_lsts[priority ? 0 : 1];
1116
- return _route_remove([lst], topic_route)}
998
+ , remove(query, ...args) {
999
+ let lst = pri_lsts;
1000
+ if ('boolean' === typeof args[0]) {
1001
+ lst = [pri_lsts[args.shift() ? 0 : 1]];}
1002
+
1003
+ if ('string' === typeof query) {
1004
+ query ={topic: query, tgt: args.pop()}; }
1005
+ return _route_remove(lst, query)}
1117
1006
 
1118
1007
  , clear(priority) {
1119
- pri_lsts[priority ? 0 : 1] = [];
1120
1008
  if (null == priority) {
1121
- pri_lsts[1] = []; } }// null clears both lists
1009
+ pri_lsts = [[],[]]; }// null clears both lists
1010
+ else {
1011
+ pri_lsts[priority ? 0 : 1] = [];} }
1122
1012
 
1123
1013
  , async invoke(pkt, ctx) {
1124
1014
  ctx.idx = 0;
1125
1015
  ctx.rm = rm;
1126
1016
 
1127
- for (let [fn, params] of find(pkt.topic)) {
1017
+ for (let [fn, params, route] of find(pkt.topic)) {
1128
1018
  let res = await fn(pkt, params, ctx);
1129
1019
 
1130
1020
  if (rm === res) {
1131
- _route_remove(pri_lsts, fn);}
1021
+ _route_remove(pri_lsts, route);}
1132
1022
 
1133
- if (ctx.done) {
1134
- break}
1023
+ if (ctx.done) {break}
1135
1024
  else ctx.idx++;}
1136
1025
 
1137
1026
  if (1 === pkt.qos) {
@@ -1141,70 +1030,68 @@ function mqtt_topic_path_router() {
1141
1030
  function * _routes_iter(all_route_lists, topic) {
1142
1031
  topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
1143
1032
  for (let route_list of all_route_lists) {
1144
- for (let {keys, pattern, tgt} of route_list) {
1145
- let match = pattern.exec(topic);
1033
+ for (let route of route_list) {
1034
+ let match = route.pattern.exec(topic);
1146
1035
  if (match) {
1147
- let params = keys
1148
- ? keys.reduce(
1036
+ let params = route.keys
1037
+ ? route.keys.reduce(
1149
1038
  (o, k, i) => (o[k] = match[1+i], o)
1150
1039
  , {})
1151
1040
  : match.groups ?? match;
1152
- yield [tgt, params];} } } }
1041
+ yield [route.tgt, params, route];} } } }
1153
1042
 
1154
1043
 
1155
1044
  function _route_remove(all_route_lists, query) {
1156
- let fn_match = route =>(
1157
- route===query
1158
- || route.tgt===query
1159
- || route.key===query);
1045
+ let ans = false;
1160
1046
  for (let lst of all_route_lists) {
1161
- let i = lst.findIndex(fn_match);
1162
- if (0 <= i) {
1163
- lst.splice(i,1);
1164
- return true} }
1165
- return false}
1166
-
1167
- /*
1168
- export function decode_varint_loop(u8, i=0) {
1169
- let i0 = i
1170
- let shift = 0, n = (u8[i] & 0x7f)
1171
- while ( 0x80 & u8[i++] )
1172
- n |= (u8[i] & 0x7f) << (shift += 7)
1173
-
1174
- return [n, i, i0]
1175
- }
1176
- */
1177
-
1178
-
1179
- function decode_varint(u8, i=0) {
1180
- let i0 = i;
1181
- // unrolled for a max of 4 chains
1182
- let n = (u8[i] & 0x7f) << 0;
1183
- if ( 0x80 & u8[i++] ) {
1184
- n |= (u8[i] & 0x7f) << 7;
1185
- if ( 0x80 & u8[i++] ) {
1186
- n |= (u8[i] & 0x7f) << 14;
1187
- if ( 0x80 & u8[i++] ) {
1188
- n |= (u8[i] & 0x7f) << 21;
1189
- }
1190
- }
1191
- }
1192
- return [n, i, i0]
1047
+ let idx_tip = 0;
1048
+ for (let route of lst) {
1049
+ // skip matching routes to remove from compacted list
1050
+ if (route === query) continue
1051
+ if (route.topic === query.topic) {
1052
+ if (null == query.tgt) continue
1053
+ if (route.tgt === query.tgt) continue}
1054
+
1055
+ lst[idx_tip++] = route;}
1056
+
1057
+ // truncate remaining list
1058
+ if (lst.splice(idx_tip).length)
1059
+ ans = true;}
1060
+
1061
+ return ans}
1062
+
1063
+ function decode_varint(u8, i0=0, invalid) {
1064
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
1065
+ for(; b & 0x80;)
1066
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
1067
+
1068
+ return (u8.length < i)
1069
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
1070
+ : [n, i, i0] // successful value
1193
1071
  }
1194
1072
 
1195
1073
  function mqtt_raw_dispatch(opt) {
1196
- let u8 = new Uint8Array(0);
1074
+ let u8 = new Uint8Array(0), len_tip=0;
1197
1075
  return u8_buf => {
1198
1076
  u8 = 0 === u8.byteLength
1199
1077
  ? u8_buf : _u8_join(u8, u8_buf);
1200
1078
 
1201
1079
  let res = [];
1202
- while (1) {
1203
- let [len_body, len_vh] = decode_varint(u8, 1);
1204
- let len_pkt = len_body + len_vh;
1205
1080
 
1206
- if ( u8.byteLength < len_pkt )
1207
- return res
1081
+ // wait for at least len_tip bytes for next (tip) message
1082
+ while ( u8.byteLength >= len_tip ) {
1083
+
1084
+ // if varint is incomplete, return len_body=NaN
1085
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
1086
+ let len_pkt = len_body + len_vh; // may be NaN
1087
+
1088
+ if (!( len_pkt <= u8.byteLength )) {
1089
+ // incomplete packet cases:
1090
+ // - len_pkt is less than available bytes
1091
+ // - len_pkt is NaN from decode_varint() due to lack of data
1092
+ len_tip = len_pkt || 0; // 0 when NaN
1093
+ break
1094
+ }
1208
1095
 
1209
1096
  let b0 = u8[0];
1210
1097
  let u8_body = 0 === len_body ? null
@@ -1216,6 +1103,8 @@ function mqtt_raw_dispatch(opt) {
1216
1103
  if (null != pkt)
1217
1104
  res.push( pkt );
1218
1105
  }
1106
+
1107
+ return res
1219
1108
  }
1220
1109
  }
1221
1110
 
@@ -1226,16 +1115,17 @@ function _u8_join(a, b) {
1226
1115
  return r
1227
1116
  }
1228
1117
 
1229
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
1118
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
1119
+
1120
+
1121
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
1122
+ let _as_pkt_ctx = pkt_api => ({
1123
+ __proto__: pkt_api,
1124
+ get hdr() { return this.b0 & 0xf },
1125
+ get id() { return this.b0 >>> 4 },
1126
+ get type() { return _pkt_types[this.b0 >>> 4] },
1127
+ mqtt_level });
1230
1128
 
1231
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1232
- pkt_ctx = {
1233
- __proto__: pkt_ctx || opts.pkt_ctx,
1234
- mqtt_level,
1235
- get hdr() { return this.b0 & 0xf },
1236
- get id() { return this.b0 >>> 4 },
1237
- get type() { return _pkt_types[this.b0 >>> 4] },
1238
- };
1239
1129
 
1240
1130
  let op, _decode_by_id=[], _encode_by_type={};
1241
1131
  for (op of opts.encode_fns)
@@ -1244,10 +1134,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1244
1134
  op(_decode_by_id, opts.mqtt_reader);
1245
1135
 
1246
1136
  return {
1247
- pkt_ctx,
1137
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
1248
1138
 
1249
- encode_pkt(type, pkt) {
1250
- return _encode_by_type[type]( mqtt_level, pkt ) },
1139
+ encode_pkt: (type, pkt) =>
1140
+ _encode_by_type[type]( mqtt_level, pkt ),
1251
1141
 
1252
1142
  decode_pkt(b0, u8_body) {
1253
1143
  if (b0.map) // Uint8Array in first arg
@@ -1256,12 +1146,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1256
1146
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
1257
1147
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
1258
1148
 
1259
- mqtt_stream() {
1260
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
1261
- self.pkt_ctx._base_ = self.pkt_ctx;
1149
+ mqtt_stream(pkt_api=this.pkt_api) {
1150
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
1262
1151
  self.decode = mqtt_raw_dispatch(self);
1263
- return self
1264
- },
1152
+ return self },
1265
1153
  }
1266
1154
  }
1267
1155
 
@@ -1785,7 +1673,7 @@ class MQTTCore extends MQTTBase {
1785
1673
 
1786
1674
  return this} }
1787
1675
 
1788
- const version = '0.6.2-node';
1676
+ const version = '0.6.4-node';
1789
1677
 
1790
1678
  const MQTTClient_v4 = /* #__PURE__ */
1791
1679
  with_topic_path_router(