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

node-opcua / node-opcua / 22636309940

03 Mar 2026 06:03PM UTC coverage: 92.756% (+1.9%) from 90.81%
22636309940

push

github

erossignon
test: disable ENOENT on overlapping trustCertificate invocations in test environments with concurrency tests

18684 of 22141 branches covered (84.39%)

23 of 37 new or added lines in 1 file covered. (62.16%)

5775 existing lines in 228 files now uncovered.

160668 of 173216 relevant lines covered (92.76%)

875869.8 hits per line

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

88.33
/packages/node-opcua-binary-stream/source/binaryStream.ts
1
/**
2✔
2
 * @module node-opcua-binary-stream
4✔
3
 */
4✔
4
import "util";
4✔
5

4✔
6
import { assert } from "node-opcua-assert";
4✔
7
import { createFastUninitializedBuffer } from "node-opcua-buffer-utils";
4✔
8

4✔
9
const MAXUINT32 = 4294967295; // 2**32 -1;
4✔
10
const performCheck = false;
4✔
11

4✔
12
/**
4✔
13
 * a BinaryStream can be use to perform sequential read or write
4✔
14
 * inside a buffer.
4✔
15
 * The BinaryStream maintains a cursor up to date as the caller
4✔
16
 * operates on the stream using the various read/write methods.
4✔
17
 * It uses the [Little Endian](http://en.wikipedia.org/wiki/Little_endian#Little-endian)
4✔
18
 * It uses the [Little Endian](http://en.wikipedia.org/wiki/Little_endian#Little-endian)
4✔
19
 * convention.
4✔
20
 *
4✔
21
 * data can either be:
4✔
22
 *
4✔
23
 * * a Buffer , in this case the BinaryStream operates on this Buffer
4✔
24
 * * null     , in this case a BinaryStream with 1024 bytes is created
4✔
25
 * * any data , in this case the object is converted into a binary buffer.
4✔
26
 *
4✔
27
 * example:
4✔
28
 *
4✔
29
 *    ``` javascript
4✔
30
 *    var stream = new BinaryStream(32)
4✔
31
 *    ```
4✔
32
 *
4✔
33
 
4✔
34
 */
