• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  BigInt,
5  Float32Array,
6  Float64Array,
7  MathFloor,
8  Number,
9  Uint8Array,
10} = primordials;
11
12const {
13  ERR_BUFFER_OUT_OF_BOUNDS,
14  ERR_INVALID_ARG_TYPE,
15  ERR_OUT_OF_RANGE,
16} = require('internal/errors').codes;
17const { validateNumber } = require('internal/validators');
18const {
19  asciiSlice,
20  base64Slice,
21  base64urlSlice,
22  latin1Slice,
23  hexSlice,
24  ucs2Slice,
25  utf8Slice,
26  asciiWrite,
27  base64Write,
28  base64urlWrite,
29  latin1Write,
30  hexWrite,
31  ucs2Write,
32  utf8Write,
33  getZeroFillToggle,
34} = internalBinding('buffer');
35
36const {
37  privateSymbols: {
38    untransferable_object_private_symbol,
39  },
40} = internalBinding('util');
41
42// Temporary buffers to convert numbers.
43const float32Array = new Float32Array(1);
44const uInt8Float32Array = new Uint8Array(float32Array.buffer);
45const float64Array = new Float64Array(1);
46const uInt8Float64Array = new Uint8Array(float64Array.buffer);
47
48// Check endianness.
49float32Array[0] = -1; // 0xBF800000
50// Either it is [0, 0, 128, 191] or [191, 128, 0, 0]. It is not possible to
51// check this with `os.endianness()` because that is determined at compile time.
52const bigEndian = uInt8Float32Array[3] === 0;
53
54function checkBounds(buf, offset, byteLength) {
55  validateNumber(offset, 'offset');
56  if (buf[offset] === undefined || buf[offset + byteLength] === undefined)
57    boundsError(offset, buf.length - (byteLength + 1));
58}
59
60function checkInt(value, min, max, buf, offset, byteLength) {
61  if (value > max || value < min) {
62    const n = typeof min === 'bigint' ? 'n' : '';
63    let range;
64    if (byteLength > 3) {
65      if (min === 0 || min === 0n) {
66        range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`;
67      } else {
68        range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and ` +
69                `< 2${n} ** ${(byteLength + 1) * 8 - 1}${n}`;
70      }
71    } else {
72      range = `>= ${min}${n} and <= ${max}${n}`;
73    }
74    throw new ERR_OUT_OF_RANGE('value', range, value);
75  }
76  checkBounds(buf, offset, byteLength);
77}
78
79function boundsError(value, length, type) {
80  if (MathFloor(value) !== value) {
81    validateNumber(value, type);
82    throw new ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value);
83  }
84
85  if (length < 0)
86    throw new ERR_BUFFER_OUT_OF_BOUNDS();
87
88  throw new ERR_OUT_OF_RANGE(type || 'offset',
89                             `>= ${type ? 1 : 0} and <= ${length}`,
90                             value);
91}
92
93// Read integers.
94function readBigUInt64LE(offset = 0) {
95  validateNumber(offset, 'offset');
96  const first = this[offset];
97  const last = this[offset + 7];
98  if (first === undefined || last === undefined)
99    boundsError(offset, this.length - 8);
100
101  const lo = first +
102    this[++offset] * 2 ** 8 +
103    this[++offset] * 2 ** 16 +
104    this[++offset] * 2 ** 24;
105
106  const hi = this[++offset] +
107    this[++offset] * 2 ** 8 +
108    this[++offset] * 2 ** 16 +
109    last * 2 ** 24;
110
111  return BigInt(lo) + (BigInt(hi) << 32n);
112}
113
114function readBigUInt64BE(offset = 0) {
115  validateNumber(offset, 'offset');
116  const first = this[offset];
117  const last = this[offset + 7];
118  if (first === undefined || last === undefined)
119    boundsError(offset, this.length - 8);
120
121  const hi = first * 2 ** 24 +
122    this[++offset] * 2 ** 16 +
123    this[++offset] * 2 ** 8 +
124    this[++offset];
125
126  const lo = this[++offset] * 2 ** 24 +
127    this[++offset] * 2 ** 16 +
128    this[++offset] * 2 ** 8 +
129    last;
130
131  return (BigInt(hi) << 32n) + BigInt(lo);
132}
133
134function readBigInt64LE(offset = 0) {
135  validateNumber(offset, 'offset');
136  const first = this[offset];
137  const last = this[offset + 7];
138  if (first === undefined || last === undefined)
139    boundsError(offset, this.length - 8);
140
141  const val = this[offset + 4] +
142    this[offset + 5] * 2 ** 8 +
143    this[offset + 6] * 2 ** 16 +
144    (last << 24); // Overflow
145  return (BigInt(val) << 32n) +
146    BigInt(first +
147    this[++offset] * 2 ** 8 +
148    this[++offset] * 2 ** 16 +
149    this[++offset] * 2 ** 24);
150}
151
152function readBigInt64BE(offset = 0) {
153  validateNumber(offset, 'offset');
154  const first = this[offset];
155  const last = this[offset + 7];
156  if (first === undefined || last === undefined)
157    boundsError(offset, this.length - 8);
158
159  const val = (first << 24) + // Overflow
160    this[++offset] * 2 ** 16 +
161    this[++offset] * 2 ** 8 +
162    this[++offset];
163  return (BigInt(val) << 32n) +
164    BigInt(this[++offset] * 2 ** 24 +
165    this[++offset] * 2 ** 16 +
166    this[++offset] * 2 ** 8 +
167    last);
168}
169
170function readUIntLE(offset, byteLength) {
171  if (offset === undefined)
172    throw new ERR_INVALID_ARG_TYPE('offset', 'number', offset);
173  if (byteLength === 6)
174    return readUInt48LE(this, offset);
175  if (byteLength === 5)
176    return readUInt40LE(this, offset);
177  if (byteLength === 3)
178    return readUInt24LE(this, offset);
179  if (byteLength === 4)
180    return this.readUInt32LE(offset);
181  if (byteLength === 2)
182    return this.readUInt16LE(offset);
183  if (byteLength === 1)
184    return this.readUInt8(offset);
185
186  boundsError(byteLength, 6, 'byteLength');
187}
188
189function readUInt48LE(buf, offset = 0) {
190  validateNumber(offset, 'offset');
191  const first = buf[offset];
192  const last = buf[offset + 5];
193  if (first === undefined || last === undefined)
194    boundsError(offset, buf.length - 6);
195
196  return first +
197    buf[++offset] * 2 ** 8 +
198    buf[++offset] * 2 ** 16 +
199    buf[++offset] * 2 ** 24 +
200    (buf[++offset] + last * 2 ** 8) * 2 ** 32;
201}
202
203function readUInt40LE(buf, offset = 0) {
204  validateNumber(offset, 'offset');
205  const first = buf[offset];
206  const last = buf[offset + 4];
207  if (first === undefined || last === undefined)
208    boundsError(offset, buf.length - 5);
209
210  return first +
211    buf[++offset] * 2 ** 8 +
212    buf[++offset] * 2 ** 16 +
213    buf[++offset] * 2 ** 24 +
214    last * 2 ** 32;
215}
216
217function readUInt32LE(offset = 0) {
218  validateNumber(offset, 'offset');
219  const first = this[offset];
220  const last = this[offset + 3];
221  if (first === undefined || last === undefined)
222    boundsError(offset, this.length - 4);
223
224  return first +
225    this[++offset] * 2 ** 8 +
226    this[++offset] * 2 ** 16 +
227    last * 2 ** 24;
228}
229
230function readUInt24LE(buf, offset = 0) {
231  validateNumber(offset, 'offset');
232  const first = buf[offset];
233  const last = buf[offset + 2];
234  if (first === undefined || last === undefined)
235    boundsError(offset, buf.length - 3);
236
237  return first + buf[++offset] * 2 ** 8 + last * 2 ** 16;
238}
239
240function readUInt16LE(offset = 0) {
241  validateNumber(offset, 'offset');
242  const first = this[offset];
243  const last = this[offset + 1];
244  if (first === undefined || last === undefined)
245    boundsError(offset, this.length - 2);
246
247  return first + last * 2 ** 8;
248}
249
250function readUInt8(offset = 0) {
251  validateNumber(offset, 'offset');
252  const val = this[offset];
253  if (val === undefined)
254    boundsError(offset, this.length - 1);
255
256  return val;
257}
258
259function readUIntBE(offset, byteLength) {
260  if (offset === undefined)
261    throw new ERR_INVALID_ARG_TYPE('offset', 'number', offset);
262  if (byteLength === 6)
263    return readUInt48BE(this, offset);
264  if (byteLength === 5)
265    return readUInt40BE(this, offset);
266  if (byteLength === 3)
267    return readUInt24BE(this, offset);
268  if (byteLength === 4)
269    return this.readUInt32BE(offset);
270  if (byteLength === 2)
271    return this.readUInt16BE(offset);
272  if (byteLength === 1)
273    return this.readUInt8(offset);
274
275  boundsError(byteLength, 6, 'byteLength');
276}
277
278function readUInt48BE(buf, offset = 0) {
279  validateNumber(offset, 'offset');
280  const first = buf[offset];
281  const last = buf[offset + 5];
282  if (first === undefined || last === undefined)
283    boundsError(offset, buf.length - 6);
284
285  return (first * 2 ** 8 + buf[++offset]) * 2 ** 32 +
286    buf[++offset] * 2 ** 24 +
287    buf[++offset] * 2 ** 16 +
288    buf[++offset] * 2 ** 8 +
289    last;
290}
291
292function readUInt40BE(buf, offset = 0) {
293  validateNumber(offset, 'offset');
294  const first = buf[offset];
295  const last = buf[offset + 4];
296  if (first === undefined || last === undefined)
297    boundsError(offset, buf.length - 5);
298
299  return first * 2 ** 32 +
300    buf[++offset] * 2 ** 24 +
301    buf[++offset] * 2 ** 16 +
302    buf[++offset] * 2 ** 8 +
303    last;
304}
305
306function readUInt32BE(offset = 0) {
307  validateNumber(offset, 'offset');
308  const first = this[offset];
309  const last = this[offset + 3];
310  if (first === undefined || last === undefined)
311    boundsError(offset, this.length - 4);
312
313  return first * 2 ** 24 +
314    this[++offset] * 2 ** 16 +
315    this[++offset] * 2 ** 8 +
316    last;
317}
318
319function readUInt24BE(buf, offset = 0) {
320  validateNumber(offset, 'offset');
321  const first = buf[offset];
322  const last = buf[offset + 2];
323  if (first === undefined || last === undefined)
324    boundsError(offset, buf.length - 3);
325
326  return first * 2 ** 16 + buf[++offset] * 2 ** 8 + last;
327}
328
329function readUInt16BE(offset = 0) {
330  validateNumber(offset, 'offset');
331  const first = this[offset];
332  const last = this[offset + 1];
333  if (first === undefined || last === undefined)
334    boundsError(offset, this.length - 2);
335
336  return first * 2 ** 8 + last;
337}
338
339function readIntLE(offset, byteLength) {
340  if (offset === undefined)
341    throw new ERR_INVALID_ARG_TYPE('offset', 'number', offset);
342  if (byteLength === 6)
343    return readInt48LE(this, offset);
344  if (byteLength === 5)
345    return readInt40LE(this, offset);
346  if (byteLength === 3)
347    return readInt24LE(this, offset);
348  if (byteLength === 4)
349    return this.readInt32LE(offset);
350  if (byteLength === 2)
351    return this.readInt16LE(offset);
352  if (byteLength === 1)
353    return this.readInt8(offset);
354
355  boundsError(byteLength, 6, 'byteLength');
356}
357
358function readInt48LE(buf, offset = 0) {
359  validateNumber(offset, 'offset');
360  const first = buf[offset];
361  const last = buf[offset + 5];
362  if (first === undefined || last === undefined)
363    boundsError(offset, buf.length - 6);
364
365  const val = buf[offset + 4] + last * 2 ** 8;
366  return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 +
367    first +
368    buf[++offset] * 2 ** 8 +
369    buf[++offset] * 2 ** 16 +
370    buf[++offset] * 2 ** 24;
371}
372
373function readInt40LE(buf, offset = 0) {
374  validateNumber(offset, 'offset');
375  const first = buf[offset];
376  const last = buf[offset + 4];
377  if (first === undefined || last === undefined)
378    boundsError(offset, buf.length - 5);
379
380  return (last | (last & 2 ** 7) * 0x1fffffe) * 2 ** 32 +
381    first +
382    buf[++offset] * 2 ** 8 +
383    buf[++offset] * 2 ** 16 +
384    buf[++offset] * 2 ** 24;
385}
386
387function readInt32LE(offset = 0) {
388  validateNumber(offset, 'offset');
389  const first = this[offset];
390  const last = this[offset + 3];
391  if (first === undefined || last === undefined)
392    boundsError(offset, this.length - 4);
393
394  return first +
395    this[++offset] * 2 ** 8 +
396    this[++offset] * 2 ** 16 +
397    (last << 24); // Overflow
398}
399
400function readInt24LE(buf, offset = 0) {
401  validateNumber(offset, 'offset');
402  const first = buf[offset];
403  const last = buf[offset + 2];
404  if (first === undefined || last === undefined)
405    boundsError(offset, buf.length - 3);
406
407  const val = first + buf[++offset] * 2 ** 8 + last * 2 ** 16;
408  return val | (val & 2 ** 23) * 0x1fe;
409}
410
411function readInt16LE(offset = 0) {
412  validateNumber(offset, 'offset');
413  const first = this[offset];
414  const last = this[offset + 1];
415  if (first === undefined || last === undefined)
416    boundsError(offset, this.length - 2);
417
418  const val = first + last * 2 ** 8;
419  return val | (val & 2 ** 15) * 0x1fffe;
420}
421
422function readInt8(offset = 0) {
423  validateNumber(offset, 'offset');
424  const val = this[offset];
425  if (val === undefined)
426    boundsError(offset, this.length - 1);
427
428  return val | (val & 2 ** 7) * 0x1fffffe;
429}
430
431function readIntBE(offset, byteLength) {
432  if (offset === undefined)
433    throw new ERR_INVALID_ARG_TYPE('offset', 'number', offset);
434  if (byteLength === 6)
435    return readInt48BE(this, offset);
436  if (byteLength === 5)
437    return readInt40BE(this, offset);
438  if (byteLength === 3)
439    return readInt24BE(this, offset);
440  if (byteLength === 4)
441    return this.readInt32BE(offset);
442  if (byteLength === 2)
443    return this.readInt16BE(offset);
444  if (byteLength === 1)
445    return this.readInt8(offset);
446
447  boundsError(byteLength, 6, 'byteLength');
448}
449
450function readInt48BE(buf, offset = 0) {
451  validateNumber(offset, 'offset');
452  const first = buf[offset];
453  const last = buf[offset + 5];
454  if (first === undefined || last === undefined)
455    boundsError(offset, buf.length - 6);
456
457  const val = buf[++offset] + first * 2 ** 8;
458  return (val | (val & 2 ** 15) * 0x1fffe) * 2 ** 32 +
459    buf[++offset] * 2 ** 24 +
460    buf[++offset] * 2 ** 16 +
461    buf[++offset] * 2 ** 8 +
462    last;
463}
464
465function readInt40BE(buf, offset = 0) {
466  validateNumber(offset, 'offset');
467  const first = buf[offset];
468  const last = buf[offset + 4];
469  if (first === undefined || last === undefined)
470    boundsError(offset, buf.length - 5);
471
472  return (first | (first & 2 ** 7) * 0x1fffffe) * 2 ** 32 +
473    buf[++offset] * 2 ** 24 +
474    buf[++offset] * 2 ** 16 +
475    buf[++offset] * 2 ** 8 +
476    last;
477}
478
479function readInt32BE(offset = 0) {
480  validateNumber(offset, 'offset');
481  const first = this[offset];
482  const last = this[offset + 3];
483  if (first === undefined || last === undefined)
484    boundsError(offset, this.length - 4);
485
486  return (first << 24) + // Overflow
487    this[++offset] * 2 ** 16 +
488    this[++offset] * 2 ** 8 +
489    last;
490}
491
492function readInt24BE(buf, offset = 0) {
493  validateNumber(offset, 'offset');
494  const first = buf[offset];
495  const last = buf[offset + 2];
496  if (first === undefined || last === undefined)
497    boundsError(offset, buf.length - 3);
498
499  const val = first * 2 ** 16 + buf[++offset] * 2 ** 8 + last;
500  return val | (val & 2 ** 23) * 0x1fe;
501}
502
503function readInt16BE(offset = 0) {
504  validateNumber(offset, 'offset');
505  const first = this[offset];
506  const last = this[offset + 1];
507  if (first === undefined || last === undefined)
508    boundsError(offset, this.length - 2);
509
510  const val = first * 2 ** 8 + last;
511  return val | (val & 2 ** 15) * 0x1fffe;
512}
513
514// Read floats
515function readFloatBackwards(offset = 0) {
516  validateNumber(offset, 'offset');
517  const first = this[offset];
518  const last = this[offset + 3];
519  if (first === undefined || last === undefined)
520    boundsError(offset, this.length - 4);
521
522  uInt8Float32Array[3] = first;
523  uInt8Float32Array[2] = this[++offset];
524  uInt8Float32Array[1] = this[++offset];
525  uInt8Float32Array[0] = last;
526  return float32Array[0];
527}
528
529function readFloatForwards(offset = 0) {
530  validateNumber(offset, 'offset');
531  const first = this[offset];
532  const last = this[offset + 3];
533  if (first === undefined || last === undefined)
534    boundsError(offset, this.length - 4);
535
536  uInt8Float32Array[0] = first;
537  uInt8Float32Array[1] = this[++offset];
538  uInt8Float32Array[2] = this[++offset];
539  uInt8Float32Array[3] = last;
540  return float32Array[0];
541}
542
543function readDoubleBackwards(offset = 0) {
544  validateNumber(offset, 'offset');
545  const first = this[offset];
546  const last = this[offset + 7];
547  if (first === undefined || last === undefined)
548    boundsError(offset, this.length - 8);
549
550  uInt8Float64Array[7] = first;
551  uInt8Float64Array[6] = this[++offset];
552  uInt8Float64Array[5] = this[++offset];
553  uInt8Float64Array[4] = this[++offset];
554  uInt8Float64Array[3] = this[++offset];
555  uInt8Float64Array[2] = this[++offset];
556  uInt8Float64Array[1] = this[++offset];
557  uInt8Float64Array[0] = last;
558  return float64Array[0];
559}
560
561function readDoubleForwards(offset = 0) {
562  validateNumber(offset, 'offset');
563  const first = this[offset];
564  const last = this[offset + 7];
565  if (first === undefined || last === undefined)
566    boundsError(offset, this.length - 8);
567
568  uInt8Float64Array[0] = first;
569  uInt8Float64Array[1] = this[++offset];
570  uInt8Float64Array[2] = this[++offset];
571  uInt8Float64Array[3] = this[++offset];
572  uInt8Float64Array[4] = this[++offset];
573  uInt8Float64Array[5] = this[++offset];
574  uInt8Float64Array[6] = this[++offset];
575  uInt8Float64Array[7] = last;
576  return float64Array[0];
577}
578
579// Write integers.
580function writeBigU_Int64LE(buf, value, offset, min, max) {
581  checkInt(value, min, max, buf, offset, 7);
582
583  let lo = Number(value & 0xffffffffn);
584  buf[offset++] = lo;
585  lo = lo >> 8;
586  buf[offset++] = lo;
587  lo = lo >> 8;
588  buf[offset++] = lo;
589  lo = lo >> 8;
590  buf[offset++] = lo;
591  let hi = Number(value >> 32n & 0xffffffffn);
592  buf[offset++] = hi;
593  hi = hi >> 8;
594  buf[offset++] = hi;
595  hi = hi >> 8;
596  buf[offset++] = hi;
597  hi = hi >> 8;
598  buf[offset++] = hi;
599  return offset;
600}
601
602function writeBigUInt64LE(value, offset = 0) {
603  return writeBigU_Int64LE(this, value, offset, 0n, 0xffffffffffffffffn);
604}
605
606function writeBigU_Int64BE(buf, value, offset, min, max) {
607  checkInt(value, min, max, buf, offset, 7);
608
609  let lo = Number(value & 0xffffffffn);
610  buf[offset + 7] = lo;
611  lo = lo >> 8;
612  buf[offset + 6] = lo;
613  lo = lo >> 8;
614  buf[offset + 5] = lo;
615  lo = lo >> 8;
616  buf[offset + 4] = lo;
617  let hi = Number(value >> 32n & 0xffffffffn);
618  buf[offset + 3] = hi;
619  hi = hi >> 8;
620  buf[offset + 2] = hi;
621  hi = hi >> 8;
622  buf[offset + 1] = hi;
623  hi = hi >> 8;
624  buf[offset] = hi;
625  return offset + 8;
626}
627
628function writeBigUInt64BE(value, offset = 0) {
629  return writeBigU_Int64BE(this, value, offset, 0n, 0xffffffffffffffffn);
630}
631
632function writeBigInt64LE(value, offset = 0) {
633  return writeBigU_Int64LE(
634    this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn);
635}
636
637function writeBigInt64BE(value, offset = 0) {
638  return writeBigU_Int64BE(
639    this, value, offset, -0x8000000000000000n, 0x7fffffffffffffffn);
640}
641
642function writeUIntLE(value, offset, byteLength) {
643  if (byteLength === 6)
644    return writeU_Int48LE(this, value, offset, 0, 0xffffffffffff);
645  if (byteLength === 5)
646    return writeU_Int40LE(this, value, offset, 0, 0xffffffffff);
647  if (byteLength === 3)
648    return writeU_Int24LE(this, value, offset, 0, 0xffffff);
649  if (byteLength === 4)
650    return writeU_Int32LE(this, value, offset, 0, 0xffffffff);
651  if (byteLength === 2)
652    return writeU_Int16LE(this, value, offset, 0, 0xffff);
653  if (byteLength === 1)
654    return writeU_Int8(this, value, offset, 0, 0xff);
655
656  boundsError(byteLength, 6, 'byteLength');
657}
658
659function writeU_Int48LE(buf, value, offset, min, max) {
660  value = +value;
661  checkInt(value, min, max, buf, offset, 5);
662
663  const newVal = MathFloor(value * 2 ** -32);
664  buf[offset++] = value;
665  value = value >>> 8;
666  buf[offset++] = value;
667  value = value >>> 8;
668  buf[offset++] = value;
669  value = value >>> 8;
670  buf[offset++] = value;
671  buf[offset++] = newVal;
672  buf[offset++] = (newVal >>> 8);
673  return offset;
674}
675
676function writeU_Int40LE(buf, value, offset, min, max) {
677  value = +value;
678  checkInt(value, min, max, buf, offset, 4);
679
680  const newVal = value;
681  buf[offset++] = value;
682  value = value >>> 8;
683  buf[offset++] = value;
684  value = value >>> 8;
685  buf[offset++] = value;
686  value = value >>> 8;
687  buf[offset++] = value;
688  buf[offset++] = MathFloor(newVal * 2 ** -32);
689  return offset;
690}
691
692function writeU_Int32LE(buf, value, offset, min, max) {
693  value = +value;
694  checkInt(value, min, max, buf, offset, 3);
695
696  buf[offset++] = value;
697  value = value >>> 8;
698  buf[offset++] = value;
699  value = value >>> 8;
700  buf[offset++] = value;
701  value = value >>> 8;
702  buf[offset++] = value;
703  return offset;
704}
705
706function writeUInt32LE(value, offset = 0) {
707  return writeU_Int32LE(this, value, offset, 0, 0xffffffff);
708}
709
710function writeU_Int24LE(buf, value, offset, min, max) {
711  value = +value;
712  checkInt(value, min, max, buf, offset, 2);
713
714  buf[offset++] = value;
715  value = value >>> 8;
716  buf[offset++] = value;
717  value = value >>> 8;
718  buf[offset++] = value;
719  return offset;
720}
721
722function writeU_Int16LE(buf, value, offset, min, max) {
723  value = +value;
724  checkInt(value, min, max, buf, offset, 1);
725
726  buf[offset++] = value;
727  buf[offset++] = (value >>> 8);
728  return offset;
729}
730
731function writeUInt16LE(value, offset = 0) {
732  return writeU_Int16LE(this, value, offset, 0, 0xffff);
733}
734
735function writeU_Int8(buf, value, offset, min, max) {
736  value = +value;
737  // `checkInt()` can not be used here because it checks two entries.
738  validateNumber(offset, 'offset');
739  if (value > max || value < min) {
740    throw new ERR_OUT_OF_RANGE('value', `>= ${min} and <= ${max}`, value);
741  }
742  if (buf[offset] === undefined)
743    boundsError(offset, buf.length - 1);
744
745  buf[offset] = value;
746  return offset + 1;
747}
748
749function writeUInt8(value, offset = 0) {
750  return writeU_Int8(this, value, offset, 0, 0xff);
751}
752
753function writeUIntBE(value, offset, byteLength) {
754  if (byteLength === 6)
755    return writeU_Int48BE(this, value, offset, 0, 0xffffffffffff);
756  if (byteLength === 5)
757    return writeU_Int40BE(this, value, offset, 0, 0xffffffffff);
758  if (byteLength === 3)
759    return writeU_Int24BE(this, value, offset, 0, 0xffffff);
760  if (byteLength === 4)
761    return writeU_Int32BE(this, value, offset, 0, 0xffffffff);
762  if (byteLength === 2)
763    return writeU_Int16BE(this, value, offset, 0, 0xffff);
764  if (byteLength === 1)
765    return writeU_Int8(this, value, offset, 0, 0xff);
766
767  boundsError(byteLength, 6, 'byteLength');
768}
769
770function writeU_Int48BE(buf, value, offset, min, max) {
771  value = +value;
772  checkInt(value, min, max, buf, offset, 5);
773
774  const newVal = MathFloor(value * 2 ** -32);
775  buf[offset++] = (newVal >>> 8);
776  buf[offset++] = newVal;
777  buf[offset + 3] = value;
778  value = value >>> 8;
779  buf[offset + 2] = value;
780  value = value >>> 8;
781  buf[offset + 1] = value;
782  value = value >>> 8;
783  buf[offset] = value;
784  return offset + 4;
785}
786
787function writeU_Int40BE(buf, value, offset, min, max) {
788  value = +value;
789  checkInt(value, min, max, buf, offset, 4);
790
791  buf[offset++] = MathFloor(value * 2 ** -32);
792  buf[offset + 3] = value;
793  value = value >>> 8;
794  buf[offset + 2] = value;
795  value = value >>> 8;
796  buf[offset + 1] = value;
797  value = value >>> 8;
798  buf[offset] = value;
799  return offset + 4;
800}
801
802function writeU_Int32BE(buf, value, offset, min, max) {
803  value = +value;
804  checkInt(value, min, max, buf, offset, 3);
805
806  buf[offset + 3] = value;
807  value = value >>> 8;
808  buf[offset + 2] = value;
809  value = value >>> 8;
810  buf[offset + 1] = value;
811  value = value >>> 8;
812  buf[offset] = value;
813  return offset + 4;
814}
815
816function writeUInt32BE(value, offset = 0) {
817  return writeU_Int32BE(this, value, offset, 0, 0xffffffff);
818}
819
820function writeU_Int24BE(buf, value, offset, min, max) {
821  value = +value;
822  checkInt(value, min, max, buf, offset, 2);
823
824  buf[offset + 2] = value;
825  value = value >>> 8;
826  buf[offset + 1] = value;
827  value = value >>> 8;
828  buf[offset] = value;
829  return offset + 3;
830}
831
832function writeU_Int16BE(buf, value, offset, min, max) {
833  value = +value;
834  checkInt(value, min, max, buf, offset, 1);
835
836  buf[offset++] = (value >>> 8);
837  buf[offset++] = value;
838  return offset;
839}
840
841function writeUInt16BE(value, offset = 0) {
842  return writeU_Int16BE(this, value, offset, 0, 0xffff);
843}
844
845function writeIntLE(value, offset, byteLength) {
846  if (byteLength === 6)
847    return writeU_Int48LE(this, value, offset, -0x800000000000, 0x7fffffffffff);
848  if (byteLength === 5)
849    return writeU_Int40LE(this, value, offset, -0x8000000000, 0x7fffffffff);
850  if (byteLength === 3)
851    return writeU_Int24LE(this, value, offset, -0x800000, 0x7fffff);
852  if (byteLength === 4)
853    return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff);
854  if (byteLength === 2)
855    return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff);
856  if (byteLength === 1)
857    return writeU_Int8(this, value, offset, -0x80, 0x7f);
858
859  boundsError(byteLength, 6, 'byteLength');
860}
861
862function writeInt32LE(value, offset = 0) {
863  return writeU_Int32LE(this, value, offset, -0x80000000, 0x7fffffff);
864}
865
866function writeInt16LE(value, offset = 0) {
867  return writeU_Int16LE(this, value, offset, -0x8000, 0x7fff);
868}
869
870function writeInt8(value, offset = 0) {
871  return writeU_Int8(this, value, offset, -0x80, 0x7f);
872}
873
874function writeIntBE(value, offset, byteLength) {
875  if (byteLength === 6)
876    return writeU_Int48BE(this, value, offset, -0x800000000000, 0x7fffffffffff);
877  if (byteLength === 5)
878    return writeU_Int40BE(this, value, offset, -0x8000000000, 0x7fffffffff);
879  if (byteLength === 3)
880    return writeU_Int24BE(this, value, offset, -0x800000, 0x7fffff);
881  if (byteLength === 4)
882    return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff);
883  if (byteLength === 2)
884    return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff);
885  if (byteLength === 1)
886    return writeU_Int8(this, value, offset, -0x80, 0x7f);
887
888  boundsError(byteLength, 6, 'byteLength');
889}
890
891function writeInt32BE(value, offset = 0) {
892  return writeU_Int32BE(this, value, offset, -0x80000000, 0x7fffffff);
893}
894
895function writeInt16BE(value, offset = 0) {
896  return writeU_Int16BE(this, value, offset, -0x8000, 0x7fff);
897}
898
899// Write floats.
900function writeDoubleForwards(val, offset = 0) {
901  val = +val;
902  checkBounds(this, offset, 7);
903
904  float64Array[0] = val;
905  this[offset++] = uInt8Float64Array[0];
906  this[offset++] = uInt8Float64Array[1];
907  this[offset++] = uInt8Float64Array[2];
908  this[offset++] = uInt8Float64Array[3];
909  this[offset++] = uInt8Float64Array[4];
910  this[offset++] = uInt8Float64Array[5];
911  this[offset++] = uInt8Float64Array[6];
912  this[offset++] = uInt8Float64Array[7];
913  return offset;
914}
915
916function writeDoubleBackwards(val, offset = 0) {
917  val = +val;
918  checkBounds(this, offset, 7);
919
920  float64Array[0] = val;
921  this[offset++] = uInt8Float64Array[7];
922  this[offset++] = uInt8Float64Array[6];
923  this[offset++] = uInt8Float64Array[5];
924  this[offset++] = uInt8Float64Array[4];
925  this[offset++] = uInt8Float64Array[3];
926  this[offset++] = uInt8Float64Array[2];
927  this[offset++] = uInt8Float64Array[1];
928  this[offset++] = uInt8Float64Array[0];
929  return offset;
930}
931
932function writeFloatForwards(val, offset = 0) {
933  val = +val;
934  checkBounds(this, offset, 3);
935
936  float32Array[0] = val;
937  this[offset++] = uInt8Float32Array[0];
938  this[offset++] = uInt8Float32Array[1];
939  this[offset++] = uInt8Float32Array[2];
940  this[offset++] = uInt8Float32Array[3];
941  return offset;
942}
943
944function writeFloatBackwards(val, offset = 0) {
945  val = +val;
946  checkBounds(this, offset, 3);
947
948  float32Array[0] = val;
949  this[offset++] = uInt8Float32Array[3];
950  this[offset++] = uInt8Float32Array[2];
951  this[offset++] = uInt8Float32Array[1];
952  this[offset++] = uInt8Float32Array[0];
953  return offset;
954}
955
956class FastBuffer extends Uint8Array {
957  // Using an explicit constructor here is necessary to avoid relying on
958  // `Array.prototype[Symbol.iterator]`, which can be mutated by users.
959  // eslint-disable-next-line no-useless-constructor
960  constructor(bufferOrLength, byteOffset, length) {
961    super(bufferOrLength, byteOffset, length);
962  }
963}
964
965function addBufferPrototypeMethods(proto) {
966  proto.readBigUInt64LE = readBigUInt64LE;
967  proto.readBigUInt64BE = readBigUInt64BE;
968  proto.readBigUint64LE = readBigUInt64LE;
969  proto.readBigUint64BE = readBigUInt64BE;
970  proto.readBigInt64LE = readBigInt64LE;
971  proto.readBigInt64BE = readBigInt64BE;
972  proto.writeBigUInt64LE = writeBigUInt64LE;
973  proto.writeBigUInt64BE = writeBigUInt64BE;
974  proto.writeBigUint64LE = writeBigUInt64LE;
975  proto.writeBigUint64BE = writeBigUInt64BE;
976  proto.writeBigInt64LE = writeBigInt64LE;
977  proto.writeBigInt64BE = writeBigInt64BE;
978
979  proto.readUIntLE = readUIntLE;
980  proto.readUInt32LE = readUInt32LE;
981  proto.readUInt16LE = readUInt16LE;
982  proto.readUInt8 = readUInt8;
983  proto.readUIntBE = readUIntBE;
984  proto.readUInt32BE = readUInt32BE;
985  proto.readUInt16BE = readUInt16BE;
986  proto.readUintLE = readUIntLE;
987  proto.readUint32LE = readUInt32LE;
988  proto.readUint16LE = readUInt16LE;
989  proto.readUint8 = readUInt8;
990  proto.readUintBE = readUIntBE;
991  proto.readUint32BE = readUInt32BE;
992  proto.readUint16BE = readUInt16BE;
993  proto.readIntLE = readIntLE;
994  proto.readInt32LE = readInt32LE;
995  proto.readInt16LE = readInt16LE;
996  proto.readInt8 = readInt8;
997  proto.readIntBE = readIntBE;
998  proto.readInt32BE = readInt32BE;
999  proto.readInt16BE = readInt16BE;
1000
1001  proto.writeUIntLE = writeUIntLE;
1002  proto.writeUInt32LE = writeUInt32LE;
1003  proto.writeUInt16LE = writeUInt16LE;
1004  proto.writeUInt8 = writeUInt8;
1005  proto.writeUIntBE = writeUIntBE;
1006  proto.writeUInt32BE = writeUInt32BE;
1007  proto.writeUInt16BE = writeUInt16BE;
1008  proto.writeUintLE = writeUIntLE;
1009  proto.writeUint32LE = writeUInt32LE;
1010  proto.writeUint16LE = writeUInt16LE;
1011  proto.writeUint8 = writeUInt8;
1012  proto.writeUintBE = writeUIntBE;
1013  proto.writeUint32BE = writeUInt32BE;
1014  proto.writeUint16BE = writeUInt16BE;
1015  proto.writeIntLE = writeIntLE;
1016  proto.writeInt32LE = writeInt32LE;
1017  proto.writeInt16LE = writeInt16LE;
1018  proto.writeInt8 = writeInt8;
1019  proto.writeIntBE = writeIntBE;
1020  proto.writeInt32BE = writeInt32BE;
1021  proto.writeInt16BE = writeInt16BE;
1022
1023  proto.readFloatLE = bigEndian ? readFloatBackwards : readFloatForwards;
1024  proto.readFloatBE = bigEndian ? readFloatForwards : readFloatBackwards;
1025  proto.readDoubleLE = bigEndian ? readDoubleBackwards : readDoubleForwards;
1026  proto.readDoubleBE = bigEndian ? readDoubleForwards : readDoubleBackwards;
1027  proto.writeFloatLE = bigEndian ? writeFloatBackwards : writeFloatForwards;
1028  proto.writeFloatBE = bigEndian ? writeFloatForwards : writeFloatBackwards;
1029  proto.writeDoubleLE = bigEndian ? writeDoubleBackwards : writeDoubleForwards;
1030  proto.writeDoubleBE = bigEndian ? writeDoubleForwards : writeDoubleBackwards;
1031
1032  proto.asciiSlice = asciiSlice;
1033  proto.base64Slice = base64Slice;
1034  proto.base64urlSlice = base64urlSlice;
1035  proto.latin1Slice = latin1Slice;
1036  proto.hexSlice = hexSlice;
1037  proto.ucs2Slice = ucs2Slice;
1038  proto.utf8Slice = utf8Slice;
1039  proto.asciiWrite = asciiWrite;
1040  proto.base64Write = base64Write;
1041  proto.base64urlWrite = base64urlWrite;
1042  proto.latin1Write = latin1Write;
1043  proto.hexWrite = hexWrite;
1044  proto.ucs2Write = ucs2Write;
1045  proto.utf8Write = utf8Write;
1046}
1047
1048// This would better be placed in internal/worker/io.js, but that doesn't work
1049// because Buffer needs this and that would introduce a cyclic dependency.
1050function markAsUntransferable(obj) {
1051  if ((typeof obj !== 'object' && typeof obj !== 'function') || obj === null)
1052    return;  // This object is a primitive and therefore already untransferable.
1053  obj[untransferable_object_private_symbol] = true;
1054}
1055
1056// A toggle used to access the zero fill setting of the array buffer allocator
1057// in C++.
1058// |zeroFill| can be undefined when running inside an isolate where we
1059// do not own the ArrayBuffer allocator.  Zero fill is always on in that case.
1060let zeroFill = getZeroFillToggle();
1061function createUnsafeBuffer(size) {
1062  zeroFill[0] = 0;
1063  try {
1064    return new FastBuffer(size);
1065  } finally {
1066    zeroFill[0] = 1;
1067  }
1068}
1069
1070// The connection between the JS land zero fill toggle and the
1071// C++ one in the NodeArrayBufferAllocator gets lost if the toggle
1072// is deserialized from the snapshot, because V8 owns the underlying
1073// memory of this toggle. This resets the connection.
1074function reconnectZeroFillToggle() {
1075  zeroFill = getZeroFillToggle();
1076}
1077
1078module.exports = {
1079  FastBuffer,
1080  addBufferPrototypeMethods,
1081  markAsUntransferable,
1082  createUnsafeBuffer,
1083  readUInt16BE,
1084  readUInt32BE,
1085  reconnectZeroFillToggle,
1086};
1087