• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / nats.js / 13138112391

04 Feb 2025 02:48PM UTC coverage: 69.574% (-13.2%) from 82.726%
13138112391

push

github

web-flow
feat(core): MsgCallback is now typed as returning `void | Promise<never>` to indicate that they cannot contain `await` (#202)

Signed-off-by: Alberto Ricart <alberto@synadia.com>

1367 of 2112 branches covered (64.73%)

Branch coverage included in aggregate %.

7608 of 10788 relevant lines covered (70.52%)

826335.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.07
/core/src/parser.ts
1
// deno-lint-ignore-file no-undef
2
/*
3
 * Copyright 2020-2021 The NATS Authors
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
import { DenoBuffer } from "./denobuffer.ts";
55✔
17
import { TD } from "./encoders.ts";
55✔
18
import type { Dispatcher } from "./core.ts";
19

20
export enum Kind {
110✔
21
  OK,
22
  ERR,
23
  MSG,
24
  INFO,
25
  PING,
26
  PONG,
27
}
28

29
export interface ParserEvent {
30
  kind: Kind;
31
  msg?: MsgArg;
32
  data?: Uint8Array;
33
}
34

35
export function describe(e: ParserEvent): string {
×
36
  let ks: string;
×
37
  let data = "";
×
38

39
  switch (e.kind) {
×
40
    case Kind.MSG:
×
41
      ks = "MSG";
×
42
      break;
×
43
    case Kind.OK:
×
44
      ks = "OK";
×
45
      break;
×
46
    case Kind.ERR:
×
47
      ks = "ERR";
×
48
      data = TD.decode(e.data);
×
49
      break;
×
50
    case Kind.PING:
×
51
      ks = "PING";
×
52
      break;
×
53
    case Kind.PONG:
×
54
      ks = "PONG";
×
55
      break;
×
56
    case Kind.INFO:
×
57
      ks = "INFO";
×
58
      data = TD.decode(e.data);
×
59
  }
×
60
  return `${ks}: ${data}`;
×
61
}
×
62

63
export interface MsgArg {
64
  subject: Uint8Array;
65
  reply?: Uint8Array;
66
  sid: number;
67
  hdr: number;
68
  size: number;
69
}
70

71
function newMsgArg(): MsgArg {
395,874✔
72
  const ma = {} as MsgArg;
395,874✔
73
  ma.sid = -1;
395,874✔
74
  ma.hdr = -1;
395,874✔
75
  ma.size = -1;
395,874✔
76

77
  return ma;
395,874✔
78
}
395,874✔
79

80
const ASCII_0 = 48;
55✔
81
const ASCII_9 = 57;
55✔
82

83
// This is an almost verbatim port of the Go NATS parser
84
// https://github.com/nats-io/nats.go/blob/master/parser.go
85
export class Parser {
55✔
86
  dispatcher: Dispatcher<ParserEvent>;
54✔
87
  state: State;
1,604✔
88
  as: number;
1,604✔
89
  drop: number;
1,604✔
90
  hdr: number;
1,604✔
91
  ma!: MsgArg;
1,604✔
92
  argBuf?: DenoBuffer;
1,604✔
93
  msgBuf?: DenoBuffer;
54✔
94

95
  constructor(dispatcher: Dispatcher<ParserEvent>) {
54✔
96
    this.dispatcher = dispatcher;
1,604✔
97
    this.state = State.OP_START;
1,604✔
98
    this.as = 0;
1,604✔
99
    this.drop = 0;
1,604✔
100
    this.hdr = 0;
1,604✔
101
  }
1,604✔
102

103
  parse(buf: Uint8Array): void {
54✔
104
    let i: number;
8,819✔
105
    for (i = 0; i < buf.length; i++) {
8,819✔
106
      const b = buf[i];
20,570,652✔
107
      switch (this.state) {
20,570,652✔
108
        case State.OP_START:
20,570,652✔
109
          switch (b) {
20,968,368✔
110
            case cc.M:
20,968,368✔
111
            case cc.m:
20,968,368✔
112
              this.state = State.OP_M;
21,363,606✔
113
              this.hdr = -1;
21,363,606✔
114
              this.ma = newMsgArg();
21,363,606✔
115
              break;
21,363,606✔
116
            case cc.H:
20,968,368✔
117
            case cc.h:
20,968,368✔
118
              this.state = State.OP_H;
20,968,950✔
119
              this.hdr = 0;
20,968,950✔
120
              this.ma = newMsgArg();
20,968,950✔
121
              break;
20,968,950✔
122
            case cc.P:
20,968,368✔
123
            case cc.p:
20,968,368✔
124
              this.state = State.OP_P;
20,969,430✔
125
              break;
20,969,430✔
126
            case cc.PLUS:
12,184,489✔
127
              this.state = State.OP_PLUS;
12,184,497✔
128
              break;
12,184,497✔
129
            case cc.MINUS:
12,204,463✔
130
              this.state = State.OP_MINUS;
12,204,531✔
131
              break;
12,204,531✔
132
            case cc.I:
20,968,368✔
133
            case cc.i:
20,968,368✔
134
              this.state = State.OP_I;
20,969,122✔
135
              break;
20,969,122✔
136
            default:
12,184,489✔
137
              throw this.fail(buf.subarray(i));
12,184,493✔
138
          }
20,968,368✔
139
          break;
21,237,281✔
140
        case State.OP_H:
20,570,652✔
141
          switch (b) {
20,571,234✔
142
            case cc.M:
20,571,234✔
143
            case cc.m:
20,571,234✔
144
              this.state = State.OP_M;
20,571,234✔
145
              break;
20,571,234✔
146
            default:
×
147
              throw this.fail(buf.subarray(i));
×
148
          }
20,571,234✔
149
          break;
20,571,234✔
150
        case State.OP_M:
20,570,652✔
151
          switch (b) {
20,966,472✔
152
            case cc.S:
20,966,472✔
153
            case cc.s:
20,966,472✔
154
              this.state = State.OP_MS;
21,234,452✔
155
              break;
21,234,452✔
156
            default:
12,183,554!
157
              throw this.fail(buf.subarray(i));
12,183,556✔
158
          }
20,966,472✔
159
          break;
21,234,452✔
160
        case State.OP_MS:
20,570,652✔
161
          switch (b) {
20,966,470✔
162
            case cc.G:
20,966,470✔
163
            case cc.g:
20,966,470✔
164
              this.state = State.OP_MSG;
21,234,448✔
165
              break;
21,234,448✔
166
            default:
12,183,552!
167
              throw this.fail(buf.subarray(i));
12,183,554✔
168
          }
20,966,470✔
169
          break;
21,234,448✔
170
        case State.OP_MSG:
20,570,652✔
171
          switch (b) {
20,966,468✔
172
            case cc.SPACE:
20,966,468✔
173
            case cc.TAB:
20,966,468✔
174
              this.state = State.OP_MSG_SPC;
21,234,444✔
175
              break;
21,234,444✔
176
            default:
12,183,550!
177
              throw this.fail(buf.subarray(i));
12,183,552✔
178
          }
20,966,468✔
179
          break;
21,234,444✔
180
        case State.OP_MSG_SPC:
20,570,652✔
181
          switch (b) {
20,966,466✔
182
            case cc.SPACE:
×
183
            case cc.TAB:
×
184
              continue;
×
185
            default:
20,966,466✔
186
              this.state = State.MSG_ARG;
20,966,466✔
187
              this.as = i;
20,966,466✔
188
          }
20,966,466✔
189
          break;
20,966,466✔
190
        case State.MSG_ARG:
20,570,652✔
191
          switch (b) {
38,048,083✔
192
            case cc.CR:
38,048,083✔
193
              this.drop = 1;
38,443,895✔
194
              break;
38,443,895✔
195
            case cc.NL: {
76,491,980✔
196
              const arg: Uint8Array = this.argBuf
23,745,461✔
197
                ? this.argBuf.bytes()
23,745,461✔
198
                : buf.subarray(this.as, i - this.drop);
23,745,461✔
199
              this.processMsgArgs(arg);
38,443,897✔
200
              this.drop = 0;
38,443,897✔
201
              this.as = i + 1;
38,443,897✔
202
              this.state = State.MSG_PAYLOAD;
38,443,897✔
203

204
              // jump ahead with the index. If this overruns
205
              // what is left we fall out and process a split buffer.
206
              i = this.as + this.ma.size - 1;
38,443,897✔
207
              break;
38,443,897✔
208
            }
38,443,897✔
209
            default:
38,048,083✔
210
              if (this.argBuf) {
33,572,679!
211
                this.argBuf.writeByte(b);
33,573,074✔
212
              }
33,573,074✔
213
          }
38,048,083✔
214
          break;
47,948,160✔
215
        case State.MSG_PAYLOAD:
20,570,652✔
216
          if (this.msgBuf) {
20,841,699✔
217
            if (this.msgBuf.length >= this.ma.size) {
20,844,541✔
218
              const data = this.msgBuf.bytes({ copy: false });
62,542,446✔
219
              this.dispatcher.push(
20,847,482✔
220
                { kind: Kind.MSG, msg: this.ma, data: data },
104,237,410✔
221
              );
222
              this.argBuf = undefined;
20,847,482✔
223
              this.msgBuf = undefined;
20,847,482✔
224
              this.state = State.MSG_END;
20,847,482✔
225
            } else {
20,846,320✔
226
              let toCopy = this.ma.size - this.msgBuf.length;
20,848,000✔
227
              const avail = buf.length - i;
20,848,000✔
228

229
              if (avail < toCopy) {
20,848,000✔
230
                toCopy = avail;
20,848,516✔
231
              }
20,848,516✔
232

233
              if (toCopy > 0) {
20,848,000✔
234
                this.msgBuf.write(buf.subarray(i, i + toCopy));
20,848,000✔
235
                i = (i + toCopy) - 1;
20,848,000✔
236
              } else {
×
237
                this.msgBuf.writeByte(b);
×
238
              }
×
239
            }
20,848,000✔
240
          } else if (i - this.as >= this.ma.size) {
20,841,699✔
241
            this.dispatcher.push(
21,361,672✔
242
              { kind: Kind.MSG, msg: this.ma, data: buf.subarray(this.as, i) },
106,808,360✔
243
            );
244
            this.argBuf = undefined;
21,361,672✔
245
            this.msgBuf = undefined;
21,361,672✔
246
            this.state = State.MSG_END;
21,361,672✔
247
          }
21,361,672✔
248
          break;
20,968,127✔
249
        case State.MSG_END:
20,570,652✔
250
          switch (b) {
20,966,447✔
251
            case cc.NL:
20,966,447✔
252
              this.drop = 0;
20,966,447✔
253
              this.as = i + 1;
20,966,447✔
254
              this.state = State.OP_START;
20,966,447✔
255
              break;
20,966,447✔
256
            default:
×
257
              continue;
×
258
          }
20,966,447✔
259
          break;
20,966,447✔
260
        case State.OP_PLUS:
11,915,572!
261
          switch (b) {
11,915,580✔
262
            case cc.O:
11,915,580✔
263
            case cc.o:
11,915,580✔
264
              this.state = State.OP_PLUS_O;
11,915,584✔
265
              break;
11,915,584✔
266
            default:
11,915,580✔
267
              throw this.fail(buf.subarray(i));
11,915,584✔
268
          }
11,915,580✔
269
          break;
11,915,584✔
270
        case State.OP_PLUS_O:
11,915,572!
271
          switch (b) {
11,915,576✔
272
            case cc.K:
11,915,576✔
273
            case cc.k:
11,915,576✔
274
              this.state = State.OP_PLUS_OK;
11,915,576✔
275
              break;
11,915,576✔
276
            default:
×
277
              throw this.fail(buf.subarray(i));
×
278
          }
11,915,576✔
279
          break;
11,915,576✔
280
        case State.OP_PLUS_OK:
11,915,572!
281
          switch (b) {
11,915,584✔
282
            case cc.NL:
11,915,584✔
283
              this.dispatcher.push({ kind: Kind.OK });
35,746,764✔
284
              this.drop = 0;
11,915,588✔
285
              this.state = State.OP_START;
11,915,588✔
286
              break;
11,915,588✔
287
          }
11,915,584✔
288
          break;
11,915,584✔
289
        case State.OP_MINUS:
11,935,315!
290
          switch (b) {
11,935,383✔
291
            case cc.E:
11,935,383✔
292
            case cc.e:
11,935,383✔
293
              this.state = State.OP_MINUS_E;
11,935,447✔
294
              break;
11,935,447✔
295
            default:
11,915,638!
296
              throw this.fail(buf.subarray(i));
11,915,640✔
297
          }
11,935,383✔
298
          break;
11,935,447✔
299
        case State.OP_MINUS_E:
11,935,315!
300
          switch (b) {
11,935,381✔
301
            case cc.R:
11,935,381✔
302
            case cc.r:
11,935,381✔
303
              this.state = State.OP_MINUS_ER;
11,935,443✔
304
              break;
11,935,443✔
305
            default:
11,915,636!
306
              throw this.fail(buf.subarray(i));
11,915,638✔
307
          }
11,935,381✔
308
          break;
11,935,443✔
309
        case State.OP_MINUS_ER:
11,935,315!
310
          switch (b) {
11,935,379✔
311
            case cc.R:
11,935,379✔
312
            case cc.r:
11,935,379✔
313
              this.state = State.OP_MINUS_ERR;
11,935,439✔
314
              break;
11,935,439✔
315
            default:
11,915,634!
316
              throw this.fail(buf.subarray(i));
11,915,636✔
317
          }
11,935,379✔
318
          break;
11,935,439✔
319
        case State.OP_MINUS_ERR:
11,935,315!
320
          switch (b) {
11,935,377✔
321
            case cc.SPACE:
11,935,377✔
322
            case cc.TAB:
11,935,377✔
323
              this.state = State.OP_MINUS_ERR_SPC;
11,935,435✔
324
              break;
11,935,435✔
325
            default:
11,915,632!
326
              throw this.fail(buf.subarray(i));
11,915,634✔
327
          }
11,935,377✔
328
          break;
11,935,435✔
329
        case State.OP_MINUS_ERR_SPC:
11,935,315!
330
          switch (b) {
11,935,375✔
331
            case cc.SPACE:
×
332
            case cc.TAB:
×
333
              continue;
×
334
            default:
11,935,375✔
335
              this.state = State.MINUS_ERR_ARG;
11,935,375✔
336
              this.as = i;
11,935,375✔
337
          }
11,935,375✔
338
          break;
11,935,375✔
339
        case State.MINUS_ERR_ARG:
11,935,315!
340
          switch (b) {
11,937,461✔
341
            case cc.CR:
11,937,461✔
342
              this.drop = 1;
11,937,521✔
343
              break;
11,937,521✔
344
            case cc.NL: {
23,874,982✔
345
              let arg: Uint8Array;
11,937,521✔
346
              if (this.argBuf) {
11,917,642!
347
                arg = this.argBuf.bytes();
11,917,700✔
348
                this.argBuf = undefined;
11,917,700✔
349
              } else {
11,917,698✔
350
                arg = buf.subarray(this.as, i - this.drop);
11,937,577✔
351
              }
11,937,577✔
352
              this.dispatcher.push({ kind: Kind.ERR, data: arg });
47,750,084✔
353
              this.drop = 0;
11,937,521✔
354
              this.as = i + 1;
11,937,521✔
355
              this.state = State.OP_START;
11,937,521✔
356
              break;
11,937,521✔
357
            }
11,937,521✔
358
            default:
11,937,461✔
359
              if (this.argBuf) {
11,919,480!
360
                this.argBuf.write(Uint8Array.of(b));
11,919,498✔
361
              }
11,919,498✔
362
          }
11,937,461✔
363
          break;
11,937,461✔
364
        case State.OP_P:
20,570,652✔
365
          switch (b) {
20,571,714✔
366
            case cc.I:
20,571,714✔
367
            case cc.i:
20,571,714✔
368
              this.state = State.OP_PI;
20,571,761✔
369
              break;
20,571,761✔
370
            case cc.O:
20,571,714✔
371
            case cc.o:
20,571,714✔
372
              this.state = State.OP_PO;
20,572,727✔
373
              break;
20,572,727✔
374
            default:
11,916,096!
375
              throw this.fail(buf.subarray(i));
11,916,098✔
376
          }
20,571,714✔
377
          break;
20,572,236✔
378
        case State.OP_PO:
20,570,652✔
379
          switch (b) {
20,571,665✔
380
            case cc.N:
20,571,665✔
381
            case cc.n:
20,571,665✔
382
              this.state = State.OP_PON;
20,572,168✔
383
              break;
20,572,168✔
384
            default:
11,916,077!
385
              throw this.fail(buf.subarray(i));
11,916,079✔
386
          }
20,571,665✔
387
          break;
20,572,168✔
388
        case State.OP_PON:
20,570,652✔
389
          switch (b) {
20,571,663✔
390
            case cc.G:
20,571,663✔
391
            case cc.g:
20,571,663✔
392
              this.state = State.OP_PONG;
20,572,164✔
393
              break;
20,572,164✔
394
            default:
11,916,075!
395
              throw this.fail(buf.subarray(i));
11,916,077✔
396
          }
20,571,663✔
397
          break;
20,572,164✔
398
        case State.OP_PONG:
20,570,652✔
399
          switch (b) {
20,572,670✔
400
            case cc.NL:
20,572,670✔
401
              this.dispatcher.push({ kind: Kind.PONG });
61,721,037✔
402
              this.drop = 0;
20,573,679✔
403
              this.state = State.OP_START;
20,573,679✔
404
              break;
20,573,679✔
405
          }
20,572,670✔
406
          break;
20,572,670✔
407
        case State.OP_PI:
20,570,652✔
408
          switch (b) {
20,570,699✔
409
            case cc.N:
20,570,699✔
410
            case cc.n:
20,570,699✔
411
              this.state = State.OP_PIN;
20,570,714✔
412
              break;
20,570,714✔
413
            default:
11,915,589!
414
              throw this.fail(buf.subarray(i));
11,915,591✔
415
          }
20,570,699✔
416
          break;
20,570,714✔
417
        case State.OP_PIN:
20,570,652✔
418
          switch (b) {
20,570,697✔
419
            case cc.G:
20,570,697✔
420
            case cc.g:
20,570,697✔
421
              this.state = State.OP_PING;
20,570,710✔
422
              break;
20,570,710✔
423
            default:
11,915,587!
424
              throw this.fail(buf.subarray(i));
11,915,589✔
425
          }
20,570,697✔
426
          break;
20,570,710✔
427
        case State.OP_PING:
20,570,652✔
428
          switch (b) {
20,570,754✔
429
            case cc.NL:
20,570,754✔
430
              this.dispatcher.push({ kind: Kind.PING });
61,712,391✔
431
              this.drop = 0;
20,570,797✔
432
              this.state = State.OP_START;
20,570,797✔
433
              break;
20,570,797✔
434
          }
20,570,754✔
435
          break;
20,570,754✔
436
        case State.OP_I:
20,570,652✔
437
          switch (b) {
20,571,416✔
438
            case cc.N:
20,571,416✔
439
            case cc.n:
20,571,416✔
440
              this.state = State.OP_IN;
20,571,747✔
441
              break;
20,571,747✔
442
            default:
11,915,915!
443
              throw this.fail(buf.subarray(i));
11,915,927✔
444
          }
20,571,416✔
445
          break;
20,571,747✔
446
        case State.OP_IN:
20,570,652✔
447
          switch (b) {
20,571,404✔
448
            case cc.F:
20,571,404✔
449
            case cc.f:
20,571,404✔
450
              this.state = State.OP_INF;
20,571,404✔
451
              break;
20,571,404✔
452
            default:
×
453
              throw this.fail(buf.subarray(i));
×
454
          }
20,571,404✔
455
          break;
20,571,404✔
456
        case State.OP_INF:
20,570,652✔
457
          switch (b) {
20,571,404✔
458
            case cc.O:
20,571,404✔
459
            case cc.o:
20,571,404✔
460
              this.state = State.OP_INFO;
20,571,404✔
461
              break;
20,571,404✔
462
            default:
×
463
              throw this.fail(buf.subarray(i));
×
464
          }
20,571,404✔
465
          break;
20,571,404✔
466
        case State.OP_INFO:
20,570,652✔
467
          switch (b) {
20,571,404✔
468
            case cc.SPACE:
20,571,404✔
469
            case cc.TAB:
20,571,404✔
470
              this.state = State.OP_INFO_SPC;
20,571,404✔
471
              break;
20,571,404✔
472
            default:
×
473
              throw this.fail(buf.subarray(i));
×
474
          }
20,571,404✔
475
          break;
20,571,404✔
476
        case State.OP_INFO_SPC:
20,570,652✔
477
          switch (b) {
20,571,406✔
478
            case cc.SPACE:
11,915,905!
479
            case cc.TAB:
11,915,905!
480
              continue;
11,915,907✔
481
            default:
20,571,406✔
482
              this.state = State.INFO_ARG;
20,571,737✔
483
              this.as = i;
20,571,737✔
484
          }
20,571,406✔
485
          break;
20,571,737✔
486
        case State.INFO_ARG:
20,570,652✔
487
          switch (b) {
20,868,656✔
488
            case cc.CR:
20,868,656✔
489
              this.drop = 1;
20,869,408✔
490
              break;
20,869,408✔
491
            case cc.NL: {
41,738,064✔
492
              let arg: Uint8Array;
20,869,408✔
493
              if (this.argBuf) {
12,042,839!
494
                arg = this.argBuf.bytes();
12,042,843✔
495
                this.argBuf = undefined;
12,042,843✔
496
              } else {
12,042,839✔
497
                arg = buf.subarray(this.as, i - this.drop);
20,869,735✔
498
              }
20,869,735✔
499
              this.dispatcher.push({ kind: Kind.INFO, data: arg });
83,477,632✔
500
              this.drop = 0;
20,869,408✔
501
              this.as = i + 1;
20,869,408✔
502
              this.state = State.OP_START;
20,869,408✔
503
              break;
20,869,408✔
504
            }
20,869,408✔
505
            default:
20,868,656✔
506
              if (this.argBuf) {
12,168,782!
507
                this.argBuf.writeByte(b);
12,169,142✔
508
              }
12,169,142✔
509
          }
20,868,656✔
510
          break;
20,868,656✔
511
        default:
×
512
          throw this.fail(buf.subarray(i));
×
513
      }
20,570,652✔
514
    }
20,570,652✔
515

516
    if (
3,860✔
517
      (this.state === State.MSG_ARG || this.state === State.MINUS_ERR_ARG ||
3,860✔
518
        this.state === State.INFO_ARG) && !this.argBuf
3,860!
519
    ) {
3,860!
520
      this.argBuf = new DenoBuffer(buf.subarray(this.as, i - this.drop));
3,903✔
521
    }
3,903✔
522

523
    if (this.state === State.MSG_PAYLOAD && !this.msgBuf) {
7,669!
524
      if (!this.argBuf) {
8,834✔
525
        this.cloneMsgArg();
9,944✔
526
      }
9,944✔
527
      this.msgBuf = new DenoBuffer(buf.subarray(this.as));
8,834✔
528
    }
8,834✔
529
  }
8,819✔
530

531
  cloneMsgArg() {
52✔
532
    const s = this.ma.subject.length;
1,215✔
533
    const r = this.ma.reply ? this.ma.reply.length : 0;
1,215✔
534
    const buf = new Uint8Array(s + r);
1,215✔
535
    buf.set(this.ma.subject);
1,215✔
536
    if (this.ma.reply) {
1,215✔
537
      buf.set(this.ma.reply, s);
1,367✔
538
    }
1,367✔
539
    this.argBuf = new DenoBuffer(buf);
1,215✔
540
    this.ma.subject = buf.subarray(0, s);
1,215✔
541
    if (this.ma.reply) {
1,215✔
542
      this.ma.reply = buf.subarray(s);
1,367✔
543
    }
1,367✔
544
  }
1,215✔
545

546
  processMsgArgs(arg: Uint8Array): void {
54✔
547
    if (this.hdr >= 0) {
395,868✔
548
      return this.processHeaderMsgArgs(arg);
664,424✔
549
    }
664,424✔
550

551
    const args: Uint8Array[] = [];
1,059,074✔
552
    let start = -1;
1,059,074✔
553
    for (let i = 0; i < arg.length; i++) {
663,842✔
554
      const b = arg[i];
17,708,015✔
555
      switch (b) {
17,708,015✔
556
        case cc.SPACE:
17,708,015✔
557
        case cc.TAB:
17,708,015✔
558
        case cc.CR:
17,708,015✔
559
        case cc.NL:
17,708,015✔
560
          if (start >= 0) {
18,503,961✔
561
            args.push(arg.subarray(start, i));
19,271,392✔
562
            start = -1;
19,271,392✔
563
          }
19,271,392✔
564
          break;
18,503,961✔
565
        default:
17,708,015✔
566
          if (start < 0) {
33,956,242✔
567
            start = i;
35,147,414✔
568
          }
35,147,414✔
569
      }
17,708,015✔
570
    }
17,708,015✔
571
    if (start >= 0) {
1,440,867✔
572
      args.push(arg.subarray(start));
1,708,614✔
573
    }
1,708,614✔
574

575
    switch (args.length) {
1,708,616✔
576
      case 3:
1,045,422✔
577
        this.ma.subject = args[0];
1,435,154✔
578
        this.ma.sid = this.protoParseInt(args[1]);
1,435,154✔
579
        this.ma.reply = undefined;
1,435,154✔
580
        this.ma.size = this.protoParseInt(args[2]);
1,435,154✔
581
        break;
1,435,154✔
582
      case 4:
395,868✔
583
        this.ma.subject = args[0];
401,360✔
584
        this.ma.sid = this.protoParseInt(args[1]);
401,360✔
585
        this.ma.reply = args[2];
401,360✔
586
        this.ma.size = this.protoParseInt(args[3]);
401,360✔
587
        break;
401,360✔
588
      default:
268,009!
589
        throw this.fail(arg, "processMsgArgs Parse Error");
268,017✔
590
    }
395,868✔
591

592
    if (this.ma.sid < 0) {
535,983!
593
      throw this.fail(arg, "processMsgArgs Bad or Missing Sid Error");
535,989✔
594
    }
535,989✔
595
    if (this.ma.size < 0) {
535,983!
596
      throw this.fail(arg, "processMsgArgs Bad or Missing Size Error");
535,985✔
597
    }
535,985✔
598
  }
395,868✔
599

600
  fail(data: Uint8Array, label = ""): Error {
33✔
601
    if (!label) {
93✔
602
      label = `parse error [${this.state}]`;
137✔
603
    } else {
93✔
604
      label = `${label} [${this.state}]`;
109✔
605
    }
109✔
606

607
    return new Error(`${label}: ${TD.decode(data)}`);
93✔
608
  }
93✔
609

610
  processHeaderMsgArgs(arg: Uint8Array): void {
54✔
611
    const args: Uint8Array[] = [];
636✔
612
    let start = -1;
636✔
613
    for (let i = 0; i < arg.length; i++) {
636✔
614
      const b = arg[i];
38,082✔
615
      switch (b) {
38,082✔
616
        case cc.SPACE:
38,082✔
617
        case cc.TAB:
38,082✔
618
        case cc.CR:
38,082✔
619
        case cc.NL:
38,082✔
620
          if (start >= 0) {
40,149✔
621
            args.push(arg.subarray(start, i));
41,037✔
622
            start = -1;
41,037✔
623
          }
41,037✔
624
          break;
40,149✔
625
        default:
38,082✔
626
          if (start < 0) {
73,461✔
627
            start = i;
76,109✔
628
          }
76,109✔
629
      }
38,082✔
630
    }
38,082✔
631
    if (start >= 0) {
636✔
632
      args.push(arg.subarray(start));
636✔
633
    }
636✔
634

635
    switch (args.length) {
636✔
636
      case 4:
625✔
637
        this.ma.subject = args[0];
881✔
638
        this.ma.sid = this.protoParseInt(args[1]);
881✔
639
        this.ma.reply = undefined;
881✔
640
        this.ma.hdr = this.protoParseInt(args[2]);
881✔
641
        this.ma.size = this.protoParseInt(args[3]);
881✔
642
        break;
881✔
643
      case 5:
629!
644
        this.ma.subject = args[0];
939✔
645
        this.ma.sid = this.protoParseInt(args[1]);
939✔
646
        this.ma.reply = args[2];
939✔
647
        this.ma.hdr = this.protoParseInt(args[3]);
939✔
648
        this.ma.size = this.protoParseInt(args[4]);
939✔
649
        break;
939✔
650
      default:
×
651
        throw this.fail(arg, "processHeaderMsgArgs Parse Error");
×
652
    }
636✔
653

654
    if (this.ma.sid < 0) {
×
655
      throw this.fail(arg, "processHeaderMsgArgs Bad or Missing Sid Error");
×
656
    }
×
657
    if (this.ma.hdr < 0 || this.ma.hdr > this.ma.size) {
×
658
      throw this.fail(
×
659
        arg,
×
660
        "processHeaderMsgArgs Bad or Missing Header Size Error",
×
661
      );
662
    }
×
663
    if (this.ma.size < 0) {
×
664
      throw this.fail(arg, "processHeaderMsgArgs Bad or Missing Size Error");
×
665
    }
×
666
  }
636✔
667

668
  protoParseInt(a: Uint8Array): number {
54✔
669
    if (a.length === 0) {
×
670
      return -1;
×
671
    }
×
672
    let n = 0;
792,248✔
673
    for (let i = 0; i < a.length; i++) {
792,248✔
674
      if (a[i] < ASCII_0 || a[i] > ASCII_9) {
1,843,646✔
675
        return -1;
1,843,658✔
676
      }
1,843,658✔
677
      n = n * 10 + (a[i] - ASCII_0);
3,789,584✔
678
    }
3,789,584✔
679
    return n;
1,328,399✔
680
  }
792,248✔
681
}
55✔
682

683
export enum State {
110✔
684
  OP_START = 0,
685
  OP_PLUS,
686
  OP_PLUS_O,
687
  OP_PLUS_OK,
688
  OP_MINUS,
689
  OP_MINUS_E,
690
  OP_MINUS_ER,
691
  OP_MINUS_ERR,
692
  OP_MINUS_ERR_SPC,
693
  MINUS_ERR_ARG,
694
  OP_M,
695
  OP_MS,
696
  OP_MSG,
697
  OP_MSG_SPC,
698
  MSG_ARG,
699
  MSG_PAYLOAD,
700
  MSG_END,
701
  OP_H,
702
  OP_P,
703
  OP_PI,
704
  OP_PIN,
705
  OP_PING,
706
  OP_PO,
707
  OP_PON,
708
  OP_PONG,
709
  OP_I,
710
  OP_IN,
711
  OP_INF,
712
  OP_INFO,
713
  OP_INFO_SPC,
714
  INFO_ARG,
715
}
716

717
enum cc {
110✔
718
  CR = "\r".charCodeAt(0),
110✔
719
  E = "E".charCodeAt(0),
110✔
720
  e = "e".charCodeAt(0),
110✔
721
  F = "F".charCodeAt(0),
110✔
722
  f = "f".charCodeAt(0),
110✔
723
  G = "G".charCodeAt(0),
110✔
724
  g = "g".charCodeAt(0),
110✔
725
  H = "H".charCodeAt(0),
110✔
726
  h = "h".charCodeAt(0),
110✔
727
  I = "I".charCodeAt(0),
110✔
728
  i = "i".charCodeAt(0),
110✔
729
  K = "K".charCodeAt(0),
110✔
730
  k = "k".charCodeAt(0),
110✔
731
  M = "M".charCodeAt(0),
110✔
732
  m = "m".charCodeAt(0),
110✔
733
  MINUS = "-".charCodeAt(0),
110✔
734
  N = "N".charCodeAt(0),
110✔
735
  n = "n".charCodeAt(0),
110✔
736
  NL = "\n".charCodeAt(0),
110✔
737
  O = "O".charCodeAt(0),
110✔
738
  o = "o".charCodeAt(0),
110✔
739
  P = "P".charCodeAt(0),
110✔
740
  p = "p".charCodeAt(0),
110✔
741
  PLUS = "+".charCodeAt(0),
110✔
742
  R = "R".charCodeAt(0),
110✔
743
  r = "r".charCodeAt(0),
110✔
744
  S = "S".charCodeAt(0),
110✔
745
  s = "s".charCodeAt(0),
110✔
746
  SPACE = " ".charCodeAt(0),
110✔
747
  TAB = "\t".charCodeAt(0),
110✔
748
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc