@felixdrp/gcf-wasm 0.0.0-stage → 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/dist/index.js ADDED
@@ -0,0 +1,1006 @@
1
+ // src/host.ts
2
+ class GcfError extends Error {
3
+ code;
4
+ detail;
5
+ line;
6
+ constructor(code, detail, line) {
7
+ super(line > 0 ? `${code} (line ${line}): ${detail}` : `${code}: ${detail}`);
8
+ this.name = "GcfError";
9
+ this.code = code;
10
+ this.detail = detail;
11
+ this.line = line;
12
+ }
13
+ }
14
+ var GcfDecodeError = GcfError;
15
+ var utf8 = new TextEncoder;
16
+ var fromUtf8 = new TextDecoder;
17
+ function isPlainGraph(text) {
18
+ if (!text.startsWith("GCF profile=graph"))
19
+ return false;
20
+ const nl = text.indexOf(`
21
+ `);
22
+ const header = nl < 0 ? text : text.slice(0, nl);
23
+ return !/ delta=true(\s|$)/.test(header);
24
+ }
25
+ function toJsonText(value) {
26
+ try {
27
+ const s = JSON.stringify(value);
28
+ if (s !== undefined && !/(?<![\d.eE+-])-?\d{16,}(?![\d.eE])/.test(s))
29
+ return s;
30
+ } catch {}
31
+ const skip = (v) => v === undefined || typeof v === "function" || typeof v === "symbol";
32
+ const walk = (v0, key) => {
33
+ const v = v0 !== null && typeof v0 === "object" && typeof v0.toJSON === "function" ? v0.toJSON(key) : v0;
34
+ if (typeof v === "bigint")
35
+ return v.toString();
36
+ if (typeof v === "number" && Number.isInteger(v) && Math.abs(v) >= 9007199254740992)
37
+ return v.toExponential();
38
+ if (v === null || skip(v) || typeof v === "number" || typeof v === "boolean" || typeof v === "string")
39
+ return skip(v) ? "null" : JSON.stringify(v);
40
+ if (Array.isArray(v)) {
41
+ const items = [];
42
+ for (let i = 0;i < v.length; i++)
43
+ items.push(skip(v[i]) ? "null" : walk(v[i], String(i)));
44
+ return `[${items.join(",")}]`;
45
+ }
46
+ const entries = v instanceof Map ? [...v.entries()] : Object.entries(v);
47
+ return `{${entries.filter(([, x]) => !skip(x)).map(([k, x]) => `${JSON.stringify(String(k))}:${walk(x, String(k))}`).join(",")}}`;
48
+ };
49
+ return walk(value, "");
50
+ }
51
+ function isPlainRecord(v) {
52
+ if (v === null || typeof v !== "object" || Array.isArray(v))
53
+ return false;
54
+ const proto = Object.getPrototypeOf(v);
55
+ return (proto === Object.prototype || proto === null) && v.toJSON === undefined;
56
+ }
57
+ function utf8LengthStrict(s) {
58
+ let n = 0;
59
+ for (let i = 0;i < s.length; i++) {
60
+ const c = s.charCodeAt(i);
61
+ if (c < 128)
62
+ n += 1;
63
+ else if (c < 2048)
64
+ n += 2;
65
+ else if (c >= 55296 && c <= 56319) {
66
+ const d = i + 1 < s.length ? s.charCodeAt(i + 1) : 0;
67
+ if (d < 56320 || d > 57343)
68
+ return -1;
69
+ n += 4;
70
+ i++;
71
+ } else if (c >= 56320 && c <= 57343)
72
+ return -1;
73
+ else
74
+ n += 3;
75
+ }
76
+ return n;
77
+ }
78
+ function parseLargeInts(text, mode) {
79
+ let i = 0;
80
+ const ws = () => {
81
+ while (i < text.length && (text[i] === " " || text[i] === `
82
+ ` || text[i] === "\r" || text[i] === "\t"))
83
+ i++;
84
+ };
85
+ const value = () => {
86
+ ws();
87
+ const c = text[i];
88
+ if (c === "{") {
89
+ i++;
90
+ const o = {};
91
+ ws();
92
+ if (text[i] === "}") {
93
+ i++;
94
+ return o;
95
+ }
96
+ for (;; ) {
97
+ ws();
98
+ const k = value();
99
+ ws();
100
+ i++;
101
+ o[k] = value();
102
+ ws();
103
+ if (text[i++] === "}")
104
+ return o;
105
+ }
106
+ }
107
+ if (c === "[") {
108
+ i++;
109
+ const a = [];
110
+ ws();
111
+ if (text[i] === "]") {
112
+ i++;
113
+ return a;
114
+ }
115
+ for (;; ) {
116
+ a.push(value());
117
+ ws();
118
+ if (text[i++] === "]")
119
+ return a;
120
+ }
121
+ }
122
+ if (c === '"') {
123
+ const start = i++;
124
+ while (text[i] !== '"')
125
+ i += text[i] === "\\" ? 2 : 1;
126
+ i++;
127
+ return JSON.parse(text.slice(start, i));
128
+ }
129
+ const start = i;
130
+ while (i < text.length && !`,}]
131
+ \r `.includes(text[i]))
132
+ i++;
133
+ const lex = text.slice(start, i);
134
+ if (lex === "true")
135
+ return true;
136
+ if (lex === "false")
137
+ return false;
138
+ if (lex === "null")
139
+ return null;
140
+ if (/^-?\d+$/.test(lex)) {
141
+ const n = Number(lex);
142
+ if (!Number.isSafeInteger(n))
143
+ return mode === "bigint" ? BigInt(lex) : lex;
144
+ return n;
145
+ }
146
+ return Number(lex);
147
+ };
148
+ return value();
149
+ }
150
+
151
+ class GcfCodec {
152
+ exports;
153
+ constructor(exports) {
154
+ this.exports = exports;
155
+ }
156
+ static async instantiate(wasm) {
157
+ const instance = wasm instanceof WebAssembly.Module ? await WebAssembly.instantiate(wasm, {}) : (await WebAssembly.instantiate(wasm, {})).instance;
158
+ return new GcfCodec(instance.exports);
159
+ }
160
+ load(input) {
161
+ const x = this.exports;
162
+ if (typeof input !== "string") {
163
+ const ptr = x.gcf_input_alloc(input.length);
164
+ new Uint8Array(x.memory.buffer, ptr, input.length).set(input);
165
+ return input.length;
166
+ }
167
+ const cap = input.length * 3;
168
+ const ptr = x.gcf_input_alloc(cap);
169
+ return utf8.encodeInto(input, new Uint8Array(x.memory.buffer, ptr, cap)).written;
170
+ }
171
+ output(status) {
172
+ const x = this.exports;
173
+ const text = (p, n) => fromUtf8.decode(new Uint8Array(x.memory.buffer, p, n));
174
+ if (status !== 0) {
175
+ throw new GcfError(text(x.gcf_error_name_ptr(), x.gcf_error_name_len()), text(x.gcf_error_message_ptr(), x.gcf_error_message_len()), x.gcf_error_line());
176
+ }
177
+ return text(x.gcf_output_ptr(), x.gcf_output_len());
178
+ }
179
+ outputBytes(status, view) {
180
+ if (status !== 0)
181
+ this.output(status);
182
+ const x = this.exports;
183
+ const bytes = new Uint8Array(x.memory.buffer, x.gcf_output_ptr(), x.gcf_output_len());
184
+ return view ? bytes : bytes.slice();
185
+ }
186
+ run(fn, input) {
187
+ return this.output(fn.call(this.exports, this.load(input)));
188
+ }
189
+ parse(json, mode) {
190
+ if (!this.exports.gcf_output_unsafe_ints() || mode === "number")
191
+ return JSON.parse(json);
192
+ if (mode === "error") {
193
+ const m = /-?\d{16,}/.exec(json);
194
+ throw new GcfError("unsafe_integer", `integer ${m ? m[0] : ""} exceeds the safe-integer range (2^53-1) of a JavaScript number; decode with largeInt 'string' | 'bigint' | 'number', or model the value as a string`, 0);
195
+ }
196
+ return parseLargeInts(json, mode);
197
+ }
198
+ decodeToJson(input) {
199
+ return this.output(this.exports.gcf_decode(this.load(input)));
200
+ }
201
+ decode(input, opts = {}) {
202
+ const mode = opts.largeInt ?? "error";
203
+ if (typeof input === "string" && isPlainGraph(input)) {
204
+ const cols = this.parse(this.output(this.exports.gcf_decode_graph_columns(this.load(input))), mode);
205
+ return GcfCodec.graphFromColumns(cols);
206
+ }
207
+ return this.parse(this.decodeToJson(input), mode);
208
+ }
209
+ decodeLazy(input, opts = {}) {
210
+ const tape = this.outputBytes(this.exports.gcf_decode_tape(this.load(input)), false);
211
+ return new LazyTape(tape.buffer, opts.largeInt ?? "error").root();
212
+ }
213
+ static graphFromColumns(c) {
214
+ const { names, kinds, provs, types, statuses, k, p, s, d, es, et, ty, st } = c;
215
+ const n = k.length;
216
+ const symbols = new Array(n);
217
+ for (let i = 0;i < n; i++) {
218
+ symbols[i] = { qualifiedName: names[i], kind: kinds[k[i]], score: s[i], provenance: provs[p[i]], distance: d[i] };
219
+ }
220
+ const m = es.length;
221
+ const edges = new Array(m);
222
+ for (let j = 0;j < m; j++) {
223
+ edges[j] = { source: names[es[j]], target: names[et[j]], edgeType: types[ty[j]], status: statuses[st[j]] };
224
+ }
225
+ const out = { tool: c.tool, tokenBudget: c.tokenBudget, tokensUsed: c.tokensUsed, packRoot: c.packRoot };
226
+ if (c.unchanged)
227
+ out.unchanged = true;
228
+ if (c.session)
229
+ out.session = true;
230
+ out.symbols = symbols;
231
+ out.edges = edges;
232
+ if (c.references)
233
+ out.references = c.references;
234
+ return out;
235
+ }
236
+ encodeJsonBytes(json, opts = {}) {
237
+ const len = this.load(json);
238
+ const status = opts.profile === "graph" ? this.exports.gcf_encode_graph(len) : this.exports.gcf_encode(len, opts.noFlatten ? 1 : 0);
239
+ return this.outputBytes(status, opts.view ?? false);
240
+ }
241
+ decodeToJsonBytes(gcf, opts = {}) {
242
+ return this.outputBytes(this.exports.gcf_decode(this.load(gcf)), opts.view ?? false);
243
+ }
244
+ encode(value, opts = {}) {
245
+ const x = this.exports;
246
+ if (x.gcf_features && (x.gcf_features() & 2) !== 0) {
247
+ let text;
248
+ try {
249
+ text = JSON.stringify(value);
250
+ } catch {
251
+ text = undefined;
252
+ }
253
+ if (text !== undefined)
254
+ return this.output(x.gcf_encode(this.load(text), (opts.noFlatten ? 1 : 0) | 2));
255
+ }
256
+ return this.encodeJson(toJsonText(value), opts);
257
+ }
258
+ encodeJson(json, opts = {}) {
259
+ return this.output(this.exports.gcf_encode(this.load(json), opts.noFlatten ? 1 : 0));
260
+ }
261
+ encodeGraph(payload) {
262
+ if (this.exports.gcf_encode_graph_cols) {
263
+ const out = this.encodeGraphColumns(payload);
264
+ if (out !== null)
265
+ return out;
266
+ }
267
+ return this.run(this.exports.gcf_encode_graph, toJsonText(payload));
268
+ }
269
+ encodeGraphColumns(p) {
270
+ if (!isPlainRecord(p))
271
+ return null;
272
+ const syms = Array.isArray(p.symbols) && p.symbols.toJSON === undefined ? p.symbols : [];
273
+ const edges = Array.isArray(p.edges) && p.edges.toJSON === undefined ? p.edges : [];
274
+ const ns = syms.length;
275
+ const ne = edges.length;
276
+ const parts = new Array(2 + 3 * ns + 4 * ne);
277
+ const nums = new Float64Array(2 + 2 * ns);
278
+ let k = 0;
279
+ let bail = false;
280
+ const str = (v) => {
281
+ if (typeof v === "string")
282
+ return v;
283
+ if (v !== null && typeof v === "object")
284
+ bail = true;
285
+ return "";
286
+ };
287
+ const num = (v) => {
288
+ if (typeof v === "number")
289
+ return Number.isFinite(v) && v !== 0 ? v : 0;
290
+ if (typeof v === "bigint" || v !== null && typeof v === "object" || typeof v === "string" && utf8LengthStrict(v) < 0)
291
+ bail = true;
292
+ return 0;
293
+ };
294
+ parts[k++] = str(p.tool);
295
+ parts[k++] = str(p.packRoot);
296
+ nums[0] = num(p.tokenBudget);
297
+ nums[1] = num(p.tokensUsed);
298
+ for (let i = 0;i < ns; i++) {
299
+ const s = syms[i];
300
+ if (s !== null && typeof s === "object" && !Array.isArray(s)) {
301
+ if (!isPlainRecord(s))
302
+ return null;
303
+ parts[k++] = str(s.qualifiedName);
304
+ parts[k++] = str(s.kind);
305
+ parts[k++] = str(s.provenance);
306
+ nums[2 + 2 * i] = num(s.score);
307
+ nums[3 + 2 * i] = num(s.distance);
308
+ } else {
309
+ parts[k++] = "";
310
+ parts[k++] = "";
311
+ parts[k++] = "";
312
+ }
313
+ }
314
+ for (let i = 0;i < ne; i++) {
315
+ const e = edges[i];
316
+ if (e !== null && typeof e === "object" && !Array.isArray(e)) {
317
+ if (!isPlainRecord(e))
318
+ return null;
319
+ parts[k++] = str(e.source);
320
+ parts[k++] = str(e.target);
321
+ parts[k++] = str(e.edgeType);
322
+ parts[k++] = str(e.status);
323
+ } else {
324
+ parts[k++] = "";
325
+ parts[k++] = "";
326
+ parts[k++] = "";
327
+ parts[k++] = "";
328
+ }
329
+ }
330
+ if (bail)
331
+ return null;
332
+ const joined = parts.join("");
333
+ const head = 48 + 40 * ns + 32 * ne;
334
+ const cap = head + 3 * joined.length;
335
+ const x = this.exports;
336
+ const ptr = x.gcf_input_alloc(cap);
337
+ const buf = x.memory.buffer;
338
+ const written = utf8.encodeInto(joined, new Uint8Array(buf, ptr + head, cap - head)).written;
339
+ const lens = new Uint32Array(parts.length);
340
+ if (written === joined.length) {
341
+ for (let i = 0;i < parts.length; i++)
342
+ lens[i] = parts[i].length;
343
+ } else {
344
+ for (let i = 0;i < parts.length; i++) {
345
+ const n = utf8LengthStrict(parts[i]);
346
+ if (n < 0)
347
+ return null;
348
+ lens[i] = n;
349
+ }
350
+ }
351
+ const u32 = new Uint32Array(buf, ptr, head >>> 2);
352
+ const f64 = new Float64Array(buf, ptr, head >>> 3);
353
+ u32[0] = 1195787079;
354
+ u32[1] = ns;
355
+ u32[2] = ne;
356
+ u32[3] = head;
357
+ let off = 0;
358
+ let j = 0;
359
+ const put = (at) => {
360
+ u32[at] = off;
361
+ u32[at + 1] = lens[j];
362
+ off += lens[j++];
363
+ };
364
+ put(4);
365
+ put(6);
366
+ f64[4] = nums[0];
367
+ f64[5] = nums[1];
368
+ for (let i = 0;i < ns; i++) {
369
+ f64[6 + 5 * i] = nums[2 + 2 * i];
370
+ f64[7 + 5 * i] = nums[3 + 2 * i];
371
+ const w = 16 + 10 * i;
372
+ put(w);
373
+ put(w + 2);
374
+ put(w + 4);
375
+ }
376
+ const e0 = 12 + 10 * ns;
377
+ for (let i = 0;i < ne; i++) {
378
+ const w = e0 + 8 * i;
379
+ put(w);
380
+ put(w + 2);
381
+ put(w + 4);
382
+ put(w + 6);
383
+ }
384
+ return this.output(x.gcf_encode_graph_cols(head + written));
385
+ }
386
+ encodeGraphDelta(delta) {
387
+ return this.run(this.exports.gcf_encode_graph_delta, toJsonText(delta));
388
+ }
389
+ encodeGrouped(data, keyField, groupField) {
390
+ return this.run(this.exports.gcf_encode_grouped, toJsonText({ data, keyField, groupField }));
391
+ }
392
+ encodeGenericFull(set, tool = "") {
393
+ return this.run(this.exports.gcf_encode_generic_full, toJsonText({ set, tool }));
394
+ }
395
+ encodeGenericDelta(delta) {
396
+ return this.run(this.exports.gcf_encode_generic_delta, toJsonText(delta));
397
+ }
398
+ encodeGenericDiff(base, next, opts = {}) {
399
+ return this.run(this.exports.gcf_generic_diff, toJsonText({ base, next, ...opts }));
400
+ }
401
+ packRoot(input) {
402
+ return this.run(this.exports.gcf_pack_root, toJsonText(input));
403
+ }
404
+ applyGenericDelta(wire, base, expectedNewRoot) {
405
+ return this.run(this.exports.gcf_delta_decode_apply, toJsonText({ wire, base, expectedNewRoot }));
406
+ }
407
+ applyGraphDelta(wire, base) {
408
+ return JSON.parse(this.run(this.exports.gcf_graph_delta_apply, toJsonText({ wire, base })));
409
+ }
410
+ encodeGraphSessionRaw(payload, known, next) {
411
+ return this.run(this.exports.gcf_encode_graph_session, toJsonText({ payload, known, next }));
412
+ }
413
+ }
414
+ var GcfDecoder = GcfCodec;
415
+
416
+ class GraphSession {
417
+ ids = new Map;
418
+ nextId = 0;
419
+ codec;
420
+ constructor(codec) {
421
+ this.codec = codec;
422
+ }
423
+ encode(payload) {
424
+ const known = {};
425
+ for (const s of payload.symbols) {
426
+ const id = this.ids.get(s.qualifiedName);
427
+ if (id !== undefined)
428
+ known[s.qualifiedName] = id;
429
+ }
430
+ const wire = this.codec.encodeGraphSessionRaw(payload, known, this.nextId);
431
+ for (const s of payload.symbols) {
432
+ if (!this.ids.has(s.qualifiedName))
433
+ this.ids.set(s.qualifiedName, this.nextId++);
434
+ }
435
+ return wire;
436
+ }
437
+ get size() {
438
+ return this.ids.size;
439
+ }
440
+ reset() {
441
+ this.ids.clear();
442
+ this.nextId = 0;
443
+ }
444
+ }
445
+ var DEFAULT_REANCHOR_N = 15;
446
+ function utf8Length(s) {
447
+ let n = 0;
448
+ for (let i = 0;i < s.length; i++) {
449
+ const c = s.charCodeAt(i);
450
+ if (c < 128)
451
+ n += 1;
452
+ else if (c < 2048)
453
+ n += 2;
454
+ else if (c >= 55296 && c <= 56319) {
455
+ n += 4;
456
+ i++;
457
+ } else
458
+ n += 3;
459
+ }
460
+ return n;
461
+ }
462
+
463
+ class GenericDeltaSession {
464
+ turnCount = 0;
465
+ cum = 0;
466
+ policy;
467
+ codec;
468
+ base;
469
+ tool;
470
+ constructor(codec, base, tool = "", policy = { mode: "fixedN", n: DEFAULT_REANCHOR_N }) {
471
+ this.codec = codec;
472
+ this.base = base;
473
+ this.tool = tool;
474
+ this.policy = policy.mode === "fixedN" && policy.n <= 0 ? { mode: "fixedN", n: DEFAULT_REANCHOR_N } : policy;
475
+ }
476
+ currentFull() {
477
+ return this.codec.encodeGenericFull(this.base, this.tool);
478
+ }
479
+ turn() {
480
+ return this.turnCount;
481
+ }
482
+ next(nextSet) {
483
+ this.turnCount++;
484
+ const sameSchema = nextSet.key === this.base.key && nextSet.fields.length === this.base.fields.length && nextSet.fields.every((f, i) => f === this.base.fields[i]);
485
+ if (!sameSchema)
486
+ return { wire: this.reanchor(nextSet), isFull: true };
487
+ const deltaWire = this.codec.encodeGenericDiff(this.base, nextSet);
488
+ const reanchor = this.policy.mode === "sizeGuard" ? this.cum + utf8Length(deltaWire) >= utf8Length(this.codec.encodeGenericFull(nextSet, this.tool)) : this.turnCount % this.policy.n === 0;
489
+ if (reanchor)
490
+ return { wire: this.reanchor(nextSet), isFull: true };
491
+ this.base = nextSet;
492
+ this.cum += utf8Length(deltaWire);
493
+ return { wire: deltaWire, isFull: false };
494
+ }
495
+ reanchor(nextSet) {
496
+ this.base = nextSet;
497
+ this.cum = 0;
498
+ return this.codec.encodeGenericFull(nextSet, this.tool);
499
+ }
500
+ }
501
+ var TAPE_HEADER = 20;
502
+ var textDecoder = new TextDecoder;
503
+ var lazyNodes = new WeakMap;
504
+
505
+ class LazyTape {
506
+ w;
507
+ pool;
508
+ dv;
509
+ rootIndex;
510
+ keyText = new Map;
511
+ keyOffset = new Map;
512
+ proxies = new Map;
513
+ largeInt;
514
+ constructor(buf, largeInt) {
515
+ this.largeInt = largeInt;
516
+ const h = new Uint32Array(buf, 0, 5);
517
+ if (h[0] !== 1413890887 || h[1] !== 1)
518
+ throw new GcfError("invalid_input", "not a GCF tape", 0);
519
+ this.rootIndex = h[2];
520
+ this.w = new Uint32Array(buf, TAPE_HEADER, h[3]);
521
+ this.pool = new Uint8Array(buf, TAPE_HEADER + h[3] * 4, h[4]);
522
+ this.dv = new DataView(buf);
523
+ }
524
+ root() {
525
+ return this.value(this.rootIndex);
526
+ }
527
+ text(off, len) {
528
+ const p = this.pool;
529
+ if (len <= 24) {
530
+ let s = "";
531
+ for (let i = off, end = off + len;i < end; i++) {
532
+ const b = p[i];
533
+ if (b >= 128)
534
+ return textDecoder.decode(p.subarray(off, off + len));
535
+ s += String.fromCharCode(b);
536
+ }
537
+ return s;
538
+ }
539
+ return textDecoder.decode(p.subarray(off, off + len));
540
+ }
541
+ key(off, len) {
542
+ let k = this.keyText.get(off);
543
+ if (k === undefined) {
544
+ k = this.text(off, len);
545
+ this.keyText.set(off, k);
546
+ this.keyOffset.set(k, off);
547
+ }
548
+ return k;
549
+ }
550
+ int64(i) {
551
+ const lo = this.w[i + 1];
552
+ const hi = this.w[i + 2] | 0;
553
+ const n = hi * 4294967296 + lo;
554
+ if (Number.isSafeInteger(n))
555
+ return n;
556
+ const big = BigInt(hi) << 32n | BigInt(lo);
557
+ switch (this.largeInt) {
558
+ case "bigint":
559
+ return big;
560
+ case "string":
561
+ return big.toString();
562
+ case "number":
563
+ return Number(big);
564
+ default:
565
+ throw new GcfError("unsafe_integer", `integer ${big} exceeds the safe-integer range (2^53-1) of a JavaScript number; decode with largeInt 'string' | 'bigint' | 'number'`, 0);
566
+ }
567
+ }
568
+ value(i) {
569
+ const h = this.w[i];
570
+ switch (h & 15) {
571
+ case 0:
572
+ return null;
573
+ case 1:
574
+ return false;
575
+ case 2:
576
+ return true;
577
+ case 3:
578
+ return (h | 0) >> 4;
579
+ case 4:
580
+ return this.int64(i);
581
+ case 5:
582
+ return this.dv.getFloat64(TAPE_HEADER + (i + 1) * 4, true);
583
+ case 6:
584
+ return this.text(this.w[i + 1], h >>> 4);
585
+ default: {
586
+ let p = this.proxies.get(i);
587
+ if (p === undefined) {
588
+ p = (h & 15) === 7 ? this.arrayProxy(i) : this.objectProxy(i);
589
+ this.proxies.set(i, p);
590
+ lazyNodes.set(p, [this, i]);
591
+ }
592
+ return p;
593
+ }
594
+ }
595
+ }
596
+ find(i, name) {
597
+ const n = this.w[i] >>> 4;
598
+ const base = i + 1;
599
+ const w = this.w;
600
+ const off = this.keyOffset.get(name);
601
+ if (off !== undefined) {
602
+ for (let k = 0, j = base;k < n; k++, j += 3)
603
+ if (w[j] === off)
604
+ return w[j + 2];
605
+ return -1;
606
+ }
607
+ for (let k = 0, j = base;k < n; k++, j += 3) {
608
+ if (this.key(w[j], w[j + 1]) === name)
609
+ return w[j + 2];
610
+ }
611
+ return -1;
612
+ }
613
+ keys(i) {
614
+ const n = this.w[i] >>> 4;
615
+ const out = new Array(n);
616
+ for (let k = 0, j = i + 1;k < n; k++, j += 3)
617
+ out[k] = this.key(this.w[j], this.w[j + 1]);
618
+ return out;
619
+ }
620
+ objectProxy(i) {
621
+ const tape = this;
622
+ const readOnly = () => false;
623
+ return new Proxy({}, {
624
+ get(t, prop, receiver) {
625
+ if (typeof prop === "string") {
626
+ const c = tape.find(i, prop);
627
+ if (c >= 0)
628
+ return tape.value(c);
629
+ }
630
+ return Reflect.get(t, prop, receiver);
631
+ },
632
+ has(t, prop) {
633
+ return typeof prop === "string" && tape.find(i, prop) >= 0 || Reflect.has(t, prop);
634
+ },
635
+ ownKeys() {
636
+ return tape.keys(i);
637
+ },
638
+ getOwnPropertyDescriptor(_t, prop) {
639
+ if (typeof prop !== "string")
640
+ return;
641
+ const c = tape.find(i, prop);
642
+ return c < 0 ? undefined : { value: tape.value(c), writable: false, enumerable: true, configurable: true };
643
+ },
644
+ set: readOnly,
645
+ defineProperty: readOnly,
646
+ deleteProperty: readOnly
647
+ });
648
+ }
649
+ arrayProxy(i) {
650
+ const tape = this;
651
+ const n = this.w[i] >>> 4;
652
+ const index = (prop) => {
653
+ if (typeof prop !== "string" || prop.length === 0)
654
+ return -1;
655
+ const c = prop.charCodeAt(0);
656
+ if (c < 48 || c > 57)
657
+ return -1;
658
+ const k = Number(prop);
659
+ return Number.isInteger(k) && k < n && String(k) === prop ? k : -1;
660
+ };
661
+ const readOnly = () => false;
662
+ return new Proxy(new Array(n), {
663
+ get(t, prop, receiver) {
664
+ const k = index(prop);
665
+ if (k >= 0)
666
+ return tape.value(tape.w[i + 1 + k]);
667
+ return Reflect.get(t, prop, receiver);
668
+ },
669
+ has(t, prop) {
670
+ return index(prop) >= 0 || Reflect.has(t, prop);
671
+ },
672
+ ownKeys() {
673
+ const keys = new Array(n + 1);
674
+ for (let k = 0;k < n; k++)
675
+ keys[k] = String(k);
676
+ keys[n] = "length";
677
+ return keys;
678
+ },
679
+ getOwnPropertyDescriptor(t, prop) {
680
+ const k = index(prop);
681
+ if (k >= 0)
682
+ return { value: tape.value(tape.w[i + 1 + k]), writable: false, enumerable: true, configurable: true };
683
+ return Reflect.getOwnPropertyDescriptor(t, prop);
684
+ },
685
+ set: readOnly,
686
+ defineProperty: readOnly,
687
+ deleteProperty: readOnly
688
+ });
689
+ }
690
+ plain(i) {
691
+ const h = this.w[i];
692
+ const tag = h & 15;
693
+ if (tag === 7) {
694
+ const n = h >>> 4;
695
+ const out = new Array(n);
696
+ for (let k = 0;k < n; k++)
697
+ out[k] = this.plain(this.w[i + 1 + k]);
698
+ return out;
699
+ }
700
+ if (tag === 8) {
701
+ const n = h >>> 4;
702
+ const out = {};
703
+ for (let k = 0, j = i + 1;k < n; k++, j += 3)
704
+ out[this.key(this.w[j], this.w[j + 1])] = this.plain(this.w[j + 2]);
705
+ return out;
706
+ }
707
+ return this.value(i);
708
+ }
709
+ }
710
+ function toPlain(value) {
711
+ if (value === null || typeof value !== "object")
712
+ return value;
713
+ const node = lazyNodes.get(value);
714
+ return node ? node[0].plain(node[1]) : value;
715
+ }
716
+ var JSON_NUMBER_RE = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
717
+ var NUMERIC_LIKE_RE = /^[+-]\.?\d|^\.\d|^0\d/;
718
+ var INLINE_ARRAY_RE = /\[[^\]]*\][ \t\n\v\f\r]*:/;
719
+ var BARE_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
720
+ function needsQuote(s) {
721
+ if (s === "" || s === "-" || s === "~" || s === "^" || s === "true" || s === "false")
722
+ return true;
723
+ if (s.length >= 3 && s[0] === "^" && s[1] === "{" && s[s.length - 1] === "}")
724
+ return true;
725
+ if (JSON_NUMBER_RE.test(s) || NUMERIC_LIKE_RE.test(s))
726
+ return true;
727
+ if (s[0] === " " || s[s.length - 1] === " " || s[0] === "#" || s[0] === "@" || s[0] === ".")
728
+ return true;
729
+ if (INLINE_ARRAY_RE.test(s))
730
+ return true;
731
+ for (let i = 0;i < s.length; i++) {
732
+ const c = s.charCodeAt(i);
733
+ if (c === 34 || c === 92 || c < 32 || c === 124 || c === 44)
734
+ return true;
735
+ if (c >= 128 && (c <= 160 || c === 5760 || c >= 8192 && c <= 8202 || c === 8232 || c === 8233 || c === 8239 || c === 8287 || c === 12288 || c === 65279))
736
+ return true;
737
+ }
738
+ return false;
739
+ }
740
+ function quoteString(s) {
741
+ let out = '"';
742
+ for (let i = 0;i < s.length; i++) {
743
+ const c = s.charCodeAt(i);
744
+ if (c === 34)
745
+ out += "\\\"";
746
+ else if (c === 92)
747
+ out += "\\\\";
748
+ else if (c === 8)
749
+ out += "\\b";
750
+ else if (c === 12)
751
+ out += "\\f";
752
+ else if (c === 10)
753
+ out += "\\n";
754
+ else if (c === 13)
755
+ out += "\\r";
756
+ else if (c === 9)
757
+ out += "\\t";
758
+ else if (c < 32)
759
+ out += "\\u" + c.toString(16).padStart(4, "0");
760
+ else
761
+ out += s[i];
762
+ }
763
+ return out + '"';
764
+ }
765
+ function formatKey(k) {
766
+ return BARE_KEY_RE.test(k) ? k : quoteString(k);
767
+ }
768
+ var I64_MIN = -9223372036854775808n;
769
+ var I64_MAX = 9223372036854775807n;
770
+ function formatNumber(f) {
771
+ if (!Number.isFinite(f))
772
+ throw new GcfError("invalid_input", `non-finite number ${f} is outside the JSON data model`, 0);
773
+ if (f === 0)
774
+ return "0";
775
+ const a = Math.abs(f);
776
+ if (a >= 0.000001 && a < 9007199254740992)
777
+ return String(f);
778
+ return f.toExponential().replace(/e\+?0*(\d)/, "e+$1").replace(/e-0*(\d)/, "e-$1");
779
+ }
780
+ function formatScalar(v) {
781
+ if (v === null || v === undefined)
782
+ return "-";
783
+ if (typeof v === "boolean")
784
+ return v ? "true" : "false";
785
+ if (typeof v === "number")
786
+ return formatNumber(v);
787
+ if (typeof v === "bigint") {
788
+ if (v < I64_MIN || v > I64_MAX)
789
+ throw new GcfError("out_of_range", `integer ${v} is outside int64; model it as a string`, 0);
790
+ return v.toString();
791
+ }
792
+ const s = String(v);
793
+ return needsQuote(s) ? quoteString(s) : s;
794
+ }
795
+ function formatScore(x) {
796
+ if (!Number.isFinite(x))
797
+ return "0.00";
798
+ const neg = x < 0;
799
+ const exact = Math.abs(x).toFixed(20);
800
+ const dot = exact.indexOf(".");
801
+ const keep = exact.slice(dot + 1, dot + 3);
802
+ const rest = exact.slice(dot + 3);
803
+ const first = rest.charCodeAt(0) - 48;
804
+ const up = first > 5 || first === 5 && (/[1-9]/.test(rest.slice(1)) || (keep.charCodeAt(1) - 48) % 2 === 1);
805
+ let cents = parseInt(exact.slice(0, dot), 10) * 100 + parseInt(keep, 10) + (up ? 1 : 0);
806
+ const whole = Math.floor(cents / 100);
807
+ cents %= 100;
808
+ return `${neg ? "-" : ""}${whole}.${String(cents).padStart(2, "0")}`;
809
+ }
810
+ var KIND_ABBREV = {
811
+ function: "fn",
812
+ type: "type",
813
+ method: "method",
814
+ interface: "iface",
815
+ var: "var",
816
+ const: "const",
817
+ resource: "resource",
818
+ table: "table",
819
+ class: "class",
820
+ selector: "selector",
821
+ field: "field",
822
+ route_handler: "route",
823
+ external: "ext",
824
+ file: "file",
825
+ package: "pkg",
826
+ service: "svc"
827
+ };
828
+ var groupName = (d) => d === 0 ? "targets" : d === 1 ? "related" : d === 2 ? "extended" : `distance_${d}`;
829
+
830
+ class GraphStreamEncoder {
831
+ ids = new Map;
832
+ nextId = 0;
833
+ group = "";
834
+ groupCounts = new Map;
835
+ edges = 0;
836
+ edgesStarted = false;
837
+ w;
838
+ opts;
839
+ constructor(w, tool, opts = {}) {
840
+ this.w = w;
841
+ this.opts = opts;
842
+ let h = "GCF profile=graph";
843
+ if (tool)
844
+ h += ` tool=${tool}`;
845
+ if (opts.tokenBudget)
846
+ h += ` budget=${opts.tokenBudget}`;
847
+ if (opts.tokensUsed)
848
+ h += ` tokens=${opts.tokensUsed}`;
849
+ if (opts.packRoot)
850
+ h += ` pack_root=${opts.packRoot}`;
851
+ if (opts.session)
852
+ h += " session=true";
853
+ w.write(h + `
854
+ `);
855
+ }
856
+ enterGroup(distance) {
857
+ const g = groupName(distance);
858
+ if (g !== this.group) {
859
+ this.w.write(`## ${g}
860
+ `);
861
+ this.group = g;
862
+ }
863
+ this.groupCounts.set(g, (this.groupCounts.get(g) ?? 0) + 1);
864
+ return g;
865
+ }
866
+ writeSymbol(s) {
867
+ this.enterGroup(s.distance ?? 0);
868
+ const id = this.nextId++;
869
+ this.ids.set(s.qualifiedName, id);
870
+ this.w.write(`@${id} ${KIND_ABBREV[s.kind] ?? s.kind} ${s.qualifiedName} ${formatScore(s.score)} ${s.provenance}
871
+ `);
872
+ }
873
+ writeBareRef(qualifiedName, distance) {
874
+ this.enterGroup(distance);
875
+ const id = this.nextId++;
876
+ this.ids.set(qualifiedName, id);
877
+ this.w.write(`@${id} # previously transmitted
878
+ `);
879
+ }
880
+ writeEdge(e) {
881
+ const src = this.ids.get(e.source);
882
+ const tgt = this.ids.get(e.target);
883
+ if (src === undefined || tgt === undefined)
884
+ return;
885
+ if (!this.edgesStarted) {
886
+ this.w.write(`## edges [?]
887
+ `);
888
+ this.edgesStarted = true;
889
+ }
890
+ const status = e.status && e.status !== "unchanged" ? ` ${e.status}` : "";
891
+ this.w.write(`@${tgt}<@${src} ${e.edgeType}${status}
892
+ `);
893
+ this.edges++;
894
+ }
895
+ close() {
896
+ const parts = [...this.groupCounts].filter(([, c]) => c > 0).map(([g, c]) => `${g}:${c}`);
897
+ parts.push(`edges:${this.edges}`);
898
+ const counts = this.opts.labeledTrailerCounts ? parts.join(",") : parts.map((p) => p.split(":")[1]).join(",");
899
+ this.w.write(`##! summary symbols=${this.nextId} edges=${this.edges} counts=${counts}
900
+ `);
901
+ }
902
+ }
903
+
904
+ class GenericStreamEncoder {
905
+ sections = [];
906
+ current = null;
907
+ w;
908
+ constructor(w) {
909
+ this.w = w;
910
+ w.write(`GCF profile=generic
911
+ `);
912
+ }
913
+ checkFields(fields) {
914
+ for (const f of fields) {
915
+ if (f.includes(">"))
916
+ throw new GcfError("invalid_input", `streaming field name ${JSON.stringify(f)} contains '>' (a flattened path is not representable in a streaming row)`, 0);
917
+ }
918
+ }
919
+ beginArray(name, fields) {
920
+ this.checkFields(fields);
921
+ this.endArray();
922
+ this.w.write(`## ${formatKey(name)} [?]{${fields.map(formatKey).join(",")}}
923
+ `);
924
+ this.current = { count: 0 };
925
+ }
926
+ beginKeyedMap(name, keyLabel, valueFields) {
927
+ this.checkFields(valueFields);
928
+ this.endArray();
929
+ this.w.write(`## ${formatKey(name)} [?:]{${[keyLabel, ...valueFields].map(formatKey).join(",")}}
930
+ `);
931
+ this.current = { count: 0 };
932
+ }
933
+ writeRow(values) {
934
+ if (!this.current)
935
+ throw new GcfError("invalid_input", "writeRow outside beginArray/beginKeyedMap", 0);
936
+ this.w.write(values.map(formatScalar).join("|") + `
937
+ `);
938
+ this.current.count++;
939
+ }
940
+ endArray() {
941
+ if (this.current)
942
+ this.sections.push(this.current.count);
943
+ this.current = null;
944
+ }
945
+ writeKV(key, value) {
946
+ this.endArray();
947
+ this.w.write(`${formatKey(key)}=${formatScalar(value)}
948
+ `);
949
+ }
950
+ writeInlineArray(name, values) {
951
+ this.endArray();
952
+ this.w.write(`${formatKey(name)}[${values.length}]: ${values.map(formatScalar).join(",")}
953
+ `);
954
+ }
955
+ close() {
956
+ this.endArray();
957
+ if (this.sections.length > 0)
958
+ this.w.write(`##! summary counts=${this.sections.join(",")}
959
+ `);
960
+ }
961
+ }
962
+ // src/index.ts
963
+ var shared;
964
+ async function wasmBytes(source) {
965
+ if (source instanceof URL || typeof source === "string") {
966
+ const url = source instanceof URL ? source : new URL(source, import.meta.url);
967
+ if (url.protocol === "file:") {
968
+ const { readFile } = await import("node:fs/promises");
969
+ return readFile(url);
970
+ }
971
+ source = fetch(url);
972
+ }
973
+ const res = await source;
974
+ if (!res.ok)
975
+ throw new Error(`failed to load gcf.wasm: HTTP ${res.status}`);
976
+ return res.arrayBuffer();
977
+ }
978
+ function init(source) {
979
+ if (source === undefined) {
980
+ shared ??= wasmBytes(new URL("./gcf.wasm", import.meta.url)).then((b) => GcfCodec.instantiate(b));
981
+ return shared;
982
+ }
983
+ if (source instanceof WebAssembly.Module || source instanceof ArrayBuffer || ArrayBuffer.isView(source)) {
984
+ return GcfCodec.instantiate(source);
985
+ }
986
+ return wasmBytes(source).then((b) => GcfCodec.instantiate(b));
987
+ }
988
+ export {
989
+ DEFAULT_REANCHOR_N,
990
+ GcfCodec,
991
+ GcfDecodeError,
992
+ GcfDecoder,
993
+ GcfError,
994
+ GenericDeltaSession,
995
+ GenericStreamEncoder,
996
+ GraphSession,
997
+ GraphStreamEncoder,
998
+ formatKey,
999
+ formatNumber,
1000
+ formatScalar,
1001
+ formatScore,
1002
+ init,
1003
+ needsQuote,
1004
+ quoteString,
1005
+ toPlain
1006
+ };