@bcts/dcbor-pattern 1.0.0-alpha.11

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 (73) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +14 -0
  3. package/dist/index.cjs +6561 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2732 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.mts +2732 -0
  8. package/dist/index.d.mts.map +1 -0
  9. package/dist/index.iife.js +6562 -0
  10. package/dist/index.iife.js.map +1 -0
  11. package/dist/index.mjs +6244 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +85 -0
  14. package/src/error.ts +333 -0
  15. package/src/format.ts +299 -0
  16. package/src/index.ts +20 -0
  17. package/src/interval.ts +230 -0
  18. package/src/parse/index.ts +95 -0
  19. package/src/parse/meta/and-parser.ts +47 -0
  20. package/src/parse/meta/capture-parser.ts +56 -0
  21. package/src/parse/meta/index.ts +13 -0
  22. package/src/parse/meta/not-parser.ts +28 -0
  23. package/src/parse/meta/or-parser.ts +47 -0
  24. package/src/parse/meta/primary-parser.ts +420 -0
  25. package/src/parse/meta/repeat-parser.ts +133 -0
  26. package/src/parse/meta/search-parser.ts +56 -0
  27. package/src/parse/parse-registry.ts +31 -0
  28. package/src/parse/structure/array-parser.ts +210 -0
  29. package/src/parse/structure/index.ts +9 -0
  30. package/src/parse/structure/map-parser.ts +128 -0
  31. package/src/parse/structure/tagged-parser.ts +269 -0
  32. package/src/parse/token.ts +997 -0
  33. package/src/parse/value/bool-parser.ts +33 -0
  34. package/src/parse/value/bytestring-parser.ts +42 -0
  35. package/src/parse/value/date-parser.ts +24 -0
  36. package/src/parse/value/digest-parser.ts +24 -0
  37. package/src/parse/value/index.ts +14 -0
  38. package/src/parse/value/known-value-parser.ts +24 -0
  39. package/src/parse/value/null-parser.ts +19 -0
  40. package/src/parse/value/number-parser.ts +19 -0
  41. package/src/parse/value/text-parser.ts +43 -0
  42. package/src/pattern/index.ts +740 -0
  43. package/src/pattern/match-registry.ts +137 -0
  44. package/src/pattern/matcher.ts +388 -0
  45. package/src/pattern/meta/and-pattern.ts +56 -0
  46. package/src/pattern/meta/any-pattern.ts +43 -0
  47. package/src/pattern/meta/capture-pattern.ts +57 -0
  48. package/src/pattern/meta/index.ts +168 -0
  49. package/src/pattern/meta/not-pattern.ts +70 -0
  50. package/src/pattern/meta/or-pattern.ts +56 -0
  51. package/src/pattern/meta/repeat-pattern.ts +117 -0
  52. package/src/pattern/meta/search-pattern.ts +298 -0
  53. package/src/pattern/meta/sequence-pattern.ts +72 -0
  54. package/src/pattern/structure/array-pattern/assigner.ts +95 -0
  55. package/src/pattern/structure/array-pattern/backtrack.ts +240 -0
  56. package/src/pattern/structure/array-pattern/helpers.ts +140 -0
  57. package/src/pattern/structure/array-pattern/index.ts +502 -0
  58. package/src/pattern/structure/index.ts +122 -0
  59. package/src/pattern/structure/map-pattern.ts +255 -0
  60. package/src/pattern/structure/tagged-pattern.ts +190 -0
  61. package/src/pattern/value/bool-pattern.ts +67 -0
  62. package/src/pattern/value/bytes-utils.ts +48 -0
  63. package/src/pattern/value/bytestring-pattern.ts +111 -0
  64. package/src/pattern/value/date-pattern.ts +162 -0
  65. package/src/pattern/value/digest-pattern.ts +136 -0
  66. package/src/pattern/value/index.ts +168 -0
  67. package/src/pattern/value/known-value-pattern.ts +123 -0
  68. package/src/pattern/value/null-pattern.ts +46 -0
  69. package/src/pattern/value/number-pattern.ts +181 -0
  70. package/src/pattern/value/text-pattern.ts +82 -0
  71. package/src/pattern/vm.ts +619 -0
  72. package/src/quantifier.ts +185 -0
  73. package/src/reluctance.ts +65 -0
