react-native-nitro-buffer 0.0.1

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.
Files changed (31) hide show
  1. package/README.md +129 -0
  2. package/cpp/HybridNitroBuffer.cpp +497 -0
  3. package/cpp/HybridNitroBuffer.hpp +44 -0
  4. package/lib/Buffer.d.ts +79 -0
  5. package/lib/Buffer.js +642 -0
  6. package/lib/NitroBuffer.nitro.d.ts +18 -0
  7. package/lib/NitroBuffer.nitro.js +2 -0
  8. package/lib/index.d.ts +12 -0
  9. package/lib/index.js +34 -0
  10. package/lib/utils.d.ts +7 -0
  11. package/lib/utils.js +90 -0
  12. package/nitrogen/generated/.gitattributes +1 -0
  13. package/nitrogen/generated/android/NitroBuffer+autolinking.cmake +81 -0
  14. package/nitrogen/generated/android/NitroBuffer+autolinking.gradle +27 -0
  15. package/nitrogen/generated/android/NitroBufferOnLoad.cpp +44 -0
  16. package/nitrogen/generated/android/NitroBufferOnLoad.hpp +25 -0
  17. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitro_buffer/NitroBufferOnLoad.kt +35 -0
  18. package/nitrogen/generated/ios/NitroBuffer+autolinking.rb +60 -0
  19. package/nitrogen/generated/ios/NitroBuffer-Swift-Cxx-Bridge.cpp +17 -0
  20. package/nitrogen/generated/ios/NitroBuffer-Swift-Cxx-Bridge.hpp +27 -0
  21. package/nitrogen/generated/ios/NitroBuffer-Swift-Cxx-Umbrella.hpp +38 -0
  22. package/nitrogen/generated/ios/NitroBufferAutolinking.mm +35 -0
  23. package/nitrogen/generated/ios/NitroBufferAutolinking.swift +12 -0
  24. package/nitrogen/generated/shared/c++/HybridNitroBufferSpec.cpp +32 -0
  25. package/nitrogen/generated/shared/c++/HybridNitroBufferSpec.hpp +74 -0
  26. package/package.json +55 -0
  27. package/react-native-nitro-buffer.podspec +40 -0
  28. package/src/Buffer.ts +675 -0
  29. package/src/NitroBuffer.nitro.ts +19 -0
  30. package/src/index.ts +18 -0
  31. package/src/utils.ts +76 -0
