@gjsify/buffer 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/buffer.ts ADDED
@@ -0,0 +1,786 @@
1
+ // Native Buffer implementation for GJS
2
+ // Reference: Node.js lib/buffer.js, Deno ext/node/polyfills/buffer.ts
3
+
4
+ // BufferEncoding is a global type provided by @types/node
5
+
6
+ import { normalizeEncoding, checkEncoding, atobPolyfill as _atob, btoaPolyfill as _btoa, base64Decode } from '@gjsify/utils';
7
+
8
+ const textEncoder = new TextEncoder();
9
+ const textDecoder = new TextDecoder();
10
+
11
+ // SharedArrayBuffer may not be available in GJS
12
+ const hasSharedArrayBuffer = typeof SharedArrayBuffer !== 'undefined';
13
+
14
+ // normalizeEncoding and checkEncoding are imported from @gjsify/utils
15
+
16
+ // Encode string to Uint8Array
17
+ function encodeString(str: string, encoding: BufferEncoding): Uint8Array {
18
+ switch (encoding) {
19
+ case 'utf8':
20
+ return textEncoder.encode(str);
21
+
22
+ case 'ascii': {
23
+ const buf = new Uint8Array(str.length);
24
+ for (let i = 0; i < str.length; i++) {
25
+ buf[i] = str.charCodeAt(i) & 0x7f;
26
+ }
27
+ return buf;
28
+ }
29
+
30
+ case 'latin1': {
31
+ const buf = new Uint8Array(str.length);
32
+ for (let i = 0; i < str.length; i++) {
33
+ buf[i] = str.charCodeAt(i) & 0xff;
34
+ }
35
+ return buf;
36
+ }
37
+
38
+ case 'base64': {
39
+ const standard = str.replace(/-/g, '+').replace(/_/g, '/');
40
+ return base64Decode(standard);
41
+ }
42
+
43
+ case 'base64url': {
44
+ const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
45
+ return encodeString(base64, 'base64');
46
+ }
47
+
48
+ case 'hex': {
49
+ const bytes = str.length >>> 1;
50
+ const buf = new Uint8Array(bytes);
51
+ for (let i = 0; i < bytes; i++) {
52
+ const hi = parseInt(str[i * 2], 16);
53
+ const lo = parseInt(str[i * 2 + 1], 16);
54
+ if (Number.isNaN(hi) || Number.isNaN(lo)) break;
55
+ buf[i] = (hi << 4) | lo;
56
+ }
57
+ return buf;
58
+ }
59
+
60
+ case 'utf16le': {
61
+ const buf = new Uint8Array(str.length * 2);
62
+ for (let i = 0; i < str.length; i++) {
63
+ const code = str.charCodeAt(i);
64
+ buf[i * 2] = code & 0xff;
65
+ buf[i * 2 + 1] = (code >> 8) & 0xff;
66
+ }
67
+ return buf;
68
+ }
69
+
70
+ default:
71
+ return textEncoder.encode(str);
72
+ }
73
+ }
74
+
75
+ // Decode Uint8Array to string
76
+ function decodeString(buf: Uint8Array, encoding: BufferEncoding, start?: number, end?: number): string {
77
+ const slice = start !== undefined || end !== undefined
78
+ ? buf.subarray(start ?? 0, end ?? buf.length)
79
+ : buf;
80
+
81
+ switch (encoding) {
82
+ case 'utf8':
83
+ return textDecoder.decode(slice);
84
+
85
+ case 'ascii': {
86
+ let result = '';
87
+ for (let i = 0; i < slice.length; i++) {
88
+ result += String.fromCharCode(slice[i] & 0x7f);
89
+ }
90
+ return result;
91
+ }
92
+
93
+ case 'latin1': {
94
+ let result = '';
95
+ for (let i = 0; i < slice.length; i++) {
96
+ result += String.fromCharCode(slice[i]);
97
+ }
98
+ return result;
99
+ }
100
+
101
+ case 'base64': {
102
+ let binary = '';
103
+ for (let i = 0; i < slice.length; i++) {
104
+ binary += String.fromCharCode(slice[i]);
105
+ }
106
+ return _btoa(binary);
107
+ }
108
+
109
+ case 'base64url': {
110
+ const base64 = decodeString(slice, 'base64');
111
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
112
+ }
113
+
114
+ case 'hex': {
115
+ let result = '';
116
+ for (let i = 0; i < slice.length; i++) {
117
+ result += slice[i].toString(16).padStart(2, '0');
118
+ }
119
+ return result;
120
+ }
121
+
122
+ case 'utf16le': {
123
+ let result = '';
124
+ for (let i = 0; i + 1 < slice.length; i += 2) {
125
+ result += String.fromCharCode(slice[i] | (slice[i + 1] << 8));
126
+ }
127
+ return result;
128
+ }
129
+
130
+ default:
131
+ return textDecoder.decode(slice);
132
+ }
133
+ }
134
+
135
+ function checkOffset(offset: number, ext: number, length: number): void {
136
+ if (offset + ext > length) {
137
+ throw new RangeError('Attempt to access memory outside buffer bounds');
138
+ }
139
+ }
140
+
141
+ const INSPECT_MAX_BYTES = 50;
142
+
143
+ /**
144
+ * Node.js-compatible Buffer class.
145
+ */
146
+ export class Buffer extends Uint8Array {
147
+ // Marker to identify Buffer instances
148
+ private static readonly _isBuffer = true;
149
+
150
+ // ---- Static constructors ----
151
+
152
+ static alloc(size: number, fill?: number | string | Uint8Array | Buffer, encoding?: string): Buffer {
153
+ if (typeof size !== 'number') {
154
+ throw new TypeError(`The "size" argument must be of type number. Received type ${typeof size}`);
155
+ }
156
+ if (size < 0) {
157
+ throw new RangeError(`The value "${size}" is invalid for option "size"`);
158
+ }
159
+
160
+ const buf = new Buffer(size);
161
+
162
+ if (fill !== undefined && fill !== 0) {
163
+ buf.fill(fill, 0, size, encoding);
164
+ }
165
+
166
+ return buf;
167
+ }
168
+
169
+ static allocUnsafe(size: number): Buffer {
170
+ if (typeof size !== 'number') {
171
+ throw new TypeError(`The "size" argument must be of type number. Received type ${typeof size}`);
172
+ }
173
+ return new Buffer(size);
174
+ }
175
+
176
+ static allocUnsafeSlow(size: number): Buffer {
177
+ return Buffer.allocUnsafe(size);
178
+ }
179
+
180
+ static from(arrayLike: ArrayLike<number>): Buffer;
181
+ static from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: unknown): Buffer;
182
+ static from(elements: Iterable<number>): Buffer;
183
+ static from(value: string, encoding?: string): Buffer;
184
+ static from(value: ArrayBuffer | SharedArrayBuffer, byteOffset?: number, length?: number): Buffer;
185
+ static from(value: Uint8Array | Buffer): Buffer;
186
+ static from(
187
+ value: ArrayBuffer | SharedArrayBuffer | ArrayLike<number> | Iterable<number> | Uint8Array | Buffer | string,
188
+ encodingOrOffset?: string | number | ((v: unknown, k: number) => number),
189
+ length?: number
190
+ ): Buffer {
191
+ if (typeof value === 'string') {
192
+ const encoding = normalizeEncoding(encodingOrOffset as string);
193
+ if (encodingOrOffset && typeof encodingOrOffset === 'string') {
194
+ // Only check encoding for non-empty, non-falsy strings
195
+ const lower = ('' + encodingOrOffset).toLowerCase().replace(/-/g, '');
196
+ const valid = ['utf8', 'ascii', 'latin1', 'binary', 'base64', 'base64url', 'hex', 'ucs2', 'utf16le', ''];
197
+ if (!valid.includes(lower)) {
198
+ checkEncoding(encodingOrOffset);
199
+ }
200
+ }
201
+ const encoded = encodeString(value as string, encoding);
202
+ const buf = new Buffer(encoded.buffer as ArrayBuffer, encoded.byteOffset, encoded.byteLength);
203
+ return buf;
204
+ }
205
+
206
+ if (ArrayBuffer.isView(value)) {
207
+ const buf = new Buffer(value.buffer as ArrayBuffer, value.byteOffset, value.byteLength);
208
+ // Make a copy to avoid shared memory
209
+ const copy = new Buffer(buf.length);
210
+ copy.set(buf);
211
+ return copy;
212
+ }
213
+
214
+ if (value instanceof ArrayBuffer) {
215
+ const offset = (encodingOrOffset as number) || 0;
216
+ const len = length !== undefined ? length : value.byteLength - offset;
217
+ return new Buffer(value, offset, len);
218
+ }
219
+
220
+ if (hasSharedArrayBuffer && value instanceof SharedArrayBuffer) {
221
+ const offset = (encodingOrOffset as number) || 0;
222
+ const len = length !== undefined ? length : value.byteLength - offset;
223
+ return new Buffer(new Uint8Array(value, offset, len));
224
+ }
225
+
226
+ if (Array.isArray(value)) {
227
+ const buf = new Buffer(value.length);
228
+ for (let i = 0; i < value.length; i++) {
229
+ buf[i] = value[i] & 0xff;
230
+ }
231
+ return buf;
232
+ }
233
+
234
+ throw new TypeError('The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array');
235
+ }
236
+
237
+ // ---- Static methods ----
238
+
239
+ static isBuffer(obj: unknown): obj is Buffer {
240
+ return obj instanceof Buffer;
241
+ }
242
+
243
+ static isEncoding(encoding: unknown): encoding is BufferEncoding {
244
+ if (typeof encoding !== 'string') return false;
245
+ const lower = encoding.toLowerCase().replace(/-/g, '');
246
+ return ['utf8', 'ascii', 'latin1', 'binary', 'base64', 'base64url', 'hex', 'ucs2', 'utf16le'].includes(lower);
247
+ }
248
+
249
+ static byteLength(string: string | ArrayBuffer | SharedArrayBuffer | ArrayBufferView, encoding?: string): number {
250
+ if (typeof string !== 'string') {
251
+ if (ArrayBuffer.isView(string)) return string.byteLength;
252
+ if (string instanceof ArrayBuffer) return string.byteLength;
253
+ if (hasSharedArrayBuffer && string instanceof SharedArrayBuffer) return string.byteLength;
254
+ throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer');
255
+ }
256
+
257
+ const enc = normalizeEncoding(encoding);
258
+ switch (enc) {
259
+ case 'utf8':
260
+ return textEncoder.encode(string).byteLength;
261
+ case 'ascii':
262
+ case 'latin1':
263
+ return string.length;
264
+ case 'base64':
265
+ case 'base64url': {
266
+ // Calculate base64 decoded length
267
+ let len = string.length;
268
+ // Remove padding
269
+ while (len > 0 && (string[len - 1] === '=' || string[len - 1] === ' ')) len--;
270
+ return (len * 3) >>> 2;
271
+ }
272
+ case 'hex':
273
+ return string.length >>> 1;
274
+ case 'utf16le':
275
+ return string.length * 2;
276
+ default:
277
+ return textEncoder.encode(string).byteLength;
278
+ }
279
+ }
280
+
281
+ static compare(buf1: Buffer | Uint8Array, buf2: Buffer | Uint8Array): -1 | 0 | 1 {
282
+ if (!(buf1 instanceof Uint8Array) || !(buf2 instanceof Uint8Array)) {
283
+ throw new TypeError('Arguments must be Buffers or Uint8Arrays');
284
+ }
285
+ const len = Math.min(buf1.length, buf2.length);
286
+ for (let i = 0; i < len; i++) {
287
+ if (buf1[i] < buf2[i]) return -1;
288
+ if (buf1[i] > buf2[i]) return 1;
289
+ }
290
+ if (buf1.length < buf2.length) return -1;
291
+ if (buf1.length > buf2.length) return 1;
292
+ return 0;
293
+ }
294
+
295
+ static concat(list: (Buffer | Uint8Array)[], totalLength?: number): Buffer {
296
+ if (list.length === 0) return Buffer.alloc(0);
297
+
298
+ if (totalLength === undefined) {
299
+ totalLength = 0;
300
+ for (let i = 0; i < list.length; i++) {
301
+ totalLength += list[i].length;
302
+ }
303
+ }
304
+
305
+ const result = Buffer.alloc(totalLength);
306
+ let offset = 0;
307
+ for (let i = 0; i < list.length; i++) {
308
+ const buf = list[i];
309
+ const toCopy = Math.min(buf.length, totalLength - offset);
310
+ if (toCopy <= 0) continue;
311
+ result.set(buf.subarray(0, toCopy), offset);
312
+ offset += toCopy;
313
+ }
314
+ return result;
315
+ }
316
+
317
+ static poolSize = 8192;
318
+
319
+ // ---- Instance methods ----
320
+
321
+ toString(encoding?: string, start?: number, end?: number): string {
322
+ const enc = normalizeEncoding(encoding);
323
+ return decodeString(this, enc, start, end);
324
+ }
325
+
326
+ toJSON(): { type: 'Buffer'; data: number[] } {
327
+ return {
328
+ type: 'Buffer',
329
+ data: Array.from(this),
330
+ };
331
+ }
332
+
333
+ equals(otherBuffer: Buffer | Uint8Array): boolean {
334
+ if (!(otherBuffer instanceof Uint8Array)) {
335
+ throw new TypeError('Argument must be a Buffer or Uint8Array');
336
+ }
337
+ if (this.length !== otherBuffer.length) return false;
338
+ for (let i = 0; i < this.length; i++) {
339
+ if (this[i] !== otherBuffer[i]) return false;
340
+ }
341
+ return true;
342
+ }
343
+
344
+ compare(target: Buffer | Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): -1 | 0 | 1 {
345
+ if (!(target instanceof Uint8Array)) {
346
+ throw new TypeError('Argument must be a Buffer or Uint8Array');
347
+ }
348
+ const src = sourceStart !== undefined || sourceEnd !== undefined
349
+ ? this.subarray(sourceStart ?? 0, sourceEnd ?? this.length)
350
+ : this;
351
+ const tgt = targetStart !== undefined || targetEnd !== undefined
352
+ ? target.subarray(targetStart ?? 0, targetEnd ?? target.length)
353
+ : target;
354
+ return Buffer.compare(src, tgt);
355
+ }
356
+
357
+ copy(target: Buffer | Uint8Array, targetStart = 0, sourceStart = 0, sourceEnd?: number): number {
358
+ const end = sourceEnd ?? this.length;
359
+ const toCopy = Math.min(end - sourceStart, target.length - targetStart);
360
+ if (toCopy <= 0) return 0;
361
+ target.set(this.subarray(sourceStart, sourceStart + toCopy), targetStart);
362
+ return toCopy;
363
+ }
364
+
365
+ // slice returns a Buffer (not Uint8Array) that shares memory
366
+ slice(start?: number, end?: number): Buffer {
367
+ const s = start ?? 0;
368
+ const e = end ?? this.length;
369
+ const sub = super.subarray(s, e);
370
+ return new Buffer(sub.buffer, sub.byteOffset, sub.byteLength);
371
+ }
372
+
373
+ // subarray also returns a Buffer
374
+ subarray(start?: number, end?: number): Buffer {
375
+ const sub = super.subarray(start, end);
376
+ return new Buffer(sub.buffer, sub.byteOffset, sub.byteLength);
377
+ }
378
+
379
+ write(string: string, offset?: number, length?: number, encoding?: string): number {
380
+ offset = offset ?? 0;
381
+ const enc = normalizeEncoding(encoding || (typeof length === 'string' ? length : undefined));
382
+ const encoded = encodeString(string, enc);
383
+ const maxLen = length !== undefined && typeof length === 'number' ? Math.min(length, this.length - offset) : this.length - offset;
384
+ const toCopy = Math.min(encoded.length, maxLen);
385
+ this.set(encoded.subarray(0, toCopy), offset);
386
+ return toCopy;
387
+ }
388
+
389
+ fill(value: number | string | Uint8Array | Buffer, offset?: number, end?: number, encoding?: string): this {
390
+ const start = offset ?? 0;
391
+ const stop = end ?? this.length;
392
+
393
+ if (typeof value === 'number') {
394
+ super.fill(value & 0xff, start, stop);
395
+ } else if (typeof value === 'string') {
396
+ const enc = normalizeEncoding(encoding);
397
+ const encoded = encodeString(value, enc);
398
+ if (encoded.length === 0) {
399
+ super.fill(0, start, stop);
400
+ } else if (encoded.length === 1) {
401
+ super.fill(encoded[0], start, stop);
402
+ } else {
403
+ for (let i = start; i < stop; i++) {
404
+ this[i] = encoded[(i - start) % encoded.length];
405
+ }
406
+ }
407
+ } else if (value instanceof Uint8Array) {
408
+ if (value.length === 0) {
409
+ super.fill(0, start, stop);
410
+ } else {
411
+ for (let i = start; i < stop; i++) {
412
+ this[i] = value[(i - start) % value.length];
413
+ }
414
+ }
415
+ }
416
+
417
+ return this;
418
+ }
419
+
420
+ indexOf(value: number | string | Uint8Array | Buffer, byteOffset?: number, encoding?: string): number {
421
+ if (typeof value === 'number') {
422
+ return super.indexOf(value & 0xff, byteOffset);
423
+ }
424
+ const needle = typeof value === 'string' ? encodeString(value, normalizeEncoding(encoding)) : value;
425
+ const start = byteOffset ?? 0;
426
+ outer:
427
+ for (let i = start; i <= this.length - needle.length; i++) {
428
+ for (let j = 0; j < needle.length; j++) {
429
+ if (this[i + j] !== needle[j]) continue outer;
430
+ }
431
+ return i;
432
+ }
433
+ return -1;
434
+ }
435
+
436
+ lastIndexOf(value: number | string | Uint8Array | Buffer, byteOffset?: number, encoding?: string): number {
437
+ if (typeof value === 'number') {
438
+ // SpiderMonkey treats undefined fromIndex as 0, not array end
439
+ return byteOffset !== undefined ? super.lastIndexOf(value & 0xff, byteOffset) : super.lastIndexOf(value & 0xff);
440
+ }
441
+ const needle = typeof value === 'string' ? encodeString(value, normalizeEncoding(encoding)) : value;
442
+ const start = byteOffset !== undefined ? Math.min(byteOffset, this.length - needle.length) : this.length - needle.length;
443
+ outer:
444
+ for (let i = start; i >= 0; i--) {
445
+ for (let j = 0; j < needle.length; j++) {
446
+ if (this[i + j] !== needle[j]) continue outer;
447
+ }
448
+ return i;
449
+ }
450
+ return -1;
451
+ }
452
+
453
+ includes(value: number | string | Uint8Array | Buffer, byteOffset?: number, encoding?: string): boolean {
454
+ return this.indexOf(value, byteOffset, encoding) !== -1;
455
+ }
456
+
457
+ // ---- Read methods ----
458
+
459
+ readUInt8(offset = 0): number {
460
+ checkOffset(offset, 1, this.length);
461
+ return this[offset];
462
+ }
463
+
464
+ readUInt16BE(offset = 0): number {
465
+ checkOffset(offset, 2, this.length);
466
+ return (this[offset] << 8) | this[offset + 1];
467
+ }
468
+
469
+ readUInt16LE(offset = 0): number {
470
+ checkOffset(offset, 2, this.length);
471
+ return this[offset] | (this[offset + 1] << 8);
472
+ }
473
+
474
+ readUInt32BE(offset = 0): number {
475
+ checkOffset(offset, 4, this.length);
476
+ return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]);
477
+ }
478
+
479
+ readUInt32LE(offset = 0): number {
480
+ checkOffset(offset, 4, this.length);
481
+ return ((this[offset + 3] * 0x1000000) + ((this[offset + 2] << 16) | (this[offset + 1] << 8) | this[offset])) >>> 0;
482
+ }
483
+
484
+ readInt8(offset = 0): number {
485
+ checkOffset(offset, 1, this.length);
486
+ return this[offset] | (this[offset] & 0x80 ? 0xffffff00 : 0);
487
+ }
488
+
489
+ readInt16BE(offset = 0): number {
490
+ checkOffset(offset, 2, this.length);
491
+ const val = (this[offset] << 8) | this[offset + 1];
492
+ return val & 0x8000 ? val | 0xffff0000 : val;
493
+ }
494
+
495
+ readInt16LE(offset = 0): number {
496
+ checkOffset(offset, 2, this.length);
497
+ const val = this[offset] | (this[offset + 1] << 8);
498
+ return val & 0x8000 ? val | 0xffff0000 : val;
499
+ }
500
+
501
+ readInt32BE(offset = 0): number {
502
+ checkOffset(offset, 4, this.length);
503
+ return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3];
504
+ }
505
+
506
+ readInt32LE(offset = 0): number {
507
+ checkOffset(offset, 4, this.length);
508
+ return this[offset] | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24);
509
+ }
510
+
511
+ readFloatBE(offset = 0): number {
512
+ checkOffset(offset, 4, this.length);
513
+ const view = new DataView(this.buffer, this.byteOffset + offset, 4);
514
+ return view.getFloat32(0, false);
515
+ }
516
+
517
+ readFloatLE(offset = 0): number {
518
+ checkOffset(offset, 4, this.length);
519
+ const view = new DataView(this.buffer, this.byteOffset + offset, 4);
520
+ return view.getFloat32(0, true);
521
+ }
522
+
523
+ readDoubleBE(offset = 0): number {
524
+ checkOffset(offset, 8, this.length);
525
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
526
+ return view.getFloat64(0, false);
527
+ }
528
+
529
+ readDoubleLE(offset = 0): number {
530
+ checkOffset(offset, 8, this.length);
531
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
532
+ return view.getFloat64(0, true);
533
+ }
534
+
535
+ readBigInt64BE(offset = 0): bigint {
536
+ checkOffset(offset, 8, this.length);
537
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
538
+ return view.getBigInt64(0, false);
539
+ }
540
+
541
+ readBigInt64LE(offset = 0): bigint {
542
+ checkOffset(offset, 8, this.length);
543
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
544
+ return view.getBigInt64(0, true);
545
+ }
546
+
547
+ readBigUInt64BE(offset = 0): bigint {
548
+ checkOffset(offset, 8, this.length);
549
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
550
+ return view.getBigUint64(0, false);
551
+ }
552
+
553
+ readBigUInt64LE(offset = 0): bigint {
554
+ checkOffset(offset, 8, this.length);
555
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
556
+ return view.getBigUint64(0, true);
557
+ }
558
+
559
+ readUIntBE(offset: number, byteLength: number): number {
560
+ checkOffset(offset, byteLength, this.length);
561
+ let val = 0;
562
+ for (let i = 0; i < byteLength; i++) {
563
+ val = val * 256 + this[offset + i];
564
+ }
565
+ return val;
566
+ }
567
+
568
+ readUIntLE(offset: number, byteLength: number): number {
569
+ checkOffset(offset, byteLength, this.length);
570
+ let val = 0;
571
+ let mul = 1;
572
+ for (let i = 0; i < byteLength; i++) {
573
+ val += this[offset + i] * mul;
574
+ mul *= 256;
575
+ }
576
+ return val;
577
+ }
578
+
579
+ readIntBE(offset: number, byteLength: number): number {
580
+ checkOffset(offset, byteLength, this.length);
581
+ let val = 0;
582
+ for (let i = 0; i < byteLength; i++) {
583
+ val = val * 256 + this[offset + i];
584
+ }
585
+ if (val >= Math.pow(2, 8 * byteLength - 1)) {
586
+ val -= Math.pow(2, 8 * byteLength);
587
+ }
588
+ return val;
589
+ }
590
+
591
+ readIntLE(offset: number, byteLength: number): number {
592
+ checkOffset(offset, byteLength, this.length);
593
+ let val = 0;
594
+ let mul = 1;
595
+ for (let i = 0; i < byteLength; i++) {
596
+ val += this[offset + i] * mul;
597
+ mul *= 256;
598
+ }
599
+ if (val >= Math.pow(2, 8 * byteLength - 1)) {
600
+ val -= Math.pow(2, 8 * byteLength);
601
+ }
602
+ return val;
603
+ }
604
+
605
+ // ---- Write methods ----
606
+
607
+ writeUInt8(value: number, offset = 0): number {
608
+ checkOffset(offset, 1, this.length);
609
+ this[offset] = value & 0xff;
610
+ return offset + 1;
611
+ }
612
+
613
+ writeUInt16BE(value: number, offset = 0): number {
614
+ checkOffset(offset, 2, this.length);
615
+ this[offset] = (value >>> 8) & 0xff;
616
+ this[offset + 1] = value & 0xff;
617
+ return offset + 2;
618
+ }
619
+
620
+ writeUInt16LE(value: number, offset = 0): number {
621
+ checkOffset(offset, 2, this.length);
622
+ this[offset] = value & 0xff;
623
+ this[offset + 1] = (value >>> 8) & 0xff;
624
+ return offset + 2;
625
+ }
626
+
627
+ writeUInt32BE(value: number, offset = 0): number {
628
+ checkOffset(offset, 4, this.length);
629
+ this[offset] = (value >>> 24) & 0xff;
630
+ this[offset + 1] = (value >>> 16) & 0xff;
631
+ this[offset + 2] = (value >>> 8) & 0xff;
632
+ this[offset + 3] = value & 0xff;
633
+ return offset + 4;
634
+ }
635
+
636
+ writeUInt32LE(value: number, offset = 0): number {
637
+ checkOffset(offset, 4, this.length);
638
+ this[offset] = value & 0xff;
639
+ this[offset + 1] = (value >>> 8) & 0xff;
640
+ this[offset + 2] = (value >>> 16) & 0xff;
641
+ this[offset + 3] = (value >>> 24) & 0xff;
642
+ return offset + 4;
643
+ }
644
+
645
+ writeInt8(value: number, offset = 0): number {
646
+ checkOffset(offset, 1, this.length);
647
+ if (value < 0) value = 0xff + value + 1;
648
+ this[offset] = value & 0xff;
649
+ return offset + 1;
650
+ }
651
+
652
+ writeInt16BE(value: number, offset = 0): number {
653
+ checkOffset(offset, 2, this.length);
654
+ this[offset] = (value >>> 8) & 0xff;
655
+ this[offset + 1] = value & 0xff;
656
+ return offset + 2;
657
+ }
658
+
659
+ writeInt16LE(value: number, offset = 0): number {
660
+ checkOffset(offset, 2, this.length);
661
+ this[offset] = value & 0xff;
662
+ this[offset + 1] = (value >>> 8) & 0xff;
663
+ return offset + 2;
664
+ }
665
+
666
+ writeInt32BE(value: number, offset = 0): number {
667
+ checkOffset(offset, 4, this.length);
668
+ this[offset] = (value >>> 24) & 0xff;
669
+ this[offset + 1] = (value >>> 16) & 0xff;
670
+ this[offset + 2] = (value >>> 8) & 0xff;
671
+ this[offset + 3] = value & 0xff;
672
+ return offset + 4;
673
+ }
674
+
675
+ writeInt32LE(value: number, offset = 0): number {
676
+ checkOffset(offset, 4, this.length);
677
+ this[offset] = value & 0xff;
678
+ this[offset + 1] = (value >>> 8) & 0xff;
679
+ this[offset + 2] = (value >>> 16) & 0xff;
680
+ this[offset + 3] = (value >>> 24) & 0xff;
681
+ return offset + 4;
682
+ }
683
+
684
+ writeFloatBE(value: number, offset = 0): number {
685
+ checkOffset(offset, 4, this.length);
686
+ const view = new DataView(this.buffer, this.byteOffset + offset, 4);
687
+ view.setFloat32(0, value, false);
688
+ return offset + 4;
689
+ }
690
+
691
+ writeFloatLE(value: number, offset = 0): number {
692
+ checkOffset(offset, 4, this.length);
693
+ const view = new DataView(this.buffer, this.byteOffset + offset, 4);
694
+ view.setFloat32(0, value, true);
695
+ return offset + 4;
696
+ }
697
+
698
+ writeDoubleBE(value: number, offset = 0): number {
699
+ checkOffset(offset, 8, this.length);
700
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
701
+ view.setFloat64(0, value, false);
702
+ return offset + 8;
703
+ }
704
+
705
+ writeDoubleLE(value: number, offset = 0): number {
706
+ checkOffset(offset, 8, this.length);
707
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
708
+ view.setFloat64(0, value, true);
709
+ return offset + 8;
710
+ }
711
+
712
+ writeBigInt64BE(value: bigint, offset = 0): number {
713
+ checkOffset(offset, 8, this.length);
714
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
715
+ view.setBigInt64(0, value, false);
716
+ return offset + 8;
717
+ }
718
+
719
+ writeBigInt64LE(value: bigint, offset = 0): number {
720
+ checkOffset(offset, 8, this.length);
721
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
722
+ view.setBigInt64(0, value, true);
723
+ return offset + 8;
724
+ }
725
+
726
+ writeBigUInt64BE(value: bigint, offset = 0): number {
727
+ checkOffset(offset, 8, this.length);
728
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
729
+ view.setBigUint64(0, value, false);
730
+ return offset + 8;
731
+ }
732
+
733
+ writeBigUInt64LE(value: bigint, offset = 0): number {
734
+ checkOffset(offset, 8, this.length);
735
+ const view = new DataView(this.buffer, this.byteOffset + offset, 8);
736
+ view.setBigUint64(0, value, true);
737
+ return offset + 8;
738
+ }
739
+
740
+ // ---- Swap methods ----
741
+
742
+ swap16(): this {
743
+ const len = this.length;
744
+ if (len % 2 !== 0) throw new RangeError('Buffer size must be a multiple of 16-bits');
745
+ for (let i = 0; i < len; i += 2) {
746
+ const a = this[i];
747
+ this[i] = this[i + 1];
748
+ this[i + 1] = a;
749
+ }
750
+ return this;
751
+ }
752
+
753
+ swap32(): this {
754
+ const len = this.length;
755
+ if (len % 4 !== 0) throw new RangeError('Buffer size must be a multiple of 32-bits');
756
+ for (let i = 0; i < len; i += 4) {
757
+ const a = this[i]; const b = this[i + 1];
758
+ this[i] = this[i + 3]; this[i + 1] = this[i + 2];
759
+ this[i + 2] = b; this[i + 3] = a;
760
+ }
761
+ return this;
762
+ }
763
+
764
+ swap64(): this {
765
+ const len = this.length;
766
+ if (len % 8 !== 0) throw new RangeError('Buffer size must be a multiple of 64-bits');
767
+ for (let i = 0; i < len; i += 8) {
768
+ const a = this[i]; const b = this[i + 1]; const c = this[i + 2]; const d = this[i + 3];
769
+ this[i] = this[i + 7]; this[i + 1] = this[i + 6]; this[i + 2] = this[i + 5]; this[i + 3] = this[i + 4];
770
+ this[i + 4] = d; this[i + 5] = c; this[i + 6] = b; this[i + 7] = a;
771
+ }
772
+ return this;
773
+ }
774
+ }
775
+
776
+ // Constants
777
+ export const kMaxLength = 2 ** 31 - 1;
778
+ export const kStringMaxLength = 2 ** 28 - 16;
779
+ export const constants = { MAX_LENGTH: kMaxLength, MAX_STRING_LENGTH: kStringMaxLength };
780
+
781
+ /** @deprecated Use Buffer.alloc() instead */
782
+ export class SlowBuffer extends Buffer {
783
+ constructor(size: number) {
784
+ super(size);
785
+ }
786
+ }