@bcts/envelope-pattern 1.0.0-alpha.12

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 (53) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +13 -0
  3. package/dist/index.cjs +6781 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2628 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.mts +2628 -0
  8. package/dist/index.d.mts.map +1 -0
  9. package/dist/index.iife.js +6781 -0
  10. package/dist/index.iife.js.map +1 -0
  11. package/dist/index.mjs +6545 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +77 -0
  14. package/src/error.ts +262 -0
  15. package/src/format.ts +375 -0
  16. package/src/index.ts +27 -0
  17. package/src/parse/index.ts +923 -0
  18. package/src/parse/token.ts +906 -0
  19. package/src/parse/utils.ts +339 -0
  20. package/src/pattern/index.ts +719 -0
  21. package/src/pattern/leaf/array-pattern.ts +273 -0
  22. package/src/pattern/leaf/bool-pattern.ts +140 -0
  23. package/src/pattern/leaf/byte-string-pattern.ts +172 -0
  24. package/src/pattern/leaf/cbor-pattern.ts +355 -0
  25. package/src/pattern/leaf/date-pattern.ts +178 -0
  26. package/src/pattern/leaf/index.ts +280 -0
  27. package/src/pattern/leaf/known-value-pattern.ts +192 -0
  28. package/src/pattern/leaf/map-pattern.ts +152 -0
  29. package/src/pattern/leaf/null-pattern.ts +110 -0
  30. package/src/pattern/leaf/number-pattern.ts +248 -0
  31. package/src/pattern/leaf/tagged-pattern.ts +228 -0
  32. package/src/pattern/leaf/text-pattern.ts +165 -0
  33. package/src/pattern/matcher.ts +88 -0
  34. package/src/pattern/meta/and-pattern.ts +109 -0
  35. package/src/pattern/meta/any-pattern.ts +81 -0
  36. package/src/pattern/meta/capture-pattern.ts +111 -0
  37. package/src/pattern/meta/group-pattern.ts +110 -0
  38. package/src/pattern/meta/index.ts +269 -0
  39. package/src/pattern/meta/not-pattern.ts +91 -0
  40. package/src/pattern/meta/or-pattern.ts +146 -0
  41. package/src/pattern/meta/search-pattern.ts +201 -0
  42. package/src/pattern/meta/traverse-pattern.ts +146 -0
  43. package/src/pattern/structure/assertions-pattern.ts +244 -0
  44. package/src/pattern/structure/digest-pattern.ts +225 -0
  45. package/src/pattern/structure/index.ts +272 -0
  46. package/src/pattern/structure/leaf-structure-pattern.ts +85 -0
  47. package/src/pattern/structure/node-pattern.ts +188 -0
  48. package/src/pattern/structure/object-pattern.ts +149 -0
  49. package/src/pattern/structure/obscured-pattern.ts +159 -0
  50. package/src/pattern/structure/predicate-pattern.ts +151 -0
  51. package/src/pattern/structure/subject-pattern.ts +152 -0
  52. package/src/pattern/structure/wrapped-pattern.ts +195 -0
  53. package/src/pattern/vm.ts +1021 -0