4✔
35
export class BinaryStream {
4✔
36
    public static maxByteStringLength = 16 * 1024 * 1024;
6✔
37
    public static maxStringLength = 16 * 1024 * 1024;
6✔
38
    /**
6✔
39
     * the current position inside the buffer
6✔
40
     */
6✔
41
    public length: number;
6✔
42

6✔
43
    /**
6✔
44
     * @internal
6✔
45
     */
6✔
46
    public buffer: Buffer;
6✔
47

6✔
48
    constructor(data: undefined | Buffer | number) {
6✔
49
        if (data === undefined) {
1,800,811✔
50
            this.buffer = createFastUninitializedBuffer(1024);
670✔
51
        } else if (typeof data === "number") {
1,800,811✔
52
            this.buffer = createFastUninitializedBuffer(data);
206,350✔
53
        } else {
1,800,141✔
54
            assert(data instanceof Buffer);
1,593,791✔
55
            this.buffer = data;
1,593,791✔
56
        }
1,593,791✔
57
        this.length = 0;
1,800,811✔
58
    }
1,800,811✔
59

6✔
60
    /**
6✔
61
     * set the cursor to the begining of the stream
6✔
62

6✔
63
     */
6✔
64
    public rewind(): void {
6✔
65
        this.length = 0;
397,120✔
66
    }
397,120✔
67

6✔
68
    /**
6✔
69
     * write a single signed byte (8 bits) to the stream.
6✔
70
     * value must be in the range of [-127,128]
6✔
71
     * @param value the value to write
6✔
72
     */
6✔
73
    public writeInt8(value: number): void {
6✔
74
        // c8 ignore next
1,956✔
75
        if (performCheck) {
1,956✔
UNCOV
76
            assert(this.buffer.length >= this.length + 1, "not enough space in buffer");
×
UNCOV
77
            assert(value >= -128 && value < 128);
×
UNCOV
78
        }
×
79
        this.buffer.writeInt8(value, this.length);
1,956✔
80
        this.length += 1;
1,956✔
81
    }
1,956✔
82

6✔
83
    /**
6✔
84
     * write a single unsigned byte (8 bits) to the stream.
6✔
85
     * @param value  the value to write
6✔
86
     */
6✔
87
    public writeUInt8(value: number): void {
6✔
88
        // c8 ignore next
35,829,458✔
89
        if (performCheck) {
35,829,458✔
UNCOV
90
            assert(this.buffer.length >= this.length + 1, "not enough space in buffer");
×
UNCOV
91
            assert(value >= 0 && value < 256, " writeUInt8 : out of bound ");
×
UNCOV
92
        }
×
93
        this.buffer.writeUInt8(value, this.length);
35,829,458✔
94
        this.length += 1;
35,829,458✔
95
    }
35,829,458✔
96

6✔
97
    /**
6✔
98
     * write a single 16 bit signed integer to the stream.
6✔
99
     * @param  value  the value to write
6✔
100
     */
6✔
101
    public writeInt16(value: number): void {
6✔
102
        // c8 ignore next
2,038✔
103
        if (performCheck) {
2,038✔
UNCOV
104
            assert(this.buffer.length >= this.length + 2, "not enough space in buffer");
×
UNCOV
105
        }
×
106
        this.buffer.writeInt16LE(value, this.length);
2,038✔
107
        this.length += 2;
2,038✔
108
    }
2,038✔
109

6✔
110
    /**
6✔
111
     * write a single 16 bit unsigned integer to the stream.
6✔
112
     * @param  value  the value to write
6✔
113
     */
6✔
114
    public writeUInt16(value: number): void {
6✔
115
        // c8 ignore next
9,072,266✔
116
        if (performCheck) {
9,072,266✔
UNCOV
117
            assert(this.buffer.length >= this.length + 2, "not enough space in buffer");
×
UNCOV
118
        }
×
119
        this.buffer.writeUInt16LE(value, this.length);
9,072,266✔
120
        this.length += 2;
9,072,266✔
121
    }
9,072,266✔
122

6✔
123
    /**
6✔
124
     * write a single 32 bit signed integer to the stream.
6✔
125
     * @param  value  the value to write
6✔
126
     */
6✔
127
    public writeInteger(value: number): void {
6✔
128
        // c8 ignore next
11,341,043✔
129
        if (performCheck) {
11,341,043✔
UNCOV
130
            assert(this.buffer.length >= this.length + 4, "not enough space in buffer");
×
UNCOV
131
        }
×
132
        this.buffer.writeInt32LE(value, this.length);
11,341,043✔
133
        this.length += 4;
11,341,043✔
134
    }
11,341,043✔
135

6✔
136
    /**
6✔
137
     * write a single 32 bit unsigned integer to the stream.
6✔
138
     *
6✔
139
     * @param  value the value to write
6✔
140
     */
6✔
141
    public writeUInt32(value: number): void {
6✔
142
        // c8 ignore next
40,989,596✔
143
        if (performCheck) {
40,989,596✔
UNCOV
144
            assert(this.buffer.length >= this.length + 4, "not enough space in buffer");
×
UNCOV
145
            assert(isFinite(value));
×
UNCOV
146
            assert(value >= 0 && value <= MAXUINT32);
×
UNCOV
147
        }
×
148
        this.buffer.writeUInt32LE(value, this.length);
40,989,596✔
149
        this.length += 4;
40,989,596✔
150
        /*
40,989,596✔
151
          assert(this.buffer[this.length - 4] === value % 256);
40,989,596✔
152
          assert(this.buffer[this.length - 3] === (value >>> 8) % 256);
40,989,596✔
153
          assert(this.buffer[this.length - 2] === (value >>> 16) % 256);
40,989,596✔
154
          assert(this.buffer[this.length - 1] === (value >>> 24) % 256);
40,989,596✔
155
          */
40,989,596✔
156
    }
40,989,596✔
157

6✔
158
    /**
6✔
159
     * write a single 32 bit floating number to the stream.
6✔
160
     * @param  value  the value to write
6✔
161
     */
6✔
162
    public writeFloat(value: number): void {
6✔
163
        // c8 ignore next
4,919,394✔
164
        if (performCheck) {
4,919,394✔
UNCOV
165
            assert(this.buffer.length >= this.length + 4, "not enough space in buffer");
×
UNCOV
166
        }
×
167
        this.buffer.writeFloatLE(value, this.length);
4,919,394✔
168
        this.length += 4;
4,919,394✔
169
    }
4,919,394✔
170

6✔
171
    /**
6✔
172
     * write a single 64 bit floating number to the stream.
6✔
173
     * @param  value  the value to write
6✔
174
     */
6✔
175
    public writeDouble(value: number): void {
6✔
176
        // c8 ignore next
201,288✔
177
        if (performCheck) {
201,288✔
UNCOV
178
            assert(this.buffer.length >= this.length + 8, "not enough space in buffer");
×
UNCOV
179
        }
×
180
        this.buffer.writeDoubleLE(value, this.length);
201,288✔
181
        this.length += 8;
201,288✔
182
    }
201,288✔
183

6✔
184
    /**
6✔
185
     * @param arrayBuf a buffer or byte array write
6✔
186
     * @param offset   the offset position (default =0)
6✔
187
     * @param length   the number of byte to write
6✔
188
     */
6✔
189
    public writeArrayBuffer(arrayBuf: ArrayBuffer, offset = 0, length = 0): void {
6✔
190
        // c8 ignore next
21,640✔
191
        if (performCheck) {
21,640✔
UNCOV
192
            assert(arrayBuf instanceof ArrayBuffer);
×
UNCOV
193
        }
×
194
        const byteArr = new Uint8Array(arrayBuf);
21,640✔
195
        const n = (length || byteArr.length) + offset;
21,640✔
196
        for (let i = offset; i < n; i++) {
21,640✔
197
            this.buffer[this.length++] = byteArr[i];
677,013,154✔
198
        }
677,013,154✔
199
    }
21,640✔
200

6✔
201
    // writeArrayBuffer(arrayBuf, offset, length) {
6✔
202
    //     offset = offset || 0;
6✔
203
    //
6✔
204
    //     assert(arrayBuf instanceof ArrayBuffer);
6✔
205
    //     const byteArr = new Uint8Array(arrayBuf);
6✔
206
    //     length = length || byteArr.length;
6✔
207
    //     if (length === 0) {
6✔
208
    //         return;
6✔
209
    //     }
6✔
210
    //     this.length += my_memcpy(this.buffer, this.length, byteArr, offset, offset + length);
6✔
211
    // }
6✔
212

6✔
213
    /**
6✔
214
     * read a single signed byte  (8 bits) from the stream.
6✔
215
     * @return the value read
6✔
216
     */
6✔
217
    public readByte(): number {
6✔
218
        const retVal = this.buffer.readInt8(this.length);
1,956✔
219
        this.length += 1;
1,956✔
220
        return retVal;
1,956✔
221
    }
1,956✔
222

6✔
223
    public readInt8(): number {
6✔
224
        return this.readByte();
1,956✔
225
    }
1,956✔
226

6✔
227
    /**
6✔
228
     * read a single unsigned byte (8 bits) from the stream.
6✔
229
     */
6✔
230
    public readUInt8(): number {
6✔
231
        // c8 ignore next
20,185,868✔
232
        if (performCheck) {
20,185,868!
UNCOV
233
            assert(this.buffer.length >= this.length + 1);
×
UNCOV
234
        }
×
235
        const retVal = this.buffer.readUInt8(this.length);
20,185,868✔
236
        this.length += 1;
20,185,868✔
237
        return retVal;
20,185,868✔
238
    }
20,185,868✔
239

6✔
240
    /**
6✔
241
     * read a single signed 16-bit integer from the stream.
6✔
242
     */
6✔
243
    public readInt16(): number {
6✔
244
        const retVal = this.buffer.readInt16LE(this.length);
2,060✔
245
        this.length += 2;
2,060✔
246
        return retVal;
2,060✔
247
    }
2,060✔
248

6✔
249
    /**
6✔
250
     * read a single unsigned 16-bit integer from the stream.
6✔
251
     */
6✔
252
    public readUInt16(): number {
6✔
253
        const retVal = this.buffer.readUInt16LE(this.length);
5,603,654✔
254
        this.length += 2;
5,603,654✔
255
        return retVal;
5,603,654✔
256
    }
5,603,654✔
257

6✔
258
    /**
6✔
259
     * read a single signed 32-bit integer from the stream.
6✔
260
     */
6✔
261
    public readInteger(): number {
6✔
262
        const retVal = this.buffer.readInt32LE(this.length);
3,920,221✔
263
        this.length += 4;
3,920,221✔
264
        return retVal;
3,920,221✔
265
    }
3,920,221✔
266

6✔
267
    /**
6✔
268
     * read a single unsigned 32-bit integer from the stream.
6✔
269
     */
6✔
270
    public readUInt32(): number {
6✔
271
        const retVal = this.buffer.readUInt32LE(this.length);
19,427,007✔
272
        this.length += 4;
19,427,007✔
273
        return retVal;
19,427,007✔
274
    }
19,427,007✔
275

6✔
276
    /**
6✔
277
     * read a single  32-bit floating point number from the stream.
6✔
278
     */
6✔
279
    public readFloat(): number {
6✔
280
        const retVal = this.buffer.readFloatLE(this.length);
2,134✔
281
        this.length += 4;
2,134✔
282
        return retVal;
2,134✔
283
    }
2,134✔
284

6✔
285
    /**
6✔
286
     * read a single 64-bit floating point number from the stream.
6✔
287
     */
6✔
288
    public readDouble(): number {
6✔
289
        const retVal = this.buffer.readDoubleLE(this.length);
3,318,204✔
290
        this.length += 8;
3,318,204✔
291
        return retVal;
3,318,204✔
292
    }
3,318,204✔
293

6✔
294
    /**
6✔
295
     * write a byte stream to the stream.
6✔
296
     * The method writes the length of the byte array into the stream as a 32 bits integer before the byte stream.
6✔
297
     *
6✔
298
     * @param buf the buffer to write.
6✔
299
     */
6✔
300
    public writeByteStream(buf: Buffer): void {
6✔
301
        if (!buf) {
2,827,045✔
302
            this.writeInteger(-1);
2,178,031✔
303
            return;
2,178,031✔
304
        }
2,178,031✔
305
        assert(buf instanceof Buffer);
649,014✔
306
        this.writeInteger(buf.length);
649,014✔
307
        // make sure there is enough room in destination buffer
649,014✔
308
        const remainingBytes = this.buffer.length - this.length;
649,014✔
309

649,014✔
310
        /* c8 ignore next */
4✔
311
        if (remainingBytes < buf.length) {
4✔
UNCOV
312
            throw new Error(
×
UNCOV
313
                "BinaryStream.writeByteStream error : not enough bytes left in buffer :  bufferLength is " +
×
UNCOV
314
                buf.length +
×
UNCOV
315
                " but only " +
×
UNCOV
316
                remainingBytes +
×
UNCOV
317
                " left"
×
UNCOV
318
            );
×
UNCOV
319
        }
×
320
        buf.copy(this.buffer, this.length, 0, buf.length);
649,014✔
321
        this.length += buf.length;
649,014✔
322
    }
649,014✔
323

6✔
324
    public writeString(value: null | string): void {
6✔
325
        if (value === undefined || value === null) {
8,730,542✔
326
            this.writeUInt32(0xffffffff);
6,107,183✔
327
            return;
6,107,183✔
328
        }
6,107,183✔
329
        const byteLength = calculateByteLength(value);
2,623,359✔
330
        this.writeInteger(byteLength);
2,623,359✔
331
        if (byteLength === 0) {
8,730,542✔
332
            return;
661,535✔
333
        }
661,535✔
334
        // make sure there is enough room in destination buffer
1,961,824✔
335
        const remainingBytes = this.buffer.length - this.length;
1,961,824✔
336
        /* c8 ignore next */
4✔
337
        if (remainingBytes < byteLength) {
4✔
UNCOV
338
            throw new Error(
×
UNCOV
339
                "BinaryStream.writeByteStream error : not enough bytes left in buffer :  bufferLength is " +
×
UNCOV
340
                byteLength +
×
UNCOV
341
                " but only " +
×
UNCOV
342
                remainingBytes +
×
UNCOV
343
                " left"
×
UNCOV
344
            );
×
UNCOV
345
        }
×
346
        this.buffer.write(value, this.length);
1,961,824✔
347
        this.length += byteLength;
1,961,824✔
348
    }
1,961,824✔
349

6✔
350
    // readArrayBuffer(length: number): ArrayBuffer {
6✔
351
    //     assert(this.length + length <= this.buffer.length, "not enough bytes in buffer");
6✔
352
    //     const byteArr = new Uint8Array(new ArrayBuffer(length));
6✔
353
    //     my_memcpy(byteArr, 0, this.buffer, this.length, this.length + length);
6✔
354
    //     this.length += length;
6✔
355
    //     return byteArr;
6✔
356
    // }
6✔
357
    /**
6✔
358

6✔
359
     * @param length
6✔
360
     */
6✔
361
    public readBuffer(length: number): Buffer {
6✔
362
        if (this.length + length > this.buffer.length) {
14,766!
363
            throw new Error("BinaryStream: buffer overrun detected");
×
UNCOV
364
        }
×
365
        const buf = this.buffer.subarray(this.length, this.length + length);
14,766✔
366
        this.length += length;
14,766✔
367
        return buf;
14,766✔
368
    }
14,766✔
369

6✔
370
    public readArrayBuffer(length: number): Uint8Array {
6✔
371
        if (length > BinaryStream.maxByteStringLength) {
86✔
372
            throw new Error(`maxStringLength(${BinaryStream.maxByteStringLength}) has been exceeded in BinaryStream.readArrayBuffer len=${length}`);
2✔
373
        }
2✔
374
        // c8 ignore next
84✔
375
        if (performCheck) {
86✔
UNCOV
376
            assert(this.length + length <= this.buffer.length, "not enough bytes in buffer");
×
UNCOV
377
        }
×
378
        const slice = this.buffer.subarray(this.length, this.length + length);
84✔
379
        // c8 ignore next
84✔
380
        if (performCheck) {
86✔
UNCOV
381
            assert(slice.length === length);
×
UNCOV
382
        }
×
383
        const byteArr = new Uint8Array(slice);
84✔
384
        // c8 ignore next
84✔
385
        if (performCheck) {
86✔
UNCOV
386
            assert(byteArr.length === length);
×
UNCOV
387
        }
×
388
        this.length += length;
84✔
389
        return byteArr;
84✔
390
    }
84✔
391

6✔
392
    /**
6✔
393
     * read a byte stream to the stream.
6✔
394
     * The method reads the length of the byte array from the stream as a 32 bits integer
6✔
395
     * before reading the byte stream.
6✔
396
     *
6✔
397
     */
6✔
398
    public readByteStream(): Buffer | null {
6✔
399
        const bufLen = this.readUInt32();
2,828,577✔
400
        if (bufLen === 0xffffffff) {
2,828,577✔
401
            return null;
2,178,240✔
402
        }
2,178,240✔
403
        if (bufLen === 0) {
2,828,577✔
404
            return zeroLengthBuffer;
24✔
405
        }
24✔
406
        if (bufLen > BinaryStream.maxByteStringLength) {
2,828,577✔
407
            throw new Error(`maxStringLength(${BinaryStream.maxByteStringLength}) has been exceeded in BinaryStream.readArrayBuffer len=${bufLen}`);
2✔
408
        }
2✔
409
        // check that there is enough space in the buffer
650,311✔
410
        const remainingBytes = this.buffer.length - this.length;
650,311✔
411
        // c8 ignore next
650,311✔
412
        if (remainingBytes < bufLen) {
2,828,577✔
UNCOV
413
            throw new Error(
×
UNCOV
414
                "BinaryStream.readByteStream error : not enough bytes left in buffer :  bufferLength is " +
×
UNCOV
415
                bufLen +
×
UNCOV
416
                " but only " +
×
UNCOV
417
                remainingBytes +
×
UNCOV
418
                " left"
×
UNCOV
419
            );
×
UNCOV
420
        }
×
421
        // create a shared memory buffer ! for speed
650,311✔
422
        const buf = this.buffer.subarray(this.length, this.length + bufLen);
650,311✔
423
        this.length += bufLen;
650,311✔
424
        return buf;
650,311✔
425
    }
650,311✔
426

6✔
427
    public readString(): string | null {
6✔
428
        const bufLen = this.readUInt32();
6,640,425✔
429
        if (bufLen === 0xffffffff) {
6,640,425✔
430
            return null;
4,013,947✔
431
        }
4,013,947✔
432
        if (bufLen === 0) {
6,640,425✔
433
            return "";
661,020✔
434
        }
661,020✔
435
        if (bufLen > BinaryStream.maxStringLength) {
6,640,425✔
436
            throw new Error(`maxStringLength(${BinaryStream.maxStringLength}) has been exceeded in BinaryStream.readString len=${bufLen}`);
12✔
437
        }
12✔
438
        // check that there is enough space in the buffer
1,965,446✔
439
        const remainingBytes = this.buffer.length - this.length;
1,965,446✔
440
        // c8 ignore next
1,965,446✔
441
        if (remainingBytes < bufLen) {
6,640,425✔
442
            throw new Error(
4✔
443
                "BinaryStream.readByteStream error : not enough bytes left in buffer :  bufferLength is " +
4✔
444
                bufLen +
4✔
445
                " but only " +
4✔
446
                remainingBytes +
4✔
447
                " left"
4✔
448
            );
4✔
449
        }
4✔
450
        const str = this.buffer.toString("utf-8", this.length, this.length + bufLen);
1,965,442✔
451
        this.length += bufLen;
1,965,442✔
452
        return str;
1,965,442✔
453
    }
1,965,442✔
454
}
6✔
455

4✔
456
/**
4✔
457
 * @function calculateByteLength
4✔
458
 * calculate the size in bytes of a utf8 string
4✔
459
 * @param str {String}
4✔
460
 * @internal
4✔
461
 */
4✔
462
export function calculateByteLength(str: string): number {
7,031,315✔
463
    // returns the byte length of an utf8 string
7,031,313✔
464
    let s = str.length;
7,031,313✔
465
    for (let i = s - 1; i >= 0; i--) {
7,031,313✔
466
        const code = str.charCodeAt(i);
203,676,114✔
467
        if (code > 0x7f && code <= 0x7ff) {
203,676,114✔
468
            s++;
15,760,252✔
469
        } else if (code > 0x7ff && code <= 0xffff) {
203,676,114✔
470
            s += 2;
18,011,254✔
471
        }
18,011,254✔
472
        if (code >= 0xdc00 && code <= 0xdfff) {
203,676,114✔
473
            // trail surrogate
562,883✔
474
            i--;
562,883✔
475
        }
562,883✔
476
    }
203,676,114✔
477
    return s;
7,031,313✔
478
}
7,031,313✔
479

4✔
480
const zeroLengthBuffer = createFastUninitializedBuffer(0);
4!
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