@delali/narsil 0.3.1-next.74 → 0.3.1-next.76

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 (45) hide show
  1. package/dist/{capabilities-CAMzmkAg.d.ts → capabilities-1lEYL3WK.d.ts} +16 -2
  2. package/dist/{chunk-Z3DQPOJQ.mjs → chunk-356UOTK2.mjs} +1 -1
  3. package/dist/chunk-4344I4MR.mjs +2217 -0
  4. package/dist/{chunk-PO53FV4Q.mjs → chunk-AMGDG4ZJ.mjs} +1 -1
  5. package/dist/{chunk-LX4JERXI.mjs → chunk-BT62MUM5.mjs} +1 -1
  6. package/dist/{chunk-NOZUQM7J.mjs → chunk-BT6BI4GV.mjs} +41 -3
  7. package/dist/{chunk-VKX2BPXD.mjs → chunk-D4EF7J3I.mjs} +127 -20
  8. package/dist/{chunk-BVBIQQKG.mjs → chunk-DFFQOA7S.mjs} +26 -67
  9. package/dist/{chunk-CTOSGRM7.mjs → chunk-G7IP3UDZ.mjs} +6 -5
  10. package/dist/chunk-GES7U2PM.mjs +68 -0
  11. package/dist/{chunk-CUZOX6CN.mjs → chunk-HH6ALOUZ.mjs} +31 -27
  12. package/dist/{chunk-LJYTW7GT.mjs → chunk-IBR6634K.mjs} +1 -1
  13. package/dist/{chunk-I23G3IZC.mjs → chunk-NO3ABFLE.mjs} +2 -63
  14. package/dist/{chunk-T5ZWEWVD.mjs → chunk-PJU6EF22.mjs} +3 -2
  15. package/dist/{chunk-TVFLHM7M.mjs → chunk-PXDY5VRT.mjs} +3 -3
  16. package/dist/{chunk-3DDUNI6N.mjs → chunk-V3B24XR7.mjs} +7 -1
  17. package/dist/{client-C-I70ArH.d.ts → client-ZXcbSViH.d.ts} +2 -2
  18. package/dist/client.d.ts +6 -6
  19. package/dist/{config-C6Iw5rCX.d.ts → config-DHL2KsfD.d.ts} +1 -1
  20. package/dist/{config-DJPH3IQB.d.ts → config-DTe5EbWW.d.ts} +4 -2
  21. package/dist/direct-executor-Q7PNCGZB.mjs +17 -0
  22. package/dist/distribution/coordinator/etcd.mjs +1 -1
  23. package/dist/distribution/coordinator/in-memory.mjs +1 -1
  24. package/dist/distribution.d.ts +5 -5
  25. package/dist/distribution.mjs +22 -15
  26. package/dist/{engine-B8eRPO7m.d.ts → engine-BjPBzWkA.d.ts} +1 -1
  27. package/dist/index.browser.mjs +158 -38
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.mjs +13 -13
  30. package/dist/invalidation/filesystem.mjs +1 -1
  31. package/dist/{memory-DJEwWoCi.d.ts → memory-DW3OJ0im.d.ts} +105 -24
  32. package/dist/partial-words.mjs +5 -4
  33. package/dist/pattern.mjs +3 -2
  34. package/dist/persistence/durability/checkpoint-worker.mjs +13 -13
  35. package/dist/react.d.ts +6 -6
  36. package/dist/server.d.ts +8 -8
  37. package/dist/server.mjs +34 -11
  38. package/dist/{tasks-BVmAKYBh.d.ts → tasks-BTbwBqar.d.ts} +1 -1
  39. package/dist/{thread-W6DPKEF6.mjs → thread-YOTNJEVY.mjs} +15 -10
  40. package/dist/vector/search-worker.mjs +2 -2
  41. package/dist/workers/entry.mjs +3 -3
  42. package/package.json +8 -7
  43. package/dist/chunk-XW25X6AU.mjs +0 -614
  44. package/dist/chunk-ZKRV5M2P.mjs +0 -75
  45. package/dist/direct-executor-KFAGILJC.mjs +0 -17