@@ -0,0 +1,280 @@
1
+ /**
2
+ * @bcts/envelope-pattern - Leaf patterns module
3
+ *
4
+ * This is a 1:1 TypeScript port of bc-envelope-pattern-rust pattern/leaf/mod.rs
5
+ *
6
+ * @module envelope-pattern/pattern/leaf
7
+ */
8
+
9
+ import type { Envelope } from "@bcts/envelope";
10
+ import type { Path } from "../../format";
11
+ import type { Instr } from "../vm";
12
+ import type { Pattern } from "../index";
13
+
14
+ // Re-export all leaf pattern types
15
+ export { BoolPattern, registerBoolPatternFactory } from "./bool-pattern";
16
+ export { NullPattern, registerNullPatternFactory } from "./null-pattern";
17
+ export { NumberPattern, registerNumberPatternFactory } from "./number-pattern";
18
+ export { TextPattern, registerTextPatternFactory } from "./text-pattern";
19
+ export { ByteStringPattern, registerByteStringPatternFactory } from "./byte-string-pattern";
20
+ export { DatePattern, registerDatePatternFactory } from "./date-pattern";
21
+ export { ArrayPattern, type ArrayPatternType, registerArrayPatternFactory } from "./array-pattern";
22
+ export { MapPattern, type MapPatternType, registerMapPatternFactory } from "./map-pattern";
23
+ export { KnownValuePattern, registerKnownValuePatternFactory } from "./known-value-pattern";
24
+ export { TaggedPattern, registerTaggedPatternFactory } from "./tagged-pattern";
25
+ export { CBORPattern, type CBORPatternType, registerCBORPatternFactory } from "./cbor-pattern";
26
+
27
+ // Import concrete types for use in LeafPattern
28
+ import { type BoolPattern } from "./bool-pattern";
29
+ import { type NullPattern } from "./null-pattern";
30
+ import { type NumberPattern } from "./number-pattern";
31
+ import { type TextPattern } from "./text-pattern";
32
+ import { type ByteStringPattern } from "./byte-string-pattern";
33
+ import { type DatePattern } from "./date-pattern";
34
+ import { type ArrayPattern } from "./array-pattern";
35
+ import { type MapPattern } from "./map-pattern";
36
+ import { type KnownValuePattern } from "./known-value-pattern";
37
+ import { type TaggedPattern } from "./tagged-pattern";
38
+ import { type CBORPattern } from "./cbor-pattern";
39
+
40
+ /**
41
+ * Union type for all leaf patterns.
42
+ *
43
+ * Corresponds to the Rust `LeafPattern` enum in pattern/leaf/mod.rs
44
+ */
45
+ export type LeafPattern =
46
+ | { readonly type: "Cbor"; readonly pattern: CBORPattern }
47
+ | { readonly type: "Number"; readonly pattern: NumberPattern }
48
+ | { readonly type: "Text"; readonly pattern: TextPattern }
49
+ | { readonly type: "ByteString"; readonly pattern: ByteStringPattern }
50
+ | { readonly type: "Tag"; readonly pattern: TaggedPattern }
51
+ | { readonly type: "Array"; readonly pattern: ArrayPattern }
52
+ | { readonly type: "Map"; readonly pattern: MapPattern }
53
+ | { readonly type: "Bool"; readonly pattern: BoolPattern }
54
+ | { readonly type: "Null"; readonly pattern: NullPattern }
55
+ | { readonly type: "Date"; readonly pattern: DatePattern }
56
+ | { readonly type: "KnownValue"; readonly pattern: KnownValuePattern };
57
+
58
+ /**
59
+ * Creates a CBOR leaf pattern.
60
+ */
61
+ export function leafCbor(pattern: CBORPattern): LeafPattern {
62
+ return { type: "Cbor", pattern };
63
+ }
64
+
65
+ /**
66
+ * Creates a Number leaf pattern.
67
+ */
68
+ export function leafNumber(pattern: NumberPattern): LeafPattern {
69
+ return { type: "Number", pattern };
70
+ }
71
+
72
+ /**
73
+ * Creates a Text leaf pattern.
74
+ */
75
+ export function leafText(pattern: TextPattern): LeafPattern {
76
+ return { type: "Text", pattern };
77
+ }
78
+
79
+ /**
80
+ * Creates a ByteString leaf pattern.
81
+ */
82
+ export function leafByteString(pattern: ByteStringPattern): LeafPattern {
83
+ return { type: "ByteString", pattern };
84
+ }
85
+
86
+ /**
87
+ * Creates a Tag leaf pattern.
88
+ */
89
+ export function leafTag(pattern: TaggedPattern): LeafPattern {
90
+ return { type: "Tag", pattern };
91
+ }
92
+
93
+ /**
94
+ * Creates an Array leaf pattern.
95
+ */
96
+ export function leafArray(pattern: ArrayPattern): LeafPattern {
97
+ return { type: "Array", pattern };
98
+ }
99
+
100
+ /**
101
+ * Creates a Map leaf pattern.
102
+ */
103
+ export function leafMap(pattern: MapPattern): LeafPattern {
104
+ return { type: "Map", pattern };
105
+ }
106
+
107
+ /**
108
+ * Creates a Bool leaf pattern.
109
+ */
110
+ export function leafBool(pattern: BoolPattern): LeafPattern {
111
+ return { type: "Bool", pattern };
112
+ }
113
+
114
+ /**
115
+ * Creates a Null leaf pattern.
116
+ */
117
+ export function leafNull(pattern: NullPattern): LeafPattern {
118
+ return { type: "Null", pattern };
119
+ }
120
+
121
+ /**
122
+ * Creates a Date leaf pattern.
123
+ */
124
+ export function leafDate(pattern: DatePattern): LeafPattern {
125
+ return { type: "Date", pattern };
126
+ }
127
+
128
+ /**
129
+ * Creates a KnownValue leaf pattern.
130
+ */
131
+ export function leafKnownValue(pattern: KnownValuePattern): LeafPattern {
132
+ return { type: "KnownValue", pattern };
133
+ }
134
+
135
+ /**
136
+ * Gets paths with captures for a leaf pattern.
137
+ */
138
+ export function leafPatternPathsWithCaptures(
139
+ pattern: LeafPattern,
140
+ haystack: Envelope,
141
+ ): [Path[], Map<string, Path[]>] {
142
+ switch (pattern.type) {
143
+ case "Cbor":
144
+ // CBOR patterns from dcbor-pattern need special handling
145
+ return [[], new Map<string, Path[]>()];
146
+ case "Number":
147
+ return pattern.pattern.pathsWithCaptures(haystack);
148
+ case "Text":
149
+ return pattern.pattern.pathsWithCaptures(haystack);
150
+ case "ByteString":
151
+ return pattern.pattern.pathsWithCaptures(haystack);
152
+ case "Tag":
153
+ return pattern.pattern.pathsWithCaptures(haystack);
154
+ case "Array":
155
+ return pattern.pattern.pathsWithCaptures(haystack);
156
+ case "Map":
157
+ return pattern.pattern.pathsWithCaptures(haystack);
158
+ case "Bool":
159
+ return pattern.pattern.pathsWithCaptures(haystack);
160
+ case "Null":
161
+ return pattern.pattern.pathsWithCaptures(haystack);
162
+ case "Date":
163
+ return pattern.pattern.pathsWithCaptures(haystack);
164
+ case "KnownValue":
165
+ return pattern.pattern.pathsWithCaptures(haystack);
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Gets paths for a leaf pattern.
171
+ */
172
+ export function leafPatternPaths(pattern: LeafPattern, haystack: Envelope): Path[] {
173
+ return leafPatternPathsWithCaptures(pattern, haystack)[0];
174
+ }
175
+
176
+ /**
177
+ * Compiles a leaf pattern to bytecode.
178
+ */
179
+ export function leafPatternCompile(
180
+ pattern: LeafPattern,
181
+ code: Instr[],
182
+ literals: Pattern[],
183
+ captures: string[],
184
+ ): void {
185
+ switch (pattern.type) {
186
+ case "Cbor":
187
+ pattern.pattern.compile(code, literals, captures);
188
+ break;
189
+ case "Number":
190
+ pattern.pattern.compile(code, literals, captures);
191
+ break;
192
+ case "Text":
193
+ pattern.pattern.compile(code, literals, captures);
194
+ break;
195
+ case "ByteString":
196
+ pattern.pattern.compile(code, literals, captures);
197
+ break;
198
+ case "Tag":
199
+ pattern.pattern.compile(code, literals, captures);
200
+ break;
201
+ case "Array":
202
+ pattern.pattern.compile(code, literals, captures);
203
+ break;
204
+ case "Map":
205
+ pattern.pattern.compile(code, literals, captures);
206
+ break;
207
+ case "Bool":
208
+ pattern.pattern.compile(code, literals, captures);
209
+ break;
210
+ case "Null":
211
+ pattern.pattern.compile(code, literals, captures);
212
+ break;
213
+ case "Date":
214
+ pattern.pattern.compile(code, literals, captures);
215
+ break;
216
+ case "KnownValue":
217
+ pattern.pattern.compile(code, literals, captures);
218
+ break;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Checks if a leaf pattern is complex.
224
+ */
225
+ export function leafPatternIsComplex(pattern: LeafPattern): boolean {
226
+ switch (pattern.type) {
227
+ case "Cbor":
228
+ return pattern.pattern.isComplex();
229
+ case "Number":
230
+ return pattern.pattern.isComplex();
231
+ case "Text":
232
+ return pattern.pattern.isComplex();
233
+ case "ByteString":
234
+ return pattern.pattern.isComplex();
235
+ case "Tag":
236
+ return pattern.pattern.isComplex();
237
+ case "Array":
238
+ return pattern.pattern.isComplex();
239
+ case "Map":
240
+ return pattern.pattern.isComplex();
241
+ case "Bool":
242
+ return pattern.pattern.isComplex();
243
+ case "Null":
244
+ return pattern.pattern.isComplex();
245
+ case "Date":
246
+ return pattern.pattern.isComplex();
247
+ case "KnownValue":
248
+ return pattern.pattern.isComplex();
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Converts a leaf pattern to string.
254
+ */
255
+ export function leafPatternToString(pattern: LeafPattern): string {
256
+ switch (pattern.type) {
257
+ case "Cbor":
258
+ return pattern.pattern.toString();
259
+ case "Number":
260
+ return pattern.pattern.toString();
261
+ case "Text":
262
+ return pattern.pattern.toString();
263
+ case "ByteString":
264
+ return pattern.pattern.toString();
265
+ case "Tag":
266
+ return pattern.pattern.toString();
267
+ case "Array":
268
+ return pattern.pattern.toString();
269
+ case "Map":
270
+ return pattern.pattern.toString();
271
+ case "Bool":
272
+ return pattern.pattern.toString();
273
+ case "Null":
274
+ return pattern.pattern.toString();
275
+ case "Date":
276
+ return pattern.pattern.toString();
277
+ case "KnownValue":
278
+ return pattern.pattern.toString();
279
+ }
280
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * @bcts/envelope-pattern - Known value pattern matching
3
+ *
4
+ * This is a 1:1 TypeScript port of bc-envelope-pattern-rust known_value_pattern.rs
5
+ *
6
+ * @module envelope-pattern/pattern/leaf/known-value-pattern
7
+ */
8
+
9
+ import type { Envelope } from "@bcts/envelope";
10
+ import { type KnownValue } from "@bcts/known-values";
11
+ import {
12
+ type KnownValuePattern as DCBORKnownValuePattern,
13
+ knownValuePatternAny,
14
+ knownValuePatternValue,
15
+ knownValuePatternNamed,
16
+ knownValuePatternRegex,
17
+ knownValuePatternMatches,
18
+ knownValuePatternDisplay,
19
+ } from "@bcts/dcbor-pattern";
20
+ import type { Path } from "../../format";
21
+ import type { Matcher } from "../matcher";
22
+ import { compileAsAtomic } from "../matcher";
23
+ import type { Instr } from "../vm";
24
+ import type { Pattern } from "../index";
25
+
26
+ // Forward declaration for Pattern factory
27
+ let createLeafKnownValuePattern: ((pattern: KnownValuePattern) => Pattern) | undefined;
28
+
29
+ export function registerKnownValuePatternFactory(
30
+ factory: (pattern: KnownValuePattern) => Pattern,
31
+ ): void {
32
+ createLeafKnownValuePattern = factory;
33
+ }
34
+
35
+ /**
36
+ * Pattern for matching known values.
37
+ *
38
+ * This is a wrapper around dcbor_pattern::KnownValuePattern that provides
39
+ * envelope-specific integration.
40
+ *
41
+ * Corresponds to the Rust `KnownValuePattern` struct in known_value_pattern.rs
42
+ */
43
+ export class KnownValuePattern implements Matcher {
44
+ readonly #inner: DCBORKnownValuePattern;
45
+
46
+ private constructor(inner: DCBORKnownValuePattern) {
47
+ this.#inner = inner;
48
+ }
49
+
50
+ /**
51
+ * Creates a new KnownValuePattern that matches any known value.
52
+ */
53
+ static any(): KnownValuePattern {
54
+ return new KnownValuePattern(knownValuePatternAny());
55
+ }
56
+
57
+ /**
58
+ * Creates a new KnownValuePattern that matches the specific known value.
59
+ */
60
+ static value(value: KnownValue): KnownValuePattern {
61
+ return new KnownValuePattern(knownValuePatternValue(value));
62
+ }
63
+
64
+ /**
65
+ * Creates a new KnownValuePattern that matches known values by name.
66
+ */
67
+ static named(name: string): KnownValuePattern {
68
+ return new KnownValuePattern(knownValuePatternNamed(name));
69
+ }
70
+
71
+ /**
72
+ * Creates a new KnownValuePattern that matches known values by regex on their name.
73
+ */
74
+ static regex(regex: RegExp): KnownValuePattern {
75
+ return new KnownValuePattern(knownValuePatternRegex(regex));
76
+ }
77
+
78
+ /**
79
+ * Creates a new KnownValuePattern from a dcbor-pattern KnownValuePattern.
80
+ */
81
+ static fromDcborPattern(dcborPattern: DCBORKnownValuePattern): KnownValuePattern {
82
+ return new KnownValuePattern(dcborPattern);
83
+ }
84
+
85
+ /**
86
+ * Gets the underlying dcbor-pattern KnownValuePattern.
87
+ */
88
+ get inner(): DCBORKnownValuePattern {
89
+ return this.#inner;
90
+ }
91
+
92
+ pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
93
+ // Check if the envelope is a known value via case()
94
+ const envCase = haystack.case();
95
+
96
+ if (envCase.type === "knownValue") {
97
+ // Get the KnownValue and create CBOR for pattern matching
98
+ const knownValueCbor = envCase.value.taggedCbor();
99
+ if (knownValuePatternMatches(this.#inner, knownValueCbor)) {
100
+ return [[[haystack]], new Map<string, Path[]>()];
101
+ }
102
+ }
103
+
104
+ // Also try matching as a leaf (for tagged CBOR containing known values)
105
+ const leafCbor = haystack.asLeaf();
106
+ if (leafCbor !== undefined) {
107
+ if (knownValuePatternMatches(this.#inner, leafCbor)) {
108
+ return [[[haystack]], new Map<string, Path[]>()];
109
+ }
110
+ }
111
+
112
+ return [[], new Map<string, Path[]>()];
113
+ }
114
+
115
+ paths(haystack: Envelope): Path[] {
116
+ return this.pathsWithCaptures(haystack)[0];
117
+ }
118
+
119
+ matches(haystack: Envelope): boolean {
120
+ return this.paths(haystack).length > 0;
121
+ }
122
+
123
+ compile(code: Instr[], literals: Pattern[], captures: string[]): void {
124
+ if (createLeafKnownValuePattern === undefined) {
125
+ throw new Error("KnownValuePattern factory not registered");
126
+ }
127
+ compileAsAtomic(createLeafKnownValuePattern(this), code, literals, captures);
128
+ }
129
+
130
+ isComplex(): boolean {
131
+ return false;
132
+ }
133
+
134
+ toString(): string {
135
+ return knownValuePatternDisplay(this.#inner);
136
+ }
137
+
138
+ /**
139
+ * Equality comparison.
140
+ */
141
+ equals(other: KnownValuePattern): boolean {
142
+ // Compare by variant type and values
143
+ if (this.#inner.variant !== other.#inner.variant) {
144
+ return false;
145
+ }
146
+ switch (this.#inner.variant) {
147
+ case "Any":
148
+ return true;
149
+ case "Value":
150
+ return (
151
+ this.#inner.value.valueBigInt() ===
152
+ (other.#inner as { variant: "Value"; value: KnownValue }).value.valueBigInt()
153
+ );
154
+ case "Named":
155
+ return this.#inner.name === (other.#inner as { variant: "Named"; name: string }).name;
156
+ case "Regex":
157
+ return (
158
+ this.#inner.pattern.source ===
159
+ (other.#inner as { variant: "Regex"; pattern: RegExp }).pattern.source
160
+ );
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Hash code for use in Maps/Sets.
166
+ */
167
+ hashCode(): number {
168
+ switch (this.#inner.variant) {
169
+ case "Any":
170
+ return 0;
171
+ case "Value":
172
+ return Number(this.#inner.value.valueBigInt() & BigInt(0xffffffff));
173
+ case "Named":
174
+ return simpleStringHash(this.#inner.name);
175
+ case "Regex":
176
+ return simpleStringHash(this.#inner.pattern.source);
177
+ }
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Simple string hash function for hashCode implementations.
183
+ */
184
+ function simpleStringHash(str: string): number {
185
+ let hash = 0;
186
+ for (let i = 0; i < str.length; i++) {
187
+ const char = str.charCodeAt(i);
188
+ hash = (hash << 5) - hash + char;
189
+ hash = hash & hash; // Convert to 32-bit integer
190
+ }
191
+ return hash;
192
+ }
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @bcts/envelope-pattern - Map pattern matching
3
+ *
4
+ * This is a 1:1 TypeScript port of bc-envelope-pattern-rust map_pattern.rs
5
+ *
6
+ * @module envelope-pattern/pattern/leaf/map-pattern
7
+ */
8
+
9
+ import type { Envelope } from "@bcts/envelope";
10
+ import { asCborMap } from "@bcts/dcbor";
11
+ import { Interval } from "@bcts/dcbor-pattern";
12
+ import type { Path } from "../../format";
13
+ import type { Matcher } from "../matcher";
14
+ import { compileAsAtomic } from "../matcher";
15
+ import type { Instr } from "../vm";
16
+ import type { Pattern } from "../index";
17
+
18
+ // Forward declaration for Pattern factory
19
+ let createLeafMapPattern: ((pattern: MapPattern) => Pattern) | undefined;
20
+
21
+ export function registerMapPatternFactory(factory: (pattern: MapPattern) => Pattern): void {
22
+ createLeafMapPattern = factory;
23
+ }
24
+
25
+ /**
26
+ * Pattern for matching map values.
27
+ *
28
+ * Corresponds to the Rust `MapPattern` enum in map_pattern.rs
29
+ */
30
+ export type MapPatternType =
31
+ | { readonly type: "Any" }
32
+ | { readonly type: "Interval"; readonly interval: Interval };
33
+
34
+ /**
35
+ * Pattern for matching map values in envelope leaf nodes.
36
+ *
37
+ * Corresponds to the Rust `MapPattern` struct in map_pattern.rs
38
+ */
39
+ export class MapPattern implements Matcher {
40
+ readonly #pattern: MapPatternType;
41
+
42
+ private constructor(pattern: MapPatternType) {
43
+ this.#pattern = pattern;
44
+ }
45
+
46
+ /**
47
+ * Creates a new MapPattern that matches any map.
48
+ */
49
+ static any(): MapPattern {
50
+ return new MapPattern({ type: "Any" });
51
+ }
52
+
53
+ /**
54
+ * Creates a new MapPattern that matches maps within a size range.
55
+ */
56
+ static interval(min: number, max?: number): MapPattern {
57
+ const interval = max !== undefined ? Interval.from(min, max) : Interval.atLeast(min);
58
+ return new MapPattern({ type: "Interval", interval });
59
+ }
60
+
61
+ /**
62
+ * Gets the pattern type.
63
+ */
64
+ get pattern(): MapPatternType {
65
+ return this.#pattern;
66
+ }
67
+
68
+ pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
69
+ // Try to extract CBOR from the envelope
70
+ const cbor = haystack.asLeaf();
71
+ if (cbor === undefined) {
72
+ return [[], new Map<string, Path[]>()];
73
+ }
74
+
75
+ // Check if it's a map
76
+ const map = asCborMap(cbor);
77
+ if (map === undefined) {
78
+ return [[], new Map<string, Path[]>()];
79
+ }
80
+
81
+ switch (this.#pattern.type) {
82
+ case "Any":
83
+ return [[[haystack]], new Map<string, Path[]>()];
84
+
85
+ case "Interval": {
86
+ const size = map.size;
87
+ if (this.#pattern.interval.contains(size)) {
88
+ return [[[haystack]], new Map<string, Path[]>()];
89
+ }
90
+ return [[], new Map<string, Path[]>()];
91
+ }
92
+ }
93
+ }
94
+
95
+ paths(haystack: Envelope): Path[] {
96
+ return this.pathsWithCaptures(haystack)[0];
97
+ }
98
+
99
+ matches(haystack: Envelope): boolean {
100
+ return this.paths(haystack).length > 0;
101
+ }
102
+
103
+ compile(code: Instr[], literals: Pattern[], captures: string[]): void {
104
+ if (createLeafMapPattern === undefined) {
105
+ throw new Error("MapPattern factory not registered");
106
+ }
107
+ compileAsAtomic(createLeafMapPattern(this), code, literals, captures);
108
+ }
109
+
110
+ isComplex(): boolean {
111
+ return false;
112
+ }
113
+
114
+ toString(): string {
115
+ switch (this.#pattern.type) {
116
+ case "Any":
117
+ return "{*}";
118
+ case "Interval":
119
+ return `{{${this.#pattern.interval.toString()}}}`;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Equality comparison.
125
+ */
126
+ equals(other: MapPattern): boolean {
127
+ if (this.#pattern.type !== other.#pattern.type) {
128
+ return false;
129
+ }
130
+ switch (this.#pattern.type) {
131
+ case "Any":
132
+ return true;
133
+ case "Interval":
134
+ return this.#pattern.interval.equals(
135
+ (other.#pattern as { type: "Interval"; interval: Interval }).interval,
136
+ );
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Hash code for use in Maps/Sets.
142
+ */
143
+ hashCode(): number {
144
+ switch (this.#pattern.type) {
145
+ case "Any":
146
+ return 0;
147
+ case "Interval":
148
+ // Simple hash based on interval min/max
149
+ return this.#pattern.interval.min() * 31 + (this.#pattern.interval.max() ?? 0);
150
+ }
151
+ }
152
+ }