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

nats-io / nats.js / 13209732514

07 Feb 2025 11:25PM UTC coverage: 57.703% (-25.0%) from 82.694%
13209732514

push

github

web-flow
Convert enums to constant objects with `as const` for better type safety (#204)

* Convert enums to constant objects with `as const` for better type safety

Replaced TypeScript `enum` declarations with constant objects using `as const`. This change preserves the same api, but removes enums, and allows using the values directly without importing the constant. Enums are problematic because they require transpilation, with this change erasure is possible.

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

* fix tests

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

---------

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

868 of 1542 branches covered (56.29%)

Branch coverage included in aggregate %.

227 of 228 new or added lines in 12 files covered. (99.56%)

58 existing lines in 4 files now uncovered.

6642 of 11473 relevant lines covered (57.89%)

24643.41 hits per line

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

71.48
/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";
4✔
17
import { TD } from "./encoders.ts";
4✔
18
import type { Dispatcher } from "./core.ts";
19

20
export const Kind = {
4✔
21
  OK: 0,
4✔
22
  ERR: 1,
4✔
23
  MSG: 2,
4✔
24
  INFO: 3,
4✔
25
  PING: 4,
4✔
26
  PONG: 5,
4✔
27
} as const;
4✔
28

29
export type Kind = typeof Kind[keyof typeof Kind];
30

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

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

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

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

73
function newMsgArg(): MsgArg {
14,212✔
74
  const ma = {} as MsgArg;
14,212✔
75
  ma.sid = -1;
14,212✔
76
  ma.hdr = -1;
14,212✔
77
  ma.size = -1;
14,212✔
78

79
  return ma;
14,212✔
80
}
14,212✔
81

82
const ASCII_0 = 48;
4✔
83
const ASCII_9 = 57;
4✔
84

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

97
  constructor(dispatcher: Dispatcher<ParserEvent>) {
3✔
98
    this.dispatcher = dispatcher;
276✔
99
    this.state = State.OP_START;
276✔
100
    this.as = 0;
276✔
101
    this.drop = 0;
276✔
102
    this.hdr = 0;
276✔
103
  }
276✔
104

105
  parse(buf: Uint8Array): void {
3✔
106
    let i: number;
1,680✔
107
    for (i = 0; i < buf.length; i++) {
1,680✔
108
      const b = buf[i];
1,003,617✔
109
      switch (this.state) {
1,003,617✔
110
        case State.OP_START:
1,003,617✔
111
          switch (b) {
1,018,178✔
112
            case cc.M:
1,018,178✔
113
            case cc.m:
1,018,178✔
114
              this.state = State.OP_M;
1,032,240✔
115
              this.hdr = -1;
1,032,240✔
116
              this.ma = newMsgArg();
1,032,240✔
117
              break;
1,032,240✔
118
            case cc.H:
1,018,178✔
119
            case cc.h:
1,018,178✔
120
              this.state = State.OP_H;
1,018,325✔
121
              this.hdr = 0;
1,018,325✔
122
              this.ma = newMsgArg();
1,018,325✔
123
              break;
1,018,325✔
124
            case cc.P:
1,018,178✔
125
            case cc.p:
1,018,178✔
126
              this.state = State.OP_P;
1,018,391✔
127
              break;
1,018,391✔
128
            case cc.PLUS:
×
129
              this.state = State.OP_PLUS;
×
130
              break;
×
131
            case cc.MINUS:
19,974✔
132
              this.state = State.OP_MINUS;
19,976✔
133
              break;
19,976✔
134
            case cc.I:
1,018,178✔
135
            case cc.i:
1,018,178✔
136
              this.state = State.OP_I;
1,018,315✔
137
              break;
1,018,315✔
138
            default:
×
139
              throw this.fail(buf.subarray(i));
×
140
          }
1,018,178✔
141
          break;
1,018,178✔
142
        case State.OP_H:
1,003,617✔
143
          switch (b) {
1,003,764✔
144
            case cc.M:
1,003,764✔
145
            case cc.m:
1,003,764✔
146
              this.state = State.OP_M;
1,003,764✔
147
              break;
1,003,764✔
148
            default:
×
149
              throw this.fail(buf.subarray(i));
×
150
          }
1,003,764✔
151
          break;
1,003,764✔
152
        case State.OP_M:
1,003,617✔
153
          switch (b) {
1,017,826✔
154
            case cc.S:
1,017,826✔
155
            case cc.s:
1,017,826✔
156
              this.state = State.OP_MS;
1,017,826✔
157
              break;
1,017,826✔
158
            default:
×
159
              throw this.fail(buf.subarray(i));
×
160
          }
1,017,826✔
161
          break;
1,017,826✔
162
        case State.OP_MS:
1,003,617✔
163
          switch (b) {
1,017,826✔
164
            case cc.G:
1,017,826✔
165
            case cc.g:
1,017,826✔
166
              this.state = State.OP_MSG;
1,017,826✔
167
              break;
1,017,826✔
168
            default:
×
169
              throw this.fail(buf.subarray(i));
×
170
          }
1,017,826✔
171
          break;
1,017,826✔
172
        case State.OP_MSG:
1,003,617✔
173
          switch (b) {
1,017,826✔
174
            case cc.SPACE:
1,017,826✔
175
            case cc.TAB:
1,017,826✔
176
              this.state = State.OP_MSG_SPC;
1,017,826✔
177
              break;
1,017,826✔
178
            default:
×
179
              throw this.fail(buf.subarray(i));
×
180
          }
1,017,826✔
181
          break;
1,017,826✔
182
        case State.OP_MSG_SPC:
1,003,617✔
183
          switch (b) {
1,017,826✔
184
            case cc.SPACE:
×
185
            case cc.TAB:
×
186
              continue;
×
187
            default:
1,017,826✔
188
              this.state = State.MSG_ARG;
1,017,826✔
189
              this.as = i;
1,017,826✔
190
          }
1,017,826✔
191
          break;
1,017,826✔
192
        case State.MSG_ARG:
1,003,617✔
193
          switch (b) {
1,848,412✔
194
            case cc.CR:
1,848,412✔
195
              this.drop = 1;
1,862,621✔
196
              break;
1,862,621✔
197
            case cc.NL: {
3,711,033✔
198
              const arg: Uint8Array = this.argBuf
1,661,814✔
199
                ? this.argBuf.bytes()
1,661,814✔
200
                : buf.subarray(this.as, i - this.drop);
1,661,814✔
201
              this.processMsgArgs(arg);
1,862,621✔
202
              this.drop = 0;
1,862,621✔
203
              this.as = i + 1;
1,862,621✔
204
              this.state = State.MSG_PAYLOAD;
1,862,621✔
205

206
              // jump ahead with the index. If this overruns
207
              // what is left we fall out and process a split buffer.
208
              i = this.as + this.ma.size - 1;
1,862,621✔
209
              break;
1,862,621✔
210
            }
1,862,621✔
211
            default:
1,848,412✔
212
              if (this.argBuf) {
2,392,865!
213
                this.argBuf.writeByte(b);
2,392,882✔
214
              }
2,392,882✔
215
          }
1,848,412✔
216
          break;
1,848,412✔
217
        case State.MSG_PAYLOAD:
1,003,617✔
218
          if (this.msgBuf) {
891,413!
219
            if (this.msgBuf.length >= this.ma.size) {
891,430✔
220
              const data = this.msgBuf.bytes({ copy: false });
2,674,302✔
221
              this.dispatcher.push(
891,434✔
222
                { kind: Kind.MSG, msg: this.ma, data: data },
4,457,170✔
223
              );
224
              this.argBuf = undefined;
891,434✔
225
              this.msgBuf = undefined;
891,434✔
226
              this.state = State.MSG_END;
891,434✔
227
            } else {
891,430✔
228
              let toCopy = this.ma.size - this.msgBuf.length;
891,443✔
229
              const avail = buf.length - i;
891,443✔
230

231
              if (avail < toCopy) {
891,443✔
232
                toCopy = avail;
891,452✔
233
              }
891,452✔
234

235
              if (toCopy > 0) {
891,443✔
236
                this.msgBuf.write(buf.subarray(i, i + toCopy));
891,443✔
237
                i = (i + toCopy) - 1;
891,443✔
238
              } else {
×
239
                this.msgBuf.writeByte(b);
×
240
              }
×
241
            }
891,443✔
242
          } else if (i - this.as >= this.ma.size) {
891,413✔
243
            this.dispatcher.push(
1,030,956✔
244
              { kind: Kind.MSG, msg: this.ma, data: buf.subarray(this.as, i) },
5,154,780✔
245
            );
246
            this.argBuf = undefined;
1,030,956✔
247
            this.msgBuf = undefined;
1,030,956✔
248
            this.state = State.MSG_END;
1,030,956✔
249
          }
1,030,956✔
250
          break;
1,017,839✔
251
        case State.MSG_END:
1,003,617✔
252
          switch (b) {
1,017,826✔
253
            case cc.NL:
1,017,826✔
254
              this.drop = 0;
1,017,826✔
255
              this.as = i + 1;
1,017,826✔
256
              this.state = State.OP_START;
1,017,826✔
257
              break;
1,017,826✔
258
            default:
×
259
              continue;
×
260
          }
1,017,826✔
261
          break;
1,017,826✔
262
        case State.OP_PLUS:
×
263
          switch (b) {
×
264
            case cc.O:
×
265
            case cc.o:
×
266
              this.state = State.OP_PLUS_O;
×
267
              break;
×
268
            default:
×
269
              throw this.fail(buf.subarray(i));
×
270
          }
×
271
          break;
×
272
        case State.OP_PLUS_O:
×
273
          switch (b) {
×
274
            case cc.K:
×
275
            case cc.k:
×
276
              this.state = State.OP_PLUS_OK;
×
277
              break;
×
278
            default:
×
279
              throw this.fail(buf.subarray(i));
×
280
          }
×
281
          break;
×
282
        case State.OP_PLUS_OK:
×
283
          switch (b) {
×
284
            case cc.NL:
×
285
              this.dispatcher.push({ kind: Kind.OK });
×
286
              this.drop = 0;
×
287
              this.state = State.OP_START;
×
288
              break;
×
289
          }
×
290
          break;
×
291
        case State.OP_MINUS:
19,743!
292
          switch (b) {
19,745✔
293
            case cc.E:
19,745✔
294
            case cc.e:
19,745✔
295
              this.state = State.OP_MINUS_E;
19,745✔
296
              break;
19,745✔
297
            default:
×
298
              throw this.fail(buf.subarray(i));
×
299
          }
19,745✔
300
          break;
19,745✔
301
        case State.OP_MINUS_E:
19,743!
302
          switch (b) {
19,745✔
303
            case cc.R:
19,745✔
304
            case cc.r:
19,745✔
305
              this.state = State.OP_MINUS_ER;
19,745✔
306
              break;
19,745✔
307
            default:
×
308
              throw this.fail(buf.subarray(i));
×
309
          }
19,745✔
310
          break;
19,745✔
311
        case State.OP_MINUS_ER:
19,743!
312
          switch (b) {
19,745✔
313
            case cc.R:
19,745✔
314
            case cc.r:
19,745✔
315
              this.state = State.OP_MINUS_ERR;
19,745✔
316
              break;
19,745✔
317
            default:
×
318
              throw this.fail(buf.subarray(i));
×
319
          }
19,745✔
320
          break;
19,745✔
321
        case State.OP_MINUS_ERR:
19,743!
322
          switch (b) {
19,745✔
323
            case cc.SPACE:
19,745✔
324
            case cc.TAB:
19,745✔
325
              this.state = State.OP_MINUS_ERR_SPC;
19,745✔
326
              break;
19,745✔
327
            default:
×
328
              throw this.fail(buf.subarray(i));
×
329
          }
19,745✔
330
          break;
19,745✔
331
        case State.OP_MINUS_ERR_SPC:
19,743!
332
          switch (b) {
19,745✔
333
            case cc.SPACE:
×
334
            case cc.TAB:
×
335
              continue;
×
336
            default:
19,745✔
337
              this.state = State.MINUS_ERR_ARG;
19,745✔
338
              this.as = i;
19,745✔
339
          }
19,745✔
340
          break;
19,745✔
341
        case State.MINUS_ERR_ARG:
19,743!
342
          switch (b) {
19,877✔
343
            case cc.CR:
19,877✔
344
              this.drop = 1;
19,879✔
345
              break;
19,879✔
346
            case cc.NL: {
39,756✔
347
              let arg: Uint8Array;
19,879✔
348
              if (this.argBuf) {
×
349
                arg = this.argBuf.bytes();
×
350
                this.argBuf = undefined;
×
351
              } else {
×
352
                arg = buf.subarray(this.as, i - this.drop);
19,879✔
353
              }
19,879✔
354
              this.dispatcher.push({ kind: Kind.ERR, data: arg });
79,516✔
355
              this.drop = 0;
19,879✔
356
              this.as = i + 1;
19,879✔
357
              this.state = State.OP_START;
19,879✔
358
              break;
19,879✔
359
            }
19,879✔
360
            default:
19,877✔
361
              if (this.argBuf) {
×
362
                this.argBuf.write(Uint8Array.of(b));
×
363
              }
×
364
          }
19,877✔
365
          break;
19,877✔
366
        case State.OP_P:
1,003,617✔
367
          switch (b) {
1,003,830✔
UNCOV
368
            case cc.I:
125,514!
UNCOV
369
            case cc.i:
125,514!
UNCOV
370
              this.state = State.OP_PI;
125,518✔
UNCOV
371
              break;
125,518✔
372
            case cc.O:
1,003,830✔
373
            case cc.o:
1,003,830✔
374
              this.state = State.OP_PO;
1,004,002✔
375
              break;
1,004,002✔
376
            default:
×
377
              throw this.fail(buf.subarray(i));
×
378
          }
1,003,830✔
379
          break;
1,003,830✔
380
        case State.OP_PO:
1,003,617✔
381
          switch (b) {
1,003,826✔
382
            case cc.N:
1,003,826✔
383
            case cc.n:
1,003,826✔
384
              this.state = State.OP_PON;
1,003,826✔
385
              break;
1,003,826✔
386
            default:
×
387
              throw this.fail(buf.subarray(i));
×
388
          }
1,003,826✔
389
          break;
1,003,826✔
390
        case State.OP_PON:
1,003,617✔
391
          switch (b) {
1,003,826✔
392
            case cc.G:
1,003,826✔
393
            case cc.g:
1,003,826✔
394
              this.state = State.OP_PONG;
1,003,826✔
395
              break;
1,003,826✔
396
            default:
×
397
              throw this.fail(buf.subarray(i));
×
398
          }
1,003,826✔
399
          break;
1,003,826✔
400
        case State.OP_PONG:
1,003,617✔
401
          switch (b) {
1,004,035✔
402
            case cc.NL:
1,004,035✔
403
              this.dispatcher.push({ kind: Kind.PONG });
3,012,732✔
404
              this.drop = 0;
1,004,244✔
405
              this.state = State.OP_START;
1,004,244✔
406
              break;
1,004,244✔
407
          }
1,004,035✔
408
          break;
1,004,035✔
UNCOV
409
        case State.OP_PI:
125,338!
UNCOV
410
          switch (b) {
125,342✔
UNCOV
411
            case cc.N:
125,342✔
UNCOV
412
            case cc.n:
125,342✔
UNCOV
413
              this.state = State.OP_PIN;
125,342✔
UNCOV
414
              break;
125,342✔
415
            default:
×
416
              throw this.fail(buf.subarray(i));
×
UNCOV
417
          }
125,342✔
UNCOV
418
          break;
125,342✔
UNCOV
419
        case State.OP_PIN:
125,338!
UNCOV
420
          switch (b) {
125,342✔
UNCOV
421
            case cc.G:
125,342✔
UNCOV
422
            case cc.g:
125,342✔
UNCOV
423
              this.state = State.OP_PING;
125,342✔
UNCOV
424
              break;
125,342✔
425
            default:
×
426
              throw this.fail(buf.subarray(i));
×
UNCOV
427
          }
125,342✔
UNCOV
428
          break;
125,342✔
UNCOV
429
        case State.OP_PING:
125,338!
UNCOV
430
          switch (b) {
125,346✔
UNCOV
431
            case cc.NL:
125,346✔
UNCOV
432
              this.dispatcher.push({ kind: Kind.PING });
376,050✔
UNCOV
433
              this.drop = 0;
125,350✔
UNCOV
434
              this.state = State.OP_START;
125,350✔
UNCOV
435
              break;
125,350✔
UNCOV
436
          }
125,346✔
UNCOV
437
          break;
125,346✔
438
        case State.OP_I:
1,003,617✔
439
          switch (b) {
1,003,754✔
440
            case cc.N:
1,003,754✔
441
            case cc.n:
1,003,754✔
442
              this.state = State.OP_IN;
1,003,754✔
443
              break;
1,003,754✔
444
            default:
×
445
              throw this.fail(buf.subarray(i));
×
446
          }
1,003,754✔
447
          break;
1,003,754✔
448
        case State.OP_IN:
1,003,617✔
449
          switch (b) {
1,003,754✔
450
            case cc.F:
1,003,754✔
451
            case cc.f:
1,003,754✔
452
              this.state = State.OP_INF;
1,003,754✔
453
              break;
1,003,754✔
454
            default:
×
455
              throw this.fail(buf.subarray(i));
×
456
          }
1,003,754✔
457
          break;
1,003,754✔
458
        case State.OP_INF:
1,003,617✔
459
          switch (b) {
1,003,754✔
460
            case cc.O:
1,003,754✔
461
            case cc.o:
1,003,754✔
462
              this.state = State.OP_INFO;
1,003,754✔
463
              break;
1,003,754✔
464
            default:
×
465
              throw this.fail(buf.subarray(i));
×
466
          }
1,003,754✔
467
          break;
1,003,754✔
468
        case State.OP_INFO:
1,003,617✔
469
          switch (b) {
1,003,754✔
470
            case cc.SPACE:
1,003,754✔
471
            case cc.TAB:
1,003,754✔
472
              this.state = State.OP_INFO_SPC;
1,003,754✔
473
              break;
1,003,754✔
474
            default:
×
475
              throw this.fail(buf.subarray(i));
×
476
          }
1,003,754✔
477
          break;
1,003,754✔
478
        case State.OP_INFO_SPC:
1,003,617✔
479
          switch (b) {
1,003,754✔
480
            case cc.SPACE:
×
481
            case cc.TAB:
×
482
              continue;
×
483
            default:
1,003,754✔
484
              this.state = State.INFO_ARG;
1,003,754✔
485
              this.as = i;
1,003,754✔
486
          }
1,003,754✔
487
          break;
1,003,754✔
488
        case State.INFO_ARG:
1,003,617✔
489
          switch (b) {
1,058,890✔
490
            case cc.CR:
1,058,890✔
491
              this.drop = 1;
1,059,027✔
492
              break;
1,059,027✔
493
            case cc.NL: {
2,117,917✔
494
              let arg: Uint8Array;
1,059,027✔
495
              if (this.argBuf) {
×
496
                arg = this.argBuf.bytes();
×
497
                this.argBuf = undefined;
×
498
              } else {
×
499
                arg = buf.subarray(this.as, i - this.drop);
1,059,027✔
500
              }
1,059,027✔
501
              this.dispatcher.push({ kind: Kind.INFO, data: arg });
4,236,108✔
502
              this.drop = 0;
1,059,027✔
503
              this.as = i + 1;
1,059,027✔
504
              this.state = State.OP_START;
1,059,027✔
505
              break;
1,059,027✔
506
            }
1,059,027✔
507
            default:
1,058,890✔
508
              if (this.argBuf) {
×
509
                this.argBuf.writeByte(b);
×
510
              }
×
511
          }
1,058,890✔
512
          break;
1,058,890✔
513
        default:
×
514
          throw this.fail(buf.subarray(i));
×
515
      }
1,003,617✔
516
    }
1,003,617✔
517

518
    if (
532✔
519
      (this.state === State.MSG_ARG || this.state === State.MINUS_ERR_ARG ||
532✔
520
        this.state === State.INFO_ARG) && !this.argBuf
532!
521
    ) {
532!
522
      this.argBuf = new DenoBuffer(buf.subarray(this.as, i - this.drop));
533✔
523
    }
533✔
524

525
    if (this.state === State.MSG_PAYLOAD && !this.msgBuf) {
532!
526
      if (!this.argBuf) {
536✔
527
        this.cloneMsgArg();
536✔
528
      }
536✔
529
      this.msgBuf = new DenoBuffer(buf.subarray(this.as));
536✔
530
    }
536✔
531
  }
1,680✔
532

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

548
  processMsgArgs(arg: Uint8Array): void {
3✔
549
    if (this.hdr >= 0) {
14,212✔
550
      return this.processHeaderMsgArgs(arg);
14,359✔
551
    }
14,359✔
552

553
    const args: Uint8Array[] = [];
28,274✔
554
    let start = -1;
28,274✔
555
    for (let i = 0; i < arg.length; i++) {
14,212✔
556
      const b = arg[i];
832,010✔
557
      switch (b) {
832,010✔
558
        case cc.SPACE:
832,010✔
559
        case cc.TAB:
832,010✔
560
        case cc.CR:
832,010✔
561
        case cc.NL:
832,010✔
562
          if (start >= 0) {
860,521✔
563
            args.push(arg.subarray(start, i));
860,521✔
564
            start = -1;
860,521✔
565
          }
860,521✔
566
          break;
860,521✔
567
        default:
832,010✔
568
          if (start < 0) {
1,621,297✔
569
            start = i;
1,663,870✔
570
          }
1,663,870✔
571
      }
832,010✔
572
    }
832,010✔
573
    if (start >= 0) {
28,274✔
574
      args.push(arg.subarray(start));
28,274✔
575
    }
28,274✔
576

577
    switch (args.length) {
28,274✔
578
      case 3:
14,212✔
579
        this.ma.subject = args[0];
27,887✔
580
        this.ma.sid = this.protoParseInt(args[1]);
27,887✔
581
        this.ma.reply = undefined;
27,887✔
582
        this.ma.size = this.protoParseInt(args[2]);
27,887✔
583
        break;
27,887✔
584
      case 4:
14,212✔
585
        this.ma.subject = args[0];
14,599✔
586
        this.ma.sid = this.protoParseInt(args[1]);
14,599✔
587
        this.ma.reply = args[2];
14,599✔
588
        this.ma.size = this.protoParseInt(args[3]);
14,599✔
589
        break;
14,599✔
590
      default:
×
591
        throw this.fail(arg, "processMsgArgs Parse Error");
×
592
    }
14,212✔
593

594
    if (this.ma.sid < 0) {
×
595
      throw this.fail(arg, "processMsgArgs Bad or Missing Sid Error");
×
596
    }
✔
597
    if (this.ma.size < 0) {
×
598
      throw this.fail(arg, "processMsgArgs Bad or Missing Size Error");
×
599
    }
×
600
  }
14,212✔
601

602
  fail(data: Uint8Array, label = ""): Error {
×
603
    if (!label) {
×
604
      label = `parse error [${this.state}]`;
×
605
    } else {
×
606
      label = `${label} [${this.state}]`;
×
607
    }
×
608

609
    return new Error(`${label}: ${TD.decode(data)}`);
×
610
  }
×
611

612
  processHeaderMsgArgs(arg: Uint8Array): void {
3✔
613
    const args: Uint8Array[] = [];
150✔
614
    let start = -1;
150✔
615
    for (let i = 0; i < arg.length; i++) {
150✔
616
      const b = arg[i];
12,938✔
617
      switch (b) {
12,938✔
618
        case cc.SPACE:
12,938✔
619
        case cc.TAB:
12,938✔
620
        case cc.CR:
12,938✔
621
        case cc.NL:
12,938✔
622
          if (start >= 0) {
13,454✔
623
            args.push(arg.subarray(start, i));
13,454✔
624
            start = -1;
13,454✔
625
          }
13,454✔
626
          break;
13,454✔
627
        default:
12,938✔
628
          if (start < 0) {
25,210✔
629
            start = i;
25,873✔
630
          }
25,873✔
631
      }
12,938✔
632
    }
12,938✔
633
    if (start >= 0) {
150✔
634
      args.push(arg.subarray(start));
150✔
635
    }
150✔
636

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

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

670
  protoParseInt(a: Uint8Array): number {
3✔
671
    if (a.length === 0) {
×
672
      return -1;
×
673
    }
×
674
    let n = 0;
28,568✔
675
    for (let i = 0; i < a.length; i++) {
28,568✔
676
      if (a[i] < ASCII_0 || a[i] > ASCII_9) {
×
677
        return -1;
×
678
      }
×
679
      n = n * 10 + (a[i] - ASCII_0);
72,025✔
680
    }
72,025✔
681
    return n;
28,568✔
682
  }
28,568✔
683
}
4✔
684

685
export const State = {
4✔
686
  OP_START: 0,
4✔
687
  OP_PLUS: 1,
4✔
688
  OP_PLUS_O: 2,
4✔
689
  OP_PLUS_OK: 3,
4✔
690
  OP_MINUS: 4,
4✔
691
  OP_MINUS_E: 5,
4✔
692
  OP_MINUS_ER: 6,
4✔
693
  OP_MINUS_ERR: 7,
4✔
694
  OP_MINUS_ERR_SPC: 8,
4✔
695
  MINUS_ERR_ARG: 9,
4✔
696
  OP_M: 10,
4✔
697
  OP_MS: 11,
4✔
698
  OP_MSG: 12,
4✔
699
  OP_MSG_SPC: 13,
4✔
700
  MSG_ARG: 14,
4✔
701
  MSG_PAYLOAD: 15,
4✔
702
  MSG_END: 16,
4✔
703
  OP_H: 17,
4✔
704
  OP_P: 18,
4✔
705
  OP_PI: 19,
4✔
706
  OP_PIN: 20,
4✔
707
  OP_PING: 21,
4✔
708
  OP_PO: 22,
4✔
709
  OP_PON: 23,
4✔
710
  OP_PONG: 24,
4✔
711
  OP_I: 25,
4✔
712
  OP_IN: 26,
4✔
713
  OP_INF: 27,
4✔
714
  OP_INFO: 28,
4✔
715
  OP_INFO_SPC: 29,
4✔
716
  INFO_ARG: 30,
4✔
717
} as const;
4✔
718

719
export type State = typeof State[keyof typeof State];
720

721
export const cc = {
4✔
722
  CR: "\r".charCodeAt(0),
4✔
723
  E: "E".charCodeAt(0),
4✔
724
  e: "e".charCodeAt(0),
4✔
725
  F: "F".charCodeAt(0),
4✔
726
  f: "f".charCodeAt(0),
4✔
727
  G: "G".charCodeAt(0),
4✔
728
  g: "g".charCodeAt(0),
4✔
729
  H: "H".charCodeAt(0),
4✔
730
  h: "h".charCodeAt(0),
4✔
731
  I: "I".charCodeAt(0),
4✔
732
  i: "i".charCodeAt(0),
4✔
733
  K: "K".charCodeAt(0),
4✔
734
  k: "k".charCodeAt(0),
4✔
735
  M: "M".charCodeAt(0),
4✔
736
  m: "m".charCodeAt(0),
4✔
737
  MINUS: "-".charCodeAt(0),
4✔
738
  N: "N".charCodeAt(0),
4✔
739
  n: "n".charCodeAt(0),
4✔
740
  NL: "\n".charCodeAt(0),
4✔
741
  O: "O".charCodeAt(0),
4✔
742
  o: "o".charCodeAt(0),
4✔
743
  P: "P".charCodeAt(0),
4✔
744
  p: "p".charCodeAt(0),
4✔
745
  PLUS: "+".charCodeAt(0),
4✔
746
  R: "R".charCodeAt(0),
4✔
747
  r: "r".charCodeAt(0),
4✔
748
  S: "S".charCodeAt(0),
4✔
749
  s: "s".charCodeAt(0),
4✔
750
  SPACE: " ".charCodeAt(0),
4✔
751
  TAB: "\t".charCodeAt(0),
4✔
752
} as const;
4✔
753

754
export type cc = typeof cc[keyof typeof cc];
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