@@ -0,0 +1,2217 @@
1
+ import { tabulatedLevenshtein } from './chunk-GES7U2PM.mjs';
2
+ import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
3
+
4
+ // src/core/bitset.ts
5
+ function createBitSet(capacity) {
6
+ return new Uint32Array(capacity + 31 >>> 5 || 1);
7
+ }
8
+ function bitsetSet(bs, index) {
9
+ const word = index >>> 5;
10
+ if (word < bs.length) {
11
+ bs[word] |= 1 << (index & 31);
12
+ }
13
+ }
14
+ function bitsetHas(bs, index) {
15
+ const word = index >>> 5;
16
+ if (word >= bs.length) return false;
17
+ return (bs[word] & 1 << (index & 31)) !== 0;
18
+ }
19
+ function bitsetAnd(a, b) {
20
+ const len = Math.min(a.length, b.length);
21
+ const result = new Uint32Array(len);
22
+ for (let i = 0; i < len; i++) {
23
+ result[i] = a[i] & b[i];
24
+ }
25
+ return result;
26
+ }
27
+ function bitsetAndInto(target, other) {
28
+ const shared = Math.min(target.length, other.length);
29
+ for (let i = 0; i < shared; i++) target[i] &= other[i];
30
+ target.fill(0, shared);
31
+ }
32
+ function bitsetOrInto(target, other) {
33
+ const shared = Math.min(target.length, other.length);
34
+ for (let i = 0; i < shared; i++) target[i] |= other[i];
35
+ }
36
+ function bitsetAndNotInto(target, removed) {
37
+ const shared = Math.min(target.length, removed.length);
38
+ for (let i = 0; i < shared; i++) target[i] &= ~removed[i];
39
+ }
40
+ function bitsetNot(bs, capacity) {
41
+ const result = new Uint32Array(bs.length);
42
+ const fullWords = capacity >>> 5;
43
+ for (let i = 0; i < fullWords; i++) {
44
+ result[i] = ~bs[i];
45
+ }
46
+ const remainder = capacity & 31;
47
+ if (remainder > 0 && fullWords < bs.length) {
48
+ result[fullWords] = ~bs[fullWords] & (1 << remainder) - 1;
49
+ }
50
+ return result;
51
+ }
52
+ function bitsetIsEmpty(bs) {
53
+ for (let i = 0; i < bs.length; i++) {
54
+ if (bs[i] !== 0) return false;
55
+ }
56
+ return true;
57
+ }
58
+ function bitsetFromSet(set, capacity) {
59
+ const bs = createBitSet(capacity);
60
+ for (const id of set) {
61
+ bs[id >>> 5] |= 1 << (id & 31);
62
+ }
63
+ return bs;
64
+ }
65
+
66
+ // src/core/pattern-index/constants.ts
67
+ var DEFAULT_PATTERN_WORK_CAP = 25e6;
68
+ var MAX_PATTERN_TEXT_CODE_POINTS = 1024;
69
+ var MAX_PATTERN_POSITIONS = 2048;
70
+ var MATCHER_STATE_BUDGET_BYTES = 1e6;
71
+ var MATCHER_CODE_POINT_BYTES = 8;
72
+ var MATCHER_SIMULATION_BYTES_PER_POSITION = 16;
73
+ var MATCHER_STATE_OVERHEAD_BYTES = 96;
74
+ var PATTERN_WORK_FLUSH_UNITS = 65536;
75
+ var PATTERN_RUN_CODE_POINTS = 3;
76
+ var MAX_PATTERN_TOLERANCE = 2;
77
+ var PATTERN_TEST_OPERATORS = ["eq", "ne", "in", "nin", "startsWith", "endsWith", "contains"];
78
+ var PATTERN_EXPRESSION_OPERATORS = ["wildcard", "regex"];
79
+
80
+ // src/pattern/constants.ts
81
+ var MATCHER_TRANSITION_BYTES = 48;
82
+ var MATCHER_EDGE_SLOT_BYTES = 8;
83
+ var MAX_DENSE_EDGE_CLASSES = 64;
84
+ var MATCHER_KEY_CHARACTER_BYTES = 2;
85
+ var MATCHER_MIN_CODE_POINTS_PER_STATE = 10;
86
+ var SHORTLIST_RUN_LOOKUPS = 16;
87
+ var SHORTLIST_INTERSECT_RATIO = 8;
88
+ var RUN_LIST_INITIAL_CAPACITY = 4;
89
+ var RUN_LIST_COMPACTION_FRACTION = 0.5;
90
+ var RUN_ENTRY_OVERHEAD_BYTES = 140;
91
+ var DOCUMENT_ENTRY_BYTES = 24;
92
+ var SIMULATION_STATE_BYTES = 8;
93
+ var SIMULATION_POSITION_BYTES = 8;
94
+ var KEPT_PROGRAM_BUDGET_FRACTION = 0.5;
95
+ var DIRECT_CLASS_CODE_POINTS = 128;
96
+
97
+ // src/pattern/automaton.ts
98
+ var BEFORE_VALUE_START = 0;
99
+ var AFTER_VALUE_END = 0;
100
+ var WORD_CODE_POINT = 1;
101
+ var OTHER_CODE_POINT = 2;
102
+ var EDGE_KINDS = 3;
103
+ var START_MASK = 7;
104
+ var END_MASK = 73;
105
+ var WORD_EDGE_MASK = 170;
106
+ var ANY_CONTEXT_MASK = 511;
107
+ var CONSUME_STATE = 0;
108
+ var SPLIT_STATE = 1;
109
+ var ASSERT_STATE = 2;
110
+ var MATCH_STATE = 3;
111
+ var ANY_CODE_POINT = -2;
112
+ var TESTED_CODE_POINT = -1;
113
+ var MATCH_REACHED = -1;
114
+ var WORD_KIND_EDGES = [48, 58, 65, 91, 95, 96, 97, 123];
115
+ function searchedClass(starts, isFoldTarget, codePoint) {
116
+ if (isFoldTarget?.(codePoint)) return -1 - codePoint;
117
+ let low = 0;
118
+ let high = starts.length;
119
+ while (low < high) {
120
+ const middle = low + high >>> 1;
121
+ if (starts[middle] <= codePoint) low = middle + 1;
122
+ else high = middle;
123
+ }
124
+ return low;
125
+ }
126
+ function codePointClasses(starts, isFoldTarget) {
127
+ const direct = new Int32Array(DIRECT_CLASS_CODE_POINTS);
128
+ for (let codePoint = 0; codePoint < direct.length; codePoint++) {
129
+ direct[codePoint] = searchedClass(starts, isFoldTarget, codePoint);
130
+ }
131
+ return { starts, isFoldTarget, direct };
132
+ }
133
+ function classOf(program, codePoint) {
134
+ const { classes } = program;
135
+ if (codePoint < classes.direct.length) return classes.direct[codePoint];
136
+ return searchedClass(classes.starts, classes.isFoldTarget, codePoint);
137
+ }
138
+ function isWordCodePoint(codePoint) {
139
+ return codePoint >= 48 && codePoint <= 57 || codePoint >= 65 && codePoint <= 90 || codePoint >= 97 && codePoint <= 122 || codePoint === 95;
140
+ }
141
+ function kindOf(codePoint) {
142
+ return isWordCodePoint(codePoint) ? WORD_CODE_POINT : OTHER_CODE_POINT;
143
+ }
144
+ function contextOf(previous, next) {
145
+ return previous * EDGE_KINDS + next;
146
+ }
147
+ function accepts(program, position, codePoint) {
148
+ const literal = program.literals[position];
149
+ if (literal >= 0) return literal === codePoint;
150
+ if (literal === ANY_CODE_POINT) return true;
151
+ return program.tests[position]?.has(codePoint) ?? false;
152
+ }
153
+ var LAST_STAMP = 4294967295;
154
+ function createClosureScratch(states) {
155
+ return { marks: new Uint32Array(states), stack: new Int32Array(states), stamp: 0 };
156
+ }
157
+ function nextStamp(scratch) {
158
+ if (scratch.stamp === LAST_STAMP) {
159
+ scratch.marks.fill(0);
160
+ scratch.stamp = 0;
161
+ }
162
+ scratch.stamp++;
163
+ return scratch.stamp;
164
+ }
165
+ function closeOver(program, seeds, seedCount, fromStart, context, scratch, out) {
166
+ const { kinds, next, alternative, masks } = program;
167
+ const { marks, stack } = scratch;
168
+ const stamp = nextStamp(scratch);
169
+ let depth = 0;
170
+ for (let at = 0; at < seedCount; at++) {
171
+ const state = next[seeds[at]];
172
+ if (marks[state] === stamp) continue;
173
+ marks[state] = stamp;
174
+ stack[depth++] = state;
175
+ }
176
+ if (fromStart && marks[program.start] !== stamp) {
177
+ marks[program.start] = stamp;
178
+ stack[depth++] = program.start;
179
+ }
180
+ let count = 0;
181
+ while (depth > 0) {
182
+ const state = stack[--depth];
183
+ const kind = kinds[state];
184
+ if (kind === CONSUME_STATE) {
185
+ out[count++] = state;
186
+ continue;
187
+ }
188
+ if (kind === MATCH_STATE) return MATCH_REACHED;
189
+ if (kind === ASSERT_STATE && (masks[state] >>> context & 1) === 0) continue;
190
+ const following = next[state];
191
+ if (marks[following] !== stamp) {
192
+ marks[following] = stamp;
193
+ stack[depth++] = following;
194
+ }
195
+ if (kind !== SPLIT_STATE) continue;
196
+ const other = alternative[state];
197
+ if (marks[other] !== stamp) {
198
+ marks[other] = stamp;
199
+ stack[depth++] = other;
200
+ }
201
+ }
202
+ return count;
203
+ }
204
+
205
+ // src/pattern/position-simulation.ts
206
+ var STEP_CONTINUES = 0;
207
+ var STEP_MATCHED = 1;
208
+ var STEP_DEAD = 2;
209
+ var CONTEXTS = 9;
210
+ function simulationBytes(program) {
211
+ const startClosureBytes = CONTEXTS * Uint32Array.BYTES_PER_ELEMENT;
212
+ return program.states * SIMULATION_STATE_BYTES + program.positions * (SIMULATION_POSITION_BYTES + startClosureBytes);
213
+ }
214
+ var PositionSimulation = class {
215
+ constructor(program) {
216
+ this.program = program;
217
+ this.after = new Uint32Array(program.positions);
218
+ this.candidates = new Uint32Array(program.positions);
219
+ this.scratch = createClosureScratch(program.states);
220
+ }
221
+ steps = 0;
222
+ previousKind = BEFORE_VALUE_START;
223
+ after;
224
+ afterCount = 0;
225
+ candidates;
226
+ scratch;
227
+ starts = new Array(CONTEXTS).fill(null);
228
+ get bytes() {
229
+ return simulationBytes(this.program);
230
+ }
231
+ reset() {
232
+ this.afterCount = 0;
233
+ this.previousKind = BEFORE_VALUE_START;
234
+ }
235
+ load(positions, previousKind) {
236
+ this.after.set(positions);
237
+ this.afterCount = positions.length;
238
+ this.previousKind = previousKind;
239
+ }
240
+ sortedAfter() {
241
+ return this.after.slice(0, this.afterCount).sort();
242
+ }
243
+ step(codePoint) {
244
+ const { program, candidates } = this;
245
+ const following = kindOf(codePoint);
246
+ const reached = this.close(contextOf(this.previousKind, following));
247
+ if (reached === MATCH_REACHED) {
248
+ this.steps = 0;
249
+ return STEP_MATCHED;
250
+ }
251
+ this.steps = reached;
252
+ let kept = 0;
253
+ for (let at = 0; at < reached; at++) {
254
+ const position = candidates[at];
255
+ if (accepts(program, position, codePoint)) this.after[kept++] = position;
256
+ }
257
+ this.afterCount = kept;
258
+ this.previousKind = following;
259
+ return kept === 0 && program.anchoredStart ? STEP_DEAD : STEP_CONTINUES;
260
+ }
261
+ endMatches() {
262
+ return this.close(contextOf(this.previousKind, AFTER_VALUE_END)) === MATCH_REACHED;
263
+ }
264
+ startClosure(context) {
265
+ const known = this.starts[context];
266
+ if (known !== null) return known;
267
+ const reached = closeOver(this.program, this.after, 0, true, context, this.scratch, this.candidates);
268
+ const closure = reached === MATCH_REACHED ? { positions: new Uint32Array(0), matches: true } : { positions: this.candidates.slice(0, reached), matches: false };
269
+ this.starts[context] = closure;
270
+ return closure;
271
+ }
272
+ close(context) {
273
+ const fromStart = this.previousKind === BEFORE_VALUE_START || !this.program.anchoredStart;
274
+ const start = fromStart ? this.startClosure(context) : null;
275
+ if (start?.matches) return MATCH_REACHED;
276
+ const { program, scratch, candidates } = this;
277
+ let count = closeOver(program, this.after, this.afterCount, false, context, scratch, candidates);
278
+ if (count === MATCH_REACHED || start === null) return count;
279
+ const { marks, stamp } = scratch;
280
+ for (const position of start.positions) {
281
+ if (marks[position] === stamp) continue;
282
+ marks[position] = stamp;
283
+ candidates[count++] = position;
284
+ }
285
+ return count;
286
+ }
287
+ };
288
+
289
+ // src/pattern/expression/constants.ts
290
+ var MAX_PATTERN_GROUP_DEPTH = 32;
291
+ var MAX_PATTERN_REPEAT_COUNT = 2048;
292
+ var MAX_NUMBER_RANGE_DIGITS = 15;
293
+ var CODE_POINT_TEST_ENTRY_BYTES = 8;
294
+ var PROGRAM_STATE_BYTES = 11;
295
+ var PROGRAM_POSITION_BYTES = 12;
296
+
297
+ // src/pattern/expression/compile.ts
298
+ var UNSET = -1;
299
+ var ProgramBuilder = class {
300
+ kinds = [];
301
+ next = [];
302
+ alternative = [];
303
+ masks = [];
304
+ literals = [];
305
+ tests = [];
306
+ positions = 0;
307
+ add(kind, next, alternative, mask) {
308
+ this.kinds.push(kind);
309
+ this.next.push(next);
310
+ this.alternative.push(alternative);
311
+ this.masks.push(mask);
312
+ this.literals.push(UNSET);
313
+ this.tests.push(null);
314
+ return this.kinds.length - 1;
315
+ }
316
+ consume(literal, test, next) {
317
+ const state = this.add(CONSUME_STATE, next, UNSET, 0);
318
+ this.literals[state] = literal;
319
+ this.tests[state] = test;
320
+ this.positions++;
321
+ return state;
322
+ }
323
+ split(first, second) {
324
+ return this.add(SPLIT_STATE, first, second, 0);
325
+ }
326
+ compile(plan, next) {
327
+ switch (plan.kind) {
328
+ case "consume":
329
+ return this.consume(plan.literal, plan.test, next);
330
+ case "assert":
331
+ return plan.mask === ANY_CONTEXT_MASK ? next : this.add(ASSERT_STATE, next, UNSET, plan.mask);
332
+ case "sequence": {
333
+ let entry = next;
334
+ for (let at = plan.items.length - 1; at >= 0; at--) entry = this.compile(plan.items[at], entry);
335
+ return entry;
336
+ }
337
+ case "choice": {
338
+ let entry = this.compile(plan.branches[plan.branches.length - 1], next);
339
+ for (let at = plan.branches.length - 2; at >= 0; at--)
340
+ entry = this.split(this.compile(plan.branches[at], next), entry);
341
+ return entry;
342
+ }
343
+ case "repeat":
344
+ return this.compileRepeat(plan.body, plan.min, plan.max, next);
345
+ }
346
+ }
347
+ loop(body, next, entersBody) {
348
+ const loop = this.split(UNSET, next);
349
+ const entry = this.compile(body, loop);
350
+ this.next[loop] = entry;
351
+ return entersBody ? entry : loop;
352
+ }
353
+ compileRepeat(body, min, max, next) {
354
+ let entry;
355
+ let required = min;
356
+ if (max === null) {
357
+ entry = this.loop(body, next, min > 0);
358
+ if (min > 0) required--;
359
+ } else {
360
+ entry = next;
361
+ for (let optional = max - min; optional > 0; optional--) entry = this.split(this.compile(body, entry), next);
362
+ }
363
+ for (; required > 0; required--) entry = this.compile(body, entry);
364
+ return entry;
365
+ }
366
+ };
367
+ function startsOnlyAtStart(program) {
368
+ const scratch = createClosureScratch(program.states);
369
+ const candidates = new Uint32Array(program.positions);
370
+ const seeds = new Uint32Array(0);
371
+ for (const previous of [WORD_CODE_POINT, OTHER_CODE_POINT]) {
372
+ for (const following of [AFTER_VALUE_END, WORD_CODE_POINT, OTHER_CODE_POINT]) {
373
+ const reached = closeOver(program, seeds, 0, true, contextOf(previous, following), scratch, candidates);
374
+ if (reached === MATCH_REACHED || reached > 0) return false;
375
+ }
376
+ }
377
+ return true;
378
+ }
379
+ function collectClassEdges(plan, edges, tests) {
380
+ switch (plan.kind) {
381
+ case "consume":
382
+ if (plan.literal >= 0) {
383
+ edges.add(plan.literal);
384
+ edges.add(plan.literal + 1);
385
+ } else if (plan.test !== null && !tests.has(plan.test)) {
386
+ tests.add(plan.test);
387
+ const { ranges } = plan.test;
388
+ for (let at = 0; at < ranges.length; at += 2) {
389
+ edges.add(ranges[at]);
390
+ edges.add(ranges[at + 1] + 1);
391
+ }
392
+ }
393
+ return;
394
+ case "assert":
395
+ return;
396
+ case "sequence":
397
+ for (const item of plan.items) collectClassEdges(item, edges, tests);
398
+ return;
399
+ case "choice":
400
+ for (const branch of plan.branches) collectClassEdges(branch, edges, tests);
401
+ return;
402
+ case "repeat":
403
+ collectClassEdges(plan.body, edges, tests);
404
+ }
405
+ }
406
+ function planClasses(plan) {
407
+ const edges = new Set(WORD_KIND_EDGES);
408
+ const tests = /* @__PURE__ */ new Set();
409
+ collectClassEdges(plan, edges, tests);
410
+ let isFoldTarget = null;
411
+ for (const test of tests) isFoldTarget ??= test.isFoldTarget;
412
+ return codePointClasses(Uint32Array.from(edges).sort(), isFoldTarget);
413
+ }
414
+ function programBytes(states, positions, tests, classes) {
415
+ const distinct = /* @__PURE__ */ new Set();
416
+ for (const test of tests) if (test !== null) distinct.add(test);
417
+ let bytes = states * PROGRAM_STATE_BYTES + positions * PROGRAM_POSITION_BYTES + classes.starts.byteLength + classes.direct.byteLength;
418
+ for (const test of distinct) bytes += test.bytes;
419
+ return bytes;
420
+ }
421
+ function sizeOf(plan, tests) {
422
+ switch (plan.kind) {
423
+ case "consume":
424
+ if (plan.test !== null) tests.add(plan.test);
425
+ return { states: 1, positions: 1 };
426
+ case "assert":
427
+ return { states: plan.mask === ANY_CONTEXT_MASK ? 0 : 1, positions: 0 };
428
+ case "sequence":
429
+ case "choice": {
430
+ const children = plan.kind === "sequence" ? plan.items : plan.branches;
431
+ const total = { states: plan.kind === "choice" ? children.length - 1 : 0, positions: 0 };
432
+ for (const child of children) {
433
+ const size = sizeOf(child, tests);
434
+ total.states += size.states;
435
+ total.positions += size.positions;
436
+ }
437
+ return total;
438
+ }
439
+ case "repeat": {
440
+ const body = sizeOf(plan.body, tests);
441
+ if (plan.max === null) {
442
+ const copies = Math.max(plan.min, 1);
443
+ return { states: 1 + copies * body.states, positions: copies * body.positions };
444
+ }
445
+ const optional = plan.max - plan.min;
446
+ return { states: optional + plan.max * body.states, positions: plan.max * body.positions };
447
+ }
448
+ }
449
+ }
450
+ function planSize(plan) {
451
+ const tests = /* @__PURE__ */ new Set();
452
+ const size = sizeOf(plan, tests);
453
+ const states = size.states + 1;
454
+ return {
455
+ states,
456
+ positions: size.positions,
457
+ bytes: programBytes(states, size.positions, tests, planClasses(plan))
458
+ };
459
+ }
460
+ function compileProgram(plan) {
461
+ const builder = new ProgramBuilder();
462
+ const match = builder.add(MATCH_STATE, UNSET, UNSET, 0);
463
+ const start = builder.compile(plan, match);
464
+ const count = builder.kinds.length;
465
+ const renumbered = new Int32Array(count);
466
+ let nextPosition = 0;
467
+ let nextOther = builder.positions;
468
+ for (let state = 0; state < count; state++) {
469
+ renumbered[state] = builder.kinds[state] === CONSUME_STATE ? nextPosition++ : nextOther++;
470
+ }
471
+ const kinds = new Uint8Array(count);
472
+ const next = new Int32Array(count);
473
+ const alternative = new Int32Array(count);
474
+ const masks = new Uint16Array(count);
475
+ const literals = new Int32Array(builder.positions);
476
+ const tests = new Array(builder.positions).fill(null);
477
+ for (let state = 0; state < count; state++) {
478
+ const target = renumbered[state];
479
+ kinds[target] = builder.kinds[state];
480
+ next[target] = builder.next[state] === UNSET ? UNSET : renumbered[builder.next[state]];
481
+ alternative[target] = builder.alternative[state] === UNSET ? UNSET : renumbered[builder.alternative[state]];
482
+ masks[target] = builder.masks[state];
483
+ if (target < builder.positions) {
484
+ literals[target] = builder.literals[state];
485
+ tests[target] = builder.tests[state];
486
+ }
487
+ }
488
+ const classes = planClasses(plan);
489
+ const draft = {
490
+ positions: builder.positions,
491
+ states: count,
492
+ kinds,
493
+ next,
494
+ alternative,
495
+ masks,
496
+ literals,
497
+ tests,
498
+ start: renumbered[start],
499
+ anchoredStart: false,
500
+ classes,
501
+ bytes: programBytes(count, builder.positions, tests, classes)
502
+ };
503
+ return { ...draft, anchoredStart: startsOnlyAtStart(draft) };
504
+ }
505
+
506
+ // src/pattern/expression/code-point-tests.ts
507
+ var CLASS_RANGES = {
508
+ digit: [48, 57],
509
+ word: [48, 57, 65, 90, 95, 95, 97, 122],
510
+ space: [9, 10, 12, 13, 32, 32]
511
+ };
512
+ function mergedRanges(bounds) {
513
+ const pairs = [];
514
+ for (let at = 0; at < bounds.length; at += 2) pairs.push([bounds[at], bounds[at + 1]]);
515
+ pairs.sort((left, right) => left[0] - right[0]);
516
+ const merged = [];
517
+ for (const [low, high] of pairs) {
518
+ const last = merged.length - 1;
519
+ if (merged.length > 0 && low <= merged[last] + 1) merged[last] = Math.max(merged[last], high);
520
+ else merged.push(low, high);
521
+ }
522
+ return Uint32Array.from(merged);
523
+ }
524
+ function inRanges(ranges, codePoint) {
525
+ let low = 0;
526
+ let high = ranges.length / 2;
527
+ while (low < high) {
528
+ const middle = low + high >>> 1;
529
+ if (codePoint < ranges[middle * 2]) high = middle;
530
+ else if (codePoint > ranges[middle * 2 + 1]) low = middle + 1;
531
+ else return true;
532
+ }
533
+ return false;
534
+ }
535
+ function rangeBoundsOf(items) {
536
+ const bounds = [];
537
+ for (const item of items) {
538
+ if (item.kind === "member") bounds.push(item.codePoint, item.codePoint);
539
+ else if (item.kind === "range") bounds.push(item.low, item.high);
540
+ else bounds.push(...CLASS_RANGES[item.name]);
541
+ }
542
+ return bounds;
543
+ }
544
+ function rangeTest(ranges, negated) {
545
+ return {
546
+ bytes: ranges.byteLength + CODE_POINT_TEST_ENTRY_BYTES,
547
+ ranges,
548
+ isFoldTarget: null,
549
+ has: (codePoint) => inRanges(ranges, codePoint) !== negated
550
+ };
551
+ }
552
+ function foldedRangeTest(ranges, negated, host) {
553
+ const holdsFold = (folded) => {
554
+ if (inRanges(ranges, folded)) return true;
555
+ for (const source of host.singleFoldSources(folded)) if (inRanges(ranges, source)) return true;
556
+ return false;
557
+ };
558
+ return {
559
+ bytes: ranges.byteLength + CODE_POINT_TEST_ENTRY_BYTES,
560
+ ranges,
561
+ isFoldTarget: (folded) => host.singleFoldSources(folded).length > 0,
562
+ has: (folded) => holdsFold(folded) !== negated
563
+ };
564
+ }
565
+ function classTest(name) {
566
+ return rangeTest(mergedRanges([...CLASS_RANGES[name]]), false);
567
+ }
568
+ function setTest(items, negated, caseFold, host) {
569
+ const ranges = mergedRanges(rangeBoundsOf(items));
570
+ return caseFold ? foldedRangeTest(ranges, negated, host) : rangeTest(ranges, negated);
571
+ }
572
+ function distinctMultiFolds(items, host) {
573
+ const seen = /* @__PURE__ */ new Set();
574
+ const folds = [];
575
+ for (const item of items) {
576
+ if (item.kind !== "member") continue;
577
+ const fold = [];
578
+ host.appendFoldedCodePoint(item.codePoint, fold);
579
+ if (fold.length < 2) continue;
580
+ const key = String.fromCodePoint(...fold);
581
+ if (seen.has(key)) continue;
582
+ seen.add(key);
583
+ folds.push(fold);
584
+ }
585
+ return folds;
586
+ }
587
+
588
+ // src/pattern/expression/lower.ts
589
+ var EMPTY = { kind: "assert", mask: ANY_CONTEXT_MASK };
590
+ function literalPlan(codePoint) {
591
+ return { kind: "consume", literal: codePoint, test: null };
592
+ }
593
+ function testedPlan(test) {
594
+ return { kind: "consume", literal: TESTED_CODE_POINT, test };
595
+ }
596
+ function sequenceOf(items) {
597
+ const kept = [];
598
+ let mask = ANY_CONTEXT_MASK;
599
+ const flushMask = () => {
600
+ if (mask !== ANY_CONTEXT_MASK) kept.push({ kind: "assert", mask });
601
+ mask = ANY_CONTEXT_MASK;
602
+ };
603
+ const visit = (item) => {
604
+ if (item.kind === "sequence") {
605
+ for (const nested of item.items) visit(nested);
606
+ } else if (item.kind === "assert") {
607
+ mask &= item.mask;
608
+ } else {
609
+ flushMask();
610
+ kept.push(item);
611
+ }
612
+ };
613
+ for (const item of items) visit(item);
614
+ if (kept.length === 0) return { kind: "assert", mask };
615
+ flushMask();
616
+ return kept.length === 1 ? kept[0] : { kind: "sequence", items: kept };
617
+ }
618
+ function choiceOf(branches) {
619
+ const kept = [];
620
+ let mask = 0;
621
+ let empty = false;
622
+ const visit = (branch) => {
623
+ if (branch.kind === "choice") {
624
+ for (const nested of branch.branches) visit(nested);
625
+ } else if (branch.kind === "assert") {
626
+ mask |= branch.mask;
627
+ empty = true;
628
+ } else {
629
+ kept.push(branch);
630
+ }
631
+ };
632
+ for (const branch of branches) visit(branch);
633
+ if (kept.length === 0) return { kind: "assert", mask };
634
+ if (empty) kept.push({ kind: "assert", mask });
635
+ return kept.length === 1 ? kept[0] : { kind: "choice", branches: kept };
636
+ }
637
+ function isLoose(plan) {
638
+ return plan.kind === "repeat" && plan.min <= 1 && (plan.max === null || plan.max === 1);
639
+ }
640
+ function repeatOf(body, min, max) {
641
+ if (max === 0) return EMPTY;
642
+ if (body.kind === "assert") return min === 0 ? EMPTY : body;
643
+ if (min === 1 && max === 1) return body;
644
+ const loose = min <= 1 && (max === null || max === 1);
645
+ if (loose && isLoose(body)) {
646
+ const nullable = min === 0 || body.min === 0;
647
+ const unbounded = max === null || body.max === null;
648
+ return { kind: "repeat", body: body.body, min: nullable ? 0 : 1, max: unbounded ? null : 1 };
649
+ }
650
+ return { kind: "repeat", body, min, max };
651
+ }
652
+ function foldedLiteral(codePoint, host, scratch) {
653
+ scratch.length = 0;
654
+ host.appendFoldedCodePoint(codePoint, scratch);
655
+ return sequenceOf(scratch.map(literalPlan));
656
+ }
657
+ function setPlan(node, caseFold, host) {
658
+ const single = testedPlan(setTest(node.items, node.negated, caseFold, host));
659
+ if (!caseFold || node.negated) return single;
660
+ const sequences = distinctMultiFolds(node.items, host).map((fold) => sequenceOf(fold.map(literalPlan)));
661
+ return sequences.length === 0 ? single : choiceOf([single, ...sequences]);
662
+ }
663
+ function lowerNode(node, caseFold, host, scratch) {
664
+ switch (node.kind) {
665
+ case "literal":
666
+ return caseFold ? foldedLiteral(node.codePoint, host, scratch) : literalPlan(node.codePoint);
667
+ case "any":
668
+ return literalPlan(ANY_CODE_POINT);
669
+ case "class":
670
+ return testedPlan(classTest(node.name));
671
+ case "set":
672
+ return setPlan(node, caseFold, host);
673
+ case "assert":
674
+ return node;
675
+ case "sequence":
676
+ return sequenceOf(node.items.map((item) => lowerNode(item, caseFold, host, scratch)));
677
+ case "choice":
678
+ return choiceOf(node.branches.map((branch) => lowerNode(branch, caseFold, host, scratch)));
679
+ case "repeat":
680
+ return repeatOf(lowerNode(node.body, caseFold, host, scratch), node.min, node.max);
681
+ case "numberRange":
682
+ return lowerNode(node.expansion, caseFold, host, scratch);
683
+ }
684
+ }
685
+ function lowerPattern(node, caseFold, host) {
686
+ return lowerNode(node, caseFold, host, []);
687
+ }
688
+
689
+ // src/pattern/expression/number-range.ts
690
+ function digitAt(text, at) {
691
+ return text.charCodeAt(at) - 48;
692
+ }
693
+ function sameWidth(low, high) {
694
+ const width = low.length;
695
+ if (low === high) return low;
696
+ if (/^0+$/.test(low) && /^9+$/.test(high)) return width === 1 ? "[0-9]" : `[0-9]{${width}}`;
697
+ if (width === 1) return `[${low}-${high}]`;
698
+ if (low[0] === high[0]) return low[0] + sameWidth(low.slice(1), high.slice(1));
699
+ const parts = [low[0] + sameWidth(low.slice(1), "9".repeat(width - 1))];
700
+ const lowLead = digitAt(low, 0);
701
+ const highLead = digitAt(high, 0);
702
+ if (lowLead + 1 <= highLead - 1) parts.push(`[${lowLead + 1}-${highLead - 1}]${"[0-9]".repeat(width - 1)}`);
703
+ parts.push(high[0] + sameWidth("0".repeat(width - 1), high.slice(1)));
704
+ return `(${parts.join("|")})`;
705
+ }
706
+ function numberRange(low, high) {
707
+ if (low.length === high.length) return sameWidth(low, high);
708
+ const highest = Number(high);
709
+ const parts = [];
710
+ let start = Number(low);
711
+ const widest = String(highest).length;
712
+ for (let width = String(start).length; width <= widest; width++) {
713
+ const last = Math.min(highest, 10 ** width - 1);
714
+ parts.push(sameWidth(String(start), String(last)));
715
+ start = 10 ** width;
716
+ }
717
+ return `(${parts.join("|")})`;
718
+ }
719
+ function compareDigits(low, high) {
720
+ return Number(low) - Number(high);
721
+ }
722
+
723
+ // src/pattern/expression/reader.ts
724
+ var TRAILING_ESCAPE = 'ends in a "\\" with no code point after it';
725
+ function toCodePoints(text) {
726
+ const codePoints = [];
727
+ for (let at = 0; at < text.length; at++) {
728
+ const codePoint = text.codePointAt(at) ?? 0;
729
+ if (codePoint > 65535) at++;
730
+ codePoints.push(codePoint);
731
+ }
732
+ return codePoints;
733
+ }
734
+ function quoted(text) {
735
+ return `"${text}"`;
736
+ }
737
+
738
+ // src/pattern/expression/parse-regex.ts
739
+ var BACKSLASH = 92;
740
+ var DOT = 46;
741
+ var BAR = 124;
742
+ var STAR = 42;
743
+ var PLUS = 43;
744
+ var QUESTION = 63;
745
+ var OPEN_BRACE = 123;
746
+ var CLOSE_BRACE = 125;
747
+ var OPEN_PAREN = 40;
748
+ var CLOSE_PAREN = 41;
749
+ var OPEN_BRACKET = 91;
750
+ var CLOSE_BRACKET = 93;
751
+ var CARET = 94;
752
+ var DOLLAR = 36;
753
+ var LESS = 60;
754
+ var GREATER = 62;
755
+ var HYPHEN = 45;
756
+ var COMMA = 44;
757
+ var ZERO = 48;
758
+ var NINE = 57;
759
+ var RESERVED = /* @__PURE__ */ new Set([
760
+ BACKSLASH,
761
+ DOT,
762
+ BAR,
763
+ STAR,
764
+ PLUS,
765
+ QUESTION,
766
+ OPEN_BRACE,
767
+ CLOSE_BRACE,
768
+ OPEN_PAREN,
769
+ CLOSE_PAREN,
770
+ OPEN_BRACKET,
771
+ CLOSE_BRACKET,
772
+ CARET,
773
+ DOLLAR,
774
+ LESS,
775
+ GREATER
776
+ ]);
777
+ var NO_COUNT = `holds a "{" that doesn't open a count such as {2}, {2,}, or {2,5}. Write "\\{" to match the brace itself`;
778
+ var RANGE_ENDS_IN_CLASS = "holds a set range whose high end is a class, while both ends of a set range must be code points";
779
+ var SET_NEVER_CLOSES = "opens a set that it never closes";
780
+ var NEGATED_EMPTY_SET = 'holds the set "[^]", which has no member, because a "^" after "[" always negates the set. Write "\\^" to match a caret, "." to match any code point, or "\\]" to match "]" inside a set';
781
+ var CLASS_ESCAPES = /* @__PURE__ */ new Map([
782
+ [100, "digit"],
783
+ [119, "word"],
784
+ [115, "space"]
785
+ ]);
786
+ var WORD_EDGE_ESCAPE = 98;
787
+ function isAsciiPunctuation(codePoint) {
788
+ return codePoint >= 33 && codePoint <= 47 || codePoint >= 58 && codePoint <= 64 || codePoint >= 91 && codePoint <= 96 || codePoint >= 123 && codePoint <= 126;
789
+ }
790
+ function isDigit(codePoint) {
791
+ return codePoint !== void 0 && codePoint >= ZERO && codePoint <= NINE;
792
+ }
793
+ function unknownEscape(codePoint) {
794
+ const shown = quoted(`\\${String.fromCodePoint(codePoint)}`);
795
+ if (isDigit(codePoint)) return `holds the back-reference ${shown}, which the grammar leaves out`;
796
+ if (codePoint === 112 || codePoint === 80) {
797
+ return `holds the Unicode property class ${shown}, which the grammar leaves out`;
798
+ }
799
+ return `holds ${shown}. A "\\" can come only before an ASCII punctuation mark, "d", "w", "s", or "b"`;
800
+ }
801
+ function reservedHere(codePoint) {
802
+ const shown = String.fromCodePoint(codePoint);
803
+ if (codePoint === STAR || codePoint === PLUS || codePoint === QUESTION) {
804
+ return `holds the repeat ${quoted(shown)} with nothing before it to repeat`;
805
+ }
806
+ return `holds ${quoted(shown)}, which has a meaning of its own in the grammar. Write ${quoted(`\\${shown}`)} to match the code point itself`;
807
+ }
808
+ var RegexReader = class _RegexReader {
809
+ constructor(codePoints, fail) {
810
+ this.codePoints = codePoints;
811
+ this.fail = fail;
812
+ }
813
+ at = 0;
814
+ depth = 0;
815
+ parse() {
816
+ const pattern = this.parsePattern();
817
+ if (this.at < this.codePoints.length) this.fail("closes a group that it never opened", this.at);
818
+ return pattern;
819
+ }
820
+ peek(offset = 0) {
821
+ return this.codePoints[this.at + offset];
822
+ }
823
+ parsePattern() {
824
+ const branches = [this.parseBranch()];
825
+ while (this.peek() === BAR) {
826
+ this.at++;
827
+ branches.push(this.parseBranch());
828
+ }
829
+ return branches.length === 1 ? branches[0] : { kind: "choice", branches };
830
+ }
831
+ parseBranch() {
832
+ const items = [];
833
+ for (let next = this.peek(); next !== void 0 && next !== BAR && next !== CLOSE_PAREN; next = this.peek()) {
834
+ items.push(this.parsePiece());
835
+ }
836
+ return items.length === 1 ? items[0] : { kind: "sequence", items };
837
+ }
838
+ parsePiece() {
839
+ const atom = this.parseAtom();
840
+ const repeated = this.parseRepeat(atom);
841
+ const next = this.peek();
842
+ if (repeated !== atom && (next === STAR || next === PLUS || next === QUESTION || next === OPEN_BRACE)) {
843
+ this.fail(
844
+ `holds a second repeat ${quoted(String.fromCodePoint(next))} after one atom. The grammar allows one repeat for each atom, so it has no lazy or possessive repeats`,
845
+ this.at
846
+ );
847
+ }
848
+ return repeated;
849
+ }
850
+ parseAtom() {
851
+ const start = this.at;
852
+ const codePoint = this.codePoints[this.at++];
853
+ if (codePoint === BACKSLASH) return this.parseEscape(start);
854
+ if (codePoint === DOT) return { kind: "any" };
855
+ if (codePoint === CARET) return { kind: "assert", mask: START_MASK };
856
+ if (codePoint === DOLLAR) return { kind: "assert", mask: END_MASK };
857
+ if (codePoint === OPEN_BRACKET) return this.parseSet(start);
858
+ if (codePoint === OPEN_PAREN) return this.parseGroup(start);
859
+ if (codePoint === LESS) return this.parseNumberRange(start);
860
+ if (RESERVED.has(codePoint)) this.fail(reservedHere(codePoint), start);
861
+ return { kind: "literal", codePoint };
862
+ }
863
+ parseEscape(start) {
864
+ const escaped = this.codePoints[this.at++];
865
+ if (escaped === void 0) this.fail(TRAILING_ESCAPE, start);
866
+ const name = CLASS_ESCAPES.get(escaped);
867
+ if (name !== void 0) return { kind: "class", name };
868
+ if (escaped === WORD_EDGE_ESCAPE) return { kind: "assert", mask: WORD_EDGE_MASK };
869
+ if (isAsciiPunctuation(escaped)) return { kind: "literal", codePoint: escaped };
870
+ this.fail(unknownEscape(escaped), start);
871
+ }
872
+ parseGroup(start) {
873
+ if (this.peek() === QUESTION) {
874
+ this.fail(
875
+ 'holds "(?", which opens a lookaround, an inline flag, or a non-capturing group. The grammar leaves out all three',
876
+ start
877
+ );
878
+ }
879
+ this.depth++;
880
+ if (this.depth > MAX_PATTERN_GROUP_DEPTH) {
881
+ this.fail(`nests its groups more than ${MAX_PATTERN_GROUP_DEPTH} deep`, start);
882
+ }
883
+ const body = this.parsePattern();
884
+ if (this.peek() !== CLOSE_PAREN) this.fail("opens a group that it never closes", start);
885
+ this.at++;
886
+ this.depth--;
887
+ return body;
888
+ }
889
+ parseRepeat(atom) {
890
+ const codePoint = this.peek();
891
+ if (codePoint === STAR || codePoint === PLUS || codePoint === QUESTION) {
892
+ this.at++;
893
+ const min2 = codePoint === PLUS ? 1 : 0;
894
+ return { kind: "repeat", body: atom, min: min2, max: codePoint === QUESTION ? 1 : null };
895
+ }
896
+ if (codePoint !== OPEN_BRACE) return atom;
897
+ const start = this.at++;
898
+ const min = this.readCount(start);
899
+ let max = min;
900
+ if (this.peek() === COMMA) {
901
+ this.at++;
902
+ max = isDigit(this.peek()) ? this.readCount(start) : null;
903
+ }
904
+ if (this.peek() !== CLOSE_BRACE) {
905
+ this.fail(NO_COUNT, start);
906
+ }
907
+ this.at++;
908
+ if (max !== null && min > max) {
909
+ this.fail(`holds the count {${min},${max}}, whose lower count is above its upper count`, start);
910
+ }
911
+ return { kind: "repeat", body: atom, min, max };
912
+ }
913
+ readCount(start) {
914
+ if (!isDigit(this.peek())) {
915
+ this.fail(NO_COUNT, start);
916
+ }
917
+ let count = 0;
918
+ for (let digit = this.peek(); digit !== void 0 && isDigit(digit); digit = this.peek()) {
919
+ count = Math.min(count * 10 + digit - ZERO, MAX_PATTERN_REPEAT_COUNT + 1);
920
+ this.at++;
921
+ }
922
+ if (count > MAX_PATTERN_REPEAT_COUNT) {
923
+ this.fail(`holds a count above the limit of ${MAX_PATTERN_REPEAT_COUNT}`, start);
924
+ }
925
+ return count;
926
+ }
927
+ parseSet(start) {
928
+ const negated = this.peek() === CARET;
929
+ if (negated) this.at++;
930
+ const items = [];
931
+ for (; ; ) {
932
+ const codePoint = this.peek();
933
+ if (codePoint === void 0) this.fail(SET_NEVER_CLOSES, start);
934
+ if (codePoint === CLOSE_BRACKET) break;
935
+ items.push(this.parseSetItem());
936
+ }
937
+ this.at++;
938
+ if (items.length === 0) this.fail(negated ? NEGATED_EMPTY_SET : "holds an empty set", start);
939
+ return { kind: "set", negated, items };
940
+ }
941
+ parseSetItem() {
942
+ const start = this.at;
943
+ const low = this.parseSetMember(true);
944
+ if (typeof low !== "number") return low;
945
+ if (this.peek() !== HYPHEN || this.peek(1) === CLOSE_BRACKET) return { kind: "member", codePoint: low };
946
+ this.at++;
947
+ const high = this.parseSetMember(false);
948
+ if (typeof high !== "number") this.fail(RANGE_ENDS_IN_CLASS, start);
949
+ if (low > high) {
950
+ this.fail(
951
+ `holds the set range ${quoted(`${String.fromCodePoint(low)}-${String.fromCodePoint(high)}`)}, whose low end is above its high end`,
952
+ start
953
+ );
954
+ }
955
+ return { kind: "range", low, high };
956
+ }
957
+ parseSetMember(classAllowed) {
958
+ const start = this.at;
959
+ const codePoint = this.codePoints[this.at++];
960
+ if (codePoint === void 0) this.fail(SET_NEVER_CLOSES, start);
961
+ if (codePoint === OPEN_BRACKET || codePoint === CLOSE_BRACKET || codePoint === HYPHEN) {
962
+ const shown = String.fromCodePoint(codePoint);
963
+ this.fail(
964
+ `holds ${quoted(shown)} inside a set. Write ${quoted(`\\${shown}`)} to match that code point there`,
965
+ start
966
+ );
967
+ }
968
+ if (codePoint !== BACKSLASH) return codePoint;
969
+ const escaped = this.codePoints[this.at++];
970
+ if (escaped === void 0) this.fail(TRAILING_ESCAPE, start);
971
+ const name = CLASS_ESCAPES.get(escaped);
972
+ if (name !== void 0 && classAllowed) return { kind: "class", name };
973
+ if (isAsciiPunctuation(escaped)) return escaped;
974
+ if (name !== void 0) this.fail(RANGE_ENDS_IN_CLASS, start);
975
+ this.fail(unknownEscape(escaped), start);
976
+ }
977
+ parseNumberRange(start) {
978
+ const low = this.readDigits();
979
+ const hyphen = this.codePoints[this.at++];
980
+ const high = hyphen === HYPHEN ? this.readDigits() : "";
981
+ const closing = this.codePoints[this.at++];
982
+ if (low === "" || high === "" || closing !== GREATER) {
983
+ this.fail(
984
+ `holds a "<" that doesn't open a number range such as <1-65535>. Each end of a number range holds from 1 to ${MAX_NUMBER_RANGE_DIGITS} digits. Write "\\<" to match the "<" itself`,
985
+ start
986
+ );
987
+ }
988
+ if (compareDigits(low, high) > 0) {
989
+ this.fail(`holds the number range ${quoted(`<${low}-${high}>`)}, whose low end is above its high end`, start);
990
+ }
991
+ const expansion = new _RegexReader(toCodePoints(numberRange(low, high)), this.fail).parse();
992
+ return { kind: "numberRange", expansion };
993
+ }
994
+ readDigits() {
995
+ let digits = "";
996
+ for (let digit = this.peek(); isDigit(digit) && digit !== void 0; digit = this.peek()) {
997
+ if (digits.length === MAX_NUMBER_RANGE_DIGITS) return "";
998
+ digits += String.fromCodePoint(digit);
999
+ this.at++;
1000
+ }
1001
+ return digits;
1002
+ }
1003
+ };
1004
+ function parseRegex(codePoints, fail) {
1005
+ return new RegexReader(codePoints, fail).parse();
1006
+ }
1007
+
1008
+ // src/pattern/expression/parse-wildcard.ts
1009
+ var BACKSLASH2 = 92;
1010
+ var STAR2 = 42;
1011
+ var QUESTION2 = 63;
1012
+ function parseWildcard(codePoints, fail) {
1013
+ const items = [{ kind: "assert", mask: START_MASK }];
1014
+ for (let at = 0; at < codePoints.length; at++) {
1015
+ const codePoint = codePoints[at];
1016
+ if (codePoint === STAR2) {
1017
+ items.push({ kind: "repeat", body: { kind: "any" }, min: 0, max: null });
1018
+ } else if (codePoint === QUESTION2) {
1019
+ items.push({ kind: "any" });
1020
+ } else if (codePoint === BACKSLASH2) {
1021
+ if (at + 1 === codePoints.length) fail(TRAILING_ESCAPE, at);
1022
+ items.push({ kind: "literal", codePoint: codePoints[++at] });
1023
+ } else {
1024
+ items.push({ kind: "literal", codePoint });
1025
+ }
1026
+ }
1027
+ items.push({ kind: "assert", mask: END_MASK });
1028
+ return { kind: "sequence", items };
1029
+ }
1030
+
1031
+ // src/pattern/expression/positions.ts
1032
+ var SATURATED = MAX_PATTERN_POSITIONS + 1;
1033
+ function saturating(total) {
1034
+ return Math.min(total, SATURATED);
1035
+ }
1036
+ function literalPositions(codePoint, caseFold, host, scratch) {
1037
+ if (!caseFold) return 1;
1038
+ scratch.length = 0;
1039
+ host.appendFoldedCodePoint(codePoint, scratch);
1040
+ return scratch.length;
1041
+ }
1042
+ function positionsOf(node, caseFold, host, scratch) {
1043
+ switch (node.kind) {
1044
+ case "literal":
1045
+ return literalPositions(node.codePoint, caseFold, host, scratch);
1046
+ case "any":
1047
+ case "class":
1048
+ return 1;
1049
+ case "set": {
1050
+ if (!caseFold || node.negated) return 1;
1051
+ let total = 1;
1052
+ for (const fold of distinctMultiFolds(node.items, host)) total = saturating(total + fold.length);
1053
+ return total;
1054
+ }
1055
+ case "assert":
1056
+ return 0;
1057
+ case "sequence":
1058
+ case "choice": {
1059
+ let total = 0;
1060
+ const children = node.kind === "sequence" ? node.items : node.branches;
1061
+ for (const child of children) {
1062
+ total = saturating(total + positionsOf(child, caseFold, host, scratch));
1063
+ if (total === SATURATED) return total;
1064
+ }
1065
+ return total;
1066
+ }
1067
+ case "repeat": {
1068
+ const copies = node.max === null ? Math.max(node.min, 1) : node.max;
1069
+ return saturating(copies * positionsOf(node.body, caseFold, host, scratch));
1070
+ }
1071
+ case "numberRange":
1072
+ return positionsOf(node.expansion, caseFold, host, scratch);
1073
+ }
1074
+ }
1075
+ function patternPositions(node, caseFold, host) {
1076
+ return positionsOf(node, caseFold, host, []);
1077
+ }
1078
+
1079
+ // src/pattern/text.ts
1080
+ var BASIC_PLANE_LAST = 65535;
1081
+ function appendTextCodePoints(text, caseFold, host, out) {
1082
+ for (let at = 0; at < text.length; at++) {
1083
+ const codePoint = text.codePointAt(at) ?? 0;
1084
+ if (codePoint > BASIC_PLANE_LAST) at++;
1085
+ if (caseFold) host.appendFoldedCodePoint(codePoint, out);
1086
+ else out.push(codePoint);
1087
+ }
1088
+ }
1089
+ function runKey(first, second, third) {
1090
+ return String.fromCodePoint(first, second, third);
1091
+ }
1092
+ function runKeyCodePoints(key, out, offset) {
1093
+ let slot = offset;
1094
+ for (let at = 0; at < key.length && slot < offset + PATTERN_RUN_CODE_POINTS; at++) {
1095
+ const codePoint = key.codePointAt(at) ?? 0;
1096
+ out[slot++] = codePoint;
1097
+ if (codePoint > BASIC_PLANE_LAST) at++;
1098
+ }
1099
+ }
1100
+ function compareRuns(left, leftAt, right, rightAt) {
1101
+ for (let offset = 0; offset < PATTERN_RUN_CODE_POINTS; offset++) {
1102
+ const difference = left[leftAt + offset] - right[rightAt + offset];
1103
+ if (difference !== 0) return difference;
1104
+ }
1105
+ return 0;
1106
+ }
1107
+ function collectRunKeys(foldedCodePoints, out) {
1108
+ for (let at = 0; at + PATTERN_RUN_CODE_POINTS <= foldedCodePoints.length; at++) {
1109
+ out.add(runKey(foldedCodePoints[at], foldedCodePoints[at + 1], foldedCodePoints[at + 2]));
1110
+ }
1111
+ }
1112
+ function forEachTextValue(value, visit) {
1113
+ if (typeof value === "string") {
1114
+ visit(value);
1115
+ return;
1116
+ }
1117
+ if (!Array.isArray(value)) return;
1118
+ for (const element of value) {
1119
+ if (typeof element === "string") visit(element);
1120
+ }
1121
+ }
1122
+ function holdsTextValue(value) {
1123
+ return typeof value === "string" || Array.isArray(value);
1124
+ }
1125
+
1126
+ // src/pattern/expression/required-runs.ts
1127
+ var NO_RUNS = new Uint32Array(0);
1128
+ var FactorCollector = class {
1129
+ constructor(host) {
1130
+ this.host = host;
1131
+ }
1132
+ factors = [];
1133
+ current = [];
1134
+ flush() {
1135
+ if (this.current.length >= PATTERN_RUN_CODE_POINTS) this.factors.push(this.current);
1136
+ this.current = [];
1137
+ }
1138
+ visit(node) {
1139
+ switch (node.kind) {
1140
+ case "literal":
1141
+ this.host.appendFoldedCodePoint(node.codePoint, this.current);
1142
+ return;
1143
+ case "assert":
1144
+ return;
1145
+ case "sequence":
1146
+ for (const item of node.items) this.visit(item);
1147
+ return;
1148
+ case "repeat":
1149
+ if (node.min === 1 && node.max === 1) {
1150
+ this.visit(node.body);
1151
+ return;
1152
+ }
1153
+ this.flush();
1154
+ if (node.min >= 1) {
1155
+ this.visit(node.body);
1156
+ this.flush();
1157
+ }
1158
+ return;
1159
+ default:
1160
+ this.flush();
1161
+ }
1162
+ }
1163
+ };
1164
+ function spreadRuns(factors) {
1165
+ let total = 0;
1166
+ for (const factor of factors) total += Math.max(0, factor.length - PATTERN_RUN_CODE_POINTS + 1);
1167
+ if (total === 0) return NO_RUNS;
1168
+ const picks = Math.min(total, SHORTLIST_RUN_LOOKUPS);
1169
+ const seen = /* @__PURE__ */ new Set();
1170
+ const runs = [];
1171
+ let factorAt = 0;
1172
+ let factorStart = 0;
1173
+ for (let pick = 0; pick < picks; pick++) {
1174
+ const target = picks === 1 ? 0 : Math.round(pick * (total - 1) / (picks - 1));
1175
+ let factorRuns = Math.max(0, factors[factorAt].length - PATTERN_RUN_CODE_POINTS + 1);
1176
+ while (target >= factorStart + factorRuns) {
1177
+ factorStart += factorRuns;
1178
+ factorAt++;
1179
+ factorRuns = Math.max(0, factors[factorAt].length - PATTERN_RUN_CODE_POINTS + 1);
1180
+ }
1181
+ const factor = factors[factorAt];
1182
+ const at = target - factorStart;
1183
+ const key = runKey(factor[at], factor[at + 1], factor[at + 2]);
1184
+ if (seen.has(key)) continue;
1185
+ seen.add(key);
1186
+ runs.push(factor[at], factor[at + 1], factor[at + 2]);
1187
+ }
1188
+ return Uint32Array.from(runs);
1189
+ }
1190
+ function branchRuns(node, host) {
1191
+ const collector = new FactorCollector(host);
1192
+ collector.visit(node);
1193
+ collector.flush();
1194
+ return spreadRuns(collector.factors);
1195
+ }
1196
+ function requiredRuns(node, host) {
1197
+ if (node.kind !== "choice") return { kind: "all", runs: branchRuns(node, host) };
1198
+ const branches = node.branches.map((branch) => branchRuns(branch, host));
1199
+ if (branches.some((runs) => runs.length === 0)) return { kind: "all", runs: NO_RUNS };
1200
+ return { kind: "any", branches };
1201
+ }
1202
+
1203
+ // src/pattern/expression/index.ts
1204
+ function describe(label) {
1205
+ return label.fieldPath === null ? `the "${label.operator}" pattern` : `the "${label.operator}" pattern on pattern field "${label.fieldPath}"`;
1206
+ }
1207
+ function failureFor(label) {
1208
+ return (reason, at) => {
1209
+ throw new NarsilError(
1210
+ ErrorCodes.SEARCH_INVALID_FILTER,
1211
+ `The engine refuses ${describe(label)} at code point ${at + 1}. The pattern ${reason}`,
1212
+ { fieldPath: label.fieldPath, operator: label.operator, codePoint: at + 1 }
1213
+ );
1214
+ };
1215
+ }
1216
+ function parsedWithinLimits(label, text, caseFold, host) {
1217
+ const codePoints = toCodePoints(text);
1218
+ const fail = failureFor(label);
1219
+ const node = label.operator === "regex" ? parseRegex(codePoints, fail) : parseWildcard(codePoints, fail);
1220
+ const positions = patternPositions(node, caseFold, host);
1221
+ if (positions > MAX_PATTERN_POSITIONS) {
1222
+ throw new NarsilError(
1223
+ ErrorCodes.SEARCH_INVALID_FILTER,
1224
+ `The engine refuses ${describe(label)} before it builds a matcher, because the pattern holds more than ${MAX_PATTERN_POSITIONS} positions${caseFold ? " once the engine folds its case" : ""}. A literal code point, a class, and a set each count as one position. A count such as {5} multiplies the positions of what it repeats. A number range counts the positions of the pattern that it stands for`,
1225
+ { fieldPath: label.fieldPath, operator: label.operator, limit: MAX_PATTERN_POSITIONS }
1226
+ );
1227
+ }
1228
+ return node;
1229
+ }
1230
+ function checkExpression(operator, text, caseFold, fieldPath, host) {
1231
+ parsedWithinLimits({ operator, fieldPath }, text, caseFold, host);
1232
+ }
1233
+ function prepareExpression(operator, text, caseFold, host) {
1234
+ const node = parsedWithinLimits({ operator, fieldPath: null }, text, caseFold, host);
1235
+ return { plan: lowerPattern(node, caseFold, host), runs: requiredRuns(node, host) };
1236
+ }
1237
+ function buildProgram(prepared) {
1238
+ return compileProgram(prepared.plan);
1239
+ }
1240
+ function footprintOf(bytes, states, positions) {
1241
+ return bytes + simulationBytes({ states, positions }) + MATCHER_STATE_OVERHEAD_BYTES + positions * Uint32Array.BYTES_PER_ELEMENT;
1242
+ }
1243
+ function expressionFootprint(operator, text, caseFold, host) {
1244
+ const { bytes, states, positions } = planSize(prepareExpression(operator, text, caseFold, host).plan);
1245
+ return footprintOf(bytes, states, positions);
1246
+ }
1247
+
1248
+ // src/pattern/lazy-dfa.ts
1249
+ var UNCACHED_GENERATION = -1;
1250
+ var DECIDED_GENERATION = -2;
1251
+ function decidedState() {
1252
+ return {
1253
+ positions: new Uint32Array(0),
1254
+ previousKind: BEFORE_VALUE_START,
1255
+ generation: DECIDED_GENERATION,
1256
+ denseEdges: null,
1257
+ sparseEdges: null,
1258
+ endMatch: null
1259
+ };
1260
+ }
1261
+ function clearEdges(state) {
1262
+ state.denseEdges = null;
1263
+ state.sparseEdges = null;
1264
+ }
1265
+ var MATCHED = decidedState();
1266
+ var DEAD = decidedState();
1267
+ function stateKey(positions, previousKind) {
1268
+ return `${previousKind}:${positions.join(",")}`;
1269
+ }
1270
+ function stateBytes(positions, key) {
1271
+ return MATCHER_STATE_OVERHEAD_BYTES + positions.byteLength + key.length * MATCHER_KEY_CHARACTER_BYTES;
1272
+ }
1273
+ var LazyDfa = class {
1274
+ constructor(program, stateLimitBytes) {
1275
+ this.program = program;
1276
+ this.directClasses = program.classes.direct;
1277
+ const classCount = program.classes.starts.length + 1;
1278
+ this.denseClasses = classCount <= MAX_DENSE_EDGE_CLASSES ? classCount : 0;
1279
+ this.simulation = new PositionSimulation(program);
1280
+ this.cacheLimitBytes = stateLimitBytes - program.bytes - this.simulation.bytes;
1281
+ this.start = this.intern(new Uint32Array(0), BEFORE_VALUE_START);
1282
+ this.state = this.start;
1283
+ if (this.wantsSimulation()) this.simulate(this.start);
1284
+ }
1285
+ states = /* @__PURE__ */ new Map();
1286
+ generation = 0;
1287
+ cachedBytes = 0;
1288
+ codePointsSinceReset = 0;
1289
+ start;
1290
+ state;
1291
+ simulating = false;
1292
+ decided = null;
1293
+ simulation;
1294
+ cacheLimitBytes;
1295
+ directClasses;
1296
+ denseClasses;
1297
+ get heldBytes() {
1298
+ return this.program.bytes + this.simulation.bytes + this.cachedBytes;
1299
+ }
1300
+ begin() {
1301
+ this.decided = null;
1302
+ this.simulating = false;
1303
+ this.state = this.start;
1304
+ if (this.wantsSimulation()) this.simulate(this.start);
1305
+ return true;
1306
+ }
1307
+ feed(codePoint, tally) {
1308
+ if (this.simulating) {
1309
+ const outcome = this.simulation.step(codePoint);
1310
+ tally.add(this.simulation.steps);
1311
+ if (outcome === STEP_MATCHED) return this.decide(true);
1312
+ if (outcome === STEP_DEAD) return this.decide(false);
1313
+ return true;
1314
+ }
1315
+ this.codePointsSinceReset++;
1316
+ const direct = this.directClasses;
1317
+ const codePointClass = codePoint < direct.length ? direct[codePoint] : classOf(this.program, codePoint);
1318
+ const edge = this.edge(this.state, codePoint, codePointClass);
1319
+ tally.add(edge.steps);
1320
+ if (edge.target === MATCHED) return this.decide(true);
1321
+ if (edge.target === DEAD) return this.decide(false);
1322
+ this.state = edge.target;
1323
+ if (this.wantsSimulation()) this.simulate(this.state);
1324
+ return true;
1325
+ }
1326
+ matched() {
1327
+ if (this.decided !== null) return this.decided;
1328
+ if (this.simulating) return this.simulation.endMatches();
1329
+ const { state } = this;
1330
+ if (state.endMatch === null) {
1331
+ this.simulation.load(state.positions, state.previousKind);
1332
+ state.endMatch = this.simulation.endMatches();
1333
+ }
1334
+ return state.endMatch;
1335
+ }
1336
+ decide(outcome) {
1337
+ this.decided = outcome;
1338
+ return false;
1339
+ }
1340
+ wantsSimulation() {
1341
+ return !this.simulating && this.state.generation === UNCACHED_GENERATION;
1342
+ }
1343
+ simulate(from) {
1344
+ this.restartCache();
1345
+ this.state = this.start;
1346
+ this.simulation.load(from.positions, from.previousKind);
1347
+ this.simulating = true;
1348
+ }
1349
+ restartCache() {
1350
+ this.dropCache();
1351
+ this.codePointsSinceReset = 0;
1352
+ this.generation++;
1353
+ this.start = this.intern(this.start.positions, this.start.previousKind);
1354
+ }
1355
+ dropCache() {
1356
+ for (const state of this.states.values()) clearEdges(state);
1357
+ clearEdges(this.start);
1358
+ clearEdges(this.state);
1359
+ this.states = /* @__PURE__ */ new Map();
1360
+ this.cachedBytes = 0;
1361
+ }
1362
+ edge(state, codePoint, codePointClass) {
1363
+ const current = state.generation === this.generation;
1364
+ const dense = codePointClass >= 0 && codePointClass < this.denseClasses;
1365
+ if (current) {
1366
+ const cached = dense ? state.denseEdges?.[codePointClass] : state.sparseEdges?.get(codePointClass);
1367
+ if (cached !== void 0) return cached;
1368
+ }
1369
+ const { simulation } = this;
1370
+ simulation.load(state.positions, state.previousKind);
1371
+ const outcome = simulation.step(codePoint);
1372
+ const steps = simulation.steps;
1373
+ let target = MATCHED;
1374
+ if (outcome === STEP_DEAD) target = DEAD;
1375
+ else if (outcome !== STEP_MATCHED) target = this.intern(simulation.sortedAfter(), simulation.previousKind);
1376
+ const edge = { target, steps };
1377
+ const targetCached = target.generation === DECIDED_GENERATION || target.generation === this.generation;
1378
+ if (!current || state.generation !== this.generation || !targetCached) return edge;
1379
+ if (!this.reserve(MATCHER_TRANSITION_BYTES) || state.generation !== this.generation) return edge;
1380
+ if (!dense) {
1381
+ state.sparseEdges ??= /* @__PURE__ */ new Map();
1382
+ state.sparseEdges.set(codePointClass, edge);
1383
+ return edge;
1384
+ }
1385
+ if (state.denseEdges === null) {
1386
+ const slotBytes = this.denseClasses * MATCHER_EDGE_SLOT_BYTES;
1387
+ if (!this.reserve(slotBytes) || state.generation !== this.generation) return edge;
1388
+ state.denseEdges = new Array(this.denseClasses).fill(void 0);
1389
+ }
1390
+ state.denseEdges[codePointClass] = edge;
1391
+ return edge;
1392
+ }
1393
+ intern(positions, previousKind) {
1394
+ const key = stateKey(positions, previousKind);
1395
+ const existing = this.states.get(key);
1396
+ if (existing !== void 0) return existing;
1397
+ const fresh = (generation) => ({
1398
+ positions,
1399
+ previousKind,
1400
+ generation,
1401
+ denseEdges: null,
1402
+ sparseEdges: null,
1403
+ endMatch: null
1404
+ });
1405
+ if (!this.reserve(stateBytes(positions, key))) return fresh(UNCACHED_GENERATION);
1406
+ const state = fresh(this.generation);
1407
+ this.states.set(key, state);
1408
+ return state;
1409
+ }
1410
+ reserve(bytes) {
1411
+ if (this.cachedBytes + bytes <= this.cacheLimitBytes) {
1412
+ this.cachedBytes += bytes;
1413
+ return true;
1414
+ }
1415
+ if (this.states.size === 0 || this.codePointsSinceReset < MATCHER_MIN_CODE_POINTS_PER_STATE * this.states.size) {
1416
+ return false;
1417
+ }
1418
+ this.restartCache();
1419
+ if (this.start.generation === UNCACHED_GENERATION) return false;
1420
+ return this.reserve(bytes);
1421
+ }
1422
+ };
1423
+
1424
+ // src/pattern/expression-cache.ts
1425
+ var SearchExpressions = class {
1426
+ constructor(budgetBytes) {
1427
+ this.budgetBytes = budgetBytes;
1428
+ }
1429
+ entries = /* @__PURE__ */ new Map();
1430
+ keptProgramBytes = 0;
1431
+ current = null;
1432
+ expression(operator, text, caseFold, host) {
1433
+ const key = `${operator}\0${caseFold ? 1 : 0}\0${text}`;
1434
+ let entry = this.entries.get(key);
1435
+ if (entry === void 0) {
1436
+ entry = { key, prepared: prepareExpression(operator, text, caseFold, host), program: null };
1437
+ this.entries.set(key, entry);
1438
+ }
1439
+ return entry;
1440
+ }
1441
+ matcher(entry) {
1442
+ if (this.current?.key === entry.key) return this.current.dfa;
1443
+ this.current = null;
1444
+ const program = entry.program ?? this.programOf(entry);
1445
+ const othersBytes = this.keptProgramBytes - (entry.program === null ? 0 : program.bytes);
1446
+ const dfa = new LazyDfa(program, this.budgetBytes - othersBytes);
1447
+ this.current = { key: entry.key, dfa };
1448
+ return dfa;
1449
+ }
1450
+ programOf(entry) {
1451
+ const program = buildProgram(entry.prepared);
1452
+ if (this.keptProgramBytes + program.bytes <= this.budgetBytes * KEPT_PROGRAM_BUDGET_FRACTION) {
1453
+ entry.program = program;
1454
+ this.keptProgramBytes += program.bytes;
1455
+ }
1456
+ return program;
1457
+ }
1458
+ };
1459
+ var expressionsBySearch = /* @__PURE__ */ new WeakMap();
1460
+ function searchExpressions(meter) {
1461
+ let expressions = expressionsBySearch.get(meter);
1462
+ if (expressions === void 0) {
1463
+ expressions = new SearchExpressions(meter.matcherStateBytes);
1464
+ expressionsBySearch.set(meter, expressions);
1465
+ }
1466
+ return expressions;
1467
+ }
1468
+
1469
+ // src/pattern/literal-matcher.ts
1470
+ function bordersOf(codePoints) {
1471
+ const length = codePoints.length;
1472
+ const borders = new Uint32Array(length + 1);
1473
+ let border = 0;
1474
+ for (let at = 1; at < length; at++) {
1475
+ while (border > 0 && codePoints[at] !== codePoints[border]) border = borders[border];
1476
+ if (codePoints[at] === codePoints[border]) border++;
1477
+ borders[at + 1] = border;
1478
+ }
1479
+ return borders;
1480
+ }
1481
+ function reachablePositionsOf(borders, length) {
1482
+ const reachable = new Uint32Array(length + 1);
1483
+ for (let prefix = 1; prefix <= length; prefix++) {
1484
+ reachable[prefix] = (prefix < length ? 1 : 0) + reachable[borders[prefix]];
1485
+ }
1486
+ return reachable;
1487
+ }
1488
+ var LiteralMatcher = class {
1489
+ constructor(codePoints, anchoredStart, anchoredEnd) {
1490
+ this.codePoints = codePoints;
1491
+ this.anchoredStart = anchoredStart;
1492
+ this.anchoredEnd = anchoredEnd;
1493
+ this.borders = bordersOf(codePoints);
1494
+ this.reachable = reachablePositionsOf(this.borders, codePoints.length);
1495
+ }
1496
+ borders;
1497
+ reachable;
1498
+ prefix = 0;
1499
+ alive = true;
1500
+ accepting = false;
1501
+ decided = null;
1502
+ begin() {
1503
+ this.decided = null;
1504
+ this.prefix = 0;
1505
+ this.alive = this.codePoints.length > 0;
1506
+ this.accepting = this.codePoints.length === 0;
1507
+ if (!this.anchoredEnd && this.accepting) return this.decide(true);
1508
+ return true;
1509
+ }
1510
+ feed(codePoint, tally) {
1511
+ const steps = this.steps();
1512
+ if (steps === 0) return this.decide(!this.anchoredStart && this.codePoints.length === 0);
1513
+ tally.add(steps);
1514
+ if (this.anchoredStart) this.advanceAnchored(codePoint);
1515
+ else this.advance(codePoint);
1516
+ if (!this.anchoredEnd && this.accepting) return this.decide(true);
1517
+ return true;
1518
+ }
1519
+ matched() {
1520
+ return this.decided ?? (this.anchoredEnd && this.accepting);
1521
+ }
1522
+ steps() {
1523
+ const length = this.codePoints.length;
1524
+ if (length === 0) return 0;
1525
+ if (this.anchoredStart) return this.alive && this.prefix < length ? 1 : 0;
1526
+ return 1 + this.reachable[this.prefix];
1527
+ }
1528
+ advanceAnchored(codePoint) {
1529
+ if (this.codePoints[this.prefix] === codePoint) {
1530
+ this.prefix++;
1531
+ this.accepting = this.prefix === this.codePoints.length;
1532
+ return;
1533
+ }
1534
+ this.alive = false;
1535
+ this.accepting = false;
1536
+ }
1537
+ advance(codePoint) {
1538
+ const { codePoints, borders } = this;
1539
+ let prefix = this.prefix === codePoints.length ? borders[this.prefix] : this.prefix;
1540
+ while (prefix > 0 && codePoints[prefix] !== codePoint) prefix = borders[prefix];
1541
+ if (codePoints[prefix] === codePoint) prefix++;
1542
+ this.prefix = prefix;
1543
+ this.accepting = prefix === codePoints.length;
1544
+ }
1545
+ decide(outcome) {
1546
+ this.decided = outcome;
1547
+ return false;
1548
+ }
1549
+ };
1550
+
1551
+ // src/pattern/shortlist.ts
1552
+ function intersect(candidates, list, tally) {
1553
+ const kept = new Uint32Array(Math.min(candidates.length, list.length));
1554
+ let keptCount = 0;
1555
+ let read = 0;
1556
+ for (const candidate of candidates) {
1557
+ while (read < list.length && list[read] < candidate) read++;
1558
+ if (read === list.length) break;
1559
+ if (list[read] === candidate) kept[keptCount++] = candidate;
1560
+ }
1561
+ tally.add(Math.min(list.length, read + 1));
1562
+ return kept.subarray(0, keptCount);
1563
+ }
1564
+ function shortlistAll(index, runs, tally) {
1565
+ const lists = [];
1566
+ for (let at = 0; at < runs.length; at += PATTERN_RUN_CODE_POINTS) {
1567
+ tally.add(1);
1568
+ lists.push(index.postings(runs[at], runs[at + 1], runs[at + 2]));
1569
+ }
1570
+ lists.sort((left, right) => left.length - right.length);
1571
+ let candidates = lists[0];
1572
+ tally.add(candidates.length);
1573
+ for (let at = 1; at < lists.length && candidates.length > 0; at++) {
1574
+ if (lists[at].length > candidates.length * SHORTLIST_INTERSECT_RATIO) break;
1575
+ candidates = intersect(candidates, lists[at], tally);
1576
+ }
1577
+ return candidates;
1578
+ }
1579
+ function union(left, right) {
1580
+ if (left.length === 0) return right;
1581
+ if (right.length === 0) return left;
1582
+ const merged = new Uint32Array(left.length + right.length);
1583
+ let count = 0;
1584
+ let fromLeft = 0;
1585
+ let fromRight = 0;
1586
+ while (fromLeft < left.length && fromRight < right.length) {
1587
+ const smaller = Math.min(left[fromLeft], right[fromRight]);
1588
+ if (left[fromLeft] === smaller) fromLeft++;
1589
+ if (right[fromRight] === smaller) fromRight++;
1590
+ merged[count++] = smaller;
1591
+ }
1592
+ while (fromLeft < left.length) merged[count++] = left[fromLeft++];
1593
+ while (fromRight < right.length) merged[count++] = right[fromRight++];
1594
+ return merged.subarray(0, count);
1595
+ }
1596
+ function shortlist(index, query, tally) {
1597
+ if (query.kind === "all") return query.runs.length === 0 ? null : shortlistAll(index, query.runs, tally);
1598
+ let candidates = new Uint32Array(0);
1599
+ for (const runs of query.branches) candidates = union(candidates, shortlistAll(index, runs, tally));
1600
+ return candidates;
1601
+ }
1602
+
1603
+ // src/core/pattern-index/typo-runs.ts
1604
+ var BASIC_PLANE_LAST2 = 65535;
1605
+ function isPatternTolerance(value) {
1606
+ if (value === "auto") return true;
1607
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= MAX_PATTERN_TOLERANCE;
1608
+ }
1609
+ function foldTypoText(text, host) {
1610
+ const folded = [];
1611
+ let longestFold = 0;
1612
+ for (let at = 0; at < text.length; at++) {
1613
+ const codePoint = text.codePointAt(at) ?? 0;
1614
+ if (codePoint > BASIC_PLANE_LAST2) at++;
1615
+ const before = folded.length;
1616
+ host.appendFoldedCodePoint(codePoint, folded);
1617
+ longestFold = Math.max(longestFold, folded.length - before);
1618
+ }
1619
+ return { folded, longestFold };
1620
+ }
1621
+ function distinctTypoRuns(text, limit) {
1622
+ const { folded } = text;
1623
+ const seen = /* @__PURE__ */ new Set();
1624
+ const runs = [];
1625
+ for (let at = 0; at + PATTERN_RUN_CODE_POINTS <= folded.length && seen.size < limit; at++) {
1626
+ const key = String.fromCodePoint(folded[at], folded[at + 1], folded[at + 2]);
1627
+ if (seen.has(key)) continue;
1628
+ seen.add(key);
1629
+ runs.push(folded[at], folded[at + 1], folded[at + 2]);
1630
+ }
1631
+ return runs;
1632
+ }
1633
+ function typoRunsNeeded(tolerance, longestFold) {
1634
+ return tolerance * (2 + longestFold) + 1;
1635
+ }
1636
+ function distinctTypoRunCount(text, limit) {
1637
+ return distinctTypoRuns(text, limit).length / PATTERN_RUN_CODE_POINTS;
1638
+ }
1639
+ function resolvedTypoTolerance(tolerance, text) {
1640
+ if (tolerance !== "auto") return tolerance;
1641
+ for (let candidate = MAX_PATTERN_TOLERANCE; candidate > 0; candidate--) {
1642
+ const needed = typoRunsNeeded(candidate, text.longestFold);
1643
+ if (distinctTypoRunCount(text, needed) >= needed) return candidate;
1644
+ }
1645
+ return 0;
1646
+ }
1647
+
1648
+ // src/pattern/typo.ts
1649
+ var TypoComparison = class {
1650
+ constructor(text, caseFold, tolerance, host) {
1651
+ this.caseFold = caseFold;
1652
+ this.tolerance = tolerance;
1653
+ this.host = host;
1654
+ const codePoints = [];
1655
+ appendTextCodePoints(text, caseFold, host, codePoints);
1656
+ this.text = caseFold ? String.fromCodePoint(...codePoints) : text;
1657
+ this.shortest = codePoints.length - tolerance;
1658
+ this.longest = codePoints.length + tolerance;
1659
+ }
1660
+ text;
1661
+ shortest;
1662
+ longest;
1663
+ folded = [];
1664
+ within(value, tally) {
1665
+ const compared = this.comparedForm(value);
1666
+ if (compared === null) return false;
1667
+ const { withinTolerance, cells } = tabulatedLevenshtein(this.text, compared, this.tolerance);
1668
+ tally.add(cells);
1669
+ return withinTolerance;
1670
+ }
1671
+ comparedForm(value) {
1672
+ const folded = this.folded;
1673
+ folded.length = 0;
1674
+ let counted = 0;
1675
+ for (let at = 0; at < value.length && counted <= this.longest; at++) {
1676
+ const codePoint = value.codePointAt(at) ?? 0;
1677
+ if (codePoint > BASIC_PLANE_LAST) at++;
1678
+ if (this.caseFold) {
1679
+ this.host.appendFoldedCodePoint(codePoint, folded);
1680
+ counted = folded.length;
1681
+ } else {
1682
+ counted++;
1683
+ }
1684
+ }
1685
+ if (counted > this.longest || counted < this.shortest) return null;
1686
+ return this.caseFold ? String.fromCodePoint(...folded) : value;
1687
+ }
1688
+ };
1689
+ var typoTestsBySearch = /* @__PURE__ */ new WeakMap();
1690
+ function spreadSample(runs, picks) {
1691
+ const count = runs.length / PATTERN_RUN_CODE_POINTS;
1692
+ if (count <= picks) return Uint32Array.from(runs);
1693
+ const sample = new Uint32Array(picks * PATTERN_RUN_CODE_POINTS);
1694
+ for (let pick = 0; pick < picks; pick++) {
1695
+ const run = Math.round(pick * (count - 1) / (picks - 1));
1696
+ for (let offset = 0; offset < PATTERN_RUN_CODE_POINTS; offset++) {
1697
+ sample[pick * PATTERN_RUN_CODE_POINTS + offset] = runs[run * PATTERN_RUN_CODE_POINTS + offset];
1698
+ }
1699
+ }
1700
+ return sample;
1701
+ }
1702
+ function preparedTypoTest(request) {
1703
+ const text = foldTypoText(request.text, request.host);
1704
+ const tolerance = resolvedTypoTolerance(request.tolerance, text);
1705
+ if (tolerance === 0) return null;
1706
+ const needed = typoRunsNeeded(tolerance, text.longestFold);
1707
+ return {
1708
+ needed,
1709
+ runs: spreadSample(distinctTypoRuns(text, Number.POSITIVE_INFINITY), Math.max(needed, SHORTLIST_RUN_LOOKUPS)),
1710
+ comparison: new TypoComparison(request.text, request.caseFold, tolerance, request.host)
1711
+ };
1712
+ }
1713
+ function typoTestFor(request) {
1714
+ let tests = typoTestsBySearch.get(request.meter);
1715
+ if (tests === void 0) {
1716
+ tests = /* @__PURE__ */ new Map();
1717
+ typoTestsBySearch.set(request.meter, tests);
1718
+ }
1719
+ const key = `${request.caseFold}|${request.tolerance}|${request.text}`;
1720
+ const known = tests.get(key);
1721
+ if (known !== void 0) return known;
1722
+ const test = preparedTypoTest(request);
1723
+ tests.set(key, test);
1724
+ return test;
1725
+ }
1726
+ function rarestLists(index, test, tally) {
1727
+ const { runs, needed } = test;
1728
+ if (runs.length < needed * PATTERN_RUN_CODE_POINTS) return [index.documents()];
1729
+ const lists = [];
1730
+ for (let at = 0; at < runs.length; at += PATTERN_RUN_CODE_POINTS) {
1731
+ tally.add(1);
1732
+ lists.push(index.postings(runs[at], runs[at + 1], runs[at + 2]));
1733
+ }
1734
+ lists.sort((left, right) => left.length - right.length);
1735
+ return lists.slice(0, needed);
1736
+ }
1737
+ function matchWithinTolerance(request, test, tally) {
1738
+ const { index, matches } = request;
1739
+ const checked = new Uint32Array(matches.length);
1740
+ let matched = false;
1741
+ const testValue = (value) => {
1742
+ if (!matched) matched = test.comparison.within(value, tally);
1743
+ };
1744
+ for (const list of rarestLists(index, test, tally)) {
1745
+ tally.add(list.length);
1746
+ for (const ordinal of list) {
1747
+ if (ordinal >>> 5 >= matches.length || bitsetHas(checked, ordinal)) continue;
1748
+ bitsetSet(checked, ordinal);
1749
+ if (bitsetHas(matches, ordinal)) continue;
1750
+ matched = false;
1751
+ forEachTextValue(request.valueOf(ordinal), testValue);
1752
+ if (matched) bitsetSet(matches, ordinal);
1753
+ }
1754
+ }
1755
+ }
1756
+
1757
+ // src/pattern/work-tally.ts
1758
+ var WorkTally = class {
1759
+ constructor(meter) {
1760
+ this.meter = meter;
1761
+ this.headroom = meter.remaining();
1762
+ }
1763
+ pending = 0;
1764
+ headroom;
1765
+ add(units) {
1766
+ this.pending += units;
1767
+ if (this.pending >= this.meter.flushUnits || this.pending > this.headroom) this.flush();
1768
+ }
1769
+ flush() {
1770
+ if (this.pending === 0) return;
1771
+ const units = this.pending;
1772
+ this.pending = 0;
1773
+ this.meter.add(units);
1774
+ this.headroom = this.meter.remaining();
1775
+ }
1776
+ };
1777
+
1778
+ // src/pattern/evaluate.ts
1779
+ var ANCHORED_START = /* @__PURE__ */ new Set(["eq", "startsWith"]);
1780
+ var ANCHORED_END = /* @__PURE__ */ new Set(["eq", "endsWith"]);
1781
+ var shortlistRunsBySearch = /* @__PURE__ */ new WeakMap();
1782
+ function literalRuns(text, host, meter) {
1783
+ let runsByText = shortlistRunsBySearch.get(meter);
1784
+ if (runsByText === void 0) {
1785
+ runsByText = /* @__PURE__ */ new Map();
1786
+ shortlistRunsBySearch.set(meter, runsByText);
1787
+ }
1788
+ const known = runsByText.get(text);
1789
+ if (known !== void 0) return known;
1790
+ const folded = [];
1791
+ appendTextCodePoints(text, true, host, folded);
1792
+ const runs = { kind: "all", runs: spreadRuns([folded]) };
1793
+ runsByText.set(text, runs);
1794
+ return runs;
1795
+ }
1796
+ function literalTest(request) {
1797
+ const { operator, text, caseFold, host, meter } = request;
1798
+ return {
1799
+ runs: literalRuns(text, host, meter),
1800
+ matcher: () => {
1801
+ const testCodePoints = [];
1802
+ appendTextCodePoints(text, caseFold, host, testCodePoints);
1803
+ return new LiteralMatcher(
1804
+ Uint32Array.from(testCodePoints),
1805
+ ANCHORED_START.has(operator),
1806
+ ANCHORED_END.has(operator)
1807
+ );
1808
+ }
1809
+ };
1810
+ }
1811
+ function expressionTest(request, operator) {
1812
+ const { text, caseFold, host, meter } = request;
1813
+ const expressions = searchExpressions(meter);
1814
+ const entry = expressions.expression(operator, text, caseFold, host);
1815
+ return { runs: entry.prepared.runs, matcher: () => expressions.matcher(entry) };
1816
+ }
1817
+ function matchesText(matcher, text, caseFold, host, folded, tally) {
1818
+ if (!matcher.begin()) return matcher.matched();
1819
+ for (let at = 0; at < text.length; at++) {
1820
+ const codePoint = text.codePointAt(at) ?? 0;
1821
+ if (codePoint > BASIC_PLANE_LAST) at++;
1822
+ if (!caseFold) {
1823
+ if (!matcher.feed(codePoint, tally)) return matcher.matched();
1824
+ continue;
1825
+ }
1826
+ folded.length = 0;
1827
+ host.appendFoldedCodePoint(codePoint, folded);
1828
+ for (const foldedCodePoint of folded) {
1829
+ if (!matcher.feed(foldedCodePoint, tally)) return matcher.matched();
1830
+ }
1831
+ }
1832
+ return matcher.matched();
1833
+ }
1834
+ function answeredByTypoTest(request, tally) {
1835
+ if (request.operator !== "eq" || request.tolerance === 0) return false;
1836
+ const test = typoTestFor(request);
1837
+ if (test === null) return false;
1838
+ matchWithinTolerance(request, test, tally);
1839
+ return true;
1840
+ }
1841
+ function matchPattern(request) {
1842
+ const { operator, caseFold, index, matches, host } = request;
1843
+ const tally = new WorkTally(request.meter);
1844
+ if (answeredByTypoTest(request, tally)) {
1845
+ tally.flush();
1846
+ return;
1847
+ }
1848
+ const test = operator === "wildcard" || operator === "regex" ? expressionTest(request, operator) : literalTest(request);
1849
+ const shortlisted = shortlist(index, test.runs, tally);
1850
+ const scanning = shortlisted === null;
1851
+ const candidates = shortlisted ?? index.documents();
1852
+ const folded = [];
1853
+ let matcher = null;
1854
+ let matched = false;
1855
+ const testValue = (value) => {
1856
+ if (!matched && matcher !== null) matched = matchesText(matcher, value, caseFold, host, folded, tally);
1857
+ };
1858
+ for (const ordinal of candidates) {
1859
+ if (ordinal >>> 5 >= matches.length || bitsetHas(matches, ordinal)) continue;
1860
+ if (scanning) tally.add(1);
1861
+ matcher ??= test.matcher();
1862
+ matched = false;
1863
+ forEachTextValue(request.valueOf(ordinal), testValue);
1864
+ if (matched) bitsetSet(matches, ordinal);
1865
+ }
1866
+ tally.flush();
1867
+ }
1868
+
1869
+ // src/core/partition/growable-uint32.ts
1870
+ var GrowableUint32 = class {
1871
+ values;
1872
+ length = 0;
1873
+ constructor(capacity) {
1874
+ this.values = new Uint32Array(capacity);
1875
+ }
1876
+ growTo(needed, kept) {
1877
+ let capacity = this.values.length * 2;
1878
+ while (capacity < needed) capacity *= 2;
1879
+ const next = new Uint32Array(capacity);
1880
+ next.set(this.values.subarray(0, kept));
1881
+ this.values = next;
1882
+ }
1883
+ reserve(extra) {
1884
+ const needed = this.length + extra;
1885
+ if (needed > this.values.length) this.growTo(needed, this.length);
1886
+ }
1887
+ push(value) {
1888
+ if (this.length === this.values.length) this.growTo(this.length + 1, this.length);
1889
+ this.values[this.length++] = value;
1890
+ }
1891
+ ensureIndex(index) {
1892
+ if (index >= this.values.length) this.growTo(index + 1, this.values.length);
1893
+ }
1894
+ clear() {
1895
+ this.length = 0;
1896
+ }
1897
+ };
1898
+
1899
+ // src/pattern/runs-arrays.ts
1900
+ var EMPTY_POSTINGS = new Uint32Array(0);
1901
+ function remapAscending(source, remap, out) {
1902
+ const start = out.length;
1903
+ let ordered = true;
1904
+ for (const ordinal of source) {
1905
+ const mapped = remap === null ? ordinal : ordinal < remap.length ? remap[ordinal] : -1;
1906
+ if (mapped < 0) continue;
1907
+ if (out.length > start && out.values[out.length - 1] > mapped) ordered = false;
1908
+ out.push(mapped);
1909
+ }
1910
+ if (!ordered) out.values.subarray(start, out.length).sort();
1911
+ }
1912
+ function sortedRunOrder(codePoints, count) {
1913
+ const order = new Array(count);
1914
+ for (let run = 0; run < count; run++) order[run] = run;
1915
+ order.sort(
1916
+ (left, right) => compareRuns(codePoints, left * PATTERN_RUN_CODE_POINTS, codePoints, right * PATTERN_RUN_CODE_POINTS)
1917
+ );
1918
+ return order;
1919
+ }
1920
+ function buildArrays(fieldPath, documents, source, order, remap) {
1921
+ const docIds = new GrowableUint32(Math.max(1, documents.length));
1922
+ remapAscending(documents, remap, docIds);
1923
+ const runs = new GrowableUint32(Math.max(1, source.count * PATTERN_RUN_CODE_POINTS));
1924
+ const offsets = new GrowableUint32(source.count + 1);
1925
+ const postings = new GrowableUint32(Math.max(1, source.count));
1926
+ offsets.push(0);
1927
+ for (let position = 0; position < source.count; position++) {
1928
+ const run = order === null ? position : order[position];
1929
+ const before = postings.length;
1930
+ remapAscending(source.postingsAt(run), remap, postings);
1931
+ if (postings.length === before) continue;
1932
+ const at = run * PATTERN_RUN_CODE_POINTS;
1933
+ runs.push(source.codePoints[at]);
1934
+ runs.push(source.codePoints[at + 1]);
1935
+ runs.push(source.codePoints[at + 2]);
1936
+ offsets.push(postings.length);
1937
+ }
1938
+ return trimmedArrays(fieldPath, docIds, runs, offsets, postings);
1939
+ }
1940
+ function trimmedArrays(fieldPath, docIds, runs, offsets, postings) {
1941
+ return {
1942
+ fieldPath,
1943
+ docIds: docIds.values.slice(0, docIds.length),
1944
+ runs: runs.values.slice(0, runs.length),
1945
+ offsets: offsets.values.slice(0, offsets.length),
1946
+ postings: postings.values.slice(0, postings.length)
1947
+ };
1948
+ }
1949
+ function findRun(runs, first, second, third) {
1950
+ let low = 0;
1951
+ let high = runs.length / PATTERN_RUN_CODE_POINTS;
1952
+ while (low < high) {
1953
+ const middle = low + high >>> 1;
1954
+ const at = middle * PATTERN_RUN_CODE_POINTS;
1955
+ const difference = runs[at] - first || runs[at + 1] - second || runs[at + 2] - third;
1956
+ if (difference === 0) return middle;
1957
+ if (difference < 0) low = middle + 1;
1958
+ else high = middle;
1959
+ }
1960
+ return -1;
1961
+ }
1962
+
1963
+ // src/pattern/frozen-index.ts
1964
+ function readPatternArrays(arrays) {
1965
+ const source = {
1966
+ count: arrays.offsets.length - 1,
1967
+ codePoints: arrays.runs,
1968
+ postingsAt: (run) => arrays.postings.subarray(arrays.offsets[run], arrays.offsets[run + 1])
1969
+ };
1970
+ return {
1971
+ documents: () => arrays.docIds,
1972
+ postings(first, second, third) {
1973
+ const run = findRun(arrays.runs, first, second, third);
1974
+ return run < 0 ? EMPTY_POSTINGS : source.postingsAt(run);
1975
+ },
1976
+ toArrays(fieldPath, remap) {
1977
+ return buildArrays(fieldPath, arrays.docIds, source, null, remap);
1978
+ },
1979
+ bytes() {
1980
+ return arrays.docIds.byteLength + arrays.runs.byteLength + arrays.offsets.byteLength + arrays.postings.byteLength;
1981
+ }
1982
+ };
1983
+ }
1984
+
1985
+ // src/pattern/growing-index.ts
1986
+ function createRunList() {
1987
+ return { ids: new Uint32Array(RUN_LIST_INITIAL_CAPACITY), length: 0, removed: null, ordered: true };
1988
+ }
1989
+ function compactRemoved(list) {
1990
+ const removed = list.removed;
1991
+ if (removed === null) return;
1992
+ let kept = 0;
1993
+ for (let at = 0; at < list.length; at++) {
1994
+ const ordinal = list.ids[at];
1995
+ if (removed.has(ordinal)) continue;
1996
+ list.ids[kept++] = ordinal;
1997
+ }
1998
+ list.length = kept;
1999
+ list.removed = null;
2000
+ }
2001
+ function compactAndSort(list) {
2002
+ compactRemoved(list);
2003
+ if (!list.ordered) {
2004
+ list.ids.subarray(0, list.length).sort();
2005
+ list.ordered = true;
2006
+ }
2007
+ }
2008
+ function createGrowingPatternIndex(host) {
2009
+ const runs = /* @__PURE__ */ new Map();
2010
+ const documents = /* @__PURE__ */ new Set();
2011
+ let documentsCache = null;
2012
+ let listBytes = 0;
2013
+ const folded = [];
2014
+ function runKeysOf(value) {
2015
+ const keys = /* @__PURE__ */ new Set();
2016
+ forEachTextValue(value, (text) => {
2017
+ folded.length = 0;
2018
+ appendTextCodePoints(text, true, host, folded);
2019
+ collectRunKeys(folded, keys);
2020
+ });
2021
+ return keys;
2022
+ }
2023
+ function grow(list) {
2024
+ const next = new Uint32Array(list.ids.length * 2);
2025
+ next.set(list.ids.subarray(0, list.length));
2026
+ listBytes += next.byteLength - list.ids.byteLength;
2027
+ list.ids = next;
2028
+ }
2029
+ function listFor(key) {
2030
+ let list = runs.get(key);
2031
+ if (list === void 0) {
2032
+ list = createRunList();
2033
+ listBytes += list.ids.byteLength;
2034
+ runs.set(key, list);
2035
+ }
2036
+ return list;
2037
+ }
2038
+ function append(list, ordinal) {
2039
+ if (list.removed?.delete(ordinal)) return;
2040
+ if (list.length === list.ids.length) grow(list);
2041
+ if (list.length > 0 && list.ids[list.length - 1] > ordinal) list.ordered = false;
2042
+ list.ids[list.length++] = ordinal;
2043
+ }
2044
+ function dropIfEmpty(key, list) {
2045
+ if (list.length > 0) return;
2046
+ listBytes -= list.ids.byteLength;
2047
+ runs.delete(key);
2048
+ }
2049
+ function markRemoved(key, list, ordinal) {
2050
+ if (list.removed === null) list.removed = /* @__PURE__ */ new Set();
2051
+ list.removed.add(ordinal);
2052
+ if (list.removed.size < list.length * RUN_LIST_COMPACTION_FRACTION) return;
2053
+ compactRemoved(list);
2054
+ dropIfEmpty(key, list);
2055
+ }
2056
+ function settledPostings(key) {
2057
+ const list = runs.get(key);
2058
+ if (list === void 0) return EMPTY_POSTINGS;
2059
+ compactAndSort(list);
2060
+ if (list.length === 0) {
2061
+ dropIfEmpty(key, list);
2062
+ return EMPTY_POSTINGS;
2063
+ }
2064
+ return list.ids.subarray(0, list.length);
2065
+ }
2066
+ function sortedDocuments() {
2067
+ if (documentsCache === null) {
2068
+ documentsCache = Uint32Array.from(documents).sort();
2069
+ }
2070
+ return documentsCache;
2071
+ }
2072
+ function runSource() {
2073
+ const keys = [];
2074
+ const lists = [];
2075
+ for (const key of [...runs.keys()]) {
2076
+ const postings = settledPostings(key);
2077
+ if (postings.length === 0) continue;
2078
+ keys.push(key);
2079
+ lists.push(postings);
2080
+ }
2081
+ const codePoints = new Uint32Array(keys.length * PATTERN_RUN_CODE_POINTS);
2082
+ for (let run = 0; run < keys.length; run++) {
2083
+ runKeyCodePoints(keys[run], codePoints, run * PATTERN_RUN_CODE_POINTS);
2084
+ }
2085
+ return { count: keys.length, codePoints, postingsAt: (run) => lists[run] };
2086
+ }
2087
+ return {
2088
+ add(ordinal, value) {
2089
+ if (!holdsTextValue(value)) return;
2090
+ documents.add(ordinal);
2091
+ documentsCache = null;
2092
+ for (const key of runKeysOf(value)) append(listFor(key), ordinal);
2093
+ },
2094
+ remove(ordinal, value) {
2095
+ if (!holdsTextValue(value)) return;
2096
+ if (documents.delete(ordinal)) documentsCache = null;
2097
+ for (const key of runKeysOf(value)) {
2098
+ const list = runs.get(key);
2099
+ if (list !== void 0) markRemoved(key, list, ordinal);
2100
+ }
2101
+ },
2102
+ addArrays(arrays, mapOrdinal) {
2103
+ for (const ordinal of arrays.docIds) {
2104
+ const mapped = mapOrdinal(ordinal);
2105
+ if (mapped < 0) continue;
2106
+ documents.add(mapped);
2107
+ documentsCache = null;
2108
+ }
2109
+ const runCount = arrays.offsets.length - 1;
2110
+ for (let run = 0; run < runCount; run++) {
2111
+ const at = run * PATTERN_RUN_CODE_POINTS;
2112
+ const key = runKey(arrays.runs[at], arrays.runs[at + 1], arrays.runs[at + 2]);
2113
+ const list = listFor(key);
2114
+ for (let posting = arrays.offsets[run]; posting < arrays.offsets[run + 1]; posting++) {
2115
+ const mapped = mapOrdinal(arrays.postings[posting]);
2116
+ if (mapped >= 0) append(list, mapped);
2117
+ }
2118
+ dropIfEmpty(key, list);
2119
+ }
2120
+ },
2121
+ clear() {
2122
+ runs.clear();
2123
+ documents.clear();
2124
+ documentsCache = null;
2125
+ listBytes = 0;
2126
+ },
2127
+ documents: sortedDocuments,
2128
+ postings(first, second, third) {
2129
+ return settledPostings(runKey(first, second, third));
2130
+ },
2131
+ toArrays(fieldPath, remap) {
2132
+ const source = runSource();
2133
+ return buildArrays(fieldPath, sortedDocuments(), source, sortedRunOrder(source.codePoints, source.count), remap);
2134
+ },
2135
+ bytes() {
2136
+ return listBytes + runs.size * RUN_ENTRY_OVERHEAD_BYTES + documents.size * DOCUMENT_ENTRY_BYTES + (documentsCache?.byteLength ?? 0);
2137
+ }
2138
+ };
2139
+ }
2140
+
2141
+ // src/pattern/merge.ts
2142
+ function sortTailIfUnordered(values, start) {
2143
+ for (let at = start + 1; at < values.length; at++) {
2144
+ if (values.values[at - 1] > values.values[at]) {
2145
+ values.values.subarray(start, values.length).sort();
2146
+ return;
2147
+ }
2148
+ }
2149
+ }
2150
+ function smallestRun(inputs, cursors) {
2151
+ let smallest = -1;
2152
+ for (let input = 0; input < inputs.length; input++) {
2153
+ const runCount = inputs[input].arrays.offsets.length - 1;
2154
+ if (cursors[input] >= runCount) continue;
2155
+ if (smallest < 0) {
2156
+ smallest = input;
2157
+ continue;
2158
+ }
2159
+ const order = compareRuns(
2160
+ inputs[input].arrays.runs,
2161
+ cursors[input] * PATTERN_RUN_CODE_POINTS,
2162
+ inputs[smallest].arrays.runs,
2163
+ cursors[smallest] * PATTERN_RUN_CODE_POINTS
2164
+ );
2165
+ if (order < 0) smallest = input;
2166
+ }
2167
+ return smallest;
2168
+ }
2169
+ function mergePatternArrays(fieldPath, inputs) {
2170
+ const docIds = new GrowableUint32(1);
2171
+ for (const input of inputs) remapAscending(input.arrays.docIds, input.remap, docIds);
2172
+ sortTailIfUnordered(docIds, 0);
2173
+ const runs = new GrowableUint32(PATTERN_RUN_CODE_POINTS);
2174
+ const offsets = new GrowableUint32(1);
2175
+ const postings = new GrowableUint32(1);
2176
+ offsets.push(0);
2177
+ const cursors = inputs.map(() => 0);
2178
+ for (let smallest = smallestRun(inputs, cursors); smallest >= 0; smallest = smallestRun(inputs, cursors)) {
2179
+ const source = inputs[smallest].arrays.runs;
2180
+ const at = cursors[smallest] * PATTERN_RUN_CODE_POINTS;
2181
+ const first = source[at];
2182
+ const second = source[at + 1];
2183
+ const third = source[at + 2];
2184
+ const before = postings.length;
2185
+ for (let input = 0; input < inputs.length; input++) {
2186
+ const { arrays, remap } = inputs[input];
2187
+ const run = cursors[input];
2188
+ if (run >= arrays.offsets.length - 1) continue;
2189
+ const runAt = run * PATTERN_RUN_CODE_POINTS;
2190
+ if (arrays.runs[runAt] !== first || arrays.runs[runAt + 1] !== second || arrays.runs[runAt + 2] !== third) {
2191
+ continue;
2192
+ }
2193
+ remapAscending(arrays.postings.subarray(arrays.offsets[run], arrays.offsets[run + 1]), remap, postings);
2194
+ cursors[input] = run + 1;
2195
+ }
2196
+ if (postings.length === before) continue;
2197
+ sortTailIfUnordered(postings, before);
2198
+ runs.push(first);
2199
+ runs.push(second);
2200
+ runs.push(third);
2201
+ offsets.push(postings.length);
2202
+ }
2203
+ return trimmedArrays(fieldPath, docIds, runs, offsets, postings);
2204
+ }
2205
+
2206
+ // src/pattern/module.ts
2207
+ var patternSearchModule = {
2208
+ name: "pattern",
2209
+ createIndex: createGrowingPatternIndex,
2210
+ readArrays: readPatternArrays,
2211
+ mergeArrays: mergePatternArrays,
2212
+ matchInto: matchPattern,
2213
+ checkExpression,
2214
+ expressionFootprint
2215
+ };
2216
+
2217
+ export { DEFAULT_PATTERN_WORK_CAP, GrowableUint32, MATCHER_CODE_POINT_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_BUDGET_BYTES, MATCHER_STATE_OVERHEAD_BYTES, MAX_PATTERN_POSITIONS, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_EXPRESSION_OPERATORS, PATTERN_RUN_CODE_POINTS, PATTERN_TEST_OPERATORS, PATTERN_WORK_FLUSH_UNITS, bitsetAnd, bitsetAndInto, bitsetAndNotInto, bitsetFromSet, bitsetHas, bitsetIsEmpty, bitsetNot, bitsetOrInto, bitsetSet, createBitSet, distinctTypoRunCount, foldTypoText, isPatternTolerance, patternSearchModule, typoRunsNeeded };