sol-trade-sdk 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/README.md +390 -0
- package/dist/chunk-MMQAMIKR.mjs +3735 -0
- package/dist/chunk-NEZDFAYA.mjs +7744 -0
- package/dist/clients-VITWK7B6.mjs +1370 -0
- package/dist/index-1BK_FXsW.d.mts +2327 -0
- package/dist/index-1BK_FXsW.d.ts +2327 -0
- package/dist/index.d.mts +2659 -0
- package/dist/index.d.ts +2659 -0
- package/dist/index.js +13265 -0
- package/dist/index.mjs +562 -0
- package/dist/perf/index.d.mts +2 -0
- package/dist/perf/index.d.ts +2 -0
- package/dist/perf/index.js +3742 -0
- package/dist/perf/index.mjs +214 -0
- package/package.json +101 -0
- package/src/__tests__/complete_sdk.test.ts +354 -0
- package/src/__tests__/hotpath.test.ts +486 -0
- package/src/__tests__/nonce.test.ts +45 -0
- package/src/__tests__/sdk.test.ts +425 -0
- package/src/address-lookup/index.ts +197 -0
- package/src/cache/cache.ts +308 -0
- package/src/calc/index.ts +1058 -0
- package/src/calc/pumpfun.ts +124 -0
- package/src/common/bonding_curve.ts +272 -0
- package/src/common/compute-budget.ts +148 -0
- package/src/common/confirm-any-signature.ts +184 -0
- package/src/common/fast-timing.ts +481 -0
- package/src/common/fast_fn.ts +150 -0
- package/src/common/gas-fee-strategy.ts +253 -0
- package/src/common/map-pool.ts +23 -0
- package/src/common/nonce.ts +40 -0
- package/src/common/sdk-log.ts +460 -0
- package/src/common/seed.ts +381 -0
- package/src/common/spl-token.ts +578 -0
- package/src/common/subscription-handle.ts +644 -0
- package/src/common/trading-utils.ts +239 -0
- package/src/common/wsol-manager.ts +325 -0
- package/src/compute/compute_budget_manager.ts +187 -0
- package/src/compute/index.ts +21 -0
- package/src/constants/index.ts +96 -0
- package/src/execution/execution.ts +532 -0
- package/src/execution/index.ts +42 -0
- package/src/hotpath/executor.ts +464 -0
- package/src/hotpath/index.ts +64 -0
- package/src/hotpath/state.ts +435 -0
- package/src/index.ts +2117 -0
- package/src/instruction/bonk_builder.ts +730 -0
- package/src/instruction/index.ts +24 -0
- package/src/instruction/meteora_damm_v2_builder.ts +509 -0
- package/src/instruction/pumpfun_builder.ts +1183 -0
- package/src/instruction/pumpswap.ts +1123 -0
- package/src/instruction/raydium_amm_v4_builder.ts +692 -0
- package/src/instruction/raydium_cpmm_builder.ts +795 -0
- package/src/middleware/traits.ts +407 -0
- package/src/params/index.ts +483 -0
- package/src/perf/compiler-optimization.ts +529 -0
- package/src/perf/hardware.ts +631 -0
- package/src/perf/index.ts +9 -0
- package/src/perf/kernel-bypass.ts +656 -0
- package/src/perf/protocol.ts +682 -0
- package/src/perf/realtime.ts +592 -0
- package/src/perf/simd.ts +668 -0
- package/src/perf/syscall-bypass.ts +331 -0
- package/src/perf/ultra-low-latency.ts +505 -0
- package/src/perf/zero-copy.ts +589 -0
- package/src/pool/pool.ts +294 -0
- package/src/rpc/client.ts +345 -0
- package/src/sdk-errors.ts +13 -0
- package/src/security/index.ts +26 -0
- package/src/security/secure-key.ts +303 -0
- package/src/security/validators.ts +281 -0
- package/src/seed/pda.ts +262 -0
- package/src/serialization/index.ts +28 -0
- package/src/serialization/serialization.ts +288 -0
- package/src/swqos/clients.ts +1754 -0
- package/src/swqos/index.ts +50 -0
- package/src/swqos/providers.ts +1707 -0
- package/src/trading/core/async-executor.ts +702 -0
- package/src/trading/core/confirmation-monitor.ts +711 -0
- package/src/trading/core/index.ts +82 -0
- package/src/trading/core/retry-handler.ts +683 -0
- package/src/trading/core/transaction-pool.ts +780 -0
- package/src/trading/executor.ts +385 -0
- package/src/trading/factory.ts +282 -0
- package/src/trading/index.ts +30 -0
- package/src/types.ts +8 -0
- package/src/utils/index.ts +155 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-Copy Module for Sol Trade SDK
|
|
3
|
+
* Provides zero-copy buffer operations and serialization.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ===== Types =====
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Buffer view with zero-copy semantics
|
|
10
|
+
*/
|
|
11
|
+
export interface BufferView {
|
|
12
|
+
buffer: ArrayBuffer;
|
|
13
|
+
byteOffset: number;
|
|
14
|
+
byteLength: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Serializable interface for zero-copy operations
|
|
19
|
+
*/
|
|
20
|
+
export interface ZeroCopySerializable {
|
|
21
|
+
serialize(): Uint8Array;
|
|
22
|
+
deserialize(data: Uint8Array): void;
|
|
23
|
+
serializedSize(): number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Buffer pool configuration
|
|
28
|
+
*/
|
|
29
|
+
export interface BufferPoolConfig {
|
|
30
|
+
/** Buffer size in bytes */
|
|
31
|
+
bufferSize: number;
|
|
32
|
+
/** Number of buffers in pool */
|
|
33
|
+
poolSize: number;
|
|
34
|
+
/** Enable automatic expansion */
|
|
35
|
+
autoExpand: boolean;
|
|
36
|
+
/** Maximum pool size */
|
|
37
|
+
maxPoolSize: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Default buffer pool configuration
|
|
42
|
+
*/
|
|
43
|
+
export function defaultBufferPoolConfig(): BufferPoolConfig {
|
|
44
|
+
return {
|
|
45
|
+
bufferSize: 4096,
|
|
46
|
+
poolSize: 128,
|
|
47
|
+
autoExpand: true,
|
|
48
|
+
maxPoolSize: 1024,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ===== Zero-Copy Buffer =====
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Zero-copy buffer with view semantics.
|
|
56
|
+
* Allows multiple views into the same underlying buffer without copying.
|
|
57
|
+
*/
|
|
58
|
+
export class ZeroCopyBuffer {
|
|
59
|
+
private buffer: ArrayBuffer;
|
|
60
|
+
private view: DataView;
|
|
61
|
+
private uint8View: Uint8Array;
|
|
62
|
+
private offset: number = 0;
|
|
63
|
+
|
|
64
|
+
constructor(size: number = 4096) {
|
|
65
|
+
this.buffer = new ArrayBuffer(size);
|
|
66
|
+
this.view = new DataView(this.buffer);
|
|
67
|
+
this.uint8View = new Uint8Array(this.buffer);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create from existing buffer (zero-copy)
|
|
72
|
+
*/
|
|
73
|
+
static from(buffer: ArrayBuffer): ZeroCopyBuffer {
|
|
74
|
+
const zc = new ZeroCopyBuffer(0);
|
|
75
|
+
zc.buffer = buffer;
|
|
76
|
+
zc.view = new DataView(buffer);
|
|
77
|
+
zc.uint8View = new Uint8Array(buffer);
|
|
78
|
+
return zc;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Create a view into this buffer without copying
|
|
83
|
+
*/
|
|
84
|
+
slice(start: number, end: number): Uint8Array {
|
|
85
|
+
return new Uint8Array(this.buffer, start, end - start);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get current write offset
|
|
90
|
+
*/
|
|
91
|
+
getOffset(): number {
|
|
92
|
+
return this.offset;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Set write offset
|
|
97
|
+
*/
|
|
98
|
+
setOffset(offset: number): void {
|
|
99
|
+
this.offset = offset;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get buffer capacity
|
|
104
|
+
*/
|
|
105
|
+
capacity(): number {
|
|
106
|
+
return this.buffer.byteLength;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Write Uint8 at current offset
|
|
111
|
+
*/
|
|
112
|
+
writeUint8(value: number): void {
|
|
113
|
+
this.view.setUint8(this.offset, value);
|
|
114
|
+
this.offset += 1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Write Uint16 at current offset (little-endian)
|
|
119
|
+
*/
|
|
120
|
+
writeUint16(value: number): void {
|
|
121
|
+
this.view.setUint16(this.offset, value, true);
|
|
122
|
+
this.offset += 2;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Write Uint32 at current offset (little-endian)
|
|
127
|
+
*/
|
|
128
|
+
writeUint32(value: number): void {
|
|
129
|
+
this.view.setUint32(this.offset, value, true);
|
|
130
|
+
this.offset += 4;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Write BigUint64 at current offset (little-endian)
|
|
135
|
+
*/
|
|
136
|
+
writeUint64(value: bigint): void {
|
|
137
|
+
this.view.setBigUint64(this.offset, value, true);
|
|
138
|
+
this.offset += 8;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Write bytes at current offset
|
|
143
|
+
*/
|
|
144
|
+
writeBytes(bytes: Uint8Array): void {
|
|
145
|
+
this.uint8View.set(bytes, this.offset);
|
|
146
|
+
this.offset += bytes.length;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Read Uint8 at offset
|
|
151
|
+
*/
|
|
152
|
+
readUint8(offset: number): number {
|
|
153
|
+
return this.view.getUint8(offset);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Read Uint16 at offset (little-endian)
|
|
158
|
+
*/
|
|
159
|
+
readUint16(offset: number): number {
|
|
160
|
+
return this.view.getUint16(offset, true);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Read Uint32 at offset (little-endian)
|
|
165
|
+
*/
|
|
166
|
+
readUint32(offset: number): number {
|
|
167
|
+
return this.view.getUint32(offset, true);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Read BigUint64 at offset (little-endian)
|
|
172
|
+
*/
|
|
173
|
+
readUint64(offset: number): bigint {
|
|
174
|
+
return this.view.getBigUint64(offset, true);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Read bytes at offset
|
|
179
|
+
*/
|
|
180
|
+
readBytes(offset: number, length: number): Uint8Array {
|
|
181
|
+
return new Uint8Array(this.buffer, offset, length);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get the underlying ArrayBuffer
|
|
186
|
+
*/
|
|
187
|
+
getBuffer(): ArrayBuffer {
|
|
188
|
+
return this.buffer;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get as Uint8Array (full buffer)
|
|
193
|
+
*/
|
|
194
|
+
asUint8Array(): Uint8Array {
|
|
195
|
+
return this.uint8View;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get used portion as Uint8Array (zero-copy view)
|
|
200
|
+
*/
|
|
201
|
+
asUsedUint8Array(): Uint8Array {
|
|
202
|
+
return new Uint8Array(this.buffer, 0, this.offset);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Reset offset to beginning
|
|
207
|
+
*/
|
|
208
|
+
reset(): void {
|
|
209
|
+
this.offset = 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Ensure capacity (creates new buffer if needed, copies data)
|
|
214
|
+
*/
|
|
215
|
+
ensureCapacity(minCapacity: number): void {
|
|
216
|
+
if (this.buffer.byteLength >= minCapacity) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const newCapacity = Math.max(minCapacity, this.buffer.byteLength * 2);
|
|
221
|
+
const newBuffer = new ArrayBuffer(newCapacity);
|
|
222
|
+
const newUint8 = new Uint8Array(newBuffer);
|
|
223
|
+
newUint8.set(this.uint8View);
|
|
224
|
+
|
|
225
|
+
this.buffer = newBuffer;
|
|
226
|
+
this.view = new DataView(newBuffer);
|
|
227
|
+
this.uint8View = newUint8;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ===== Buffer Pool =====
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* High-performance buffer pool for zero-copy operations.
|
|
235
|
+
* Reduces allocation overhead by reusing buffers.
|
|
236
|
+
*/
|
|
237
|
+
export class BufferPool {
|
|
238
|
+
private pool: ArrayBuffer[] = [];
|
|
239
|
+
private inUse: Set<ArrayBuffer> = new Set();
|
|
240
|
+
private config: BufferPoolConfig;
|
|
241
|
+
|
|
242
|
+
constructor(config: BufferPoolConfig = defaultBufferPoolConfig()) {
|
|
243
|
+
this.config = config;
|
|
244
|
+
|
|
245
|
+
// Pre-allocate buffers
|
|
246
|
+
for (let i = 0; i < config.poolSize; i++) {
|
|
247
|
+
this.pool.push(new ArrayBuffer(config.bufferSize));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Acquire a buffer from the pool
|
|
253
|
+
*/
|
|
254
|
+
acquire(): ArrayBuffer {
|
|
255
|
+
if (this.pool.length > 0) {
|
|
256
|
+
const buffer = this.pool.pop()!;
|
|
257
|
+
this.inUse.add(buffer);
|
|
258
|
+
return buffer;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (this.config.autoExpand && this.pool.length + this.inUse.size < this.config.maxPoolSize) {
|
|
262
|
+
const buffer = new ArrayBuffer(this.config.bufferSize);
|
|
263
|
+
this.inUse.add(buffer);
|
|
264
|
+
return buffer;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
throw new Error('Buffer pool exhausted');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Acquire a ZeroCopyBuffer wrapper
|
|
272
|
+
*/
|
|
273
|
+
acquireZeroCopyBuffer(): ZeroCopyBuffer {
|
|
274
|
+
const buffer = this.acquire();
|
|
275
|
+
return ZeroCopyBuffer.from(buffer);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Release a buffer back to the pool
|
|
280
|
+
*/
|
|
281
|
+
release(buffer: ArrayBuffer): void {
|
|
282
|
+
if (!this.inUse.has(buffer)) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.inUse.delete(buffer);
|
|
287
|
+
|
|
288
|
+
if (this.pool.length < this.config.maxPoolSize) {
|
|
289
|
+
this.pool.push(buffer);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Execute a function with a pooled buffer
|
|
295
|
+
*/
|
|
296
|
+
with<T>(fn: (buffer: ArrayBuffer) => T): T {
|
|
297
|
+
const buffer = this.acquire();
|
|
298
|
+
try {
|
|
299
|
+
return fn(buffer);
|
|
300
|
+
} finally {
|
|
301
|
+
this.release(buffer);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get pool statistics
|
|
307
|
+
*/
|
|
308
|
+
getStats(): { available: number; inUse: number; total: number } {
|
|
309
|
+
return {
|
|
310
|
+
available: this.pool.length,
|
|
311
|
+
inUse: this.inUse.size,
|
|
312
|
+
total: this.pool.length + this.inUse.size,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Clear all buffers
|
|
318
|
+
*/
|
|
319
|
+
clear(): void {
|
|
320
|
+
this.pool = [];
|
|
321
|
+
this.inUse.clear();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ===== Zero-Copy Serializer =====
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* High-performance serializer with zero-copy semantics.
|
|
329
|
+
* Minimizes memory copies during serialization/deserialization.
|
|
330
|
+
*/
|
|
331
|
+
export class ZeroCopySerializer {
|
|
332
|
+
private buffer: ZeroCopyBuffer;
|
|
333
|
+
private textEncoder: InstanceType<typeof TextEncoder>;
|
|
334
|
+
private textDecoder: InstanceType<typeof TextDecoder>;
|
|
335
|
+
|
|
336
|
+
constructor(initialSize: number = 4096) {
|
|
337
|
+
this.buffer = new ZeroCopyBuffer(initialSize);
|
|
338
|
+
this.textEncoder = new TextEncoder();
|
|
339
|
+
this.textDecoder = new TextDecoder();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Serialize a string (length-prefixed)
|
|
344
|
+
*/
|
|
345
|
+
writeString(value: string): void {
|
|
346
|
+
const bytes = this.textEncoder.encode(value);
|
|
347
|
+
this.buffer.writeUint32(bytes.length);
|
|
348
|
+
this.buffer.writeBytes(bytes);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Serialize a PublicKey (32 bytes)
|
|
353
|
+
*/
|
|
354
|
+
writePublicKey(bytes: Uint8Array): void {
|
|
355
|
+
if (bytes.length !== 32) {
|
|
356
|
+
throw new Error('PublicKey must be 32 bytes');
|
|
357
|
+
}
|
|
358
|
+
this.buffer.writeBytes(bytes);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Serialize a BigInt (8 bytes)
|
|
363
|
+
*/
|
|
364
|
+
writeBigInt(value: bigint): void {
|
|
365
|
+
this.buffer.writeUint64(value);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Serialize a number (4 bytes)
|
|
370
|
+
*/
|
|
371
|
+
writeNumber(value: number): void {
|
|
372
|
+
this.buffer.writeUint32(value);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Serialize a boolean (1 byte)
|
|
377
|
+
*/
|
|
378
|
+
writeBoolean(value: boolean): void {
|
|
379
|
+
this.buffer.writeUint8(value ? 1 : 0);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Serialize bytes with length prefix
|
|
384
|
+
*/
|
|
385
|
+
writeByteArray(bytes: Uint8Array): void {
|
|
386
|
+
this.buffer.writeUint32(bytes.length);
|
|
387
|
+
this.buffer.writeBytes(bytes);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Deserialize a string
|
|
392
|
+
*/
|
|
393
|
+
readString(offset: number): { value: string; nextOffset: number } {
|
|
394
|
+
const length = this.buffer.readUint32(offset);
|
|
395
|
+
const bytes = this.buffer.readBytes(offset + 4, length);
|
|
396
|
+
const value = this.textDecoder.decode(bytes);
|
|
397
|
+
return { value, nextOffset: offset + 4 + length };
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Deserialize a PublicKey
|
|
402
|
+
*/
|
|
403
|
+
readPublicKey(offset: number): { value: Uint8Array; nextOffset: number } {
|
|
404
|
+
const value = this.buffer.readBytes(offset, 32);
|
|
405
|
+
return { value, nextOffset: offset + 32 };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Deserialize a BigInt
|
|
410
|
+
*/
|
|
411
|
+
readBigInt(offset: number): { value: bigint; nextOffset: number } {
|
|
412
|
+
const value = this.buffer.readUint64(offset);
|
|
413
|
+
return { value, nextOffset: offset + 8 };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Deserialize a number
|
|
418
|
+
*/
|
|
419
|
+
readNumber(offset: number): { value: number; nextOffset: number } {
|
|
420
|
+
const value = this.buffer.readUint32(offset);
|
|
421
|
+
return { value, nextOffset: offset + 4 };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Deserialize a boolean
|
|
426
|
+
*/
|
|
427
|
+
readBoolean(offset: number): { value: boolean; nextOffset: number } {
|
|
428
|
+
const value = this.buffer.readUint8(offset) !== 0;
|
|
429
|
+
return { value, nextOffset: offset + 1 };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Deserialize a byte array
|
|
434
|
+
*/
|
|
435
|
+
readByteArray(offset: number): { value: Uint8Array; nextOffset: number } {
|
|
436
|
+
const length = this.buffer.readUint32(offset);
|
|
437
|
+
const value = this.buffer.readBytes(offset + 4, length);
|
|
438
|
+
return { value, nextOffset: offset + 4 + length };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Get serialized data as Uint8Array (zero-copy view)
|
|
443
|
+
*/
|
|
444
|
+
getData(): Uint8Array {
|
|
445
|
+
return this.buffer.asUsedUint8Array();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Reset for reuse
|
|
450
|
+
*/
|
|
451
|
+
reset(): void {
|
|
452
|
+
this.buffer.reset();
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Get current offset
|
|
457
|
+
*/
|
|
458
|
+
getOffset(): number {
|
|
459
|
+
return this.buffer.getOffset();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ===== Fixed-Size Buffer Views =====
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Fixed-size view into a buffer for predictable memory layout.
|
|
467
|
+
* Useful for structures with known sizes.
|
|
468
|
+
*/
|
|
469
|
+
export class FixedBufferView {
|
|
470
|
+
private buffer: ArrayBuffer;
|
|
471
|
+
private view: DataView;
|
|
472
|
+
private uint8View: Uint8Array;
|
|
473
|
+
private baseOffset: number;
|
|
474
|
+
|
|
475
|
+
constructor(buffer: ArrayBuffer, offset: number, size: number) {
|
|
476
|
+
this.buffer = buffer;
|
|
477
|
+
this.view = new DataView(buffer, offset, size);
|
|
478
|
+
this.uint8View = new Uint8Array(buffer, offset, size);
|
|
479
|
+
this.baseOffset = offset;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Get Uint8 at relative offset
|
|
484
|
+
*/
|
|
485
|
+
getUint8(offset: number): number {
|
|
486
|
+
return this.view.getUint8(offset);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Set Uint8 at relative offset
|
|
491
|
+
*/
|
|
492
|
+
setUint8(offset: number, value: number): void {
|
|
493
|
+
this.view.setUint8(offset, value);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Get Uint32 at relative offset
|
|
498
|
+
*/
|
|
499
|
+
getUint32(offset: number): number {
|
|
500
|
+
return this.view.getUint32(offset, true);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Set Uint32 at relative offset
|
|
505
|
+
*/
|
|
506
|
+
setUint32(offset: number, value: number): void {
|
|
507
|
+
this.view.setUint32(offset, value, true);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Get BigUint64 at relative offset
|
|
512
|
+
*/
|
|
513
|
+
getUint64(offset: number): bigint {
|
|
514
|
+
return this.view.getBigUint64(offset, true);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Set BigUint64 at relative offset
|
|
519
|
+
*/
|
|
520
|
+
setUint64(offset: number, value: bigint): void {
|
|
521
|
+
this.view.setBigUint64(offset, value, true);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Get bytes at relative offset
|
|
526
|
+
*/
|
|
527
|
+
getBytes(offset: number, length: number): Uint8Array {
|
|
528
|
+
return new Uint8Array(this.buffer, this.baseOffset + offset, length);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Set bytes at relative offset
|
|
533
|
+
*/
|
|
534
|
+
setBytes(offset: number, bytes: Uint8Array): void {
|
|
535
|
+
this.uint8View.set(bytes, offset);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Get the underlying ArrayBuffer
|
|
540
|
+
*/
|
|
541
|
+
getBuffer(): ArrayBuffer {
|
|
542
|
+
return this.buffer;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Get the base offset
|
|
547
|
+
*/
|
|
548
|
+
getBaseOffset(): number {
|
|
549
|
+
return this.baseOffset;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// ===== Convenience Functions =====
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Create a buffer pool with default configuration
|
|
557
|
+
*/
|
|
558
|
+
export function createBufferPool(config?: Partial<BufferPoolConfig>): BufferPool {
|
|
559
|
+
const fullConfig = { ...defaultBufferPoolConfig(), ...config };
|
|
560
|
+
return new BufferPool(fullConfig);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Create a zero-copy buffer
|
|
565
|
+
*/
|
|
566
|
+
export function createZeroCopyBuffer(size?: number): ZeroCopyBuffer {
|
|
567
|
+
return new ZeroCopyBuffer(size);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Create a zero-copy serializer
|
|
572
|
+
*/
|
|
573
|
+
export function createSerializer(initialSize?: number): ZeroCopySerializer {
|
|
574
|
+
return new ZeroCopySerializer(initialSize);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Copy bytes without allocation (if possible)
|
|
579
|
+
*/
|
|
580
|
+
export function copyBytes(src: Uint8Array, dst: Uint8Array, dstOffset: number = 0): void {
|
|
581
|
+
dst.set(src, dstOffset);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Create a zero-copy view of a buffer
|
|
586
|
+
*/
|
|
587
|
+
export function createView(buffer: ArrayBuffer, offset: number, length: number): Uint8Array {
|
|
588
|
+
return new Uint8Array(buffer, offset, length);
|
|
589
|
+
}
|