package/src/Buffer.ts ADDED
@@ -0,0 +1,675 @@
1
+ import { NitroModules } from 'react-native-nitro-modules'
2
+ import type { NitroBuffer } from './NitroBuffer.nitro'
3
+
4
+ // Lazily load the native module
5
+ let _native: NitroBuffer | undefined
6
+
7
+ function getNative(): NitroBuffer {
8
+ if (!_native) {
9
+ _native = NitroModules.createHybridObject<NitroBuffer>('NitroBuffer')
10
+ }
11
+ return _native
12
+ }
13
+
14
+ export class Buffer extends Uint8Array {
15
+ constructor(length: number)
16
+ constructor(array: Uint8Array)
17
+ constructor(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number)
18
+ constructor(string: string, encoding?: string)
19
+ constructor(arg: any, encodingOrOffset?: any, length?: any) {
20
+ // Handling different constructor arguments roughly
21
+ if (typeof arg === 'number') {
22
+ super(arg)
23
+ } else if (typeof arg === 'string') {
24
+ const encoding = encodingOrOffset || 'utf8'
25
+ const len = getNative().byteLength(arg, encoding)
26
+ super(len)
27
+ getNative().write(this.buffer as ArrayBuffer, arg, 0, len, encoding)
28
+ } else if (arg instanceof Uint8Array) {
29
+ super(arg)
30
+ } else if (arg instanceof ArrayBuffer) {
31
+ super(arg, encodingOrOffset, length)
32
+ } else if (Object.prototype.toString.call(arg) === '[object ArrayBuffer]') {
33
+ super(arg, encodingOrOffset, length)
34
+ } else if (typeof arg === 'object' && arg !== null && arg.type === 'Buffer' && Array.isArray(arg.data)) {
35
+ // Buffer.from({ type: 'Buffer', data: [...] })
36
+ super(arg.data)
37
+ } else {
38
+ super(arg)
39
+ }
40
+ }
41
+
42
+ get parent(): ArrayBuffer {
43
+ return this.buffer as ArrayBuffer
44
+ }
45
+
46
+ static from(value: any, encodingOrOffset?: any, length?: any): Buffer {
47
+ if (typeof value === 'string') {
48
+ return new Buffer(value, encodingOrOffset)
49
+ }
50
+ if (value instanceof Uint8Array) {
51
+ // Copy
52
+ const buf = new Buffer(value.length)
53
+ buf.set(value)
54
+ return buf
55
+ }
56
+ if (value instanceof ArrayBuffer) {
57
+ return new Buffer(value, encodingOrOffset, length)
58
+ }
59
+ if (Array.isArray(value)) {
60
+ return new Buffer(new Uint8Array(value).buffer)
61
+ }
62
+ throw new TypeError('Unsupported type for Buffer.from')
63
+ }
64
+
65
+ static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer {
66
+ // Fast path: use Uint8Array directly to avoid Buffer constructor overhead
67
+ const buf = new Uint8Array(size) as unknown as Buffer
68
+ Object.setPrototypeOf(buf, Buffer.prototype)
69
+
70
+ if (fill !== undefined) {
71
+ buf.fill(fill, encoding)
72
+ }
73
+ return buf
74
+ }
75
+
76
+ static allocUnsafe(size: number): Buffer {
77
+ // In JS, memory is always zeroed for security, so allocUnsafe is same as alloc usually.
78
+ // Unless we recycled buffers (not implemented).
79
+ // Using native allocUnsafe might give uninitialized memory, but bridge overhead (~0.05ms)
80
+ // might outweight the zeroing cost (~0.02ms).
81
+ // So we stick to JS native alloc for now.
82
+ const buf = new Uint8Array(size) as unknown as Buffer
83
+ Object.setPrototypeOf(buf, Buffer.prototype)
84
+ return buf
85
+ }
86
+
87
+ static allocUnsafeSlow(size: number): Buffer {
88
+ return Buffer.allocUnsafe(size)
89
+ }
90
+
91
+ static byteLength(string: string, encoding: string = 'utf8'): number {
92
+ return getNative().byteLength(string, encoding)
93
+ }
94
+
95
+ static isBuffer(obj: any): obj is Buffer {
96
+ return obj instanceof Buffer
97
+ }
98
+
99
+ static compare(buf1: Uint8Array, buf2: Uint8Array): number {
100
+ return getNative().compare(buf1.buffer as ArrayBuffer, buf1.byteOffset, buf1.byteLength, buf2.buffer as ArrayBuffer, buf2.byteOffset, buf2.byteLength)
101
+ }
102
+
103
+ static copyBytesFrom(view: ArrayBufferView, offset?: number, length?: number): Buffer {
104
+ if (offset === undefined) offset = 0
105
+ if (length === undefined) length = view.byteLength - offset
106
+ if (offset < 0 || length < 0 || offset + length > view.byteLength) {
107
+ throw new RangeError('offset or length out of bounds')
108
+ }
109
+ const buf = Buffer.allocUnsafe(length)
110
+ const src = new Uint8Array(view.buffer, view.byteOffset + offset, length)
111
+ buf.set(src)
112
+ return buf
113
+ }
114
+
115
+ static concat(list: Uint8Array[], totalLength?: number): Buffer {
116
+ if (totalLength === undefined) {
117
+ totalLength = list.reduce((acc, curr) => acc + curr.length, 0)
118
+ }
119
+ const buf = Buffer.allocUnsafe(totalLength!)
120
+ let offset = 0
121
+ for (const item of list) {
122
+ buf.set(item, offset)
123
+ offset += item.length
124
+ }
125
+ return buf
126
+ }
127
+
128
+ write(string: string, offset?: number, length?: number, encoding?: string): number {
129
+ // Argument handling
130
+ if (offset === undefined) {
131
+ offset = 0
132
+ length = this.length
133
+ encoding = 'utf8'
134
+ } else if (length === undefined && typeof offset === 'string') {
135
+ encoding = offset
136
+ offset = 0
137
+ length = this.length
138
+ } else if (length === undefined) {
139
+ length = this.length - offset
140
+ encoding = 'utf8'
141
+ } else if (encoding === undefined) {
142
+ encoding = 'utf8'
143
+ }
144
+
145
+ return getNative().write(this.buffer as ArrayBuffer, string, this.byteOffset + (offset as number), length as number, encoding as string)
146
+ }
147
+
148
+ toString(encoding?: string, start?: number, end?: number): string {
149
+ if (encoding === undefined) encoding = 'utf8'
150
+ if (start === undefined) start = 0
151
+ if (end === undefined) end = this.length
152
+
153
+ if (start < 0) start = 0
154
+ if (end > this.length) end = this.length
155
+ if (start >= end) return ''
156
+
157
+ return getNative().decode(this.buffer as ArrayBuffer, this.byteOffset + start, end - start, encoding)
158
+ }
159
+
160
+ indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: string): number {
161
+ if (typeof value === 'string') {
162
+ const needle = Buffer.from(value, encoding)
163
+ return getNative().indexOfBuffer(this.buffer as ArrayBuffer, needle.buffer as ArrayBuffer, byteOffset || 0, this.length)
164
+ }
165
+ if (value instanceof Uint8Array) {
166
+ return getNative().indexOfBuffer(this.buffer as ArrayBuffer, value.buffer as ArrayBuffer, byteOffset || 0, this.length)
167
+ }
168
+ if (typeof value === 'number') {
169
+ return getNative().indexOf(this.buffer as ArrayBuffer, value, byteOffset || 0, this.length)
170
+ }
171
+ throw new TypeError('"value" argument must be string, number or Buffer')
172
+ }
173
+
174
+ lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: string): number {
175
+ // Node.js defaults byteOffset to buf.length - 1
176
+ // If byteOffset is provided, it is the index to start searching backwards from.
177
+ // We implement this by defining a window [0, limit] where limit is calculated.
178
+
179
+ if (byteOffset === undefined || byteOffset > this.length) {
180
+ byteOffset = this.length
181
+ }
182
+
183
+ if (typeof value === 'string') {
184
+ const needle = Buffer.from(value, encoding)
185
+ if (needle.length === 0) return -1
186
+ // We search in [0, byteOffset + needle.length].
187
+ // The match must start at <= byteOffset.
188
+ // So the match must be fully contained in [0, byteOffset + needle.length].
189
+ return getNative().lastIndexOfBuffer(this.buffer as ArrayBuffer, needle.buffer as ArrayBuffer, 0, byteOffset + needle.length)
190
+ }
191
+ if (value instanceof Uint8Array) {
192
+ if (value.length === 0) return -1
193
+ return getNative().lastIndexOfBuffer(this.buffer as ArrayBuffer, value.buffer as ArrayBuffer, 0, byteOffset + value.length)
194
+ }
195
+ if (typeof value === 'number') {
196
+ // Search in [0, byteOffset + 1]. The last byte checked is at byteOffset.
197
+ return getNative().lastIndexOfByte(this.buffer as ArrayBuffer, value, 0, byteOffset + 1)
198
+ }
199
+ throw new TypeError('"value" argument must be string, number or Buffer')
200
+ }
201
+
202
+ includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean {
203
+ return this.indexOf(value, byteOffset, encoding) !== -1
204
+ }
205
+
206
+ fill(value: string | Buffer | number | Uint8Array, offset?: any, end?: any, encoding?: string): this {
207
+ // Handle argument shifting
208
+ if (typeof offset === 'string') {
209
+ encoding = offset
210
+ offset = 0
211
+ end = this.length
212
+ } else if (typeof end === 'string') {
213
+ encoding = end
214
+ end = this.length
215
+ }
216
+
217
+ if (offset === undefined) offset = 0
218
+ if (end === undefined) end = this.length
219
+
220
+ const len = end - offset
221
+ if (len <= 0) return this
222
+
223
+ if (typeof value === 'number') {
224
+ getNative().fill(this.buffer as ArrayBuffer, value, this.byteOffset + offset, len)
225
+ return this
226
+ }
227
+
228
+ let valBuf: Uint8Array
229
+ if (typeof value === 'string') {
230
+ valBuf = Buffer.from(value, encoding)
231
+ } else if (value instanceof Uint8Array) {
232
+ valBuf = value
233
+ } else {
234
+ throw new TypeError('"value" argument must be string, number or Buffer')
235
+ }
236
+
237
+ if (valBuf.length === 0) return this
238
+
239
+ // Native fillBuffer takes ArrayBuffer, assumes generic fill logic
240
+ getNative().fillBuffer(this.buffer as ArrayBuffer, valBuf.buffer as ArrayBuffer, this.byteOffset + offset, len)
241
+ return this
242
+ }
243
+
244
+ compare(target: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number {
245
+ if (targetStart === undefined) targetStart = 0
246
+ if (targetEnd === undefined) targetEnd = target.length
247
+ if (sourceStart === undefined) sourceStart = 0
248
+ if (sourceEnd === undefined) sourceEnd = this.length
249
+
250
+ return getNative().compare(
251
+ this.buffer as ArrayBuffer, this.byteOffset + sourceStart, sourceEnd - sourceStart,
252
+ target.buffer as ArrayBuffer, target.byteOffset + targetStart, targetEnd - targetStart
253
+ )
254
+ }
255
+
256
+ slice(start?: number, end?: number): Buffer {
257
+ // Uint8Array.prototype.slice returns a copy (new buffer).
258
+ // Buffer.prototype.slice (legacy) returned a view.
259
+ // Buffer.prototype.subarray returns a view.
260
+ // In Node.js Buffer.slice is deprecated and acts like subarray? No, Buffer.slice returns a view (unlike Uint8Array.slice which returns copy).
261
+ // Wait, Node Buffer.slice returns a NEW Buffer that references the SAME memory.
262
+ // But Uint8Array.prototype.slice returns a COPY.
263
+ // So we should override slice to return a view (subarray behavior) but wrapped in Buffer?
264
+ // Actually Node documentation says: "The Buffer.prototype.slice() method is deprecated... use subarray() instead."
265
+ // BUT for compatibility, often libs expect slice to duplicate memory? No, Buffer.slice(start, end) shares memory.
266
+ // Uint8Array.prototype.slice(start, end) copies memory.
267
+ // So we should override slice to be compatible with Node behavior (view), OR standard Uint8Array behavior (copy).
268
+ // Node's `slice` shares memory. `Uint8Array`'s `slice` copies. This is a conflict.
269
+ // Let's implement `subarray` which returns a Buffer view.
270
+
271
+ const sub = this.subarray(start, end)
272
+ // sub is Uint8Array. We need to cast it to Buffer.
273
+ // We can use Object.setPrototypeOf or just new Buffer via constructor that takes Uint8Array
274
+ // but that constructor usually copies?
275
+ // `new Buffer(uint8Array)` copies.
276
+ // We need `new Buffer(arrayBuffer, byteOffset, length)`.
277
+ return new Buffer(sub.buffer as ArrayBuffer, sub.byteOffset, sub.byteLength)
278
+ }
279
+
280
+ subarray(begin?: number, end?: number): Buffer {
281
+ const sub = super.subarray(begin, end)
282
+ // Ensure we return a Buffer, not just a Uint8Array
283
+ if (sub instanceof Buffer) return sub
284
+
285
+ // Wrap the Uint8Array's memory view into a new Buffer
286
+ // Note: new Buffer(arrayBuffer, byteOffset, length) creates a view
287
+ return new Buffer(sub.buffer as ArrayBuffer, sub.byteOffset, sub.byteLength)
288
+ }
289
+ // ================== Read Methods ==================
290
+
291
+ readInt8(offset: number = 0): number {
292
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt8(offset)
293
+ }
294
+
295
+ readUInt8(offset: number = 0): number {
296
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint8(offset)
297
+ }
298
+
299
+ readInt16LE(offset: number = 0): number {
300
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(offset, true)
301
+ }
302
+
303
+ readInt16BE(offset: number = 0): number {
304
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt16(offset, false)
305
+ }
306
+
307
+ readUInt16LE(offset: number = 0): number {
308
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint16(offset, true)
309
+ }
310
+
311
+ readUInt16BE(offset: number = 0): number {
312
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint16(offset, false)
313
+ }
314
+
315
+ readInt32LE(offset: number = 0): number {
316
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(offset, true)
317
+ }
318
+
319
+ readInt32BE(offset: number = 0): number {
320
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getInt32(offset, false)
321
+ }
322
+
323
+ readUInt32LE(offset: number = 0): number {
324
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint32(offset, true)
325
+ }
326
+
327
+ readUInt32BE(offset: number = 0): number {
328
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getUint32(offset, false)
329
+ }
330
+
331
+ readBigInt64LE(offset: number = 0): bigint {
332
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getBigInt64(offset, true)
333
+ }
334
+
335
+ readBigInt64BE(offset: number = 0): bigint {
336
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getBigInt64(offset, false)
337
+ }
338
+
339
+ readBigUInt64LE(offset: number = 0): bigint {
340
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getBigUint64(offset, true)
341
+ }
342
+
343
+ readBigUInt64BE(offset: number = 0): bigint {
344
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getBigUint64(offset, false)
345
+ }
346
+
347
+ readFloatLE(offset: number = 0): number {
348
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getFloat32(offset, true)
349
+ }
350
+
351
+ readFloatBE(offset: number = 0): number {
352
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getFloat32(offset, false)
353
+ }
354
+
355
+ readDoubleLE(offset: number = 0): number {
356
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getFloat64(offset, true)
357
+ }
358
+
359
+ readDoubleBE(offset: number = 0): number {
360
+ return new DataView(this.buffer, this.byteOffset, this.byteLength).getFloat64(offset, false)
361
+ }
362
+
363
+ readIntLE(offset: number, byteLength: number): number {
364
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
365
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
366
+
367
+ offset = offset >>> 0
368
+ byteLength = byteLength >>> 0
369
+
370
+ let val = this[offset]
371
+ let mul = 1
372
+ let i = 0
373
+ while (++i < byteLength && (mul *= 0x100)) {
374
+ val += this[offset + i] * mul
375
+ }
376
+ mul *= 0x80
377
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
378
+ return val
379
+ }
380
+
381
+ readIntBE(offset: number, byteLength: number): number {
382
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
383
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
384
+
385
+ offset = offset >>> 0
386
+ byteLength = byteLength >>> 0
387
+
388
+ let i = byteLength
389
+ let mul = 1
390
+ let val = this[offset + --i]
391
+ while (i > 0 && (mul *= 0x100)) {
392
+ val += this[offset + --i] * mul
393
+ }
394
+ mul *= 0x80
395
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
396
+ return val
397
+ }
398
+
399
+ readUIntLE(offset: number, byteLength: number): number {
400
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
401
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
402
+
403
+ offset = offset >>> 0
404
+ byteLength = byteLength >>> 0
405
+
406
+ let val = this[offset]
407
+ let mul = 1
408
+ let i = 0
409
+ while (++i < byteLength && (mul *= 0x100)) {
410
+ val += this[offset + i] * mul
411
+ }
412
+ return val
413
+ }
414
+
415
+ readUIntBE(offset: number, byteLength: number): number {
416
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
417
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
418
+
419
+ offset = offset >>> 0
420
+ byteLength = byteLength >>> 0
421
+
422
+ let i = byteLength
423
+ let mul = 1
424
+ let val = this[offset + --i]
425
+ while (i > 0 && (mul *= 0x100)) {
426
+ val += this[offset + --i] * mul
427
+ }
428
+ return val
429
+ }
430
+ // ================== Write Methods ==================
431
+
432
+ writeInt8(value: number, offset: number = 0): number {
433
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setInt8(offset, value)
434
+ return offset + 1
435
+ }
436
+
437
+ writeUInt8(value: number, offset: number = 0): number {
438
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setUint8(offset, value)
439
+ return offset + 1
440
+ }
441
+
442
+ writeInt16LE(value: number, offset: number = 0): number {
443
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(offset, value, true)
444
+ return offset + 2
445
+ }
446
+
447
+ writeInt16BE(value: number, offset: number = 0): number {
448
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setInt16(offset, value, false)
449
+ return offset + 2
450
+ }
451
+
452
+ writeUInt16LE(value: number, offset: number = 0): number {
453
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(offset, value, true)
454
+ return offset + 2
455
+ }
456
+
457
+ writeUInt16BE(value: number, offset: number = 0): number {
458
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setUint16(offset, value, false)
459
+ return offset + 2
460
+ }
461
+
462
+ writeInt32LE(value: number, offset: number = 0): number {
463
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setInt32(offset, value, true)
464
+ return offset + 4
465
+ }
466
+
467
+ writeInt32BE(value: number, offset: number = 0): number {
468
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setInt32(offset, value, false)
469
+ return offset + 4
470
+ }
471
+
472
+ writeUInt32LE(value: number, offset: number = 0): number {
473
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(offset, value, true)
474
+ return offset + 4
475
+ }
476
+
477
+ writeUInt32BE(value: number, offset: number = 0): number {
478
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setUint32(offset, value, false)
479
+ return offset + 4
480
+ }
481
+
482
+ writeBigInt64LE(value: bigint, offset: number = 0): number {
483
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(offset, value, true)
484
+ return offset + 8
485
+ }
486
+
487
+ writeBigInt64BE(value: bigint, offset: number = 0): number {
488
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setBigInt64(offset, value, false)
489
+ return offset + 8
490
+ }
491
+
492
+ writeBigUInt64LE(value: bigint, offset: number = 0): number {
493
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(offset, value, true)
494
+ return offset + 8
495
+ }
496
+
497
+ writeBigUInt64BE(value: bigint, offset: number = 0): number {
498
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setBigUint64(offset, value, false)
499
+ return offset + 8
500
+ }
501
+
502
+ writeFloatLE(value: number, offset: number = 0): number {
503
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(offset, value, true)
504
+ return offset + 4
505
+ }
506
+
507
+ writeFloatBE(value: number, offset: number = 0): number {
508
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat32(offset, value, false)
509
+ return offset + 4
510
+ }
511
+
512
+ writeDoubleLE(value: number, offset: number = 0): number {
513
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(offset, value, true)
514
+ return offset + 8
515
+ }
516
+
517
+ writeDoubleBE(value: number, offset: number = 0): number {
518
+ new DataView(this.buffer, this.byteOffset, this.byteLength).setFloat64(offset, value, false)
519
+ return offset + 8
520
+ }
521
+
522
+ writeIntLE(value: number, offset: number, byteLength: number): number {
523
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
524
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
525
+
526
+ offset = offset >>> 0
527
+ byteLength = byteLength >>> 0
528
+
529
+ let i = 0
530
+ let mul = 1
531
+ let sub = 0
532
+ this[offset] = value & 0xFF
533
+ while (++i < byteLength && (mul *= 0x100)) {
534
+ if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
535
+ sub = 1
536
+ }
537
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
538
+ }
539
+ return offset + byteLength
540
+ }
541
+
542
+ writeIntBE(value: number, offset: number, byteLength: number): number {
543
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
544
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
545
+
546
+ offset = offset >>> 0
547
+ byteLength = byteLength >>> 0
548
+
549
+ let i = byteLength - 1
550
+ let mul = 1
551
+ let sub = 0
552
+ this[offset + i] = value & 0xFF
553
+ while (--i >= 0 && (mul *= 0x100)) {
554
+ if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
555
+ sub = 1
556
+ }
557
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
558
+ }
559
+ return offset + byteLength
560
+ }
561
+
562
+ writeUIntLE(value: number, offset: number, byteLength: number): number {
563
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
564
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
565
+
566
+ offset = offset >>> 0
567
+ byteLength = byteLength >>> 0
568
+
569
+ let i = 0
570
+ let mul = 1
571
+ this[offset] = value & 0xFF
572
+ while (++i < byteLength && (mul *= 0x100)) {
573
+ this[offset + i] = (value / mul) & 0xFF
574
+ }
575
+ return offset + byteLength
576
+ }
577
+
578
+ writeUIntBE(value: number, offset: number, byteLength: number): number {
579
+ if (offset === undefined) throw new TypeError('"offset" is invalid')
580
+ if (byteLength > 6 || byteLength < 0) throw new RangeError('"byteLength" out of range')
581
+
582
+ offset = offset >>> 0
583
+ byteLength = byteLength >>> 0
584
+
585
+ let i = byteLength - 1
586
+ let mul = 1
587
+ this[offset + i] = value & 0xFF
588
+ while (--i >= 0 && (mul *= 0x100)) {
589
+ this[offset + i] = (value / mul) & 0xFF
590
+ }
591
+ return offset + byteLength
592
+ }
593
+ // ================== Utils ==================
594
+ toJSON(): { type: 'Buffer', data: number[] } {
595
+ return {
596
+ type: 'Buffer',
597
+ data: Array.from(this)
598
+ }
599
+ }
600
+
601
+ static poolSize: number = 8192
602
+
603
+ static isEncoding(encoding: string): boolean {
604
+ switch (encoding.toLowerCase()) {
605
+ case 'utf8':
606
+ case 'utf-8':
607
+ case 'hex':
608
+ case 'base64':
609
+ case 'binary':
610
+ case 'latin1':
611
+ case 'ascii':
612
+ case 'utf16le':
613
+ case 'ucs2':
614
+ return true
615
+ default:
616
+ return false
617
+ }
618
+ }
619
+
620
+ swap16(): Buffer {
621
+ const len = this.length
622
+ if (len % 2 !== 0) throw new RangeError('Buffer size must be a multiple of 16-bits')
623
+ for (let i = 0; i < len; i += 2) {
624
+ const v = this[i]
625
+ this[i] = this[i + 1]
626
+ this[i + 1] = v
627
+ }
628
+ return this
629
+ }
630
+
631
+ swap32(): Buffer {
632
+ const len = this.length
633
+ if (len % 4 !== 0) throw new RangeError('Buffer size must be a multiple of 32-bits')
634
+ for (let i = 0; i < len; i += 4) {
635
+ const v0 = this[i]; const v1 = this[i + 1]; const v2 = this[i + 2]; const v3 = this[i + 3];
636
+ this[i] = v3; this[i + 1] = v2; this[i + 2] = v1; this[i + 3] = v0;
637
+ }
638
+ return this
639
+ }
640
+
641
+ swap64(): Buffer {
642
+ const len = this.length
643
+ if (len % 8 !== 0) throw new RangeError('Buffer size must be a multiple of 64-bits')
644
+ for (let i = 0; i < len; i += 8) {
645
+ const v0 = this[i]; const v1 = this[i + 1]; const v2 = this[i + 2]; const v3 = this[i + 3];
646
+ const v4 = this[i + 4]; const v5 = this[i + 5]; const v6 = this[i + 6]; const v7 = this[i + 7];
647
+ this[i] = v7; this[i + 1] = v6; this[i + 2] = v5; this[i + 3] = v4;
648
+ this[i + 4] = v3; this[i + 5] = v2; this[i + 6] = v1; this[i + 7] = v0;
649
+ }
650
+ return this
651
+ }
652
+
653
+ copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number {
654
+ if (!target) throw new TypeError('argument must be a Buffer')
655
+ if (targetStart === undefined) targetStart = 0
656
+ if (sourceStart === undefined) sourceStart = 0
657
+ if (sourceEnd === undefined) sourceEnd = this.length
658
+
659
+ if (targetStart >= target.length) return 0
660
+ if (sourceStart >= sourceEnd) return 0
661
+
662
+ if (sourceStart < 0) sourceStart = 0
663
+ if (sourceEnd > this.length) sourceEnd = this.length
664
+ if (targetStart < 0) targetStart = 0
665
+
666
+ let len = sourceEnd - sourceStart
667
+ if (target.length - targetStart < len) {
668
+ len = target.length - targetStart
669
+ }
670
+
671
+ target.set(this.subarray(sourceStart, sourceStart + len), targetStart)
672
+ return len
673
+ }
674
+ }
675
+
@@ -0,0 +1,19 @@
1
+ import { type HybridObject } from 'react-native-nitro-modules'
2
+
3
+ export interface NitroBuffer extends HybridObject<{ ios: 'c++', android: 'c++' }> {
4
+ // Allocation
5
+ alloc(size: number): ArrayBuffer
6
+ allocUnsafe(size: number): ArrayBuffer
7
+
8
+ // Operations
9
+ byteLength(string: string, encoding: string): number
10
+ write(buffer: ArrayBuffer, string: string, offset: number, length: number, encoding: string): number
11
+ decode(buffer: ArrayBuffer, offset: number, length: number, encoding: string): string
12
+ compare(a: ArrayBuffer, aOffset: number, aLength: number, b: ArrayBuffer, bOffset: number, bLength: number): number
13
+ fill(buffer: ArrayBuffer, value: number, offset: number, length: number): void
14
+ indexOf(buffer: ArrayBuffer, value: number, offset: number, length: number): number
15
+ indexOfBuffer(buffer: ArrayBuffer, needle: ArrayBuffer, offset: number, length: number): number
16
+ lastIndexOfByte(buffer: ArrayBuffer, value: number, offset: number, length: number): number
17
+ lastIndexOfBuffer(buffer: ArrayBuffer, needle: ArrayBuffer, offset: number, length: number): number
18
+ fillBuffer(buffer: ArrayBuffer, value: ArrayBuffer, offset: number, length: number): void
19
+ }