1pub const NODE_BUFFER_JS: &str = r#"
11// ─── Encoding helpers ────────────────────────────────────────────────────────
12
13function utf8Encode(str) {
14 return new TextEncoder().encode(str);
15}
16
17function utf8Decode(bytes, start, end) {
18 return new TextDecoder().decode(bytes.subarray(start, end));
19}
20
21function hexEncode(bytes) {
22 let out = '';
23 for (let i = 0; i < bytes.length; i++) {
24 out += bytes[i].toString(16).padStart(2, '0');
25 }
26 return out;
27}
28
29function hexDecode(str) {
30 const len = str.length >>> 1;
31 const bytes = new Uint8Array(len);
32 for (let i = 0; i < len; i++) {
33 bytes[i] = parseInt(str.slice(i * 2, i * 2 + 2), 16);
34 }
35 return bytes;
36}
37
38function base64Encode(bytes) {
39 let binary = '';
40 let chunk = [];
41 for (let i = 0; i < bytes.length; i++) {
42 chunk.push(bytes[i]);
43 if (chunk.length >= 4096) {
44 binary += String.fromCharCode.apply(null, chunk);
45 chunk.length = 0;
46 }
47 }
48 if (chunk.length > 0) {
49 binary += String.fromCharCode.apply(null, chunk);
50 }
51 return globalThis.btoa(binary);
52}
53
54function base64Decode(str) {
55 const binary = globalThis.atob(str);
56 const bytes = new Uint8Array(binary.length);
57 for (let i = 0; i < binary.length; i++) {
58 bytes[i] = binary.charCodeAt(i);
59 }
60 return bytes;
61}
62
63function latin1Encode(str) {
64 const bytes = new Uint8Array(str.length);
65 for (let i = 0; i < str.length; i++) {
66 bytes[i] = str.charCodeAt(i) & 0xFF;
67 }
68 return bytes;
69}
70
71function latin1Decode(bytes, start, end) {
72 let out = '';
73 let chunk = [];
74 const len = end - start;
75 for (let i = 0; i < len; i++) {
76 chunk.push(bytes[start + i]);
77 if (chunk.length >= 4096) {
78 out += String.fromCharCode.apply(null, chunk);
79 chunk.length = 0;
80 }
81 }
82 if (chunk.length > 0) {
83 out += String.fromCharCode.apply(null, chunk);
84 }
85 return out;
86}
87
88function normalizeEncoding(enc) {
89 if (!enc || enc === 'utf8' || enc === 'utf-8') return 'utf8';
90 const lower = enc.toLowerCase();
91 if (lower === 'utf8' || lower === 'utf-8') return 'utf8';
92 if (lower === 'hex') return 'hex';
93 if (lower === 'base64') return 'base64';
94 if (lower === 'ascii' || lower === 'binary' || lower === 'latin1') return 'latin1';
95 return 'utf8';
96}
97
98function encodeString(str, encoding) {
99 switch (normalizeEncoding(encoding)) {
100 case 'hex': return hexDecode(str);
101 case 'base64': return base64Decode(str);
102 case 'latin1': return latin1Encode(str);
103 default: return utf8Encode(str);
104 }
105}
106
107function decodeBytes(bytes, encoding, start, end) {
108 start = start || 0;
109 end = end != null ? end : bytes.length;
110 switch (normalizeEncoding(encoding)) {
111 case 'hex': return hexEncode(bytes.subarray(start, end));
112 case 'base64': return base64Encode(bytes.subarray(start, end));
113 case 'latin1': return latin1Decode(bytes, start, end);
114 default: return utf8Decode(bytes, start, end);
115 }
116}
117
118function normalizeSearchOffset(length, byteOffset) {
119 if (byteOffset == null) return 0;
120 const number = Number(byteOffset);
121 if (Number.isNaN(number)) return 0;
122 if (number === Infinity) return length;
123 if (number === -Infinity) return 0;
124 const offset = Math.trunc(number);
125 if (offset < 0) return Math.max(length + offset, 0);
126 if (offset > length) return length;
127 return offset;
128}
129
130// ─── Buffer class ────────────────────────────────────────────────────────────
131
132class Buffer extends Uint8Array {
133 // ── Static factory methods ─────────────────────────────────────────────
134 static from(input, encodingOrOffset, length) {
135 if (typeof input === 'string') {
136 const bytes = encodeString(input, encodingOrOffset);
137 const buf = new Buffer(bytes.length);
138 buf.set(bytes);
139 return buf;
140 }
141 if (input instanceof ArrayBuffer || input instanceof SharedArrayBuffer) {
142 const offset = encodingOrOffset || 0;
143 const len = length != null ? length : input.byteLength - offset;
144 return new Buffer(input, offset, len);
145 }
146 if (ArrayBuffer.isView(input)) {
147 const buf = new Buffer(input.length);
148 buf.set(input);
149 return buf;
150 }
151 if (Array.isArray(input)) {
152 const buf = new Buffer(input.length);
153 buf.set(input);
154 return buf;
155 }
156 if (input && typeof input === 'object' && typeof input.length === 'number') {
157 const buf = new Buffer(input.length);
158 for (let i = 0; i < input.length; i++) buf[i] = input[i] & 0xFF;
159 return buf;
160 }
161 throw new TypeError('The first argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.');
162 }
163
164 static alloc(size, fill, encoding) {
165 const buf = new Buffer(size);
166 if (fill !== undefined && fill !== 0) {
167 buf.fill(fill, 0, size, encoding);
168 }
169 return buf;
170 }
171
172 static allocUnsafe(size) {
173 return new Buffer(size);
174 }
175
176 static allocUnsafeSlow(size) {
177 return new Buffer(size);
178 }
179
180 static isBuffer(obj) {
181 return obj instanceof Buffer;
182 }
183
184 static isEncoding(encoding) {
185 return ['utf8', 'utf-8', 'hex', 'base64', 'ascii', 'binary', 'latin1']
186 .includes((encoding || '').toLowerCase());
187 }
188
189 static byteLength(string, encoding) {
190 if (typeof string !== 'string') {
191 if (ArrayBuffer.isView(string)) return string.byteLength;
192 if (string instanceof ArrayBuffer) return string.byteLength;
193 throw new TypeError('The "string" argument must be a string, Buffer, or ArrayBuffer');
194 }
195 return encodeString(string, encoding).length;
196 }
197
198 static concat(list, totalLength) {
199 if (!Array.isArray(list)) throw new TypeError('"list" argument must be an Array of Buffers');
200 if (list.length === 0) return Buffer.alloc(0);
201 const total = totalLength != null
202 ? totalLength
203 : list.reduce((acc, b) => acc + b.length, 0);
204 const result = Buffer.alloc(total);
205 let offset = 0;
206 for (const buf of list) {
207 const src = buf instanceof Uint8Array ? buf : Buffer.from(buf);
208 const copyLen = Math.min(src.length, total - offset);
209 result.set(src.subarray(0, copyLen), offset);
210 offset += copyLen;
211 if (offset >= total) break;
212 }
213 return result;
214 }
215
216 static compare(a, b) {
217 if (!(a instanceof Uint8Array) || !(b instanceof Uint8Array)) {
218 throw new TypeError('Arguments must be Buffers');
219 }
220 const len = Math.min(a.length, b.length);
221 for (let i = 0; i < len; i++) {
222 if (a[i] < b[i]) return -1;
223 if (a[i] > b[i]) return 1;
224 }
225 if (a.length < b.length) return -1;
226 if (a.length > b.length) return 1;
227 return 0;
228 }
229
230 // ── Instance methods ───────────────────────────────────────────────────
231 toString(encoding, start, end) {
232 return decodeBytes(this, encoding, start, end);
233 }
234
235 write(string, offset, length, encoding) {
236 if (typeof offset === 'string') { encoding = offset; offset = 0; length = this.length; }
237 else if (typeof length === 'string') { encoding = length; length = this.length - (offset || 0); }
238 offset = offset || 0;
239 length = length != null ? length : this.length - offset;
240 const bytes = encodeString(string, encoding);
241 const writeLen = Math.min(bytes.length, length, this.length - offset);
242 this.set(bytes.subarray(0, writeLen), offset);
243 return writeLen;
244 }
245
246 toJSON() {
247 return { type: 'Buffer', data: Array.from(this) };
248 }
249
250 equals(other) {
251 if (!(other instanceof Uint8Array)) throw new TypeError('Argument must be a Buffer');
252 return Buffer.compare(this, other) === 0;
253 }
254
255 compare(other, targetStart, targetEnd, sourceStart, sourceEnd) {
256 if (!(other instanceof Uint8Array)) throw new TypeError('Argument must be a Buffer');
257 targetStart = targetStart || 0;
258 targetEnd = targetEnd != null ? targetEnd : other.length;
259 sourceStart = sourceStart || 0;
260 sourceEnd = sourceEnd != null ? sourceEnd : this.length;
261 return Buffer.compare(
262 this.subarray(sourceStart, sourceEnd),
263 other.subarray(targetStart, targetEnd)
264 );
265 }
266
267 copy(target, targetStart, sourceStart, sourceEnd) {
268 targetStart = targetStart || 0;
269 sourceStart = sourceStart || 0;
270 sourceEnd = sourceEnd != null ? sourceEnd : this.length;
271 const len = Math.min(sourceEnd - sourceStart, target.length - targetStart);
272 target.set(this.subarray(sourceStart, sourceStart + len), targetStart);
273 return len;
274 }
275
276 indexOf(value, byteOffset, encoding) {
277 let offset = normalizeSearchOffset(this.length, byteOffset);
278 let searchEncoding = encoding;
279 if (typeof byteOffset === 'string') {
280 offset = 0;
281 searchEncoding = byteOffset;
282 }
283 if (typeof value === 'number') {
284 for (let i = offset; i < this.length; i++) {
285 if (this[i] === (value & 0xFF)) return i;
286 }
287 return -1;
288 }
289 if (typeof value === 'string') {
290 value = Buffer.from(value, searchEncoding);
291 }
292 if (value instanceof Uint8Array) {
293 if (value.length === 0) return offset;
294 outer: for (let i = offset; i <= this.length - value.length; i++) {
295 for (let j = 0; j < value.length; j++) {
296 if (this[i + j] !== value[j]) continue outer;
297 }
298 return i;
299 }
300 }
301 return -1;
302 }
303
304 includes(value, byteOffset, encoding) {
305 return this.indexOf(value, byteOffset, encoding) !== -1;
306 }
307
308 fill(value, offset, end, encoding) {
309 offset = offset || 0;
310 end = end != null ? end : this.length;
311 if (typeof value === 'number') {
312 for (let i = offset; i < end; i++) this[i] = value & 0xFF;
313 } else if (typeof value === 'string') {
314 const bytes = encodeString(value, encoding);
315 if (bytes.length === 0) return this;
316 for (let i = offset; i < end; i++) {
317 this[i] = bytes[(i - offset) % bytes.length];
318 }
319 } else if (value instanceof Uint8Array) {
320 if (value.length === 0) return this;
321 for (let i = offset; i < end; i++) {
322 this[i] = value[(i - offset) % value.length];
323 }
324 }
325 return this;
326 }
327
328 slice(start, end) {
329 return this.subarray(start, end);
330 }
331
332 subarray(start, end) {
333 // Override to return a Buffer, not a plain Uint8Array
334 const sub = super.subarray(start, end);
335 Object.setPrototypeOf(sub, Buffer.prototype);
336 return sub;
337 }
338
339 swap16() {
340 if (this.length % 2 !== 0) throw new RangeError('Buffer size must be a multiple of 16-bits');
341 for (let i = 0; i < this.length; i += 2) {
342 const t = this[i]; this[i] = this[i + 1]; this[i + 1] = t;
343 }
344 return this;
345 }
346
347 swap32() {
348 if (this.length % 4 !== 0) throw new RangeError('Buffer size must be a multiple of 32-bits');
349 for (let i = 0; i < this.length; i += 4) {
350 const t0 = this[i], t1 = this[i + 1];
351 this[i] = this[i + 3]; this[i + 1] = this[i + 2];
352 this[i + 2] = t1; this[i + 3] = t0;
353 }
354 return this;
355 }
356
357 // Read/write integers (LE/BE) — commonly used by extensions
358 readUInt8(offset) {
359 offset = offset >>> 0;
360 if (offset >= this.length) throw new RangeError('Index out of range');
361 return this[offset];
362 }
363
364 readUInt16LE(offset) {
365 offset = offset >>> 0;
366 if (offset + 2 > this.length) throw new RangeError('Index out of range');
367 return this[offset] | (this[offset + 1] << 8);
368 }
369
370 readUInt16BE(offset) {
371 offset = offset >>> 0;
372 if (offset + 2 > this.length) throw new RangeError('Index out of range');
373 return (this[offset] << 8) | this[offset + 1];
374 }
375
376 readUInt32LE(offset) {
377 offset = offset >>> 0;
378 if (offset + 4 > this.length) throw new RangeError('Index out of range');
379 return (this[offset] | (this[offset+1] << 8) | (this[offset+2] << 16)) + (this[offset+3] * 0x1000000);
380 }
381
382 readUInt32BE(offset) {
383 offset = offset >>> 0;
384 if (offset + 4 > this.length) throw new RangeError('Index out of range');
385 return (this[offset] * 0x1000000) + ((this[offset+1] << 16) | (this[offset+2] << 8) | this[offset+3]);
386 }
387
388 readInt8(offset) {
389 offset = offset >>> 0;
390 if (offset >= this.length) throw new RangeError('Index out of range');
391 const v = this[offset];
392 return v > 127 ? v - 256 : v;
393 }
394
395 readInt16LE(offset) {
396 offset = offset >>> 0;
397 if (offset + 2 > this.length) throw new RangeError('Index out of range');
398 const v = this[offset] | (this[offset + 1] << 8);
399 return v > 32767 ? v - 65536 : v;
400 }
401
402 readInt16BE(offset) {
403 offset = offset >>> 0;
404 if (offset + 2 > this.length) throw new RangeError('Index out of range');
405 const v = (this[offset] << 8) | this[offset + 1];
406 return v > 32767 ? v - 65536 : v;
407 }
408
409 readInt32LE(offset) {
410 offset = offset >>> 0;
411 if (offset + 4 > this.length) throw new RangeError('Index out of range');
412 return this[offset] | (this[offset+1] << 8) | (this[offset+2] << 16) | (this[offset+3] << 24);
413 }
414
415 readInt32BE(offset) {
416 offset = offset >>> 0;
417 if (offset + 4 > this.length) throw new RangeError('Index out of range');
418 return (this[offset] << 24) | (this[offset+1] << 16) | (this[offset+2] << 8) | this[offset+3];
419 }
420
421 writeUInt8(value, offset) {
422 offset = offset >>> 0;
423 if (offset >= this.length) throw new RangeError('Index out of range');
424 this[offset] = value & 0xFF;
425 return offset + 1;
426 }
427
428 writeInt8(value, offset) {
429 return this.writeUInt8(value, offset);
430 }
431
432 writeUInt16LE(value, offset) {
433 offset = offset >>> 0;
434 if (offset + 2 > this.length) throw new RangeError('Index out of range');
435 this[offset] = value & 0xFF;
436 this[offset + 1] = (value >>> 8) & 0xFF;
437 return offset + 2;
438 }
439
440 writeInt16LE(value, offset) {
441 return this.writeUInt16LE(value, offset);
442 }
443
444 writeUInt16BE(value, offset) {
445 offset = offset >>> 0;
446 if (offset + 2 > this.length) throw new RangeError('Index out of range');
447 this[offset] = (value >>> 8) & 0xFF;
448 this[offset + 1] = value & 0xFF;
449 return offset + 2;
450 }
451
452 writeInt16BE(value, offset) {
453 return this.writeUInt16BE(value, offset);
454 }
455
456 writeUInt32LE(value, offset) {
457 offset = offset >>> 0;
458 if (offset + 4 > this.length) throw new RangeError('Index out of range');
459 this[offset] = value & 0xFF;
460 this[offset+1] = (value >>> 8) & 0xFF;
461 this[offset+2] = (value >>> 16) & 0xFF;
462 this[offset+3] = (value >>> 24) & 0xFF;
463 return offset + 4;
464 }
465
466 writeInt32LE(value, offset) {
467 return this.writeUInt32LE(value, offset);
468 }
469
470 writeUInt32BE(value, offset) {
471 offset = offset >>> 0;
472 if (offset + 4 > this.length) throw new RangeError('Index out of range');
473 this[offset] = (value >>> 24) & 0xFF;
474 this[offset+1] = (value >>> 16) & 0xFF;
475 this[offset+2] = (value >>> 8) & 0xFF;
476 this[offset+3] = value & 0xFF;
477 return offset + 4;
478 }
479
480 writeInt32BE(value, offset) {
481 return this.writeUInt32BE(value, offset);
482 }
483}
484
485// Make Buffer available globally (Node.js compatibility)
486globalThis.Buffer = Buffer;
487
488export { Buffer };
489export default { Buffer };
490"#;