@@ -0,0 +1,740 @@
1
+ /**
2
+ * Pattern types for dCBOR pattern matching.
3
+ *
4
+ * This module provides the core Pattern type and its variants for
5
+ * matching dCBOR values.
6
+ *
7
+ * @module pattern
8
+ */
9
+
10
+ import type { Cbor } from "@bcts/dcbor";
11
+ import type { Path } from "../format";
12
+ import {
13
+ setMatchFn,
14
+ setPathsFn,
15
+ setPathsWithCapturesFn,
16
+ setPathsWithCapturesDirectFn,
17
+ } from "./match-registry";
18
+
19
+ // Re-export sub-modules
20
+ export * from "./value";
21
+ export * from "./structure";
22
+ export * from "./meta";
23
+ export * from "./vm";
24
+ export * from "./matcher";
25
+ export * from "./match-registry";
26
+
27
+ import { type ValuePattern, valuePatternPaths, valuePatternDisplay } from "./value";
28
+ import {
29
+ type StructurePattern,
30
+ structurePatternPaths,
31
+ structurePatternDisplay,
32
+ structurePatternPathsWithCaptures,
33
+ } from "./structure";
34
+ import { type MetaPattern, metaPatternPaths, metaPatternDisplay } from "./meta";
35
+ import { compilePattern } from "./matcher";
36
+ import { Vm } from "./vm";
37
+
38
+ /**
39
+ * The main Pattern type - a discriminated union of all pattern variants.
40
+ */
41
+ export type Pattern =
42
+ | { readonly kind: "Value"; readonly pattern: ValuePattern }
43
+ | { readonly kind: "Structure"; readonly pattern: StructurePattern }
44
+ | { readonly kind: "Meta"; readonly pattern: MetaPattern };
45
+
46
+ /**
47
+ * Result of pattern matching with captures.
48
+ */
49
+ export interface MatchResult {
50
+ readonly paths: Path[];
51
+ readonly captures: Map<string, Path[]>;
52
+ }
53
+
54
+ // ============================================================================
55
+ // Pattern Matching Functions
56
+ // ============================================================================
57
+
58
+ /**
59
+ * Returns paths to matching elements in a CBOR value.
60
+ *
61
+ * @param pattern - The pattern to match
62
+ * @param haystack - The CBOR value to search
63
+ * @returns Array of paths to matching elements
64
+ */
65
+ export const patternPaths = (pattern: Pattern, haystack: Cbor): Path[] => {
66
+ switch (pattern.kind) {
67
+ case "Value":
68
+ return valuePatternPaths(pattern.pattern, haystack);
69
+ case "Structure":
70
+ return structurePatternPaths(pattern.pattern, haystack);
71
+ case "Meta":
72
+ return metaPatternPaths(pattern.pattern, haystack);
73
+ }
74
+ };
75
+
76
+ /**
77
+ * Tests if a pattern matches a CBOR value.
78
+ *
79
+ * @param pattern - The pattern to match
80
+ * @param haystack - The CBOR value to test
81
+ * @returns true if the pattern matches
82
+ */
83
+ export const patternMatches = (pattern: Pattern, haystack: Cbor): boolean => {
84
+ return patternPaths(pattern, haystack).length > 0;
85
+ };
86
+
87
+ /**
88
+ * Formats a pattern as a string.
89
+ *
90
+ * @param pattern - The pattern to format
91
+ * @returns String representation of the pattern
92
+ */
93
+ export const patternDisplay = (pattern: Pattern): string => {
94
+ const displayFn = (p: Pattern): string => patternDisplay(p);
95
+ switch (pattern.kind) {
96
+ case "Value":
97
+ return valuePatternDisplay(pattern.pattern);
98
+ case "Structure":
99
+ return structurePatternDisplay(pattern.pattern, displayFn);
100
+ case "Meta":
101
+ return metaPatternDisplay(pattern.pattern, displayFn);
102
+ }
103
+ };
104
+
105
+ // ============================================================================
106
+ // Convenience Functions (aliases for backwards compatibility)
107
+ // ============================================================================
108
+
109
+ /**
110
+ * Matches a pattern against a CBOR value and returns all matching paths.
111
+ *
112
+ * @param pattern - The pattern to match
113
+ * @param haystack - The CBOR value to search
114
+ * @returns Array of paths to matching elements
115
+ */
116
+ export const paths = patternPaths;
117
+
118
+ /**
119
+ * Checks if a pattern matches a CBOR value.
120
+ *
121
+ * @param pattern - The pattern to match
122
+ * @param haystack - The CBOR value to test
123
+ * @returns true if the pattern matches
124
+ */
125
+ export const matches = patternMatches;
126
+
127
+ /**
128
+ * Computes paths with captures directly without using the VM.
129
+ * This is used internally by the VM to avoid infinite recursion.
130
+ *
131
+ * Note: This function delegates capture collection to the pattern's
132
+ * own matching mechanism. The VM has its own capture tracking, so
133
+ * this just returns paths with any captures found during matching.
134
+ *
135
+ * @param pattern - The pattern to match
136
+ * @param haystack - The CBOR value to search
137
+ * @returns Match result with paths and captures
138
+ */
139
+ export const pathsWithCapturesDirect = (pattern: Pattern, haystack: Cbor): MatchResult => {
140
+ // For structure patterns, use the specialized function that properly handles captures
141
+ if (pattern.kind === "Structure") {
142
+ const [paths, captures] = structurePatternPathsWithCaptures(pattern.pattern, haystack);
143
+ return { paths, captures };
144
+ }
145
+
146
+ // For value patterns, no captures possible
147
+ if (pattern.kind === "Value") {
148
+ const paths = patternPaths(pattern, haystack);
149
+ return { paths, captures: new Map() };
150
+ }
151
+
152
+ // For meta patterns, collect captures recursively
153
+ const paths = patternPaths(pattern, haystack);
154
+ const captures = new Map<string, Path[]>();
155
+
156
+ const collectCaptures = (p: Pattern, h: Cbor): void => {
157
+ if (p.kind === "Meta") {
158
+ switch (p.pattern.type) {
159
+ case "Capture": {
160
+ const capturePattern = p.pattern.pattern;
161
+ const capturedPaths = patternPaths(capturePattern.pattern, h);
162
+ if (capturedPaths.length > 0) {
163
+ const existing = captures.get(capturePattern.name) ?? [];
164
+ captures.set(capturePattern.name, [...existing, ...capturedPaths]);
165
+ }
166
+ collectCaptures(capturePattern.pattern, h);
167
+ break;
168
+ }
169
+ case "And":
170
+ for (const inner of p.pattern.pattern.patterns) {
171
+ collectCaptures(inner, h);
172
+ }
173
+ break;
174
+ case "Or":
175
+ for (const inner of p.pattern.pattern.patterns) {
176
+ if (patternMatches(inner, h)) {
177
+ collectCaptures(inner, h);
178
+ break;
179
+ }
180
+ }
181
+ break;
182
+ case "Not":
183
+ break;
184
+ case "Repeat":
185
+ collectCaptures(p.pattern.pattern.pattern, h);
186
+ break;
187
+ case "Sequence":
188
+ for (const inner of p.pattern.pattern.patterns) {
189
+ collectCaptures(inner, h);
190
+ }
191
+ break;
192
+ case "Search":
193
+ collectCaptures(p.pattern.pattern.pattern, h);
194
+ break;
195
+ case "Any":
196
+ break;
197
+ }
198
+ } else if (p.kind === "Structure") {
199
+ // Delegate to structure-specific function
200
+ const [_, structureCaptures] = structurePatternPathsWithCaptures(p.pattern, h);
201
+ for (const [name, capturePaths] of structureCaptures) {
202
+ const existing = captures.get(name) ?? [];
203
+ captures.set(name, [...existing, ...capturePaths]);
204
+ }
205
+ }
206
+ };
207
+
208
+ if (paths.length > 0) {
209
+ collectCaptures(pattern, haystack);
210
+ }
211
+
212
+ return { paths, captures };
213
+ };
214
+
215
+ /**
216
+ * Matches a pattern against a CBOR value and returns paths with captures.
217
+ *
218
+ * @param pattern - The pattern to match
219
+ * @param haystack - The CBOR value to search
220
+ * @returns Match result with paths and captures
221
+ */
222
+ export const pathsWithCaptures = (pattern: Pattern, haystack: Cbor): MatchResult => {
223
+ const program = compilePattern(pattern);
224
+ const result = Vm.run(program, haystack);
225
+ return result;
226
+ };
227
+
228
+ /**
229
+ * Alias for pathsWithCaptures for internal VM use.
230
+ */
231
+ export const patternPathsWithCaptures = pathsWithCaptures;
232
+
233
+ // ============================================================================
234
+ // Pattern Constructors
235
+ // ============================================================================
236
+
237
+ import { boolPatternAny, boolPatternValue } from "./value/bool-pattern";
238
+ import { nullPattern as nullPatternCreate } from "./value/null-pattern";
239
+ import {
240
+ numberPatternAny,
241
+ numberPatternValue,
242
+ numberPatternRange,
243
+ numberPatternGreaterThan,
244
+ numberPatternGreaterThanOrEqual,
245
+ numberPatternLessThan,
246
+ numberPatternLessThanOrEqual,
247
+ numberPatternNaN,
248
+ numberPatternInfinity,
249
+ numberPatternNegInfinity,
250
+ } from "./value/number-pattern";
251
+ import { textPatternAny, textPatternValue, textPatternRegex } from "./value/text-pattern";
252
+ import {
253
+ byteStringPatternAny,
254
+ byteStringPatternValue,
255
+ byteStringPatternBinaryRegex,
256
+ } from "./value/bytestring-pattern";
257
+ import {
258
+ datePatternAny,
259
+ datePatternValue,
260
+ datePatternRange,
261
+ datePatternEarliest,
262
+ datePatternLatest,
263
+ datePatternStringValue,
264
+ datePatternRegex,
265
+ } from "./value/date-pattern";
266
+ import {
267
+ digestPatternAny,
268
+ digestPatternValue,
269
+ digestPatternPrefix,
270
+ digestPatternBinaryRegex,
271
+ } from "./value/digest-pattern";
272
+ import {
273
+ knownValuePatternAny,
274
+ knownValuePatternValue,
275
+ knownValuePatternNamed,
276
+ knownValuePatternRegex,
277
+ } from "./value/known-value-pattern";
278
+
279
+ import { arrayPatternAny } from "./structure/array-pattern";
280
+ import { mapPatternAny } from "./structure/map-pattern";
281
+ import {
282
+ taggedPatternAny,
283
+ taggedPatternWithTag,
284
+ taggedPatternWithName,
285
+ taggedPatternWithRegex,
286
+ } from "./structure/tagged-pattern";
287
+
288
+ import { anyPattern as anyPatternCreate } from "./meta/any-pattern";
289
+ import { andPattern as andPatternCreate } from "./meta/and-pattern";
290
+ import { orPattern as orPatternCreate } from "./meta/or-pattern";
291
+ import { notPattern as notPatternCreate } from "./meta/not-pattern";
292
+ import { capturePattern as capturePatternCreate } from "./meta/capture-pattern";
293
+ import { searchPattern as searchPatternCreate } from "./meta/search-pattern";
294
+ import { sequencePattern as sequencePatternCreate } from "./meta/sequence-pattern";
295
+ import { repeatPattern as repeatPatternCreate } from "./meta/repeat-pattern";
296
+ import { Quantifier } from "../quantifier";
297
+ import type { Tag } from "@bcts/dcbor";
298
+ import type { CborDate } from "@bcts/dcbor";
299
+ import type { Digest } from "@bcts/components";
300
+ import type { KnownValue } from "@bcts/known-values";
301
+
302
+ /**
303
+ * Creates a pattern that matches any value.
304
+ */
305
+ export const any = (): Pattern => ({
306
+ kind: "Meta",
307
+ pattern: { type: "Any", pattern: anyPatternCreate() },
308
+ });
309
+
310
+ /**
311
+ * Creates a pattern that matches any boolean.
312
+ */
313
+ export const anyBool = (): Pattern => ({
314
+ kind: "Value",
315
+ pattern: { type: "Bool", pattern: boolPatternAny() },
316
+ });
317
+
318
+ /**
319
+ * Creates a pattern that matches a specific boolean value.
320
+ */
321
+ export const bool = (value: boolean): Pattern => ({
322
+ kind: "Value",
323
+ pattern: { type: "Bool", pattern: boolPatternValue(value) },
324
+ });
325
+
326
+ /**
327
+ * Creates a pattern that matches null.
328
+ */
329
+ export const nullPattern = (): Pattern => ({
330
+ kind: "Value",
331
+ pattern: { type: "Null", pattern: nullPatternCreate() },
332
+ });
333
+
334
+ /**
335
+ * Creates a pattern that matches any number.
336
+ */
337
+ export const anyNumber = (): Pattern => ({
338
+ kind: "Value",
339
+ pattern: { type: "Number", pattern: numberPatternAny() },
340
+ });
341
+
342
+ /**
343
+ * Creates a pattern that matches a specific number.
344
+ */
345
+ export const number = (value: number): Pattern => ({
346
+ kind: "Value",
347
+ pattern: { type: "Number", pattern: numberPatternValue(value) },
348
+ });
349
+
350
+ /**
351
+ * Creates a pattern that matches numbers in a range.
352
+ */
353
+ export const numberRange = (min: number, max: number): Pattern => ({
354
+ kind: "Value",
355
+ pattern: { type: "Number", pattern: numberPatternRange(min, max) },
356
+ });
357
+
358
+ /**
359
+ * Creates a pattern that matches any text.
360
+ */
361
+ export const anyText = (): Pattern => ({
362
+ kind: "Value",
363
+ pattern: { type: "Text", pattern: textPatternAny() },
364
+ });
365
+
366
+ /**
367
+ * Creates a pattern that matches specific text.
368
+ */
369
+ export const text = (value: string): Pattern => ({
370
+ kind: "Value",
371
+ pattern: { type: "Text", pattern: textPatternValue(value) },
372
+ });
373
+
374
+ /**
375
+ * Creates a pattern that matches text using a regex.
376
+ */
377
+ export const textRegex = (pattern: RegExp): Pattern => ({
378
+ kind: "Value",
379
+ pattern: { type: "Text", pattern: textPatternRegex(pattern) },
380
+ });
381
+
382
+ /**
383
+ * Creates a pattern that matches any byte string.
384
+ */
385
+ export const anyByteString = (): Pattern => ({
386
+ kind: "Value",
387
+ pattern: { type: "ByteString", pattern: byteStringPatternAny() },
388
+ });
389
+
390
+ /**
391
+ * Creates a pattern that matches a specific byte string.
392
+ */
393
+ export const byteString = (value: Uint8Array): Pattern => ({
394
+ kind: "Value",
395
+ pattern: { type: "ByteString", pattern: byteStringPatternValue(value) },
396
+ });
397
+
398
+ /**
399
+ * Creates a pattern that matches byte strings using a binary regex.
400
+ *
401
+ * The regex matches against raw bytes converted to a Latin-1 string.
402
+ * Use escape sequences like `\x00` to match specific byte values.
403
+ *
404
+ * @example
405
+ * ```typescript
406
+ * // Match bytes starting with 0x00
407
+ * byteStringRegex(/^\x00/)
408
+ *
409
+ * // Match ASCII "Hello"
410
+ * byteStringRegex(/Hello/)
411
+ * ```
412
+ */
413
+ export const byteStringRegex = (pattern: RegExp): Pattern => ({
414
+ kind: "Value",
415
+ pattern: { type: "ByteString", pattern: byteStringPatternBinaryRegex(pattern) },
416
+ });
417
+
418
+ /**
419
+ * Creates a pattern that matches any array.
420
+ */
421
+ export const anyArray = (): Pattern => ({
422
+ kind: "Structure",
423
+ pattern: { type: "Array", pattern: arrayPatternAny() },
424
+ });
425
+
426
+ /**
427
+ * Creates a pattern that matches any map.
428
+ */
429
+ export const anyMap = (): Pattern => ({
430
+ kind: "Structure",
431
+ pattern: { type: "Map", pattern: mapPatternAny() },
432
+ });
433
+
434
+ /**
435
+ * Creates a pattern that matches any tagged value.
436
+ */
437
+ export const anyTagged = (): Pattern => ({
438
+ kind: "Structure",
439
+ pattern: { type: "Tagged", pattern: taggedPatternAny() },
440
+ });
441
+
442
+ /**
443
+ * Creates an AND pattern that matches if all patterns match.
444
+ */
445
+ export const and = (...patterns: Pattern[]): Pattern => ({
446
+ kind: "Meta",
447
+ pattern: { type: "And", pattern: andPatternCreate(patterns) },
448
+ });
449
+
450
+ /**
451
+ * Creates an OR pattern that matches if any pattern matches.
452
+ */
453
+ export const or = (...patterns: Pattern[]): Pattern => ({
454
+ kind: "Meta",
455
+ pattern: { type: "Or", pattern: orPatternCreate(patterns) },
456
+ });
457
+
458
+ /**
459
+ * Creates a NOT pattern that matches if the pattern does not match.
460
+ */
461
+ export const not = (pattern: Pattern): Pattern => ({
462
+ kind: "Meta",
463
+ pattern: { type: "Not", pattern: notPatternCreate(pattern) },
464
+ });
465
+
466
+ /**
467
+ * Creates a capture pattern with a name.
468
+ */
469
+ export const capture = (name: string, pattern: Pattern): Pattern => ({
470
+ kind: "Meta",
471
+ pattern: { type: "Capture", pattern: capturePatternCreate(name, pattern) },
472
+ });
473
+
474
+ /**
475
+ * Creates a search pattern for recursive matching.
476
+ */
477
+ export const search = (pattern: Pattern): Pattern => ({
478
+ kind: "Meta",
479
+ pattern: { type: "Search", pattern: searchPatternCreate(pattern) },
480
+ });
481
+
482
+ /**
483
+ * Creates a sequence pattern for ordered matching.
484
+ */
485
+ export const sequence = (...patterns: Pattern[]): Pattern => ({
486
+ kind: "Meta",
487
+ pattern: { type: "Sequence", pattern: sequencePatternCreate(patterns) },
488
+ });
489
+
490
+ // ============================================================================
491
+ // Number Pattern Constructors (additional)
492
+ // ============================================================================
493
+
494
+ /**
495
+ * Creates a pattern that matches numbers greater than a value.
496
+ */
497
+ export const numberGreaterThan = (value: number): Pattern => ({
498
+ kind: "Value",
499
+ pattern: { type: "Number", pattern: numberPatternGreaterThan(value) },
500
+ });
501
+
502
+ /**
503
+ * Creates a pattern that matches numbers greater than or equal to a value.
504
+ */
505
+ export const numberGreaterThanOrEqual = (value: number): Pattern => ({
506
+ kind: "Value",
507
+ pattern: { type: "Number", pattern: numberPatternGreaterThanOrEqual(value) },
508
+ });
509
+
510
+ /**
511
+ * Creates a pattern that matches numbers less than a value.
512
+ */
513
+ export const numberLessThan = (value: number): Pattern => ({
514
+ kind: "Value",
515
+ pattern: { type: "Number", pattern: numberPatternLessThan(value) },
516
+ });
517
+
518
+ /**
519
+ * Creates a pattern that matches numbers less than or equal to a value.
520
+ */
521
+ export const numberLessThanOrEqual = (value: number): Pattern => ({
522
+ kind: "Value",
523
+ pattern: { type: "Number", pattern: numberPatternLessThanOrEqual(value) },
524
+ });
525
+
526
+ /**
527
+ * Creates a pattern that matches NaN.
528
+ */
529
+ export const numberNaN = (): Pattern => ({
530
+ kind: "Value",
531
+ pattern: { type: "Number", pattern: numberPatternNaN() },
532
+ });
533
+
534
+ /**
535
+ * Creates a pattern that matches positive infinity.
536
+ */
537
+ export const numberInfinity = (): Pattern => ({
538
+ kind: "Value",
539
+ pattern: { type: "Number", pattern: numberPatternInfinity() },
540
+ });
541
+
542
+ /**
543
+ * Creates a pattern that matches negative infinity.
544
+ */
545
+ export const numberNegInfinity = (): Pattern => ({
546
+ kind: "Value",
547
+ pattern: { type: "Number", pattern: numberPatternNegInfinity() },
548
+ });
549
+
550
+ // ============================================================================
551
+ // Date Pattern Constructors
552
+ // ============================================================================
553
+
554
+ /**
555
+ * Creates a pattern that matches any date.
556
+ */
557
+ export const anyDate = (): Pattern => ({
558
+ kind: "Value",
559
+ pattern: { type: "Date", pattern: datePatternAny() },
560
+ });
561
+
562
+ /**
563
+ * Creates a pattern that matches a specific date.
564
+ */
565
+ export const date = (value: CborDate): Pattern => ({
566
+ kind: "Value",
567
+ pattern: { type: "Date", pattern: datePatternValue(value) },
568
+ });
569
+
570
+ /**
571
+ * Creates a pattern that matches dates within a range (inclusive).
572
+ */
573
+ export const dateRange = (min: CborDate, max: CborDate): Pattern => ({
574
+ kind: "Value",
575
+ pattern: { type: "Date", pattern: datePatternRange(min, max) },
576
+ });
577
+
578
+ /**
579
+ * Creates a pattern that matches dates on or after the specified date.
580
+ */
581
+ export const dateEarliest = (value: CborDate): Pattern => ({
582
+ kind: "Value",
583
+ pattern: { type: "Date", pattern: datePatternEarliest(value) },
584
+ });
585
+
586
+ /**
587
+ * Creates a pattern that matches dates on or before the specified date.
588
+ */
589
+ export const dateLatest = (value: CborDate): Pattern => ({
590
+ kind: "Value",
591
+ pattern: { type: "Date", pattern: datePatternLatest(value) },
592
+ });
593
+
594
+ /**
595
+ * Creates a pattern that matches dates by their ISO-8601 string representation.
596
+ */
597
+ export const dateIso8601 = (value: string): Pattern => ({
598
+ kind: "Value",
599
+ pattern: { type: "Date", pattern: datePatternStringValue(value) },
600
+ });
601
+
602
+ /**
603
+ * Creates a pattern that matches dates by regex on their ISO-8601 string.
604
+ */
605
+ export const dateRegex = (pattern: RegExp): Pattern => ({
606
+ kind: "Value",
607
+ pattern: { type: "Date", pattern: datePatternRegex(pattern) },
608
+ });
609
+
610
+ // ============================================================================
611
+ // Digest Pattern Constructors
612
+ // ============================================================================
613
+
614
+ /**
615
+ * Creates a pattern that matches any digest.
616
+ */
617
+ export const anyDigest = (): Pattern => ({
618
+ kind: "Value",
619
+ pattern: { type: "Digest", pattern: digestPatternAny() },
620
+ });
621
+
622
+ /**
623
+ * Creates a pattern that matches a specific digest.
624
+ */
625
+ export const digest = (value: Digest): Pattern => ({
626
+ kind: "Value",
627
+ pattern: { type: "Digest", pattern: digestPatternValue(value) },
628
+ });
629
+
630
+ /**
631
+ * Creates a pattern that matches digests with a prefix.
632
+ */
633
+ export const digestPrefix = (prefix: Uint8Array): Pattern => ({
634
+ kind: "Value",
635
+ pattern: { type: "Digest", pattern: digestPatternPrefix(prefix) },
636
+ });
637
+
638
+ /**
639
+ * Creates a pattern that matches digests by binary regex.
640
+ */
641
+ export const digestBinaryRegex = (pattern: RegExp): Pattern => ({
642
+ kind: "Value",
643
+ pattern: { type: "Digest", pattern: digestPatternBinaryRegex(pattern) },
644
+ });
645
+
646
+ // ============================================================================
647
+ // KnownValue Pattern Constructors
648
+ // ============================================================================
649
+
650
+ /**
651
+ * Creates a pattern that matches any known value.
652
+ */
653
+ export const anyKnownValue = (): Pattern => ({
654
+ kind: "Value",
655
+ pattern: { type: "KnownValue", pattern: knownValuePatternAny() },
656
+ });
657
+
658
+ /**
659
+ * Creates a pattern that matches a specific known value.
660
+ */
661
+ export const knownValue = (value: KnownValue): Pattern => ({
662
+ kind: "Value",
663
+ pattern: { type: "KnownValue", pattern: knownValuePatternValue(value) },
664
+ });
665
+
666
+ /**
667
+ * Creates a pattern that matches a known value by name.
668
+ */
669
+ export const knownValueNamed = (name: string): Pattern => ({
670
+ kind: "Value",
671
+ pattern: { type: "KnownValue", pattern: knownValuePatternNamed(name) },
672
+ });
673
+
674
+ /**
675
+ * Creates a pattern that matches known values by regex on their name.
676
+ */
677
+ export const knownValueRegex = (pattern: RegExp): Pattern => ({
678
+ kind: "Value",
679
+ pattern: { type: "KnownValue", pattern: knownValuePatternRegex(pattern) },
680
+ });
681
+
682
+ // ============================================================================
683
+ // Tagged Pattern Constructors
684
+ // ============================================================================
685
+
686
+ /**
687
+ * Creates a pattern that matches tagged values with a specific tag.
688
+ */
689
+ export const tagged = (tag: Tag, pattern: Pattern): Pattern => ({
690
+ kind: "Structure",
691
+ pattern: { type: "Tagged", pattern: taggedPatternWithTag(tag, pattern) },
692
+ });
693
+
694
+ /**
695
+ * Creates a pattern that matches tagged values by tag name.
696
+ */
697
+ export const taggedName = (name: string, pattern: Pattern): Pattern => ({
698
+ kind: "Structure",
699
+ pattern: { type: "Tagged", pattern: taggedPatternWithName(name, pattern) },
700
+ });
701
+
702
+ /**
703
+ * Creates a pattern that matches tagged values by tag name regex.
704
+ */
705
+ export const taggedRegex = (regex: RegExp, pattern: Pattern): Pattern => ({
706
+ kind: "Structure",
707
+ pattern: { type: "Tagged", pattern: taggedPatternWithRegex(regex, pattern) },
708
+ });
709
+
710
+ // ============================================================================
711
+ // Meta Pattern Constructors (additional)
712
+ // ============================================================================
713
+
714
+ /**
715
+ * Creates a repeat pattern with the given pattern and quantifier.
716
+ */
717
+ export const repeat = (pattern: Pattern, quantifier: Quantifier): Pattern => ({
718
+ kind: "Meta",
719
+ pattern: { type: "Repeat", pattern: repeatPatternCreate(pattern, quantifier) },
720
+ });
721
+
722
+ /**
723
+ * Creates a grouped pattern (equivalent to repeat with exactly 1).
724
+ * This is useful for precedence grouping in pattern expressions.
725
+ */
726
+ export const group = (pattern: Pattern): Pattern => ({
727
+ kind: "Meta",
728
+ pattern: { type: "Repeat", pattern: repeatPatternCreate(pattern, Quantifier.exactly(1)) },
729
+ });
730
+
731
+ // ============================================================================
732
+ // Initialize Match Registry
733
+ // ============================================================================
734
+
735
+ // Register all pattern functions with the match registry
736
+ // This breaks the circular dependency between pattern files
737
+ setMatchFn(patternMatches);
738
+ setPathsFn(patternPaths);
739
+ setPathsWithCapturesFn(pathsWithCaptures);
740
+ setPathsWithCapturesDirectFn(pathsWithCapturesDirect);