@bcts/envelope-pattern 1.0.0-alpha.22 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1291 -826
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -59
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +102 -60
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +1643 -1179
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +1315 -853
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -11
- package/src/error.ts +1 -1
- package/src/format.ts +19 -31
- package/src/parse/index.ts +17 -1010
- package/src/parse/leaf/array-parser.ts +36 -0
- package/src/parse/leaf/cbor-parser.ts +43 -0
- package/src/parse/leaf/date-parser.ts +81 -0
- package/src/parse/leaf/known-value-parser.ts +73 -0
- package/src/parse/leaf/null-parser.ts +16 -0
- package/src/parse/leaf/number-parser.ts +90 -0
- package/src/parse/leaf/tag-parser.ts +160 -0
- package/src/parse/meta/and-parser.ts +40 -0
- package/src/parse/meta/capture-parser.ts +50 -0
- package/src/parse/meta/group-parser.ts +77 -0
- package/src/parse/meta/not-parser.ts +30 -0
- package/src/parse/meta/or-parser.ts +36 -0
- package/src/parse/meta/primary-parser.ts +234 -0
- package/src/parse/meta/search-parser.ts +41 -0
- package/src/parse/meta/traverse-parser.ts +42 -0
- package/src/parse/structure/assertion-obj-parser.ts +44 -0
- package/src/parse/structure/assertion-parser.ts +22 -0
- package/src/parse/structure/assertion-pred-parser.ts +45 -0
- package/src/parse/structure/compressed-parser.ts +17 -0
- package/src/parse/structure/digest-parser.ts +132 -0
- package/src/parse/structure/elided-parser.ts +17 -0
- package/src/parse/structure/encrypted-parser.ts +17 -0
- package/src/parse/structure/node-parser.ts +54 -0
- package/src/parse/structure/object-parser.ts +32 -0
- package/src/parse/structure/obscured-parser.ts +17 -0
- package/src/parse/structure/predicate-parser.ts +32 -0
- package/src/parse/structure/subject-parser.ts +32 -0
- package/src/parse/structure/wrapped-parser.ts +36 -0
- package/src/pattern/dcbor-integration.ts +40 -8
- package/src/pattern/index.ts +29 -0
- package/src/pattern/leaf/array-pattern.ts +67 -169
- package/src/pattern/leaf/cbor-pattern.ts +37 -23
- package/src/pattern/leaf/index.ts +1 -1
- package/src/pattern/leaf/map-pattern.ts +21 -2
- package/src/pattern/leaf/tagged-pattern.ts +6 -1
- package/src/pattern/meta/search-pattern.ts +13 -38
- package/src/pattern/meta/traverse-pattern.ts +2 -2
- package/src/pattern/structure/assertions-pattern.ts +19 -53
- package/src/pattern/structure/digest-pattern.ts +18 -22
- package/src/pattern/structure/index.ts +3 -0
- package/src/pattern/structure/node-pattern.ts +10 -29
- package/src/pattern/structure/object-pattern.ts +2 -2
- package/src/pattern/structure/predicate-pattern.ts +2 -2
- package/src/pattern/structure/subject-pattern.ts +31 -4
- package/src/pattern/structure/wrapped-pattern.ts +28 -9
- package/src/pattern/vm.ts +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Interval, Interval as Interval$1, Quantifier, Quantifier as Quantifier$1, Reluctance, Reluctance as Reluctance$1, boolPatternAny, boolPatternDisplay, boolPatternPaths, boolPatternValue, byteStringPatternAny, byteStringPatternBinaryRegex, byteStringPatternDisplay, byteStringPatternPaths, byteStringPatternValue, datePatternAny, datePatternDisplay, datePatternEarliest, datePatternLatest, datePatternPaths, datePatternRange, datePatternRegex, datePatternStringValue, datePatternValue, knownValuePatternAny, knownValuePatternDisplay, knownValuePatternMatches, knownValuePatternNamed, knownValuePatternRegex, knownValuePatternValue, nullPatternDisplay, nullPatternPaths, numberPatternAny, numberPatternDisplay, numberPatternGreaterThan, numberPatternGreaterThanOrEqual, numberPatternInfinity, numberPatternLessThan, numberPatternLessThanOrEqual, numberPatternNaN, numberPatternNegInfinity, numberPatternPaths, numberPatternRange, numberPatternValue, parse as parse$1, patternDisplay, patternPathsWithCaptures as patternPathsWithCaptures$1, taggedPatternAny, taggedPatternDisplay, taggedPatternPathsWithCaptures, taggedPatternWithName, taggedPatternWithRegex, taggedPatternWithTag, textPatternAny, textPatternDisplay, textPatternPaths, textPatternRegex, textPatternValue } from "@bcts/dcbor-pattern";
|
|
2
|
-
import { UNIT } from "@bcts/known-values";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { Interval, Interval as Interval$1, Quantifier, Quantifier as Quantifier$1, Reluctance, Reluctance as Reluctance$1, arrayPatternAny, arrayPatternDisplay, arrayPatternEquals, arrayPatternMatches, arrayPatternWithElements, arrayPatternWithLength, arrayPatternWithLengthInterval, arrayPatternWithLengthRange, boolPatternAny, boolPatternDisplay, boolPatternPaths, boolPatternValue, byteStringPatternAny, byteStringPatternBinaryRegex, byteStringPatternDisplay, byteStringPatternPaths, byteStringPatternValue, datePatternAny, datePatternDisplay, datePatternEarliest, datePatternLatest, datePatternPaths, datePatternRange, datePatternRegex, datePatternStringValue, datePatternValue, knownValuePatternAny, knownValuePatternDisplay, knownValuePatternMatches, knownValuePatternNamed, knownValuePatternRegex, knownValuePatternValue, nullPatternDisplay, nullPatternPaths, numberPatternAny, numberPatternDisplay, numberPatternGreaterThan, numberPatternGreaterThanOrEqual, numberPatternInfinity, numberPatternLessThan, numberPatternLessThanOrEqual, numberPatternNaN, numberPatternNegInfinity, numberPatternPaths, numberPatternRange, numberPatternValue, parse as parse$1, patternDisplay, patternPathsWithCaptures as patternPathsWithCaptures$1, taggedPatternAny, taggedPatternDisplay, taggedPatternPathsWithCaptures, taggedPatternWithName, taggedPatternWithRegex, taggedPatternWithTag, textPatternAny, textPatternDisplay, textPatternPaths, textPatternRegex, textPatternValue } from "@bcts/dcbor-pattern";
|
|
2
|
+
import { KnownValue, UNIT } from "@bcts/known-values";
|
|
3
|
+
import { CborDate, asCborMap, bytesToHex, cbor, cborData, cborEquals } from "@bcts/dcbor";
|
|
4
|
+
import { Digest, Envelope } from "@bcts/envelope";
|
|
5
5
|
import { parseDcborItemPartial } from "@bcts/dcbor-parse";
|
|
6
|
-
|
|
7
6
|
//#region src/error.ts
|
|
8
7
|
/**
|
|
9
8
|
* Creates a successful result.
|
|
@@ -218,7 +217,6 @@ function dcborPatternError(error) {
|
|
|
218
217
|
error
|
|
219
218
|
};
|
|
220
219
|
}
|
|
221
|
-
|
|
222
220
|
//#endregion
|
|
223
221
|
//#region src/format.ts
|
|
224
222
|
/**
|
|
@@ -307,6 +305,14 @@ function formatPathsOpts() {
|
|
|
307
305
|
/**
|
|
308
306
|
* Gets a summary of an envelope for display.
|
|
309
307
|
*
|
|
308
|
+
* Mirrors Rust `envelope_summary` in `format.rs`: defers to
|
|
309
|
+
* `Envelope::format_flat()` for nodes / wrapped / assertions and to
|
|
310
|
+
* `cbor.envelope_summary(usize::MAX, ...)` for raw CBOR leaves. The
|
|
311
|
+
* obscured cases (`elided` / `encrypted` / `compressed`) emit just the
|
|
312
|
+
* keyword. KnownValue envelopes look up the canonical name via
|
|
313
|
+
* `KnownValue.name()`, matching the Rust call to
|
|
314
|
+
* `KnownValuesStore::known_value_for_raw_value(value, …)`.
|
|
315
|
+
*
|
|
310
316
|
* @param env - The envelope to summarize
|
|
311
317
|
* @returns A string summary of the envelope
|
|
312
318
|
*/
|
|
@@ -315,25 +321,17 @@ function envelopeSummary(env) {
|
|
|
315
321
|
const c = env.case();
|
|
316
322
|
let summary;
|
|
317
323
|
switch (c.type) {
|
|
318
|
-
case "node":
|
|
319
|
-
|
|
320
|
-
const assertions = env.assertions();
|
|
321
|
-
if (assertions.length > 0) summary = `NODE ${subjectSummary} [ ${assertions.map((a) => {
|
|
322
|
-
const ac = a.case();
|
|
323
|
-
if (ac.type === "assertion") return `${ac.assertion.predicate().summary(Number.MAX_SAFE_INTEGER)}: ${ac.assertion.object().summary(Number.MAX_SAFE_INTEGER)}`;
|
|
324
|
-
return a.summary(Number.MAX_SAFE_INTEGER);
|
|
325
|
-
}).join(", ")} ]`;
|
|
326
|
-
else summary = `NODE ${subjectSummary}`;
|
|
324
|
+
case "node":
|
|
325
|
+
summary = `NODE ${env.formatFlat()}`;
|
|
327
326
|
break;
|
|
328
|
-
}
|
|
329
327
|
case "leaf":
|
|
330
328
|
summary = `LEAF ${env.summary(Number.MAX_SAFE_INTEGER)}`;
|
|
331
329
|
break;
|
|
332
330
|
case "wrapped":
|
|
333
|
-
summary = `WRAPPED ${env.
|
|
331
|
+
summary = `WRAPPED ${env.formatFlat()}`;
|
|
334
332
|
break;
|
|
335
333
|
case "assertion":
|
|
336
|
-
summary = `ASSERTION ${
|
|
334
|
+
summary = `ASSERTION ${env.formatFlat()}`;
|
|
337
335
|
break;
|
|
338
336
|
case "elided":
|
|
339
337
|
summary = "ELIDED";
|
|
@@ -379,8 +377,8 @@ function formatPathOpt(path, opts = defaultFormatPathsOpts()) {
|
|
|
379
377
|
if (element === void 0) return "";
|
|
380
378
|
switch (opts.elementFormat.type) {
|
|
381
379
|
case "Summary": return truncateWithEllipsis(envelopeSummary(element), opts.elementFormat.maxLength);
|
|
382
|
-
case "EnvelopeUR": return element.
|
|
383
|
-
case "DigestUR": return element.digest().
|
|
380
|
+
case "EnvelopeUR": return element.urString();
|
|
381
|
+
case "DigestUR": return element.digest().urString();
|
|
384
382
|
}
|
|
385
383
|
}
|
|
386
384
|
switch (opts.elementFormat.type) {
|
|
@@ -395,8 +393,8 @@ function formatPathOpt(path, opts = defaultFormatPathsOpts()) {
|
|
|
395
393
|
}
|
|
396
394
|
return lines.join("\n");
|
|
397
395
|
}
|
|
398
|
-
case "EnvelopeUR": return path.map((element) => element.
|
|
399
|
-
case "DigestUR": return path.map((element) => element.digest().
|
|
396
|
+
case "EnvelopeUR": return path.map((element) => element.urString()).join(" ");
|
|
397
|
+
case "DigestUR": return path.map((element) => element.digest().urString()).join(" ");
|
|
400
398
|
}
|
|
401
399
|
}
|
|
402
400
|
/**
|
|
@@ -477,19 +475,27 @@ function formatPathsOpt(paths, opts = defaultFormatPathsOpts()) {
|
|
|
477
475
|
function formatPaths(paths) {
|
|
478
476
|
return formatPathsOpt(paths, defaultFormatPathsOpts());
|
|
479
477
|
}
|
|
480
|
-
|
|
481
478
|
//#endregion
|
|
482
479
|
//#region src/pattern/matcher.ts
|
|
483
480
|
/**
|
|
484
481
|
* Default implementations for Matcher methods.
|
|
485
482
|
*/
|
|
486
483
|
const MatcherDefaults = {
|
|
484
|
+
/**
|
|
485
|
+
* Default implementation of paths() - calls pathsWithCaptures and discards captures.
|
|
486
|
+
*/
|
|
487
487
|
paths(matcher, haystack) {
|
|
488
488
|
return matcher.pathsWithCaptures(haystack)[0];
|
|
489
489
|
},
|
|
490
|
+
/**
|
|
491
|
+
* Default implementation of matches() - checks if paths() returns any results.
|
|
492
|
+
*/
|
|
490
493
|
matches(matcher, haystack) {
|
|
491
494
|
return matcher.paths(haystack).length > 0;
|
|
492
495
|
},
|
|
496
|
+
/**
|
|
497
|
+
* Default implementation of isComplex() - returns false.
|
|
498
|
+
*/
|
|
493
499
|
isComplex() {
|
|
494
500
|
return false;
|
|
495
501
|
}
|
|
@@ -577,7 +583,6 @@ function dispatchPatternToString(pattern) {
|
|
|
577
583
|
if (patternToStringFn === void 0) throw new Error("Pattern dispatch functions not registered");
|
|
578
584
|
return patternToStringFn(pattern);
|
|
579
585
|
}
|
|
580
|
-
|
|
581
586
|
//#endregion
|
|
582
587
|
//#region src/pattern/leaf/bool-pattern.ts
|
|
583
588
|
let createLeafBoolPattern;
|
|
@@ -661,7 +666,6 @@ var BoolPattern = class BoolPattern {
|
|
|
661
666
|
return hash;
|
|
662
667
|
}
|
|
663
668
|
};
|
|
664
|
-
|
|
665
669
|
//#endregion
|
|
666
670
|
//#region src/pattern/leaf/null-pattern.ts
|
|
667
671
|
let createLeafNullPattern;
|
|
@@ -730,7 +734,6 @@ var NullPattern = class NullPattern {
|
|
|
730
734
|
return 0;
|
|
731
735
|
}
|
|
732
736
|
};
|
|
733
|
-
|
|
734
737
|
//#endregion
|
|
735
738
|
//#region src/pattern/leaf/number-pattern.ts
|
|
736
739
|
let createLeafNumberPattern;
|
|
@@ -903,7 +906,6 @@ var NumberPattern = class NumberPattern {
|
|
|
903
906
|
return hash;
|
|
904
907
|
}
|
|
905
908
|
};
|
|
906
|
-
|
|
907
909
|
//#endregion
|
|
908
910
|
//#region src/pattern/leaf/text-pattern.ts
|
|
909
911
|
let createLeafTextPattern;
|
|
@@ -1008,7 +1010,6 @@ var TextPattern = class TextPattern {
|
|
|
1008
1010
|
return hash;
|
|
1009
1011
|
}
|
|
1010
1012
|
};
|
|
1011
|
-
|
|
1012
1013
|
//#endregion
|
|
1013
1014
|
//#region src/pattern/leaf/byte-string-pattern.ts
|
|
1014
1015
|
let createLeafByteStringPattern;
|
|
@@ -1119,7 +1120,6 @@ var ByteStringPattern = class ByteStringPattern {
|
|
|
1119
1120
|
return hash;
|
|
1120
1121
|
}
|
|
1121
1122
|
};
|
|
1122
|
-
|
|
1123
1123
|
//#endregion
|
|
1124
1124
|
//#region src/pattern/leaf/date-pattern.ts
|
|
1125
1125
|
let createLeafDatePattern;
|
|
@@ -1234,28 +1234,18 @@ var DatePattern = class DatePattern {
|
|
|
1234
1234
|
return hash;
|
|
1235
1235
|
}
|
|
1236
1236
|
};
|
|
1237
|
-
|
|
1238
1237
|
//#endregion
|
|
1239
1238
|
//#region src/pattern/leaf/array-pattern.ts
|
|
1240
|
-
/**
|
|
1241
|
-
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
1242
|
-
* Copyright © 2025-2026 Parity Technologies
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
1245
|
-
* @bcts/envelope-pattern - Array pattern matching
|
|
1246
|
-
*
|
|
1247
|
-
* This is a 1:1 TypeScript port of bc-envelope-pattern-rust array_pattern.rs
|
|
1248
|
-
*
|
|
1249
|
-
* @module envelope-pattern/pattern/leaf/array-pattern
|
|
1250
|
-
*/
|
|
1251
1239
|
let createLeafArrayPattern;
|
|
1252
1240
|
function registerArrayPatternFactory(factory) {
|
|
1253
1241
|
createLeafArrayPattern = factory;
|
|
1254
1242
|
}
|
|
1255
1243
|
/**
|
|
1256
|
-
* Pattern for matching
|
|
1244
|
+
* Pattern for matching arrays.
|
|
1257
1245
|
*
|
|
1258
|
-
*
|
|
1246
|
+
* Mirrors Rust `ArrayPattern(dcbor_pattern::ArrayPattern)` from
|
|
1247
|
+
* `bc-envelope-pattern-rust/src/pattern/leaf/array_pattern.rs`. All
|
|
1248
|
+
* matching, display, and equality is delegated to dcbor-pattern.
|
|
1259
1249
|
*/
|
|
1260
1250
|
var ArrayPattern = class ArrayPattern {
|
|
1261
1251
|
_pattern;
|
|
@@ -1266,93 +1256,54 @@ var ArrayPattern = class ArrayPattern {
|
|
|
1266
1256
|
* Creates a new ArrayPattern that matches any array.
|
|
1267
1257
|
*/
|
|
1268
1258
|
static any() {
|
|
1269
|
-
return new ArrayPattern(
|
|
1259
|
+
return new ArrayPattern(arrayPatternAny());
|
|
1270
1260
|
}
|
|
1271
1261
|
/**
|
|
1272
1262
|
* Creates a new ArrayPattern that matches arrays with a specific length.
|
|
1273
1263
|
*/
|
|
1274
1264
|
static count(count) {
|
|
1275
|
-
return new ArrayPattern(
|
|
1276
|
-
type: "Interval",
|
|
1277
|
-
interval: Interval$1.exactly(count)
|
|
1278
|
-
});
|
|
1265
|
+
return new ArrayPattern(arrayPatternWithLength(count));
|
|
1279
1266
|
}
|
|
1280
1267
|
/**
|
|
1281
1268
|
* Creates a new ArrayPattern that matches arrays within a length range.
|
|
1282
1269
|
*/
|
|
1283
1270
|
static interval(min, max) {
|
|
1284
|
-
return new ArrayPattern(
|
|
1285
|
-
type: "Interval",
|
|
1286
|
-
interval: max !== void 0 ? Interval$1.from(min, max) : Interval$1.atLeast(min)
|
|
1287
|
-
});
|
|
1271
|
+
return new ArrayPattern(arrayPatternWithLengthRange(min, max));
|
|
1288
1272
|
}
|
|
1289
1273
|
/**
|
|
1290
|
-
* Creates a new ArrayPattern from a
|
|
1274
|
+
* Creates a new ArrayPattern from a length Interval.
|
|
1291
1275
|
*/
|
|
1292
|
-
static
|
|
1293
|
-
return new ArrayPattern(
|
|
1294
|
-
type: "DCBORPattern",
|
|
1295
|
-
pattern: dcborPattern
|
|
1296
|
-
});
|
|
1276
|
+
static fromInterval(interval) {
|
|
1277
|
+
return new ArrayPattern(arrayPatternWithLengthInterval(interval));
|
|
1297
1278
|
}
|
|
1298
1279
|
/**
|
|
1299
|
-
* Creates a new ArrayPattern
|
|
1280
|
+
* Creates a new ArrayPattern from a top-level dcbor-pattern.
|
|
1281
|
+
*
|
|
1282
|
+
* Mirrors Rust `ArrayPattern::from_dcbor_pattern`, which constructs an
|
|
1283
|
+
* `ArrayPattern::Elements`-style dcbor array pattern.
|
|
1300
1284
|
*/
|
|
1301
|
-
static
|
|
1302
|
-
return new ArrayPattern(
|
|
1303
|
-
type: "WithPatterns",
|
|
1304
|
-
patterns
|
|
1305
|
-
});
|
|
1285
|
+
static fromDcborPattern(pattern) {
|
|
1286
|
+
return new ArrayPattern(arrayPatternWithElements(pattern));
|
|
1306
1287
|
}
|
|
1307
1288
|
/**
|
|
1308
|
-
*
|
|
1289
|
+
* Creates a new ArrayPattern from an existing dcbor-pattern ArrayPattern.
|
|
1290
|
+
*
|
|
1291
|
+
* Mirrors Rust `ArrayPattern::from_dcbor_array_pattern`.
|
|
1309
1292
|
*/
|
|
1310
|
-
|
|
1293
|
+
static fromDcborArrayPattern(arrayPattern) {
|
|
1294
|
+
return new ArrayPattern(arrayPattern);
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Returns the underlying dcbor-pattern ArrayPattern.
|
|
1298
|
+
*/
|
|
1299
|
+
inner() {
|
|
1311
1300
|
return this._pattern;
|
|
1312
1301
|
}
|
|
1313
1302
|
pathsWithCaptures(haystack) {
|
|
1314
1303
|
const cbor = haystack.subject().asLeaf();
|
|
1315
1304
|
if (cbor === void 0) return [[], /* @__PURE__ */ new Map()];
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
switch (this._pattern.type) {
|
|
1319
|
-
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1320
|
-
case "Interval": {
|
|
1321
|
-
const length = array.length;
|
|
1322
|
-
if (this._pattern.interval.contains(length)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1323
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1324
|
-
}
|
|
1325
|
-
case "DCBORPattern": {
|
|
1326
|
-
const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, cbor);
|
|
1327
|
-
if (dcborPaths.length > 0) {
|
|
1328
|
-
const envelopePaths = dcborPaths.map((dcborPath) => {
|
|
1329
|
-
const envPath = [haystack];
|
|
1330
|
-
for (let i = 1; i < dcborPath.length; i++) {
|
|
1331
|
-
const elem = dcborPath[i];
|
|
1332
|
-
if (elem !== void 0) envPath.push(Envelope.newLeaf(elem));
|
|
1333
|
-
}
|
|
1334
|
-
return envPath;
|
|
1335
|
-
});
|
|
1336
|
-
const envelopeCaptures = /* @__PURE__ */ new Map();
|
|
1337
|
-
for (const [name, capturePaths] of dcborCaptures) {
|
|
1338
|
-
const envCapturePaths = capturePaths.map((dcborPath) => {
|
|
1339
|
-
const envPath = [haystack];
|
|
1340
|
-
for (let i = 1; i < dcborPath.length; i++) {
|
|
1341
|
-
const elem = dcborPath[i];
|
|
1342
|
-
if (elem !== void 0) envPath.push(Envelope.newLeaf(elem));
|
|
1343
|
-
}
|
|
1344
|
-
return envPath;
|
|
1345
|
-
});
|
|
1346
|
-
envelopeCaptures.set(name, envCapturePaths);
|
|
1347
|
-
}
|
|
1348
|
-
return [envelopePaths, envelopeCaptures];
|
|
1349
|
-
}
|
|
1350
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1351
|
-
}
|
|
1352
|
-
case "WithPatterns":
|
|
1353
|
-
if (array.length === this._pattern.patterns.length) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1354
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1355
|
-
}
|
|
1305
|
+
if (arrayPatternMatches(this._pattern, cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1306
|
+
return [[], /* @__PURE__ */ new Map()];
|
|
1356
1307
|
}
|
|
1357
1308
|
paths(haystack) {
|
|
1358
1309
|
return this.pathsWithCaptures(haystack)[0];
|
|
@@ -1368,55 +1319,31 @@ var ArrayPattern = class ArrayPattern {
|
|
|
1368
1319
|
return false;
|
|
1369
1320
|
}
|
|
1370
1321
|
toString() {
|
|
1371
|
-
|
|
1372
|
-
case "Any": return "[*]";
|
|
1373
|
-
case "Interval": return `[{${this._pattern.interval.toString()}}]`;
|
|
1374
|
-
case "DCBORPattern": return patternDisplay(this._pattern.pattern);
|
|
1375
|
-
case "WithPatterns": return `[${this._pattern.patterns.map(String).join(", ")}]`;
|
|
1376
|
-
}
|
|
1322
|
+
return arrayPatternDisplay(this._pattern, patternDisplay);
|
|
1377
1323
|
}
|
|
1378
1324
|
/**
|
|
1379
|
-
* Equality comparison.
|
|
1325
|
+
* Equality comparison. Delegates to dcbor-pattern's structural equality
|
|
1326
|
+
* with a display-string fallback for pattern-equality (mirrors Rust's
|
|
1327
|
+
* `Hash` impl that hashes the display, since dcbor `ArrayPattern`
|
|
1328
|
+
* itself does not derive `Hash`).
|
|
1380
1329
|
*/
|
|
1381
1330
|
equals(other) {
|
|
1382
|
-
|
|
1383
|
-
switch (this._pattern.type) {
|
|
1384
|
-
case "Any": return true;
|
|
1385
|
-
case "Interval": return this._pattern.interval.equals(other._pattern.interval);
|
|
1386
|
-
case "DCBORPattern": return patternDisplay(this._pattern.pattern) === patternDisplay(other._pattern.pattern);
|
|
1387
|
-
case "WithPatterns": {
|
|
1388
|
-
const otherPatterns = other._pattern.patterns;
|
|
1389
|
-
if (this._pattern.patterns.length !== otherPatterns.length) return false;
|
|
1390
|
-
for (let i = 0; i < this._pattern.patterns.length; i++) if (this._pattern.patterns[i] !== otherPatterns[i]) return false;
|
|
1391
|
-
return true;
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1331
|
+
return arrayPatternEquals(this._pattern, other._pattern, (a, b) => patternDisplay(a) === patternDisplay(b));
|
|
1394
1332
|
}
|
|
1395
1333
|
/**
|
|
1396
|
-
* Hash code for use in Maps/Sets.
|
|
1334
|
+
* Hash code for use in Maps/Sets. Mirrors Rust's
|
|
1335
|
+
* "hash the string representation" approach.
|
|
1397
1336
|
*/
|
|
1398
1337
|
hashCode() {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1338
|
+
let hash = 0;
|
|
1339
|
+
const str = this.toString();
|
|
1340
|
+
for (let i = 0; i < str.length; i++) {
|
|
1341
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
1342
|
+
hash = hash & hash;
|
|
1404
1343
|
}
|
|
1344
|
+
return hash;
|
|
1405
1345
|
}
|
|
1406
1346
|
};
|
|
1407
|
-
/**
|
|
1408
|
-
* Simple string hash function for hashCode implementations.
|
|
1409
|
-
*/
|
|
1410
|
-
function simpleStringHash$3(str) {
|
|
1411
|
-
let hash = 0;
|
|
1412
|
-
for (let i = 0; i < str.length; i++) {
|
|
1413
|
-
const char = str.charCodeAt(i);
|
|
1414
|
-
hash = (hash << 5) - hash + char;
|
|
1415
|
-
hash = hash & hash;
|
|
1416
|
-
}
|
|
1417
|
-
return hash;
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
1347
|
//#endregion
|
|
1421
1348
|
//#region src/pattern/leaf/map-pattern.ts
|
|
1422
1349
|
let createLeafMapPattern;
|
|
@@ -1449,6 +1376,19 @@ var MapPattern = class MapPattern {
|
|
|
1449
1376
|
});
|
|
1450
1377
|
}
|
|
1451
1378
|
/**
|
|
1379
|
+
* Creates a new MapPattern from a length Interval.
|
|
1380
|
+
*
|
|
1381
|
+
* Mirrors Rust `MapPattern::from_interval`. Used by the
|
|
1382
|
+
* dcbor-pattern → envelope-pattern bridge to preserve `{{n,m}}`
|
|
1383
|
+
* length info.
|
|
1384
|
+
*/
|
|
1385
|
+
static fromInterval(interval) {
|
|
1386
|
+
return new MapPattern({
|
|
1387
|
+
type: "Interval",
|
|
1388
|
+
interval
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1452
1392
|
* Gets the pattern type.
|
|
1453
1393
|
*/
|
|
1454
1394
|
get pattern() {
|
|
@@ -1483,8 +1423,8 @@ var MapPattern = class MapPattern {
|
|
|
1483
1423
|
}
|
|
1484
1424
|
toString() {
|
|
1485
1425
|
switch (this._pattern.type) {
|
|
1486
|
-
case "Any": return "
|
|
1487
|
-
case "Interval": return `{
|
|
1426
|
+
case "Any": return "map";
|
|
1427
|
+
case "Interval": return `{${this._pattern.interval.toString()}}`;
|
|
1488
1428
|
}
|
|
1489
1429
|
}
|
|
1490
1430
|
/**
|
|
@@ -1507,7 +1447,6 @@ var MapPattern = class MapPattern {
|
|
|
1507
1447
|
}
|
|
1508
1448
|
}
|
|
1509
1449
|
};
|
|
1510
|
-
|
|
1511
1450
|
//#endregion
|
|
1512
1451
|
//#region src/pattern/leaf/known-value-pattern.ts
|
|
1513
1452
|
let createLeafKnownValuePattern;
|
|
@@ -1628,7 +1567,6 @@ function simpleStringHash$2(str) {
|
|
|
1628
1567
|
}
|
|
1629
1568
|
return hash;
|
|
1630
1569
|
}
|
|
1631
|
-
|
|
1632
1570
|
//#endregion
|
|
1633
1571
|
//#region src/pattern/leaf/tagged-pattern.ts
|
|
1634
1572
|
/**
|
|
@@ -1739,7 +1677,7 @@ var TaggedPattern = class TaggedPattern {
|
|
|
1739
1677
|
return false;
|
|
1740
1678
|
}
|
|
1741
1679
|
toString() {
|
|
1742
|
-
return taggedPatternDisplay(this._inner, patternDisplay);
|
|
1680
|
+
return taggedPatternDisplay(this._inner, patternDisplay).replace(", ", ", ");
|
|
1743
1681
|
}
|
|
1744
1682
|
/**
|
|
1745
1683
|
* Equality comparison.
|
|
@@ -1786,7 +1724,6 @@ function simpleStringHash$1(str) {
|
|
|
1786
1724
|
}
|
|
1787
1725
|
return hash;
|
|
1788
1726
|
}
|
|
1789
|
-
|
|
1790
1727
|
//#endregion
|
|
1791
1728
|
//#region src/pattern/leaf/cbor-pattern.ts
|
|
1792
1729
|
/**
|
|
@@ -1866,10 +1803,18 @@ var CBORPattern = class CBORPattern {
|
|
|
1866
1803
|
}
|
|
1867
1804
|
/**
|
|
1868
1805
|
* Convert a single dcbor path to an envelope path.
|
|
1806
|
+
*
|
|
1807
|
+
* Uses canonical CBOR-byte equality (`cborEquals`) for the "skip the
|
|
1808
|
+
* dcbor root if it duplicates our base envelope" check, mirroring
|
|
1809
|
+
* Rust's `dcbor_path.first().map(|first| first == &base_cbor)`. The
|
|
1810
|
+
* earlier port compared diagnostic strings, which collapses values
|
|
1811
|
+
* that share a textual representation but differ structurally
|
|
1812
|
+
* (e.g. NaN payloads).
|
|
1869
1813
|
*/
|
|
1870
1814
|
_convertDcborPathToEnvelopePath(dcborPath, baseEnvelope, baseCbor) {
|
|
1871
1815
|
const envelopePath = [baseEnvelope];
|
|
1872
|
-
const
|
|
1816
|
+
const first = dcborPath[0];
|
|
1817
|
+
const elementsToAdd = first !== void 0 && cborEquals(first, baseCbor) ? dcborPath.slice(1) : dcborPath;
|
|
1873
1818
|
for (const cborElement of elementsToAdd) envelopePath.push(Envelope.newLeaf(cborElement));
|
|
1874
1819
|
return envelopePath;
|
|
1875
1820
|
}
|
|
@@ -1896,7 +1841,7 @@ var CBORPattern = class CBORPattern {
|
|
|
1896
1841
|
switch (this._pattern.type) {
|
|
1897
1842
|
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1898
1843
|
case "Value":
|
|
1899
|
-
if (knownValueCbor
|
|
1844
|
+
if (cborEquals(knownValueCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1900
1845
|
return [[], /* @__PURE__ */ new Map()];
|
|
1901
1846
|
case "Pattern": {
|
|
1902
1847
|
const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, knownValueCbor);
|
|
@@ -1920,7 +1865,7 @@ var CBORPattern = class CBORPattern {
|
|
|
1920
1865
|
switch (this._pattern.type) {
|
|
1921
1866
|
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1922
1867
|
case "Value":
|
|
1923
|
-
if (leafCbor
|
|
1868
|
+
if (cborEquals(leafCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1924
1869
|
return [[], /* @__PURE__ */ new Map()];
|
|
1925
1870
|
case "Pattern": {
|
|
1926
1871
|
const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, leafCbor);
|
|
@@ -1928,7 +1873,8 @@ var CBORPattern = class CBORPattern {
|
|
|
1928
1873
|
const basePath = [haystack];
|
|
1929
1874
|
return [dcborPaths.map((dcborPath) => {
|
|
1930
1875
|
const extendedPath = [...basePath];
|
|
1931
|
-
const
|
|
1876
|
+
const first = dcborPath[0];
|
|
1877
|
+
const elementsToAdd = first !== void 0 && cborEquals(first, leafCbor) ? dcborPath.slice(1) : dcborPath;
|
|
1932
1878
|
for (const cborElement of elementsToAdd) extendedPath.push(Envelope.newLeaf(cborElement));
|
|
1933
1879
|
return extendedPath;
|
|
1934
1880
|
}), this._convertDcborCapturesToEnvelopeCaptures(dcborCaptures, haystack, leafCbor)];
|
|
@@ -1963,13 +1909,16 @@ var CBORPattern = class CBORPattern {
|
|
|
1963
1909
|
}
|
|
1964
1910
|
}
|
|
1965
1911
|
/**
|
|
1966
|
-
* Equality comparison.
|
|
1912
|
+
* Equality comparison. `Value` variants compare by canonical CBOR
|
|
1913
|
+
* byte sequence (mirrors Rust `==` on `CBOR`); `Pattern` variants fall
|
|
1914
|
+
* back to display-string compare since `DCBORPattern` doesn't expose
|
|
1915
|
+
* structural equality outside the crate.
|
|
1967
1916
|
*/
|
|
1968
1917
|
equals(other) {
|
|
1969
1918
|
if (this._pattern.type !== other._pattern.type) return false;
|
|
1970
1919
|
switch (this._pattern.type) {
|
|
1971
1920
|
case "Any": return true;
|
|
1972
|
-
case "Value": return this._pattern.cbor
|
|
1921
|
+
case "Value": return cborEquals(this._pattern.cbor, other._pattern.cbor);
|
|
1973
1922
|
case "Pattern": return patternDisplay(this._pattern.pattern) === patternDisplay(other._pattern.pattern);
|
|
1974
1923
|
}
|
|
1975
1924
|
}
|
|
@@ -1979,7 +1928,12 @@ var CBORPattern = class CBORPattern {
|
|
|
1979
1928
|
hashCode() {
|
|
1980
1929
|
switch (this._pattern.type) {
|
|
1981
1930
|
case "Any": return 0;
|
|
1982
|
-
case "Value":
|
|
1931
|
+
case "Value": {
|
|
1932
|
+
const bytes = cborData(this._pattern.cbor);
|
|
1933
|
+
let hash = 0;
|
|
1934
|
+
for (const byte of bytes) hash = hash * 31 + byte | 0;
|
|
1935
|
+
return hash;
|
|
1936
|
+
}
|
|
1983
1937
|
case "Pattern": return simpleStringHash(patternDisplay(this._pattern.pattern));
|
|
1984
1938
|
}
|
|
1985
1939
|
}
|
|
@@ -1995,7 +1949,6 @@ function simpleStringHash(str) {
|
|
|
1995
1949
|
}
|
|
1996
1950
|
return hash;
|
|
1997
1951
|
}
|
|
1998
|
-
|
|
1999
1952
|
//#endregion
|
|
2000
1953
|
//#region src/pattern/leaf/index.ts
|
|
2001
1954
|
/**
|
|
@@ -2197,7 +2150,6 @@ function leafPatternToString(pattern) {
|
|
|
2197
2150
|
case "KnownValue": return pattern.pattern.toString();
|
|
2198
2151
|
}
|
|
2199
2152
|
}
|
|
2200
|
-
|
|
2201
2153
|
//#endregion
|
|
2202
2154
|
//#region src/pattern/structure/leaf-structure-pattern.ts
|
|
2203
2155
|
let createStructureLeafPattern;
|
|
@@ -2250,12 +2202,12 @@ var LeafStructurePattern = class LeafStructurePattern {
|
|
|
2250
2202
|
return 0;
|
|
2251
2203
|
}
|
|
2252
2204
|
};
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2205
|
+
let dispatchPatternCompile$1;
|
|
2206
|
+
let dispatchPatternToString$3;
|
|
2207
|
+
function registerSubjectPatternFactory(factory) {}
|
|
2208
|
+
function registerSubjectPatternDispatch(dispatch) {
|
|
2209
|
+
dispatchPatternCompile$1 = dispatch.compile;
|
|
2210
|
+
dispatchPatternToString$3 = dispatch.toString;
|
|
2259
2211
|
}
|
|
2260
2212
|
/**
|
|
2261
2213
|
* Pattern for matching subjects in envelopes.
|
|
@@ -2320,9 +2272,10 @@ var SubjectPattern = class SubjectPattern {
|
|
|
2320
2272
|
code.push({ type: "NavigateSubject" });
|
|
2321
2273
|
break;
|
|
2322
2274
|
case "Pattern":
|
|
2275
|
+
if (dispatchPatternCompile$1 === void 0) throw new Error("SubjectPattern.compile requires the top-level Pattern compile dispatch; not registered");
|
|
2323
2276
|
code.push({ type: "NavigateSubject" });
|
|
2324
2277
|
code.push({ type: "ExtendTraversal" });
|
|
2325
|
-
this._pattern.pattern
|
|
2278
|
+
dispatchPatternCompile$1(this._pattern.pattern, code, literals, captures);
|
|
2326
2279
|
code.push({ type: "CombineTraversal" });
|
|
2327
2280
|
break;
|
|
2328
2281
|
}
|
|
@@ -2333,7 +2286,10 @@ var SubjectPattern = class SubjectPattern {
|
|
|
2333
2286
|
toString() {
|
|
2334
2287
|
switch (this._pattern.type) {
|
|
2335
2288
|
case "Any": return "subj";
|
|
2336
|
-
case "Pattern":
|
|
2289
|
+
case "Pattern": {
|
|
2290
|
+
const fmt = dispatchPatternToString$3;
|
|
2291
|
+
return `subj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2292
|
+
}
|
|
2337
2293
|
}
|
|
2338
2294
|
}
|
|
2339
2295
|
/**
|
|
@@ -2351,7 +2307,6 @@ var SubjectPattern = class SubjectPattern {
|
|
|
2351
2307
|
return this._pattern.type === "Any" ? 0 : 1;
|
|
2352
2308
|
}
|
|
2353
2309
|
};
|
|
2354
|
-
|
|
2355
2310
|
//#endregion
|
|
2356
2311
|
//#region src/pattern/structure/predicate-pattern.ts
|
|
2357
2312
|
let createStructurePredicatePattern;
|
|
@@ -2431,7 +2386,7 @@ var PredicatePattern = class PredicatePattern {
|
|
|
2431
2386
|
toString() {
|
|
2432
2387
|
switch (this._pattern.type) {
|
|
2433
2388
|
case "Any": return "pred";
|
|
2434
|
-
case "Pattern": return `pred(${this._pattern.pattern
|
|
2389
|
+
case "Pattern": return `pred(${dispatchPatternToString(this._pattern.pattern)})`;
|
|
2435
2390
|
}
|
|
2436
2391
|
}
|
|
2437
2392
|
/**
|
|
@@ -2449,7 +2404,6 @@ var PredicatePattern = class PredicatePattern {
|
|
|
2449
2404
|
return this._pattern.type === "Any" ? 0 : 1;
|
|
2450
2405
|
}
|
|
2451
2406
|
};
|
|
2452
|
-
|
|
2453
2407
|
//#endregion
|
|
2454
2408
|
//#region src/pattern/structure/object-pattern.ts
|
|
2455
2409
|
let createStructureObjectPattern;
|
|
@@ -2529,7 +2483,7 @@ var ObjectPattern = class ObjectPattern {
|
|
|
2529
2483
|
toString() {
|
|
2530
2484
|
switch (this._pattern.type) {
|
|
2531
2485
|
case "Any": return "obj";
|
|
2532
|
-
case "Pattern": return `obj(${this._pattern.pattern
|
|
2486
|
+
case "Pattern": return `obj(${dispatchPatternToString(this._pattern.pattern)})`;
|
|
2533
2487
|
}
|
|
2534
2488
|
}
|
|
2535
2489
|
/**
|
|
@@ -2547,13 +2501,16 @@ var ObjectPattern = class ObjectPattern {
|
|
|
2547
2501
|
return this._pattern.type === "Any" ? 0 : 1;
|
|
2548
2502
|
}
|
|
2549
2503
|
};
|
|
2550
|
-
|
|
2551
2504
|
//#endregion
|
|
2552
2505
|
//#region src/pattern/structure/assertions-pattern.ts
|
|
2553
2506
|
let createStructureAssertionsPattern;
|
|
2507
|
+
let dispatchPatternToString$2;
|
|
2554
2508
|
function registerAssertionsPatternFactory(factory) {
|
|
2555
2509
|
createStructureAssertionsPattern = factory;
|
|
2556
2510
|
}
|
|
2511
|
+
function registerAssertionsPatternToStringDispatch(fn) {
|
|
2512
|
+
dispatchPatternToString$2 = fn;
|
|
2513
|
+
}
|
|
2557
2514
|
/**
|
|
2558
2515
|
* Pattern for matching assertions in envelopes.
|
|
2559
2516
|
*
|
|
@@ -2591,17 +2548,6 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2591
2548
|
});
|
|
2592
2549
|
}
|
|
2593
2550
|
/**
|
|
2594
|
-
* Creates a new AssertionsPattern that matches assertions with both
|
|
2595
|
-
* predicate and object patterns.
|
|
2596
|
-
*/
|
|
2597
|
-
static withBoth(predicatePattern, objectPattern) {
|
|
2598
|
-
return new AssertionsPattern({
|
|
2599
|
-
type: "WithBoth",
|
|
2600
|
-
predicatePattern,
|
|
2601
|
-
objectPattern
|
|
2602
|
-
});
|
|
2603
|
-
}
|
|
2604
|
-
/**
|
|
2605
2551
|
* Gets the pattern type.
|
|
2606
2552
|
*/
|
|
2607
2553
|
get patternType() {
|
|
@@ -2612,14 +2558,12 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2612
2558
|
*/
|
|
2613
2559
|
predicatePattern() {
|
|
2614
2560
|
if (this._pattern.type === "WithPredicate") return this._pattern.pattern;
|
|
2615
|
-
if (this._pattern.type === "WithBoth") return this._pattern.predicatePattern;
|
|
2616
2561
|
}
|
|
2617
2562
|
/**
|
|
2618
2563
|
* Gets the object pattern if this has one, undefined otherwise.
|
|
2619
2564
|
*/
|
|
2620
2565
|
objectPattern() {
|
|
2621
2566
|
if (this._pattern.type === "WithObject") return this._pattern.pattern;
|
|
2622
|
-
if (this._pattern.type === "WithBoth") return this._pattern.objectPattern;
|
|
2623
2567
|
}
|
|
2624
2568
|
pathsWithCaptures(haystack) {
|
|
2625
2569
|
const paths = [];
|
|
@@ -2641,14 +2585,6 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2641
2585
|
}
|
|
2642
2586
|
break;
|
|
2643
2587
|
}
|
|
2644
|
-
case "WithBoth": {
|
|
2645
|
-
const predicate = assertion.asPredicate?.();
|
|
2646
|
-
const object = assertion.asObject?.();
|
|
2647
|
-
if (predicate !== void 0 && object !== void 0) {
|
|
2648
|
-
if (matchPattern(this._pattern.predicatePattern, predicate) && matchPattern(this._pattern.objectPattern, object)) paths.push([assertion]);
|
|
2649
|
-
}
|
|
2650
|
-
break;
|
|
2651
|
-
}
|
|
2652
2588
|
}
|
|
2653
2589
|
return [paths, /* @__PURE__ */ new Map()];
|
|
2654
2590
|
}
|
|
@@ -2671,11 +2607,11 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2671
2607
|
return false;
|
|
2672
2608
|
}
|
|
2673
2609
|
toString() {
|
|
2610
|
+
const fmt = dispatchPatternToString$2;
|
|
2674
2611
|
switch (this._pattern.type) {
|
|
2675
2612
|
case "Any": return "assert";
|
|
2676
|
-
case "WithPredicate": return `assertpred(${this._pattern.pattern
|
|
2677
|
-
case "WithObject": return `assertobj(${this._pattern.pattern
|
|
2678
|
-
case "WithBoth": return `assert(${this._pattern.predicatePattern.toString()}, ${this._pattern.objectPattern.toString()})`;
|
|
2613
|
+
case "WithPredicate": return `assertpred(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2614
|
+
case "WithObject": return `assertobj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2679
2615
|
}
|
|
2680
2616
|
}
|
|
2681
2617
|
/**
|
|
@@ -2687,10 +2623,6 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2687
2623
|
case "Any": return true;
|
|
2688
2624
|
case "WithPredicate":
|
|
2689
2625
|
case "WithObject": return this._pattern.pattern === other._pattern.pattern;
|
|
2690
|
-
case "WithBoth": {
|
|
2691
|
-
const otherBoth = other._pattern;
|
|
2692
|
-
return this._pattern.predicatePattern === otherBoth.predicatePattern && this._pattern.objectPattern === otherBoth.objectPattern;
|
|
2693
|
-
}
|
|
2694
2626
|
}
|
|
2695
2627
|
}
|
|
2696
2628
|
/**
|
|
@@ -2701,11 +2633,9 @@ var AssertionsPattern = class AssertionsPattern {
|
|
|
2701
2633
|
case "Any": return 0;
|
|
2702
2634
|
case "WithPredicate": return 1;
|
|
2703
2635
|
case "WithObject": return 2;
|
|
2704
|
-
case "WithBoth": return 3;
|
|
2705
2636
|
}
|
|
2706
2637
|
}
|
|
2707
2638
|
};
|
|
2708
|
-
|
|
2709
2639
|
//#endregion
|
|
2710
2640
|
//#region src/pattern/structure/digest-pattern.ts
|
|
2711
2641
|
let createStructureDigestPattern;
|
|
@@ -2731,12 +2661,6 @@ var DigestPattern = class DigestPattern {
|
|
|
2731
2661
|
this._pattern = pattern;
|
|
2732
2662
|
}
|
|
2733
2663
|
/**
|
|
2734
|
-
* Creates a new DigestPattern that matches any digest.
|
|
2735
|
-
*/
|
|
2736
|
-
static any() {
|
|
2737
|
-
return new DigestPattern({ type: "Any" });
|
|
2738
|
-
}
|
|
2739
|
-
/**
|
|
2740
2664
|
* Creates a new DigestPattern that matches the exact digest.
|
|
2741
2665
|
*/
|
|
2742
2666
|
static digest(digest) {
|
|
@@ -2774,9 +2698,6 @@ var DigestPattern = class DigestPattern {
|
|
|
2774
2698
|
const digestData = digest.data();
|
|
2775
2699
|
let isHit = false;
|
|
2776
2700
|
switch (this._pattern.type) {
|
|
2777
|
-
case "Any":
|
|
2778
|
-
isHit = true;
|
|
2779
|
-
break;
|
|
2780
2701
|
case "Digest":
|
|
2781
2702
|
isHit = digest.equals(this._pattern.digest);
|
|
2782
2703
|
break;
|
|
@@ -2814,7 +2735,6 @@ var DigestPattern = class DigestPattern {
|
|
|
2814
2735
|
}
|
|
2815
2736
|
toString() {
|
|
2816
2737
|
switch (this._pattern.type) {
|
|
2817
|
-
case "Any": return "digest";
|
|
2818
2738
|
case "Digest": return `digest(${this._pattern.digest.hex()})`;
|
|
2819
2739
|
case "Prefix": return `digest(${bytesToHex(this._pattern.prefix)})`;
|
|
2820
2740
|
case "BinaryRegex": return `digest(/${this._pattern.regex.source}/)`;
|
|
@@ -2822,17 +2742,26 @@ var DigestPattern = class DigestPattern {
|
|
|
2822
2742
|
}
|
|
2823
2743
|
/**
|
|
2824
2744
|
* Equality comparison.
|
|
2745
|
+
*
|
|
2746
|
+
* `Prefix` comparison is case-insensitive on the *hex representation* to
|
|
2747
|
+
* mirror Rust's `eq_ignore_ascii_case` (which compares the underlying
|
|
2748
|
+
* `Vec<u8>` of hex bytes byte-for-byte modulo ASCII case). For raw byte
|
|
2749
|
+
* prefixes that happen to be ASCII, this is an ordinary byte compare.
|
|
2825
2750
|
*/
|
|
2826
2751
|
equals(other) {
|
|
2827
2752
|
if (this._pattern.type !== other._pattern.type) return false;
|
|
2828
2753
|
switch (this._pattern.type) {
|
|
2829
|
-
case "Any": return true;
|
|
2830
2754
|
case "Digest": return this._pattern.digest.equals(other._pattern.digest);
|
|
2831
2755
|
case "Prefix": {
|
|
2832
2756
|
const thisPrefix = this._pattern.prefix;
|
|
2833
2757
|
const otherPrefix = other._pattern.prefix;
|
|
2834
2758
|
if (thisPrefix.length !== otherPrefix.length) return false;
|
|
2835
|
-
for (let i = 0; i < thisPrefix.length; i++)
|
|
2759
|
+
for (let i = 0; i < thisPrefix.length; i++) {
|
|
2760
|
+
const a = thisPrefix[i];
|
|
2761
|
+
const b = otherPrefix[i];
|
|
2762
|
+
if (a === b) continue;
|
|
2763
|
+
if ((a >= 65 && a <= 90 ? a + 32 : a) !== (b >= 65 && b <= 90 ? b + 32 : b)) return false;
|
|
2764
|
+
}
|
|
2836
2765
|
return true;
|
|
2837
2766
|
}
|
|
2838
2767
|
case "BinaryRegex": return this._pattern.regex.source === other._pattern.regex.source;
|
|
@@ -2843,7 +2772,6 @@ var DigestPattern = class DigestPattern {
|
|
|
2843
2772
|
*/
|
|
2844
2773
|
hashCode() {
|
|
2845
2774
|
switch (this._pattern.type) {
|
|
2846
|
-
case "Any": return 0;
|
|
2847
2775
|
case "Digest": {
|
|
2848
2776
|
const data = this._pattern.digest.data().slice(0, 8);
|
|
2849
2777
|
let hash = 0;
|
|
@@ -2852,7 +2780,10 @@ var DigestPattern = class DigestPattern {
|
|
|
2852
2780
|
}
|
|
2853
2781
|
case "Prefix": {
|
|
2854
2782
|
let hash = 0;
|
|
2855
|
-
for (const byte of this._pattern.prefix)
|
|
2783
|
+
for (const byte of this._pattern.prefix) {
|
|
2784
|
+
const folded = byte >= 65 && byte <= 90 ? byte + 32 : byte;
|
|
2785
|
+
hash = hash * 31 + folded | 0;
|
|
2786
|
+
}
|
|
2856
2787
|
return hash;
|
|
2857
2788
|
}
|
|
2858
2789
|
case "BinaryRegex": {
|
|
@@ -2863,7 +2794,6 @@ var DigestPattern = class DigestPattern {
|
|
|
2863
2794
|
}
|
|
2864
2795
|
}
|
|
2865
2796
|
};
|
|
2866
|
-
|
|
2867
2797
|
//#endregion
|
|
2868
2798
|
//#region src/pattern/structure/node-pattern.ts
|
|
2869
2799
|
let createStructureNodePattern;
|
|
@@ -2905,28 +2835,19 @@ var NodePattern = class NodePattern {
|
|
|
2905
2835
|
});
|
|
2906
2836
|
}
|
|
2907
2837
|
/**
|
|
2908
|
-
* Creates a new NodePattern with a subject pattern constraint.
|
|
2909
|
-
*/
|
|
2910
|
-
static withSubject(subjectPattern) {
|
|
2911
|
-
return new NodePattern({
|
|
2912
|
-
type: "WithSubject",
|
|
2913
|
-
subjectPattern
|
|
2914
|
-
});
|
|
2915
|
-
}
|
|
2916
|
-
/**
|
|
2917
2838
|
* Gets the pattern type.
|
|
2918
2839
|
*/
|
|
2919
2840
|
get patternType() {
|
|
2920
2841
|
return this._pattern;
|
|
2921
2842
|
}
|
|
2922
2843
|
/**
|
|
2923
|
-
*
|
|
2844
|
+
* Returns the subject pattern, if any. Rust's `NodePattern` does not carry
|
|
2845
|
+
* subject patterns, so this always returns `undefined`.
|
|
2924
2846
|
*/
|
|
2925
|
-
subjectPattern() {
|
|
2926
|
-
return this._pattern.type === "WithSubject" ? this._pattern.subjectPattern : void 0;
|
|
2927
|
-
}
|
|
2847
|
+
subjectPattern() {}
|
|
2928
2848
|
/**
|
|
2929
|
-
*
|
|
2849
|
+
* Returns the assertion patterns. Rust's `NodePattern` does not carry
|
|
2850
|
+
* assertion sub-patterns, so this always returns an empty array.
|
|
2930
2851
|
*/
|
|
2931
2852
|
assertionPatterns() {
|
|
2932
2853
|
return [];
|
|
@@ -2941,9 +2862,6 @@ var NodePattern = class NodePattern {
|
|
|
2941
2862
|
case "AssertionsInterval":
|
|
2942
2863
|
isHit = this._pattern.interval.contains(haystack.assertions().length);
|
|
2943
2864
|
break;
|
|
2944
|
-
case "WithSubject":
|
|
2945
|
-
isHit = true;
|
|
2946
|
-
break;
|
|
2947
2865
|
}
|
|
2948
2866
|
return [isHit ? [[haystack]] : [], /* @__PURE__ */ new Map()];
|
|
2949
2867
|
}
|
|
@@ -2964,7 +2882,6 @@ var NodePattern = class NodePattern {
|
|
|
2964
2882
|
switch (this._pattern.type) {
|
|
2965
2883
|
case "Any": return "node";
|
|
2966
2884
|
case "AssertionsInterval": return `node(${this._pattern.interval.toString()})`;
|
|
2967
|
-
case "WithSubject": return `node(${this._pattern.subjectPattern.toString()})`;
|
|
2968
2885
|
}
|
|
2969
2886
|
}
|
|
2970
2887
|
/**
|
|
@@ -2975,7 +2892,6 @@ var NodePattern = class NodePattern {
|
|
|
2975
2892
|
switch (this._pattern.type) {
|
|
2976
2893
|
case "Any": return true;
|
|
2977
2894
|
case "AssertionsInterval": return this._pattern.interval.equals(other._pattern.interval);
|
|
2978
|
-
case "WithSubject": return this._pattern.subjectPattern === other._pattern.subjectPattern;
|
|
2979
2895
|
}
|
|
2980
2896
|
}
|
|
2981
2897
|
/**
|
|
@@ -2985,11 +2901,9 @@ var NodePattern = class NodePattern {
|
|
|
2985
2901
|
switch (this._pattern.type) {
|
|
2986
2902
|
case "Any": return 0;
|
|
2987
2903
|
case "AssertionsInterval": return this._pattern.interval.min() * 31 + (this._pattern.interval.max() ?? 0);
|
|
2988
|
-
case "WithSubject": return 1;
|
|
2989
2904
|
}
|
|
2990
2905
|
}
|
|
2991
2906
|
};
|
|
2992
|
-
|
|
2993
2907
|
//#endregion
|
|
2994
2908
|
//#region src/pattern/structure/obscured-pattern.ts
|
|
2995
2909
|
let createStructureObscuredPattern;
|
|
@@ -3093,16 +3007,19 @@ var ObscuredPattern = class ObscuredPattern {
|
|
|
3093
3007
|
}
|
|
3094
3008
|
}
|
|
3095
3009
|
};
|
|
3096
|
-
|
|
3097
3010
|
//#endregion
|
|
3098
3011
|
//#region src/pattern/structure/wrapped-pattern.ts
|
|
3099
3012
|
let createStructureWrappedPattern;
|
|
3013
|
+
let createAnyPattern;
|
|
3100
3014
|
let dispatchPatternPathsWithCaptures;
|
|
3101
3015
|
let dispatchPatternCompile;
|
|
3102
3016
|
let dispatchPatternToString$1;
|
|
3103
3017
|
function registerWrappedPatternFactory(factory) {
|
|
3104
3018
|
createStructureWrappedPattern = factory;
|
|
3105
3019
|
}
|
|
3020
|
+
function registerWrappedPatternAny(factory) {
|
|
3021
|
+
createAnyPattern = factory;
|
|
3022
|
+
}
|
|
3106
3023
|
function registerWrappedPatternDispatch(dispatch) {
|
|
3107
3024
|
dispatchPatternPathsWithCaptures = dispatch.pathsWithCaptures;
|
|
3108
3025
|
dispatchPatternCompile = dispatch.compile;
|
|
@@ -3136,10 +3053,15 @@ var WrappedPattern = class WrappedPattern {
|
|
|
3136
3053
|
}
|
|
3137
3054
|
/**
|
|
3138
3055
|
* Creates a new WrappedPattern that matches any wrapped envelope and descends into it.
|
|
3139
|
-
*
|
|
3056
|
+
*
|
|
3057
|
+
* Mirrors Rust `WrappedPattern::unwrap()` which delegates to
|
|
3058
|
+
* `Self::unwrap_matching(Pattern::any())`. The `any` factory is wired in
|
|
3059
|
+
* during module-load registration to break the circular import on the
|
|
3060
|
+
* top-level `Pattern` type.
|
|
3140
3061
|
*/
|
|
3141
3062
|
static unwrap() {
|
|
3142
|
-
|
|
3063
|
+
if (createAnyPattern === void 0) throw new Error("WrappedPattern.unwrap() requires Pattern.any factory; not registered");
|
|
3064
|
+
return WrappedPattern.unwrapMatching(createAnyPattern());
|
|
3143
3065
|
}
|
|
3144
3066
|
/**
|
|
3145
3067
|
* Gets the pattern type.
|
|
@@ -3215,9 +3137,9 @@ var WrappedPattern = class WrappedPattern {
|
|
|
3215
3137
|
switch (this._pattern.type) {
|
|
3216
3138
|
case "Any": return "wrapped";
|
|
3217
3139
|
case "Unwrap": {
|
|
3218
|
-
const
|
|
3219
|
-
if (
|
|
3220
|
-
return `unwrap(${
|
|
3140
|
+
const inner = this._pattern.pattern;
|
|
3141
|
+
if (inner.type === "Meta" && inner.pattern.type === "Any") return "unwrap";
|
|
3142
|
+
return `unwrap(${dispatchPatternToString$1 !== void 0 ? dispatchPatternToString$1(inner) : "?"})`;
|
|
3221
3143
|
}
|
|
3222
3144
|
}
|
|
3223
3145
|
}
|
|
@@ -3236,7 +3158,6 @@ var WrappedPattern = class WrappedPattern {
|
|
|
3236
3158
|
return this._pattern.type === "Any" ? 0 : 1;
|
|
3237
3159
|
}
|
|
3238
3160
|
};
|
|
3239
|
-
|
|
3240
3161
|
//#endregion
|
|
3241
3162
|
//#region src/pattern/structure/index.ts
|
|
3242
3163
|
/**
|
|
@@ -3408,7 +3329,6 @@ function structurePatternToString(pattern) {
|
|
|
3408
3329
|
case "Wrapped": return pattern.pattern.toString();
|
|
3409
3330
|
}
|
|
3410
3331
|
}
|
|
3411
|
-
|
|
3412
3332
|
//#endregion
|
|
3413
3333
|
//#region src/pattern/vm.ts
|
|
3414
3334
|
let _patternPathsWithCaptures$1;
|
|
@@ -3443,10 +3363,7 @@ function axisChildren(axis, env) {
|
|
|
3443
3363
|
case "Wrapped":
|
|
3444
3364
|
if (envCase.type === "node") {
|
|
3445
3365
|
const subject = envCase.subject;
|
|
3446
|
-
if (subject.isWrapped())
|
|
3447
|
-
const unwrapped = subject.unwrap();
|
|
3448
|
-
if (unwrapped !== void 0) return [[unwrapped, "Content"]];
|
|
3449
|
-
}
|
|
3366
|
+
if (subject.isWrapped()) return [[subject.tryUnwrap(), "Content"]];
|
|
3450
3367
|
} else if (envCase.type === "wrapped") return [[envCase.envelope, "Content"]];
|
|
3451
3368
|
return [];
|
|
3452
3369
|
}
|
|
@@ -4055,7 +3972,6 @@ function compileMetaPattern(pattern, code, literals, captureNames) {
|
|
|
4055
3972
|
}
|
|
4056
3973
|
}
|
|
4057
3974
|
}
|
|
4058
|
-
|
|
4059
3975
|
//#endregion
|
|
4060
3976
|
//#region src/pattern/meta/any-pattern.ts
|
|
4061
3977
|
let createMetaAnyPattern;
|
|
@@ -4107,13 +4023,7 @@ var AnyPattern = class AnyPattern {
|
|
|
4107
4023
|
return 0;
|
|
4108
4024
|
}
|
|
4109
4025
|
};
|
|
4110
|
-
|
|
4111
|
-
//#endregion
|
|
4112
|
-
//#region src/pattern/meta/and-pattern.ts
|
|
4113
|
-
let createMetaAndPattern;
|
|
4114
|
-
function registerAndPatternFactory(factory) {
|
|
4115
|
-
createMetaAndPattern = factory;
|
|
4116
|
-
}
|
|
4026
|
+
function registerAndPatternFactory(factory) {}
|
|
4117
4027
|
/**
|
|
4118
4028
|
* A pattern that matches if all contained patterns match.
|
|
4119
4029
|
*
|
|
@@ -4169,13 +4079,7 @@ var AndPattern = class AndPattern {
|
|
|
4169
4079
|
return this._patterns.length;
|
|
4170
4080
|
}
|
|
4171
4081
|
};
|
|
4172
|
-
|
|
4173
|
-
//#endregion
|
|
4174
|
-
//#region src/pattern/meta/or-pattern.ts
|
|
4175
|
-
let createMetaOrPattern;
|
|
4176
|
-
function registerOrPatternFactory(factory) {
|
|
4177
|
-
createMetaOrPattern = factory;
|
|
4178
|
-
}
|
|
4082
|
+
function registerOrPatternFactory(factory) {}
|
|
4179
4083
|
/**
|
|
4180
4084
|
* A pattern that matches if any contained pattern matches.
|
|
4181
4085
|
*
|
|
@@ -4269,13 +4173,7 @@ var OrPattern = class OrPattern {
|
|
|
4269
4173
|
return this._patterns.length;
|
|
4270
4174
|
}
|
|
4271
4175
|
};
|
|
4272
|
-
|
|
4273
|
-
//#endregion
|
|
4274
|
-
//#region src/pattern/meta/not-pattern.ts
|
|
4275
|
-
let createMetaNotPattern;
|
|
4276
|
-
function registerNotPatternFactory(factory) {
|
|
4277
|
-
createMetaNotPattern = factory;
|
|
4278
|
-
}
|
|
4176
|
+
function registerNotPatternFactory(factory) {}
|
|
4279
4177
|
/**
|
|
4280
4178
|
* A pattern that negates another pattern; matches when the inner pattern does not match.
|
|
4281
4179
|
*
|
|
@@ -4334,13 +4232,7 @@ var NotPattern = class NotPattern {
|
|
|
4334
4232
|
return 1;
|
|
4335
4233
|
}
|
|
4336
4234
|
};
|
|
4337
|
-
|
|
4338
|
-
//#endregion
|
|
4339
|
-
//#region src/pattern/meta/capture-pattern.ts
|
|
4340
|
-
let createMetaCapturePattern;
|
|
4341
|
-
function registerCapturePatternFactory(factory) {
|
|
4342
|
-
createMetaCapturePattern = factory;
|
|
4343
|
-
}
|
|
4235
|
+
function registerCapturePatternFactory(factory) {}
|
|
4344
4236
|
/**
|
|
4345
4237
|
* A pattern that captures a match with a name.
|
|
4346
4238
|
*
|
|
@@ -4419,13 +4311,7 @@ var CapturePattern = class CapturePattern {
|
|
|
4419
4311
|
return hash;
|
|
4420
4312
|
}
|
|
4421
4313
|
};
|
|
4422
|
-
|
|
4423
|
-
//#endregion
|
|
4424
|
-
//#region src/pattern/meta/search-pattern.ts
|
|
4425
|
-
let createMetaSearchPattern;
|
|
4426
|
-
function registerSearchPatternFactory(factory) {
|
|
4427
|
-
createMetaSearchPattern = factory;
|
|
4428
|
-
}
|
|
4314
|
+
function registerSearchPatternFactory(factory) {}
|
|
4429
4315
|
/**
|
|
4430
4316
|
* A pattern that searches the entire envelope tree for matches.
|
|
4431
4317
|
*
|
|
@@ -4475,30 +4361,20 @@ var SearchPattern = class SearchPattern {
|
|
|
4475
4361
|
return [uniquePaths, /* @__PURE__ */ new Map()];
|
|
4476
4362
|
}
|
|
4477
4363
|
/**
|
|
4478
|
-
* Walk the envelope tree
|
|
4364
|
+
* Walk the envelope tree using the canonical `Envelope.walk` traversal.
|
|
4365
|
+
*
|
|
4366
|
+
* Mirrors Rust `bc_envelope::Envelope::walk(false, vec![], visitor)`
|
|
4367
|
+
* which is what `SearchPattern::paths_with_captures` uses. The earlier
|
|
4368
|
+
* port hand-rolled a recursion that double-recursed assertions and
|
|
4369
|
+
* stepped through wrapped subjects manually, producing a different
|
|
4370
|
+
* path order (and extra duplicates that the digest-set deduplication
|
|
4371
|
+
* would partially mask).
|
|
4479
4372
|
*/
|
|
4480
4373
|
_walkEnvelope(envelope, pathToCurrent, visitor) {
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
for (const assertion of envelope.assertions()) {
|
|
4486
|
-
this._walkEnvelope(assertion, newPath, visitor);
|
|
4487
|
-
const predicate = assertion.asPredicate?.();
|
|
4488
|
-
if (predicate !== void 0) {
|
|
4489
|
-
const assertionPath = [...newPath, assertion];
|
|
4490
|
-
this._walkEnvelope(predicate, assertionPath, visitor);
|
|
4491
|
-
}
|
|
4492
|
-
const object = assertion.asObject?.();
|
|
4493
|
-
if (object !== void 0) {
|
|
4494
|
-
const assertionPath = [...newPath, assertion];
|
|
4495
|
-
this._walkEnvelope(object, assertionPath, visitor);
|
|
4496
|
-
}
|
|
4497
|
-
}
|
|
4498
|
-
if (subject.isWrapped()) {
|
|
4499
|
-
const unwrapped = subject.tryUnwrap?.();
|
|
4500
|
-
if (unwrapped !== void 0) this._walkEnvelope(unwrapped, newPath, visitor);
|
|
4501
|
-
}
|
|
4374
|
+
envelope.walk(false, pathToCurrent, (current, _level, _edge, state) => {
|
|
4375
|
+
visitor(current, state);
|
|
4376
|
+
return [[...state, current], false];
|
|
4377
|
+
});
|
|
4502
4378
|
}
|
|
4503
4379
|
paths(haystack) {
|
|
4504
4380
|
return this.pathsWithCaptures(haystack)[0];
|
|
@@ -4552,13 +4428,7 @@ function collectCaptureNames(pattern, out) {
|
|
|
4552
4428
|
const p = pattern;
|
|
4553
4429
|
if (p.collectCaptureNames !== void 0) p.collectCaptureNames(out);
|
|
4554
4430
|
}
|
|
4555
|
-
|
|
4556
|
-
//#endregion
|
|
4557
|
-
//#region src/pattern/meta/traverse-pattern.ts
|
|
4558
|
-
let createMetaTraversePattern;
|
|
4559
|
-
function registerTraversePatternFactory(factory) {
|
|
4560
|
-
createMetaTraversePattern = factory;
|
|
4561
|
-
}
|
|
4431
|
+
function registerTraversePatternFactory(factory) {}
|
|
4562
4432
|
let _patternPathsWithCaptures;
|
|
4563
4433
|
let _patternCompile;
|
|
4564
4434
|
let _patternIsComplex;
|
|
@@ -4633,7 +4503,7 @@ var TraversePattern = class TraversePattern {
|
|
|
4633
4503
|
return _patternIsComplex(this._first) || this._rest !== void 0;
|
|
4634
4504
|
}
|
|
4635
4505
|
toString() {
|
|
4636
|
-
return this.patterns().map((p) => p
|
|
4506
|
+
return this.patterns().map((p) => dispatchPatternToString(p)).join(" -> ");
|
|
4637
4507
|
}
|
|
4638
4508
|
/**
|
|
4639
4509
|
* Equality comparison.
|
|
@@ -4652,13 +4522,7 @@ var TraversePattern = class TraversePattern {
|
|
|
4652
4522
|
return this.patterns().length;
|
|
4653
4523
|
}
|
|
4654
4524
|
};
|
|
4655
|
-
|
|
4656
|
-
//#endregion
|
|
4657
|
-
//#region src/pattern/meta/group-pattern.ts
|
|
4658
|
-
let createMetaGroupPattern;
|
|
4659
|
-
function registerGroupPatternFactory(factory) {
|
|
4660
|
-
createMetaGroupPattern = factory;
|
|
4661
|
-
}
|
|
4525
|
+
function registerGroupPatternFactory(factory) {}
|
|
4662
4526
|
/**
|
|
4663
4527
|
* A pattern that matches with repetition.
|
|
4664
4528
|
*
|
|
@@ -4734,7 +4598,6 @@ var GroupPattern = class GroupPattern {
|
|
|
4734
4598
|
return this._quantifier.min() * 31 + (this._quantifier.max() ?? 0);
|
|
4735
4599
|
}
|
|
4736
4600
|
};
|
|
4737
|
-
|
|
4738
4601
|
//#endregion
|
|
4739
4602
|
//#region src/pattern/meta/index.ts
|
|
4740
4603
|
/**
|
|
@@ -4924,7 +4787,6 @@ function collectCaptureNamesFromPattern(pattern, out) {
|
|
|
4924
4787
|
const p = pattern;
|
|
4925
4788
|
if (p.collectCaptureNames !== void 0) p.collectCaptureNames(out);
|
|
4926
4789
|
}
|
|
4927
|
-
|
|
4928
4790
|
//#endregion
|
|
4929
4791
|
//#region src/pattern/dcbor-integration.ts
|
|
4930
4792
|
/**
|
|
@@ -4990,17 +4852,44 @@ function convertValuePatternToEnvelopePattern(valuePattern) {
|
|
|
4990
4852
|
*/
|
|
4991
4853
|
function convertStructurePatternToEnvelopePattern(structurePattern) {
|
|
4992
4854
|
switch (structurePattern.type) {
|
|
4993
|
-
case "Array":
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
4855
|
+
case "Array": {
|
|
4856
|
+
const inner = structurePattern.pattern;
|
|
4857
|
+
let arrayPattern;
|
|
4858
|
+
switch (inner.variant) {
|
|
4859
|
+
case "Any":
|
|
4860
|
+
arrayPattern = ArrayPattern.any();
|
|
4861
|
+
break;
|
|
4862
|
+
case "Length":
|
|
4863
|
+
arrayPattern = ArrayPattern.fromInterval(inner.length);
|
|
4864
|
+
break;
|
|
4865
|
+
case "Elements":
|
|
4866
|
+
arrayPattern = ArrayPattern.fromDcborArrayPattern(inner);
|
|
4867
|
+
break;
|
|
4868
|
+
}
|
|
4869
|
+
return ok({
|
|
4870
|
+
type: "Leaf",
|
|
4871
|
+
pattern: leafArray(arrayPattern)
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
case "Map": {
|
|
4875
|
+
const inner = structurePattern.pattern;
|
|
4876
|
+
let mapPattern;
|
|
4877
|
+
switch (inner.variant) {
|
|
4878
|
+
case "Any":
|
|
4879
|
+
mapPattern = MapPattern.any();
|
|
4880
|
+
break;
|
|
4881
|
+
case "Length":
|
|
4882
|
+
mapPattern = MapPattern.fromInterval(inner.length);
|
|
4883
|
+
break;
|
|
4884
|
+
case "Constraints":
|
|
4885
|
+
mapPattern = MapPattern.any();
|
|
4886
|
+
break;
|
|
4887
|
+
}
|
|
4888
|
+
return ok({
|
|
4889
|
+
type: "Leaf",
|
|
4890
|
+
pattern: leafMap(mapPattern)
|
|
4891
|
+
});
|
|
4892
|
+
}
|
|
5004
4893
|
case "Tagged": return ok({
|
|
5005
4894
|
type: "Leaf",
|
|
5006
4895
|
pattern: leafTag(TaggedPattern.fromDcborPattern(structurePattern.pattern))
|
|
@@ -5057,7 +4946,169 @@ function convertMetaPatternToEnvelopePattern(metaPattern, originalPattern) {
|
|
|
5057
4946
|
});
|
|
5058
4947
|
}
|
|
5059
4948
|
}
|
|
5060
|
-
|
|
4949
|
+
//#endregion
|
|
4950
|
+
//#region src/parse/utils.ts
|
|
4951
|
+
let createCborPattern;
|
|
4952
|
+
let createCborPatternFromDcbor;
|
|
4953
|
+
let createAnyArray;
|
|
4954
|
+
let createArrayWithCount;
|
|
4955
|
+
let createArrayWithRange;
|
|
4956
|
+
let createArrayFromDcborPattern;
|
|
4957
|
+
/**
|
|
4958
|
+
* Register pattern factory functions.
|
|
4959
|
+
* This is called by the pattern module to avoid circular dependencies.
|
|
4960
|
+
*/
|
|
4961
|
+
function registerPatternFactories(factories) {
|
|
4962
|
+
createCborPattern = factories.cborPattern;
|
|
4963
|
+
createCborPatternFromDcbor = factories.cborPatternFromDcbor;
|
|
4964
|
+
createAnyArray = factories.anyArray;
|
|
4965
|
+
createArrayWithCount = factories.arrayWithCount;
|
|
4966
|
+
createArrayWithRange = factories.arrayWithRange;
|
|
4967
|
+
createArrayFromDcborPattern = factories.arrayFromDcborPattern;
|
|
4968
|
+
}
|
|
4969
|
+
/**
|
|
4970
|
+
* Skips whitespace in the source string.
|
|
4971
|
+
*
|
|
4972
|
+
* @param src - The source string
|
|
4973
|
+
* @param pos - The current position (modified in place)
|
|
4974
|
+
*/
|
|
4975
|
+
function skipWs$1(src, pos) {
|
|
4976
|
+
while (pos.value < src.length) {
|
|
4977
|
+
const ch = src[pos.value];
|
|
4978
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos.value++;
|
|
4979
|
+
else break;
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
/**
|
|
4983
|
+
* Parses a CBOR value or dcbor-pattern expression.
|
|
4984
|
+
*
|
|
4985
|
+
* @param src - The source string
|
|
4986
|
+
* @returns The parsed pattern and consumed character count, or an error
|
|
4987
|
+
*/
|
|
4988
|
+
function parseCborInner(src) {
|
|
4989
|
+
if (createCborPattern === void 0 || createCborPatternFromDcbor === void 0) return err(unknown());
|
|
4990
|
+
const pos = { value: 0 };
|
|
4991
|
+
skipWs$1(src, pos);
|
|
4992
|
+
if (src[pos.value] === "/") {
|
|
4993
|
+
pos.value++;
|
|
4994
|
+
const start = pos.value;
|
|
4995
|
+
let escape = false;
|
|
4996
|
+
while (pos.value < src.length) {
|
|
4997
|
+
const b = src[pos.value];
|
|
4998
|
+
pos.value++;
|
|
4999
|
+
if (escape) {
|
|
5000
|
+
escape = false;
|
|
5001
|
+
continue;
|
|
5002
|
+
}
|
|
5003
|
+
if (b === "\\") {
|
|
5004
|
+
escape = true;
|
|
5005
|
+
continue;
|
|
5006
|
+
}
|
|
5007
|
+
if (b === "/") {
|
|
5008
|
+
const parseResult = parse$1(src.slice(start, pos.value - 1));
|
|
5009
|
+
if (!parseResult.ok) return err(invalidPattern({
|
|
5010
|
+
start,
|
|
5011
|
+
end: pos.value - 1
|
|
5012
|
+
}));
|
|
5013
|
+
skipWs$1(src, pos);
|
|
5014
|
+
return ok([createCborPatternFromDcbor(parseResult.value), pos.value]);
|
|
5015
|
+
}
|
|
5016
|
+
}
|
|
5017
|
+
return err(unterminatedRegex({
|
|
5018
|
+
start: start - 1,
|
|
5019
|
+
end: pos.value
|
|
5020
|
+
}));
|
|
5021
|
+
}
|
|
5022
|
+
if (src.slice(pos.value, pos.value + 3) === "ur:") {
|
|
5023
|
+
const parseResult = parseDcborItemPartial(src.slice(pos.value));
|
|
5024
|
+
if (!parseResult.ok) return err(unknown());
|
|
5025
|
+
const [cborValue, consumed] = parseResult.value;
|
|
5026
|
+
return ok([createCborPattern(cborValue), pos.value + consumed]);
|
|
5027
|
+
}
|
|
5028
|
+
const parseResult = parseDcborItemPartial(src.slice(pos.value));
|
|
5029
|
+
if (!parseResult.ok) return err(unknown());
|
|
5030
|
+
const [cborValue, consumed] = parseResult.value;
|
|
5031
|
+
return ok([createCborPattern(cborValue), pos.value + consumed]);
|
|
5032
|
+
}
|
|
5033
|
+
/**
|
|
5034
|
+
* Parses an array pattern inner content.
|
|
5035
|
+
*
|
|
5036
|
+
* @param src - The source string (content between [ and ])
|
|
5037
|
+
* @returns The parsed pattern and consumed character count, or an error
|
|
5038
|
+
*/
|
|
5039
|
+
function parseArrayInner(src) {
|
|
5040
|
+
if (createAnyArray === void 0 || createArrayWithCount === void 0 || createArrayWithRange === void 0 || createArrayFromDcborPattern === void 0) return err(unknown());
|
|
5041
|
+
const pos = { value: 0 };
|
|
5042
|
+
skipWs$1(src, pos);
|
|
5043
|
+
if (src[pos.value] === "*") {
|
|
5044
|
+
pos.value++;
|
|
5045
|
+
skipWs$1(src, pos);
|
|
5046
|
+
return ok([createAnyArray(), pos.value]);
|
|
5047
|
+
}
|
|
5048
|
+
if (src[pos.value] === "{") {
|
|
5049
|
+
pos.value++;
|
|
5050
|
+
skipWs$1(src, pos);
|
|
5051
|
+
const startPos = pos.value;
|
|
5052
|
+
while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
|
|
5053
|
+
if (startPos === pos.value) return err(invalidRange({
|
|
5054
|
+
start: pos.value,
|
|
5055
|
+
end: pos.value
|
|
5056
|
+
}));
|
|
5057
|
+
const firstNum = parseInt(src.slice(startPos, pos.value), 10);
|
|
5058
|
+
if (Number.isNaN(firstNum)) return err(invalidNumberFormat({
|
|
5059
|
+
start: startPos,
|
|
5060
|
+
end: pos.value
|
|
5061
|
+
}));
|
|
5062
|
+
skipWs$1(src, pos);
|
|
5063
|
+
if (pos.value >= src.length) return err(unexpectedEndOfInput());
|
|
5064
|
+
const ch = src[pos.value];
|
|
5065
|
+
if (ch === "}") {
|
|
5066
|
+
pos.value++;
|
|
5067
|
+
skipWs$1(src, pos);
|
|
5068
|
+
return ok([createArrayWithCount(firstNum), pos.value]);
|
|
5069
|
+
}
|
|
5070
|
+
if (ch === ",") {
|
|
5071
|
+
pos.value++;
|
|
5072
|
+
skipWs$1(src, pos);
|
|
5073
|
+
if (pos.value >= src.length) return err(unexpectedEndOfInput());
|
|
5074
|
+
const nextCh = src[pos.value];
|
|
5075
|
+
if (nextCh === "}") {
|
|
5076
|
+
pos.value++;
|
|
5077
|
+
skipWs$1(src, pos);
|
|
5078
|
+
return ok([createArrayWithRange(firstNum, void 0), pos.value]);
|
|
5079
|
+
}
|
|
5080
|
+
if (nextCh !== void 0 && /\d/.test(nextCh)) {
|
|
5081
|
+
const secondStart = pos.value;
|
|
5082
|
+
while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
|
|
5083
|
+
const secondNum = parseInt(src.slice(secondStart, pos.value), 10);
|
|
5084
|
+
if (Number.isNaN(secondNum)) return err(invalidNumberFormat({
|
|
5085
|
+
start: secondStart,
|
|
5086
|
+
end: pos.value
|
|
5087
|
+
}));
|
|
5088
|
+
skipWs$1(src, pos);
|
|
5089
|
+
if (pos.value >= src.length || src[pos.value] !== "}") return err(unexpectedEndOfInput());
|
|
5090
|
+
pos.value++;
|
|
5091
|
+
skipWs$1(src, pos);
|
|
5092
|
+
return ok([createArrayWithRange(firstNum, secondNum), pos.value]);
|
|
5093
|
+
}
|
|
5094
|
+
return err(invalidRange({
|
|
5095
|
+
start: pos.value,
|
|
5096
|
+
end: pos.value
|
|
5097
|
+
}));
|
|
5098
|
+
}
|
|
5099
|
+
return err(invalidRange({
|
|
5100
|
+
start: pos.value,
|
|
5101
|
+
end: pos.value
|
|
5102
|
+
}));
|
|
5103
|
+
}
|
|
5104
|
+
const parseResult = parse$1(`[${src.slice(pos.value)}]`);
|
|
5105
|
+
if (!parseResult.ok) return err(invalidPattern({
|
|
5106
|
+
start: pos.value,
|
|
5107
|
+
end: src.length
|
|
5108
|
+
}));
|
|
5109
|
+
const consumed = src.length - pos.value;
|
|
5110
|
+
return ok([createArrayFromDcborPattern(parseResult.value), consumed]);
|
|
5111
|
+
}
|
|
5061
5112
|
//#endregion
|
|
5062
5113
|
//#region src/pattern/index.ts
|
|
5063
5114
|
/**
|
|
@@ -5573,6 +5624,12 @@ function registerAllFactories() {
|
|
|
5573
5624
|
compile: patternCompile,
|
|
5574
5625
|
toString: patternToString
|
|
5575
5626
|
});
|
|
5627
|
+
registerWrappedPatternAny(any);
|
|
5628
|
+
registerAssertionsPatternToStringDispatch(patternToString);
|
|
5629
|
+
registerSubjectPatternDispatch({
|
|
5630
|
+
compile: patternCompile,
|
|
5631
|
+
toString: patternToString
|
|
5632
|
+
});
|
|
5576
5633
|
registerAnyPatternFactory((p) => patternMeta(metaAny(p)));
|
|
5577
5634
|
registerAndPatternFactory((p) => patternMeta(metaAnd(p)));
|
|
5578
5635
|
registerOrPatternFactory((p) => patternMeta(metaOr(p)));
|
|
@@ -5584,6 +5641,14 @@ function registerAllFactories() {
|
|
|
5584
5641
|
}
|
|
5585
5642
|
registerAllFactories();
|
|
5586
5643
|
registerVMPatternFunctions(patternPathsWithCaptures, patternMatches, patternPaths);
|
|
5644
|
+
registerPatternFactories({
|
|
5645
|
+
cborPattern: (value) => cborValue(value),
|
|
5646
|
+
cborPatternFromDcbor: (pattern) => cborPattern(pattern),
|
|
5647
|
+
anyArray,
|
|
5648
|
+
arrayWithCount: (count) => patternLeaf(leafArray(ArrayPattern.count(count))),
|
|
5649
|
+
arrayWithRange: (min, max) => patternLeaf(leafArray(ArrayPattern.interval(min, max))),
|
|
5650
|
+
arrayFromDcborPattern: (pattern) => patternLeaf(leafArray(ArrayPattern.fromDcborPattern(pattern)))
|
|
5651
|
+
});
|
|
5587
5652
|
registerPatternMatchFn(patternMatches);
|
|
5588
5653
|
registerPatternDispatchFns({
|
|
5589
5654
|
pathsWithCaptures: patternPathsWithCaptures,
|
|
@@ -5593,7 +5658,6 @@ registerPatternDispatchFns({
|
|
|
5593
5658
|
toString: patternToString
|
|
5594
5659
|
});
|
|
5595
5660
|
registerTraverseDispatchFunctions(patternPathsWithCaptures, patternCompile, patternIsComplex);
|
|
5596
|
-
|
|
5597
5661
|
//#endregion
|
|
5598
5662
|
//#region src/parse/token.ts
|
|
5599
5663
|
/**
|
|
@@ -6337,307 +6401,199 @@ var Lexer = class {
|
|
|
6337
6401
|
}
|
|
6338
6402
|
}
|
|
6339
6403
|
};
|
|
6340
|
-
|
|
6341
6404
|
//#endregion
|
|
6342
|
-
//#region src/parse/
|
|
6405
|
+
//#region src/parse/leaf/array-parser.ts
|
|
6343
6406
|
/**
|
|
6344
6407
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6345
6408
|
* Copyright © 2025-2026 Parity Technologies
|
|
6346
6409
|
*
|
|
6410
|
+
* Array parser — port of `bc-envelope-pattern-rust`
|
|
6411
|
+
* `parse/leaf/array_parser.rs`.
|
|
6347
6412
|
*
|
|
6348
|
-
*
|
|
6349
|
-
*
|
|
6350
|
-
*
|
|
6351
|
-
*
|
|
6413
|
+
* Mirrors Rust's flow exactly: after the `[` token has been consumed,
|
|
6414
|
+
* delegate to `utils::parseArrayInner` (which handles `*`, `{n}`, `{n,m}`,
|
|
6415
|
+
* `{n,}` directly and otherwise wraps the body in `[...]` and re-parses
|
|
6416
|
+
* via dcbor-pattern), then expect a closing `]`.
|
|
6352
6417
|
*
|
|
6353
|
-
* @module envelope-pattern/parse
|
|
6418
|
+
* @module envelope-pattern/parse/leaf/array-parser
|
|
6354
6419
|
*/
|
|
6420
|
+
function parseArray(lexer) {
|
|
6421
|
+
const inner = parseArrayInner(lexer.remainder());
|
|
6422
|
+
if (!inner.ok) return inner;
|
|
6423
|
+
const [pattern, consumed] = inner.value;
|
|
6424
|
+
lexer.bump(consumed);
|
|
6425
|
+
const close = lexer.next();
|
|
6426
|
+
if (close === void 0) return err(expectedCloseBracket(lexer.span()));
|
|
6427
|
+
if (close.token.type !== "BracketClose") return err(unexpectedToken(close.token, close.span));
|
|
6428
|
+
return ok(pattern);
|
|
6429
|
+
}
|
|
6430
|
+
//#endregion
|
|
6431
|
+
//#region src/parse/leaf/cbor-parser.ts
|
|
6355
6432
|
/**
|
|
6356
|
-
*
|
|
6433
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6434
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6435
|
+
*
|
|
6436
|
+
* CBOR pattern parser — port of `bc-envelope-pattern-rust`
|
|
6437
|
+
* `parse/leaf/cbor_parser.rs`.
|
|
6438
|
+
*
|
|
6439
|
+
* Mirrors Rust's flow: lookahead for `(`. If absent, return `any_cbor()`.
|
|
6440
|
+
* Otherwise consume the `(`, delegate to `parseCborInner` (handles
|
|
6441
|
+
* `/regex/`, `ur:…`, and CBOR diagnostic notation), and expect a closing
|
|
6442
|
+
* `)`.
|
|
6443
|
+
*
|
|
6444
|
+
* @module envelope-pattern/parse/leaf/cbor-parser
|
|
6357
6445
|
*/
|
|
6358
|
-
function
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
if (
|
|
6368
|
-
return
|
|
6369
|
-
}
|
|
6370
|
-
/**
|
|
6371
|
-
* Parse a pattern, allowing extra data after the pattern.
|
|
6372
|
-
*/
|
|
6373
|
-
function parsePartial(input) {
|
|
6374
|
-
const lexer = new Lexer(input);
|
|
6375
|
-
const result = parseOr(lexer);
|
|
6376
|
-
if (!result.ok) return result;
|
|
6377
|
-
return ok([result.value, lexer.position]);
|
|
6378
|
-
}
|
|
6379
|
-
/**
|
|
6380
|
-
* Convert a dcbor-pattern Pattern to an envelope-pattern Pattern.
|
|
6381
|
-
*/
|
|
6382
|
-
function convertDcborPatternToEnvelopePattern$1(_dcborPattern) {
|
|
6383
|
-
return ok(any());
|
|
6446
|
+
function parseCbor(lexer) {
|
|
6447
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyCbor());
|
|
6448
|
+
lexer.next();
|
|
6449
|
+
const innerResult = parseCborInner(lexer.remainder());
|
|
6450
|
+
if (!innerResult.ok) return innerResult;
|
|
6451
|
+
const [pattern, consumed] = innerResult.value;
|
|
6452
|
+
lexer.bump(consumed);
|
|
6453
|
+
const close = lexer.next();
|
|
6454
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6455
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6456
|
+
return ok(pattern);
|
|
6384
6457
|
}
|
|
6458
|
+
//#endregion
|
|
6459
|
+
//#region src/parse/leaf/date-parser.ts
|
|
6385
6460
|
/**
|
|
6386
|
-
*
|
|
6461
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6462
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6463
|
+
*
|
|
6464
|
+
* Date content parser — port of `bc-envelope-pattern-rust`
|
|
6465
|
+
* `parse/leaf/date_parser.rs`.
|
|
6466
|
+
*
|
|
6467
|
+
* Mirrors Rust's `Date::from_string`, which accepts a strict ISO-8601
|
|
6468
|
+
* subset, by deferring to dcbor's `CborDate.fromString`. Falls back to JS
|
|
6469
|
+
* `Date.parse` only as a defensive shim — that branch is unreachable for
|
|
6470
|
+
* conformant inputs.
|
|
6471
|
+
*
|
|
6472
|
+
* @module envelope-pattern/parse/leaf/date-parser
|
|
6387
6473
|
*/
|
|
6388
|
-
function parseOr(lexer) {
|
|
6389
|
-
const patterns = [];
|
|
6390
|
-
const first = parseTraverse(lexer);
|
|
6391
|
-
if (!first.ok) return first;
|
|
6392
|
-
patterns.push(first.value);
|
|
6393
|
-
while (true) {
|
|
6394
|
-
if (lexer.peekToken()?.token.type !== "Or") break;
|
|
6395
|
-
lexer.next();
|
|
6396
|
-
const nextExpr = parseTraverse(lexer);
|
|
6397
|
-
if (!nextExpr.ok) return nextExpr;
|
|
6398
|
-
patterns.push(nextExpr.value);
|
|
6399
|
-
}
|
|
6400
|
-
if (patterns.length === 1) return ok(patterns[0]);
|
|
6401
|
-
return ok(or(patterns));
|
|
6402
|
-
}
|
|
6403
6474
|
/**
|
|
6404
|
-
* Parse a
|
|
6475
|
+
* Parse a date pattern of one of the forms accepted by Rust:
|
|
6476
|
+
*
|
|
6477
|
+
* - `/regex/` (regex match against ISO-8601 string)
|
|
6478
|
+
* - `start...end` (inclusive range)
|
|
6479
|
+
* - `start...` (earliest)
|
|
6480
|
+
* - `...end` (latest)
|
|
6481
|
+
* - `iso-8601` (exact)
|
|
6482
|
+
*
|
|
6483
|
+
* Mirrors `parse_date_content` in Rust; uses `CborDate.fromString` so the
|
|
6484
|
+
* accepted formats match Rust's `bc_envelope::prelude::Date::from_string`
|
|
6485
|
+
* exactly rather than the looser JS `Date.parse`.
|
|
6405
6486
|
*/
|
|
6406
|
-
function
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
const nextExpr = parseAnd(lexer);
|
|
6415
|
-
if (!nextExpr.ok) return nextExpr;
|
|
6416
|
-
patterns.push(nextExpr.value);
|
|
6487
|
+
function parseDateContent(content, span) {
|
|
6488
|
+
if (content.startsWith("/") && content.endsWith("/") && content.length >= 2) {
|
|
6489
|
+
const regexStr = content.slice(1, -1);
|
|
6490
|
+
try {
|
|
6491
|
+
return ok(dateRegex(new RegExp(regexStr)));
|
|
6492
|
+
} catch {
|
|
6493
|
+
return err(invalidRegex(span));
|
|
6494
|
+
}
|
|
6417
6495
|
}
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6496
|
+
const ellipsisIdx = content.indexOf("...");
|
|
6497
|
+
if (ellipsisIdx !== -1) {
|
|
6498
|
+
const left = content.slice(0, ellipsisIdx);
|
|
6499
|
+
const right = content.slice(ellipsisIdx + 3);
|
|
6500
|
+
if (left.length === 0 && right.length > 0) {
|
|
6501
|
+
const parsed = parseIsoDateStrict(right);
|
|
6502
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6503
|
+
return ok(dateLatest(parsed));
|
|
6504
|
+
}
|
|
6505
|
+
if (left.length > 0 && right.length === 0) {
|
|
6506
|
+
const parsed = parseIsoDateStrict(left);
|
|
6507
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6508
|
+
return ok(dateEarliest(parsed));
|
|
6509
|
+
}
|
|
6510
|
+
if (left.length > 0 && right.length > 0) {
|
|
6511
|
+
const start = parseIsoDateStrict(left);
|
|
6512
|
+
const end = parseIsoDateStrict(right);
|
|
6513
|
+
if (start === void 0 || end === void 0) return err(invalidDateFormat(span));
|
|
6514
|
+
return ok(dateRange(start, end));
|
|
6515
|
+
}
|
|
6516
|
+
return err(invalidDateFormat(span));
|
|
6435
6517
|
}
|
|
6436
|
-
|
|
6437
|
-
return
|
|
6518
|
+
const parsed = parseIsoDateStrict(content);
|
|
6519
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6520
|
+
return ok(date(parsed));
|
|
6438
6521
|
}
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
lexer.next();
|
|
6445
|
-
const inner = parseGroup(lexer);
|
|
6446
|
-
if (!inner.ok) return inner;
|
|
6447
|
-
return ok(notMatching(inner.value));
|
|
6522
|
+
function parseIsoDateStrict(value) {
|
|
6523
|
+
try {
|
|
6524
|
+
return CborDate.fromString(value);
|
|
6525
|
+
} catch {
|
|
6526
|
+
return;
|
|
6448
6527
|
}
|
|
6449
|
-
return parseGroup(lexer);
|
|
6450
6528
|
}
|
|
6529
|
+
//#endregion
|
|
6530
|
+
//#region src/parse/leaf/known-value-parser.ts
|
|
6451
6531
|
/**
|
|
6452
|
-
*
|
|
6532
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6533
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6534
|
+
*
|
|
6535
|
+
* Helpers for parsing the body of a `'…'` (single-quoted) known-value
|
|
6536
|
+
* literal. Mirrors the inline body of Rust's `Token::SingleQuotedPattern`
|
|
6537
|
+
* branch in `parse_primary`:
|
|
6538
|
+
*
|
|
6539
|
+
* - If the contents are a valid `u64`, build `Pattern::known_value(...)`.
|
|
6540
|
+
* - Otherwise, build `Pattern::known_value_named(...)`.
|
|
6541
|
+
*
|
|
6542
|
+
* The earlier port duck-typed a fake `KnownValue`; this version uses the
|
|
6543
|
+
* real `KnownValue` constructor so all subsequent KnownValue methods work
|
|
6544
|
+
* (e.g., `taggedCbor()`, `name()`, etc.).
|
|
6545
|
+
*
|
|
6546
|
+
* @module envelope-pattern/parse/leaf/known-value-parser
|
|
6453
6547
|
*/
|
|
6454
|
-
function parseGroup(lexer) {
|
|
6455
|
-
const primary = parsePrimary(lexer);
|
|
6456
|
-
if (!primary.ok) return primary;
|
|
6457
|
-
const next = lexer.peekToken();
|
|
6458
|
-
if (next === void 0) return primary;
|
|
6459
|
-
const tokenType = next.token.type;
|
|
6460
|
-
let quantifier;
|
|
6461
|
-
if (tokenType === "RepeatZeroOrMore") {
|
|
6462
|
-
lexer.next();
|
|
6463
|
-
quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Greedy);
|
|
6464
|
-
} else if (tokenType === "RepeatZeroOrMoreLazy") {
|
|
6465
|
-
lexer.next();
|
|
6466
|
-
quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Lazy);
|
|
6467
|
-
} else if (tokenType === "RepeatZeroOrMorePossessive") {
|
|
6468
|
-
lexer.next();
|
|
6469
|
-
quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Possessive);
|
|
6470
|
-
} else if (tokenType === "RepeatOneOrMore") {
|
|
6471
|
-
lexer.next();
|
|
6472
|
-
quantifier = Quantifier$1.oneOrMore(Reluctance$1.Greedy);
|
|
6473
|
-
} else if (tokenType === "RepeatOneOrMoreLazy") {
|
|
6474
|
-
lexer.next();
|
|
6475
|
-
quantifier = Quantifier$1.oneOrMore(Reluctance$1.Lazy);
|
|
6476
|
-
} else if (tokenType === "RepeatOneOrMorePossessive") {
|
|
6477
|
-
lexer.next();
|
|
6478
|
-
quantifier = Quantifier$1.oneOrMore(Reluctance$1.Possessive);
|
|
6479
|
-
} else if (tokenType === "RepeatZeroOrOne") {
|
|
6480
|
-
lexer.next();
|
|
6481
|
-
quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Greedy);
|
|
6482
|
-
} else if (tokenType === "RepeatZeroOrOneLazy") {
|
|
6483
|
-
lexer.next();
|
|
6484
|
-
quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Lazy);
|
|
6485
|
-
} else if (tokenType === "RepeatZeroOrOnePossessive") {
|
|
6486
|
-
lexer.next();
|
|
6487
|
-
quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Possessive);
|
|
6488
|
-
} else if (tokenType === "Range") {
|
|
6489
|
-
lexer.next();
|
|
6490
|
-
if (!next.token.value.ok) return err(next.token.value.error);
|
|
6491
|
-
quantifier = next.token.value.value;
|
|
6492
|
-
} else return primary;
|
|
6493
|
-
return ok(repeat(primary.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
|
|
6494
|
-
}
|
|
6495
6548
|
/**
|
|
6496
|
-
*
|
|
6549
|
+
* Maximum value of a Rust `u64`. Used to reject literals that would
|
|
6550
|
+
* silently wrap or lose precision when constructing a `KnownValue`.
|
|
6497
6551
|
*/
|
|
6498
|
-
|
|
6499
|
-
const tokenResult = lexer.next();
|
|
6500
|
-
if (tokenResult === void 0) return err(unexpectedEndOfInput());
|
|
6501
|
-
const { token, span } = tokenResult;
|
|
6502
|
-
switch (token.type) {
|
|
6503
|
-
case "Search": return parseSearch(lexer);
|
|
6504
|
-
case "Node": return parseNode(lexer);
|
|
6505
|
-
case "Assertion": return parseAssertion(lexer);
|
|
6506
|
-
case "AssertionPred": return parseAssertionPred(lexer);
|
|
6507
|
-
case "AssertionObj": return parseAssertionObj(lexer);
|
|
6508
|
-
case "Digest": return parseDigest(lexer);
|
|
6509
|
-
case "Obj": return parseObject(lexer);
|
|
6510
|
-
case "Obscured": return ok(obscured());
|
|
6511
|
-
case "Elided": return ok(elided());
|
|
6512
|
-
case "Encrypted": return ok(encrypted());
|
|
6513
|
-
case "Compressed": return ok(compressed());
|
|
6514
|
-
case "Pred": return parsePredicate(lexer);
|
|
6515
|
-
case "Subject": return parseSubject(lexer);
|
|
6516
|
-
case "Wrapped": return ok(wrapped());
|
|
6517
|
-
case "Unwrap": return parseUnwrap(lexer);
|
|
6518
|
-
case "Leaf": return ok(leaf());
|
|
6519
|
-
case "GroupName": return parseCapture(lexer, token.name);
|
|
6520
|
-
case "ParenOpen": return parseParenGroup(lexer);
|
|
6521
|
-
case "Cbor": return parseCbor(lexer);
|
|
6522
|
-
case "RepeatZeroOrMore": return ok(any());
|
|
6523
|
-
case "BoolKeyword": return ok(anyBool());
|
|
6524
|
-
case "BoolTrue": return ok(bool(true));
|
|
6525
|
-
case "BoolFalse": return ok(bool(false));
|
|
6526
|
-
case "NumberKeyword": return ok(anyNumber());
|
|
6527
|
-
case "TextKeyword": return ok(anyText());
|
|
6528
|
-
case "StringLiteral":
|
|
6529
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6530
|
-
return ok(text(token.value.value));
|
|
6531
|
-
case "UnsignedInteger":
|
|
6532
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6533
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6534
|
-
case "Integer":
|
|
6535
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6536
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6537
|
-
case "Float":
|
|
6538
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6539
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6540
|
-
case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
|
|
6541
|
-
case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
|
|
6542
|
-
case "GreaterThan": return parseComparisonNumber(lexer, ">");
|
|
6543
|
-
case "LessThan": return parseComparisonNumber(lexer, "<");
|
|
6544
|
-
case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
|
|
6545
|
-
case "Infinity": return ok(number(Infinity));
|
|
6546
|
-
case "NegativeInfinity": return ok(number(-Infinity));
|
|
6547
|
-
case "Regex":
|
|
6548
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6549
|
-
try {
|
|
6550
|
-
return ok(textRegex(new RegExp(token.value.value)));
|
|
6551
|
-
} catch {
|
|
6552
|
-
return err(invalidRegex(span));
|
|
6553
|
-
}
|
|
6554
|
-
case "BracketOpen": return parseArray(lexer);
|
|
6555
|
-
case "ByteString": return ok(anyByteString());
|
|
6556
|
-
case "HexPattern":
|
|
6557
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6558
|
-
return ok(byteString(token.value.value));
|
|
6559
|
-
case "HexBinaryRegex":
|
|
6560
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6561
|
-
try {
|
|
6562
|
-
return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
|
|
6563
|
-
} catch {
|
|
6564
|
-
return err(invalidRegex(span));
|
|
6565
|
-
}
|
|
6566
|
-
case "DateKeyword": return ok(anyDate());
|
|
6567
|
-
case "DatePattern":
|
|
6568
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6569
|
-
return parseDateContent(token.value.value, span);
|
|
6570
|
-
case "Tagged": return parseTag(lexer);
|
|
6571
|
-
case "Known": return ok(anyKnownValue());
|
|
6572
|
-
case "SingleQuotedPattern":
|
|
6573
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6574
|
-
return parseKnownValueContent(token.value.value);
|
|
6575
|
-
case "SingleQuotedRegex":
|
|
6576
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6577
|
-
try {
|
|
6578
|
-
return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
|
|
6579
|
-
} catch {
|
|
6580
|
-
return err(invalidRegex(span));
|
|
6581
|
-
}
|
|
6582
|
-
case "Null": return ok(nullPattern());
|
|
6583
|
-
case "And":
|
|
6584
|
-
case "Or":
|
|
6585
|
-
case "Not":
|
|
6586
|
-
case "Traverse":
|
|
6587
|
-
case "RepeatZeroOrMoreLazy":
|
|
6588
|
-
case "RepeatZeroOrMorePossessive":
|
|
6589
|
-
case "RepeatOneOrMore":
|
|
6590
|
-
case "RepeatOneOrMoreLazy":
|
|
6591
|
-
case "RepeatOneOrMorePossessive":
|
|
6592
|
-
case "RepeatZeroOrOne":
|
|
6593
|
-
case "RepeatZeroOrOneLazy":
|
|
6594
|
-
case "RepeatZeroOrOnePossessive":
|
|
6595
|
-
case "ParenClose":
|
|
6596
|
-
case "BracketClose":
|
|
6597
|
-
case "Comma":
|
|
6598
|
-
case "Ellipsis":
|
|
6599
|
-
case "Range":
|
|
6600
|
-
case "Identifier": return err(unexpectedToken(token, span));
|
|
6601
|
-
}
|
|
6602
|
-
}
|
|
6552
|
+
const U64_MAX = 18446744073709551615n;
|
|
6603
6553
|
/**
|
|
6604
|
-
* Parse a
|
|
6554
|
+
* Parse the inner contents of a `'…'` known-value pattern token.
|
|
6555
|
+
*
|
|
6556
|
+
* Mirrors the Rust dispatch
|
|
6557
|
+
* ```ignore
|
|
6558
|
+
* if let Ok(value) = content.parse::<u64>() {
|
|
6559
|
+
* Pattern::known_value(KnownValue::new(value))
|
|
6560
|
+
* } else {
|
|
6561
|
+
* Pattern::known_value_named(content)
|
|
6562
|
+
* }
|
|
6563
|
+
* ```
|
|
6564
|
+
* but uses BigInt parsing to preserve full `u64` range — the previous
|
|
6565
|
+
* `parseInt(...)` path silently truncated above `2^53-1`.
|
|
6605
6566
|
*/
|
|
6606
|
-
function
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6610
|
-
type: "ExpectedCloseParen",
|
|
6611
|
-
span: lexer.span()
|
|
6612
|
-
});
|
|
6613
|
-
return ok(group(inner.value));
|
|
6567
|
+
function parseKnownValueContent(content) {
|
|
6568
|
+
if (isU64Literal(content)) return ok(knownValue(new KnownValue(BigInt(content))));
|
|
6569
|
+
return ok(patternLeaf(leafKnownValue(KnownValuePattern.named(content))));
|
|
6614
6570
|
}
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6571
|
+
function isU64Literal(content) {
|
|
6572
|
+
if (content.length === 0) return false;
|
|
6573
|
+
for (let i = 0; i < content.length; i++) {
|
|
6574
|
+
const c = content.charCodeAt(i);
|
|
6575
|
+
if (c < 48 || c > 57) return false;
|
|
6576
|
+
}
|
|
6577
|
+
try {
|
|
6578
|
+
const value = BigInt(content);
|
|
6579
|
+
return value >= 0n && value <= U64_MAX;
|
|
6580
|
+
} catch {
|
|
6581
|
+
return false;
|
|
6582
|
+
}
|
|
6622
6583
|
}
|
|
6584
|
+
//#endregion
|
|
6585
|
+
//#region src/parse/leaf/number-parser.ts
|
|
6623
6586
|
/**
|
|
6624
|
-
*
|
|
6587
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6588
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6589
|
+
*
|
|
6590
|
+
* Number parsers — port of `bc-envelope-pattern-rust` `parse/leaf/number_parser.rs`.
|
|
6591
|
+
*
|
|
6592
|
+
* @module envelope-pattern/parse/leaf/number-parser
|
|
6625
6593
|
*/
|
|
6626
|
-
function parseSearch(lexer) {
|
|
6627
|
-
if (lexer.next()?.token.type !== "ParenOpen") return err({
|
|
6628
|
-
type: "ExpectedOpenParen",
|
|
6629
|
-
span: lexer.span()
|
|
6630
|
-
});
|
|
6631
|
-
const inner = parseOr(lexer);
|
|
6632
|
-
if (!inner.ok) return inner;
|
|
6633
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6634
|
-
type: "ExpectedCloseParen",
|
|
6635
|
-
span: lexer.span()
|
|
6636
|
-
});
|
|
6637
|
-
return ok(search(inner.value));
|
|
6638
|
-
}
|
|
6639
6594
|
/**
|
|
6640
|
-
*
|
|
6595
|
+
* Parses an optional `...end` suffix following an already-consumed number,
|
|
6596
|
+
* mirroring Rust `parse_number_range_or_comparison`.
|
|
6641
6597
|
*/
|
|
6642
6598
|
function parseNumberRangeOrComparison(lexer, firstValue) {
|
|
6643
6599
|
const next = lexer.peekToken();
|
|
@@ -6647,10 +6603,7 @@ function parseNumberRangeOrComparison(lexer, firstValue) {
|
|
|
6647
6603
|
const endToken = lexer.next();
|
|
6648
6604
|
if (endToken === void 0) return err(unexpectedEndOfInput());
|
|
6649
6605
|
let endValue;
|
|
6650
|
-
if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer") {
|
|
6651
|
-
if (!endToken.token.value.ok) return err(endToken.token.value.error);
|
|
6652
|
-
endValue = endToken.token.value.value;
|
|
6653
|
-
} else if (endToken.token.type === "Float") {
|
|
6606
|
+
if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer" || endToken.token.type === "Float") {
|
|
6654
6607
|
if (!endToken.token.value.ok) return err(endToken.token.value.error);
|
|
6655
6608
|
endValue = endToken.token.value.value;
|
|
6656
6609
|
} else return err(unexpectedToken(endToken.token, endToken.span));
|
|
@@ -6659,16 +6612,14 @@ function parseNumberRangeOrComparison(lexer, firstValue) {
|
|
|
6659
6612
|
return ok(number(firstValue));
|
|
6660
6613
|
}
|
|
6661
6614
|
/**
|
|
6662
|
-
*
|
|
6615
|
+
* Parses a number following a comparison operator, mirroring Rust
|
|
6616
|
+
* `parse_comparison_number`.
|
|
6663
6617
|
*/
|
|
6664
6618
|
function parseComparisonNumber(lexer, op) {
|
|
6665
6619
|
const numToken = lexer.next();
|
|
6666
6620
|
if (numToken === void 0) return err(unexpectedEndOfInput());
|
|
6667
6621
|
let value;
|
|
6668
|
-
if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer") {
|
|
6669
|
-
if (!numToken.token.value.ok) return err(numToken.token.value.error);
|
|
6670
|
-
value = numToken.token.value.value;
|
|
6671
|
-
} else if (numToken.token.type === "Float") {
|
|
6622
|
+
if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer" || numToken.token.type === "Float") {
|
|
6672
6623
|
if (!numToken.token.value.ok) return err(numToken.token.value.error);
|
|
6673
6624
|
value = numToken.token.value.value;
|
|
6674
6625
|
} else return err(unexpectedToken(numToken.token, numToken.span));
|
|
@@ -6677,307 +6628,818 @@ function parseComparisonNumber(lexer, op) {
|
|
|
6677
6628
|
case "<=": return ok(patternLeaf(leafNumber(NumberPattern.lessThanOrEqual(value))));
|
|
6678
6629
|
case ">": return ok(numberGreaterThan(value));
|
|
6679
6630
|
case "<": return ok(numberLessThan(value));
|
|
6680
|
-
default: return ok(number(value));
|
|
6681
6631
|
}
|
|
6682
6632
|
}
|
|
6633
|
+
//#endregion
|
|
6634
|
+
//#region src/parse/leaf/tag-parser.ts
|
|
6683
6635
|
/**
|
|
6684
|
-
*
|
|
6636
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6637
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6638
|
+
*
|
|
6639
|
+
* Tag parser — port of `bc-envelope-pattern-rust`
|
|
6640
|
+
* `parse/leaf/tag_parser.rs`.
|
|
6641
|
+
*
|
|
6642
|
+
* Mirrors the Rust dispatch exactly: lookahead for `(`; if absent, return
|
|
6643
|
+
* the bare `any_tag()`. Otherwise build a synthetic dcbor-pattern
|
|
6644
|
+
* expression `tagged(<inner>)`, parse it via `@bcts/dcbor-pattern`, and
|
|
6645
|
+
* extract the resulting `TaggedPattern` to wrap as an envelope-pattern
|
|
6646
|
+
* leaf. This keeps the **full** tag selector (number, name, regex)
|
|
6647
|
+
* intact — the previous port discarded the tag value entirely.
|
|
6648
|
+
*
|
|
6649
|
+
* @module envelope-pattern/parse/leaf/tag-parser
|
|
6685
6650
|
*/
|
|
6686
|
-
function parseArray(lexer) {
|
|
6687
|
-
const first = lexer.peekToken();
|
|
6688
|
-
if (first === void 0) return err(unexpectedEndOfInput());
|
|
6689
|
-
if (first.token.type === "BracketClose") {
|
|
6690
|
-
lexer.next();
|
|
6691
|
-
return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
|
|
6692
|
-
}
|
|
6693
|
-
if (first.token.type === "RepeatZeroOrMore") {
|
|
6694
|
-
lexer.next();
|
|
6695
|
-
if (lexer.next()?.token.type !== "BracketClose") return err({
|
|
6696
|
-
type: "ExpectedCloseBracket",
|
|
6697
|
-
span: lexer.span()
|
|
6698
|
-
});
|
|
6699
|
-
return ok(anyArray());
|
|
6700
|
-
}
|
|
6701
|
-
const patterns = [];
|
|
6702
|
-
while (true) {
|
|
6703
|
-
const next = lexer.peekToken();
|
|
6704
|
-
if (next === void 0) return err(unexpectedEndOfInput());
|
|
6705
|
-
if (next.token.type === "BracketClose") {
|
|
6706
|
-
lexer.next();
|
|
6707
|
-
break;
|
|
6708
|
-
}
|
|
6709
|
-
const pattern = parseOr(lexer);
|
|
6710
|
-
if (!pattern.ok) return pattern;
|
|
6711
|
-
patterns.push(pattern.value);
|
|
6712
|
-
const afterPattern = lexer.peekToken();
|
|
6713
|
-
if (afterPattern === void 0) return err(unexpectedEndOfInput());
|
|
6714
|
-
if (afterPattern.token.type === "Comma") lexer.next();
|
|
6715
|
-
else if (afterPattern.token.type !== "BracketClose") return err(unexpectedToken(afterPattern.token, afterPattern.span));
|
|
6716
|
-
}
|
|
6717
|
-
if (patterns.length === 0) return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
|
|
6718
|
-
return ok(patternLeaf(leafArray(ArrayPattern.withPatterns(patterns))));
|
|
6719
|
-
}
|
|
6720
6651
|
/**
|
|
6721
|
-
* Parse
|
|
6652
|
+
* Parse `tagged` and `tagged(...)` patterns.
|
|
6722
6653
|
*/
|
|
6723
6654
|
function parseTag(lexer) {
|
|
6724
|
-
if (lexer.
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
if (
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
if (content.startsWith("/") && content.endsWith("/")) {
|
|
6740
|
-
const regexStr = content.slice(1, -1);
|
|
6741
|
-
try {
|
|
6742
|
-
return ok(dateRegex(new RegExp(regexStr)));
|
|
6743
|
-
} catch {
|
|
6744
|
-
return err(invalidRegex(span));
|
|
6655
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyTag());
|
|
6656
|
+
lexer.next();
|
|
6657
|
+
const remainder = lexer.remainder();
|
|
6658
|
+
const closeIdx = findMatchingCloseParen(remainder);
|
|
6659
|
+
if (closeIdx === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6660
|
+
const innerContent = remainder.slice(0, closeIdx);
|
|
6661
|
+
const dcborResult = parse$1(`tagged(${innerContent})`);
|
|
6662
|
+
if (dcborResult.ok) {
|
|
6663
|
+
const dcborPattern = dcborResult.value;
|
|
6664
|
+
if (dcborPattern.kind === "Structure" && dcborPattern.pattern.type === "Tagged") {
|
|
6665
|
+
lexer.bump(closeIdx);
|
|
6666
|
+
const close = lexer.next();
|
|
6667
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6668
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6669
|
+
return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborPattern.pattern.pattern))));
|
|
6745
6670
|
}
|
|
6746
6671
|
}
|
|
6747
|
-
const
|
|
6748
|
-
if (
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
if (left.length > 0 && right.length > 0) {
|
|
6768
|
-
const parsedStart = Date.parse(left);
|
|
6769
|
-
const parsedEnd = Date.parse(right);
|
|
6770
|
-
if (isNaN(parsedStart) || isNaN(parsedEnd)) return err({
|
|
6771
|
-
type: "InvalidDateFormat",
|
|
6772
|
-
span
|
|
6773
|
-
});
|
|
6774
|
-
return ok(dateRange(CborDate.fromDatetime(new Date(parsedStart)), CborDate.fromDatetime(new Date(parsedEnd))));
|
|
6672
|
+
const fallback = parseTagInner(innerContent);
|
|
6673
|
+
if (!fallback.ok) return fallback;
|
|
6674
|
+
lexer.bump(closeIdx);
|
|
6675
|
+
const close = lexer.next();
|
|
6676
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6677
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6678
|
+
return ok(fallback.value);
|
|
6679
|
+
}
|
|
6680
|
+
/**
|
|
6681
|
+
* Locate the index of the closing `)` matching the `(` that has already
|
|
6682
|
+
* been consumed by `parseTag`. Mirrors Rust `find_matching_paren`.
|
|
6683
|
+
*/
|
|
6684
|
+
function findMatchingCloseParen(src) {
|
|
6685
|
+
let depth = 0;
|
|
6686
|
+
for (let i = 0; i < src.length; i++) {
|
|
6687
|
+
const ch = src.charCodeAt(i);
|
|
6688
|
+
if (ch === 40) depth += 1;
|
|
6689
|
+
else if (ch === 41) {
|
|
6690
|
+
if (depth === 0) return i;
|
|
6691
|
+
depth -= 1;
|
|
6775
6692
|
}
|
|
6776
|
-
return err({
|
|
6777
|
-
type: "InvalidDateFormat",
|
|
6778
|
-
span
|
|
6779
|
-
});
|
|
6780
6693
|
}
|
|
6781
|
-
const parsed = Date.parse(content);
|
|
6782
|
-
if (isNaN(parsed)) return err({
|
|
6783
|
-
type: "InvalidDateFormat",
|
|
6784
|
-
span
|
|
6785
|
-
});
|
|
6786
|
-
return ok(date(CborDate.fromDatetime(new Date(parsed))));
|
|
6787
6694
|
}
|
|
6788
6695
|
/**
|
|
6789
|
-
*
|
|
6696
|
+
* Fallback for `tagged(N)` and `tagged(name)` when the full delegation
|
|
6697
|
+
* to dcbor-pattern fails. Mirrors Rust `parse_tag_inner`.
|
|
6790
6698
|
*/
|
|
6791
|
-
function
|
|
6792
|
-
const
|
|
6793
|
-
if (
|
|
6794
|
-
|
|
6699
|
+
function parseTagInner(src) {
|
|
6700
|
+
const trimmed = src.trim();
|
|
6701
|
+
if (trimmed.length === 0) return err(unexpectedEndOfInput());
|
|
6702
|
+
if (trimmed.startsWith("/")) return err(unexpectedEndOfInput());
|
|
6703
|
+
if (/^\d+$/.test(trimmed)) try {
|
|
6704
|
+
const dcborResult = parse$1(`tagged(${trimmed})`);
|
|
6705
|
+
if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
|
|
6706
|
+
} catch {}
|
|
6707
|
+
const dcborResult = parse$1(`tagged(${trimmed})`);
|
|
6708
|
+
if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
|
|
6709
|
+
return err(unexpectedEndOfInput());
|
|
6795
6710
|
}
|
|
6711
|
+
//#endregion
|
|
6712
|
+
//#region src/parse/structure/assertion-parser.ts
|
|
6796
6713
|
/**
|
|
6797
|
-
*
|
|
6714
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6715
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6716
|
+
*
|
|
6717
|
+
* Assertion parser — port of `bc-envelope-pattern-rust`
|
|
6718
|
+
* `parse/structure/assertion_parser.rs`.
|
|
6798
6719
|
*
|
|
6799
|
-
*
|
|
6800
|
-
*
|
|
6801
|
-
*
|
|
6720
|
+
* Note: Rust's `parse_assertion` ignores its lexer entirely and always
|
|
6721
|
+
* returns `Pattern::any_assertion()`. There is intentionally **no**
|
|
6722
|
+
* `assert(pred, obj)` syntax — predicate/object filters are written via
|
|
6723
|
+
* the dedicated `assertpred(...)` / `assertobj(...)` keywords.
|
|
6724
|
+
*
|
|
6725
|
+
* @module envelope-pattern/parse/structure/assertion-parser
|
|
6802
6726
|
*/
|
|
6803
|
-
function
|
|
6804
|
-
|
|
6805
|
-
lexer.next();
|
|
6806
|
-
if (lexer.peek() === "/") {
|
|
6807
|
-
const regexTokenResult = lexer.next();
|
|
6808
|
-
if (regexTokenResult?.token.type === "Regex") {
|
|
6809
|
-
const regexToken = regexTokenResult.token;
|
|
6810
|
-
if (!regexToken.value.ok) return err(regexToken.value.error);
|
|
6811
|
-
const keyword = regexToken.value.value;
|
|
6812
|
-
const dcborResult = parse$1(keyword);
|
|
6813
|
-
if (!dcborResult.ok) return err(unexpectedToken(regexToken, regexTokenResult.span));
|
|
6814
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6815
|
-
type: "ExpectedCloseParen",
|
|
6816
|
-
span: lexer.span()
|
|
6817
|
-
});
|
|
6818
|
-
return ok(cborPattern(dcborResult.value));
|
|
6819
|
-
}
|
|
6820
|
-
}
|
|
6821
|
-
const cborResult = parseDcborItemPartial(lexer.remainder());
|
|
6822
|
-
if (cborResult.ok) {
|
|
6823
|
-
const [cborData, consumed] = cborResult.value;
|
|
6824
|
-
lexer.bump(consumed);
|
|
6825
|
-
while (lexer.peek() === " " || lexer.peek() === " " || lexer.peek() === "\n") lexer.bump(1);
|
|
6826
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6827
|
-
type: "ExpectedCloseParen",
|
|
6828
|
-
span: lexer.span()
|
|
6829
|
-
});
|
|
6830
|
-
return ok(cborValue(cborData));
|
|
6831
|
-
}
|
|
6832
|
-
const inner = parseOr(lexer);
|
|
6833
|
-
if (!inner.ok) return inner;
|
|
6834
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6835
|
-
type: "ExpectedCloseParen",
|
|
6836
|
-
span: lexer.span()
|
|
6837
|
-
});
|
|
6838
|
-
return inner;
|
|
6727
|
+
function parseAssertion(_lexer) {
|
|
6728
|
+
return ok(anyAssertion());
|
|
6839
6729
|
}
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6730
|
+
//#endregion
|
|
6731
|
+
//#region src/parse/structure/assertion-obj-parser.ts
|
|
6732
|
+
/**
|
|
6733
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6734
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6735
|
+
*
|
|
6736
|
+
* Assertion-object parser — port of
|
|
6737
|
+
* `bc-envelope-pattern-rust/src/parse/structure/assertion_obj_parser.rs`.
|
|
6738
|
+
*
|
|
6739
|
+
* Requires `assertobj(<pattern>)`. The bare `assertobj` keyword is a
|
|
6740
|
+
* syntax error in Rust; we now mirror that behaviour.
|
|
6741
|
+
*
|
|
6742
|
+
* @module envelope-pattern/parse/structure/assertion-obj-parser
|
|
6743
|
+
*/
|
|
6744
|
+
function parseAssertionObj(lexer) {
|
|
6745
|
+
const open = lexer.next();
|
|
6746
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6747
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6855
6748
|
const inner = parseOr(lexer);
|
|
6856
6749
|
if (!inner.ok) return inner;
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
return ok(patternStructure(structureNode(NodePattern.withSubject(inner.value))));
|
|
6862
|
-
}
|
|
6863
|
-
function parseAssertion(lexer) {
|
|
6864
|
-
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyAssertion());
|
|
6865
|
-
lexer.next();
|
|
6866
|
-
const pred = parseOr(lexer);
|
|
6867
|
-
if (!pred.ok) return pred;
|
|
6868
|
-
const comma = lexer.next();
|
|
6869
|
-
if (comma?.token.type !== "Comma") return err(unexpectedToken(comma?.token ?? { type: "Null" }, comma?.span ?? lexer.span()));
|
|
6870
|
-
const obj = parseOr(lexer);
|
|
6871
|
-
if (!obj.ok) return obj;
|
|
6872
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6873
|
-
type: "ExpectedCloseParen",
|
|
6874
|
-
span: lexer.span()
|
|
6875
|
-
});
|
|
6876
|
-
return ok(patternStructure(structureAssertions(AssertionsPattern.withBoth(pred.value, obj.value))));
|
|
6750
|
+
const close = lexer.next();
|
|
6751
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6752
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6753
|
+
return ok(assertionWithObject(inner.value));
|
|
6877
6754
|
}
|
|
6755
|
+
//#endregion
|
|
6756
|
+
//#region src/parse/structure/assertion-pred-parser.ts
|
|
6757
|
+
/**
|
|
6758
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6759
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6760
|
+
*
|
|
6761
|
+
* Assertion-predicate parser — port of
|
|
6762
|
+
* `bc-envelope-pattern-rust/src/parse/structure/assertion_pred_parser.rs`.
|
|
6763
|
+
*
|
|
6764
|
+
* Requires `assertpred(<pattern>)`. The bare `assertpred` keyword is a
|
|
6765
|
+
* syntax error in Rust (it errors on `UnexpectedEndOfInput` /
|
|
6766
|
+
* `UnexpectedToken`); we now mirror that behaviour.
|
|
6767
|
+
*
|
|
6768
|
+
* @module envelope-pattern/parse/structure/assertion-pred-parser
|
|
6769
|
+
*/
|
|
6878
6770
|
function parseAssertionPred(lexer) {
|
|
6879
|
-
|
|
6880
|
-
|
|
6771
|
+
const open = lexer.next();
|
|
6772
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6773
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6881
6774
|
const inner = parseOr(lexer);
|
|
6882
6775
|
if (!inner.ok) return inner;
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
});
|
|
6776
|
+
const close = lexer.next();
|
|
6777
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6778
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6887
6779
|
return ok(assertionWithPredicate(inner.value));
|
|
6888
6780
|
}
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6781
|
+
//#endregion
|
|
6782
|
+
//#region src/parse/structure/compressed-parser.ts
|
|
6783
|
+
/**
|
|
6784
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6785
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6786
|
+
*
|
|
6787
|
+
* Compressed parser — port of `bc-envelope-pattern-rust`
|
|
6788
|
+
* `parse/structure/compressed_parser.rs`.
|
|
6789
|
+
*
|
|
6790
|
+
* @module envelope-pattern/parse/structure/compressed-parser
|
|
6791
|
+
*/
|
|
6792
|
+
function parseCompressed(_lexer) {
|
|
6793
|
+
return ok(compressed());
|
|
6899
6794
|
}
|
|
6795
|
+
//#endregion
|
|
6796
|
+
//#region src/parse/structure/digest-parser.ts
|
|
6797
|
+
/**
|
|
6798
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6799
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6800
|
+
*
|
|
6801
|
+
* Digest parser — port of `bc-envelope-pattern-rust`
|
|
6802
|
+
* `parse/structure/digest_parser.rs`.
|
|
6803
|
+
*
|
|
6804
|
+
* Mirrors Rust exactly:
|
|
6805
|
+
*
|
|
6806
|
+
* - Requires `digest(...)` — bare `digest` is an `UnexpectedEndOfInput`
|
|
6807
|
+
* error (the previous TS port silently returned `digest(any)`).
|
|
6808
|
+
* - Inside the parens, accepts either a UR string (`ur:digest/...`,
|
|
6809
|
+
* parsed via `Digest.fromURString`) or a hex byte prefix.
|
|
6810
|
+
* - Hex prefixes must have even length and not exceed `Digest.DIGEST_SIZE`
|
|
6811
|
+
* bytes; otherwise the parser surfaces `InvalidHexString`.
|
|
6812
|
+
*
|
|
6813
|
+
* @module envelope-pattern/parse/structure/digest-parser
|
|
6814
|
+
*/
|
|
6815
|
+
const DIGEST_SIZE = Digest.DIGEST_SIZE;
|
|
6900
6816
|
function parseDigest(lexer) {
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
if (
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6817
|
+
const open = lexer.next();
|
|
6818
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6819
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6820
|
+
const innerResult = parseDigestInner(lexer.remainder(), lexer.position);
|
|
6821
|
+
if (!innerResult.ok) return innerResult;
|
|
6822
|
+
const [pattern, consumed] = innerResult.value;
|
|
6823
|
+
lexer.bump(consumed);
|
|
6824
|
+
const close = lexer.next();
|
|
6825
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6826
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6827
|
+
return ok(pattern);
|
|
6828
|
+
}
|
|
6829
|
+
function parseDigestInner(src, basePos) {
|
|
6830
|
+
let pos = 0;
|
|
6831
|
+
pos = skipWs(src, pos);
|
|
6832
|
+
if (src.startsWith("ur:", pos)) {
|
|
6833
|
+
const start = pos;
|
|
6834
|
+
while (pos < src.length && src[pos] !== ")") pos += 1;
|
|
6835
|
+
const ur = src.slice(start, pos).trimEnd();
|
|
6836
|
+
let parsed;
|
|
6837
|
+
try {
|
|
6838
|
+
parsed = Digest.fromURString(ur);
|
|
6839
|
+
} catch {
|
|
6840
|
+
return err(invalidUr(ur, {
|
|
6841
|
+
start: basePos + start,
|
|
6842
|
+
end: basePos + pos
|
|
6843
|
+
}));
|
|
6844
|
+
}
|
|
6845
|
+
pos = skipWs(src, pos);
|
|
6846
|
+
return ok([digest(parsed), pos]);
|
|
6847
|
+
}
|
|
6848
|
+
const start = pos;
|
|
6849
|
+
while (pos < src.length && isAsciiHexDigit(src.charCodeAt(pos))) pos += 1;
|
|
6850
|
+
if (pos === start) return err(invalidHexString({
|
|
6851
|
+
start: basePos + pos,
|
|
6852
|
+
end: basePos + pos
|
|
6853
|
+
}));
|
|
6854
|
+
const hexStr = src.slice(start, pos);
|
|
6855
|
+
if (hexStr.length % 2 !== 0) return err(invalidHexString({
|
|
6856
|
+
start: basePos + pos,
|
|
6857
|
+
end: basePos + pos
|
|
6858
|
+
}));
|
|
6859
|
+
const bytes = decodeHex(hexStr);
|
|
6860
|
+
if (bytes === void 0) return err(invalidHexString({
|
|
6861
|
+
start: basePos + pos,
|
|
6862
|
+
end: basePos + pos
|
|
6863
|
+
}));
|
|
6864
|
+
if (bytes.length > DIGEST_SIZE) return err(invalidHexString({
|
|
6865
|
+
start: basePos + pos,
|
|
6866
|
+
end: basePos + pos
|
|
6867
|
+
}));
|
|
6868
|
+
pos = skipWs(src, pos);
|
|
6869
|
+
return ok([digestPrefix(bytes), pos]);
|
|
6870
|
+
}
|
|
6871
|
+
function skipWs(src, pos) {
|
|
6872
|
+
while (pos < src.length) {
|
|
6873
|
+
const ch = src[pos];
|
|
6874
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos += 1;
|
|
6875
|
+
else break;
|
|
6912
6876
|
}
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
return ok(digestPrefix(bytes));
|
|
6877
|
+
return pos;
|
|
6878
|
+
}
|
|
6879
|
+
function isAsciiHexDigit(c) {
|
|
6880
|
+
return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
|
|
6881
|
+
}
|
|
6882
|
+
function decodeHex(hex) {
|
|
6883
|
+
if (hex.length % 2 !== 0) return void 0;
|
|
6884
|
+
const out = new Uint8Array(hex.length / 2);
|
|
6885
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
6886
|
+
const value = Number.parseInt(hex.slice(i, i + 2), 16);
|
|
6887
|
+
if (Number.isNaN(value)) return void 0;
|
|
6888
|
+
out[i / 2] = value;
|
|
6926
6889
|
}
|
|
6927
|
-
return
|
|
6890
|
+
return out;
|
|
6891
|
+
}
|
|
6892
|
+
//#endregion
|
|
6893
|
+
//#region src/parse/structure/elided-parser.ts
|
|
6894
|
+
/**
|
|
6895
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6896
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6897
|
+
*
|
|
6898
|
+
* Elided parser — port of `bc-envelope-pattern-rust`
|
|
6899
|
+
* `parse/structure/elided_parser.rs`.
|
|
6900
|
+
*
|
|
6901
|
+
* @module envelope-pattern/parse/structure/elided-parser
|
|
6902
|
+
*/
|
|
6903
|
+
function parseElided(_lexer) {
|
|
6904
|
+
return ok(elided());
|
|
6905
|
+
}
|
|
6906
|
+
//#endregion
|
|
6907
|
+
//#region src/parse/structure/encrypted-parser.ts
|
|
6908
|
+
/**
|
|
6909
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6910
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6911
|
+
*
|
|
6912
|
+
* Encrypted parser — port of `bc-envelope-pattern-rust`
|
|
6913
|
+
* `parse/structure/encrypted_parser.rs`.
|
|
6914
|
+
*
|
|
6915
|
+
* @module envelope-pattern/parse/structure/encrypted-parser
|
|
6916
|
+
*/
|
|
6917
|
+
function parseEncrypted(_lexer) {
|
|
6918
|
+
return ok(encrypted());
|
|
6919
|
+
}
|
|
6920
|
+
//#endregion
|
|
6921
|
+
//#region src/parse/structure/node-parser.ts
|
|
6922
|
+
/**
|
|
6923
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6924
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6925
|
+
*
|
|
6926
|
+
* Node parser — port of `bc-envelope-pattern-rust`
|
|
6927
|
+
* `parse/structure/node_parser.rs`.
|
|
6928
|
+
*
|
|
6929
|
+
* Mirrors Rust:
|
|
6930
|
+
* - Bare `node` → `any_node()`.
|
|
6931
|
+
* - `node({n})` / `node({n,m})` / `node({n,})` → `node_with_assertions_range`.
|
|
6932
|
+
* - Anything else inside the parens (e.g. `node(text)`) is a syntax error
|
|
6933
|
+
* in Rust; the previous TS port silently produced an always-matching
|
|
6934
|
+
* `WithSubject` node, which we have removed.
|
|
6935
|
+
*
|
|
6936
|
+
* @module envelope-pattern/parse/structure/node-parser
|
|
6937
|
+
*/
|
|
6938
|
+
function parseNode(lexer) {
|
|
6939
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyNode());
|
|
6940
|
+
lexer.next();
|
|
6941
|
+
const inner = lexer.next();
|
|
6942
|
+
if (inner === void 0) return err(unexpectedEndOfInput());
|
|
6943
|
+
if (inner.token.type !== "Range") return err(unexpectedToken(inner.token, inner.span));
|
|
6944
|
+
if (!inner.token.value.ok) return err(inner.token.value.error);
|
|
6945
|
+
const interval = inner.token.value.value.interval();
|
|
6946
|
+
const close = lexer.next();
|
|
6947
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6948
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6949
|
+
return ok(patternStructure(structureNode(NodePattern.fromInterval(interval))));
|
|
6928
6950
|
}
|
|
6951
|
+
//#endregion
|
|
6952
|
+
//#region src/parse/structure/object-parser.ts
|
|
6953
|
+
/**
|
|
6954
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6955
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6956
|
+
*
|
|
6957
|
+
* Object parser — port of `bc-envelope-pattern-rust`
|
|
6958
|
+
* `parse/structure/object_parser.rs`.
|
|
6959
|
+
*
|
|
6960
|
+
* @module envelope-pattern/parse/structure/object-parser
|
|
6961
|
+
*/
|
|
6929
6962
|
function parseObject(lexer) {
|
|
6930
6963
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyObject());
|
|
6931
6964
|
lexer.next();
|
|
6932
6965
|
const inner = parseOr(lexer);
|
|
6933
6966
|
if (!inner.ok) return inner;
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
});
|
|
6967
|
+
const close = lexer.next();
|
|
6968
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6969
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6938
6970
|
return ok(object(inner.value));
|
|
6939
6971
|
}
|
|
6972
|
+
//#endregion
|
|
6973
|
+
//#region src/parse/structure/obscured-parser.ts
|
|
6974
|
+
/**
|
|
6975
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6976
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6977
|
+
*
|
|
6978
|
+
* Obscured parser — port of `bc-envelope-pattern-rust`
|
|
6979
|
+
* `parse/structure/obscured_parser.rs`.
|
|
6980
|
+
*
|
|
6981
|
+
* @module envelope-pattern/parse/structure/obscured-parser
|
|
6982
|
+
*/
|
|
6983
|
+
function parseObscured(_lexer) {
|
|
6984
|
+
return ok(obscured());
|
|
6985
|
+
}
|
|
6986
|
+
//#endregion
|
|
6987
|
+
//#region src/parse/structure/predicate-parser.ts
|
|
6988
|
+
/**
|
|
6989
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6990
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6991
|
+
*
|
|
6992
|
+
* Predicate parser — port of `bc-envelope-pattern-rust`
|
|
6993
|
+
* `parse/structure/predicate_parser.rs`.
|
|
6994
|
+
*
|
|
6995
|
+
* @module envelope-pattern/parse/structure/predicate-parser
|
|
6996
|
+
*/
|
|
6940
6997
|
function parsePredicate(lexer) {
|
|
6941
6998
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyPredicate());
|
|
6942
6999
|
lexer.next();
|
|
6943
7000
|
const inner = parseOr(lexer);
|
|
6944
7001
|
if (!inner.ok) return inner;
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
});
|
|
7002
|
+
const close = lexer.next();
|
|
7003
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7004
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6949
7005
|
return ok(predicate(inner.value));
|
|
6950
7006
|
}
|
|
7007
|
+
//#endregion
|
|
7008
|
+
//#region src/parse/structure/subject-parser.ts
|
|
7009
|
+
/**
|
|
7010
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7011
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7012
|
+
*
|
|
7013
|
+
* Subject parser — port of `bc-envelope-pattern-rust`
|
|
7014
|
+
* `parse/structure/subject_parser.rs`.
|
|
7015
|
+
*
|
|
7016
|
+
* @module envelope-pattern/parse/structure/subject-parser
|
|
7017
|
+
*/
|
|
6951
7018
|
function parseSubject(lexer) {
|
|
6952
7019
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anySubject());
|
|
6953
7020
|
lexer.next();
|
|
6954
7021
|
const inner = parseOr(lexer);
|
|
6955
7022
|
if (!inner.ok) return inner;
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
});
|
|
7023
|
+
const close = lexer.next();
|
|
7024
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7025
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6960
7026
|
return ok(subject(inner.value));
|
|
6961
7027
|
}
|
|
7028
|
+
//#endregion
|
|
7029
|
+
//#region src/parse/structure/wrapped-parser.ts
|
|
7030
|
+
/**
|
|
7031
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7032
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7033
|
+
*
|
|
7034
|
+
* Wrapped/unwrap parser — port of `bc-envelope-pattern-rust`
|
|
7035
|
+
* `parse/structure/wrapped_parser.rs`.
|
|
7036
|
+
*
|
|
7037
|
+
* @module envelope-pattern/parse/structure/wrapped-parser
|
|
7038
|
+
*/
|
|
7039
|
+
function parseWrapped(_lexer) {
|
|
7040
|
+
return ok(wrapped());
|
|
7041
|
+
}
|
|
6962
7042
|
function parseUnwrap(lexer) {
|
|
6963
7043
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(unwrapEnvelope());
|
|
6964
7044
|
lexer.next();
|
|
6965
7045
|
const inner = parseOr(lexer);
|
|
6966
7046
|
if (!inner.ok) return inner;
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
});
|
|
7047
|
+
const close = lexer.next();
|
|
7048
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7049
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6971
7050
|
return ok(unwrapMatching(inner.value));
|
|
6972
7051
|
}
|
|
6973
|
-
|
|
7052
|
+
//#endregion
|
|
7053
|
+
//#region src/parse/meta/capture-parser.ts
|
|
7054
|
+
/**
|
|
7055
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7056
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7057
|
+
*
|
|
7058
|
+
* Capture parser — port of `bc-envelope-pattern-rust`
|
|
7059
|
+
* `parse/meta/capture_parser.rs`.
|
|
7060
|
+
*
|
|
7061
|
+
* The `@name(...)` form requires explicit parentheses. Mirrors Rust
|
|
7062
|
+
* exactly:
|
|
7063
|
+
* ```ignore
|
|
7064
|
+
* @name ( expr )
|
|
7065
|
+
* ```
|
|
7066
|
+
* The previous TS port called `parse_group` (primary + quantifier), which
|
|
7067
|
+
* wrapped the inner expression in a redundant `GroupPattern` and accepted
|
|
7068
|
+
* the bare `@name p` form that Rust rejects.
|
|
7069
|
+
*
|
|
7070
|
+
* @module envelope-pattern/parse/meta/capture-parser
|
|
7071
|
+
*/
|
|
7072
|
+
function parseCapture(lexer, name) {
|
|
7073
|
+
const open = lexer.next();
|
|
7074
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
7075
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
7076
|
+
const inner = parseOr(lexer);
|
|
7077
|
+
if (!inner.ok) return inner;
|
|
7078
|
+
const close = lexer.next();
|
|
7079
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7080
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7081
|
+
return ok(capture(name, inner.value));
|
|
7082
|
+
}
|
|
7083
|
+
//#endregion
|
|
7084
|
+
//#region src/parse/meta/group-parser.ts
|
|
7085
|
+
/**
|
|
7086
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7087
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7088
|
+
*
|
|
7089
|
+
* Group parser — port of `bc-envelope-pattern-rust`
|
|
7090
|
+
* `parse/meta/group_parser.rs`.
|
|
7091
|
+
*
|
|
7092
|
+
* Called from `parse_primary` after the opening `(` has been consumed.
|
|
7093
|
+
*
|
|
7094
|
+
* Mirrors Rust exactly:
|
|
7095
|
+
*
|
|
7096
|
+
* - Parse the inner expression with `parse_or`.
|
|
7097
|
+
* - Expect `)`. If missing, surface `ExpectedCloseParen`.
|
|
7098
|
+
* - Lookahead **once** for a quantifier suffix. If present, consume it
|
|
7099
|
+
* and wrap as `Pattern::repeat(inner, …)`. Otherwise return the inner
|
|
7100
|
+
* expression unchanged.
|
|
7101
|
+
*
|
|
7102
|
+
* The previous TS port wrapped every parenthesised expression in a
|
|
7103
|
+
* dedicated `GroupPattern` and applied quantifiers to bare primaries —
|
|
7104
|
+
* both broke `format(parse(s)) === s` round-tripping.
|
|
7105
|
+
*
|
|
7106
|
+
* @module envelope-pattern/parse/meta/group-parser
|
|
7107
|
+
*/
|
|
7108
|
+
function parseGroup(lexer) {
|
|
7109
|
+
const inner = parseOr(lexer);
|
|
7110
|
+
if (!inner.ok) return inner;
|
|
7111
|
+
const close = lexer.next();
|
|
7112
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7113
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7114
|
+
const next = lexer.peekToken();
|
|
7115
|
+
if (next === void 0) return inner;
|
|
7116
|
+
let quantifier;
|
|
7117
|
+
const tokenType = next.token.type;
|
|
7118
|
+
if (tokenType === "RepeatZeroOrMore") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Greedy);
|
|
7119
|
+
else if (tokenType === "RepeatZeroOrMoreLazy") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Lazy);
|
|
7120
|
+
else if (tokenType === "RepeatZeroOrMorePossessive") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Possessive);
|
|
7121
|
+
else if (tokenType === "RepeatOneOrMore") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Greedy);
|
|
7122
|
+
else if (tokenType === "RepeatOneOrMoreLazy") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Lazy);
|
|
7123
|
+
else if (tokenType === "RepeatOneOrMorePossessive") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Possessive);
|
|
7124
|
+
else if (tokenType === "RepeatZeroOrOne") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Greedy);
|
|
7125
|
+
else if (tokenType === "RepeatZeroOrOneLazy") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Lazy);
|
|
7126
|
+
else if (tokenType === "RepeatZeroOrOnePossessive") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Possessive);
|
|
7127
|
+
else if (tokenType === "Range") {
|
|
7128
|
+
if (!next.token.value.ok) return err(next.token.value.error);
|
|
7129
|
+
quantifier = next.token.value.value;
|
|
7130
|
+
} else return inner;
|
|
7131
|
+
lexer.next();
|
|
7132
|
+
return ok(repeat(inner.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
|
|
7133
|
+
}
|
|
7134
|
+
//#endregion
|
|
7135
|
+
//#region src/parse/meta/search-parser.ts
|
|
7136
|
+
/**
|
|
7137
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7138
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7139
|
+
*
|
|
7140
|
+
* Search parser — port of `bc-envelope-pattern-rust`
|
|
7141
|
+
* `parse/meta/search_parser.rs`.
|
|
7142
|
+
*
|
|
7143
|
+
* @module envelope-pattern/parse/meta/search-parser
|
|
7144
|
+
*/
|
|
7145
|
+
function parseSearch(lexer) {
|
|
7146
|
+
const open = lexer.next();
|
|
7147
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
7148
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
7149
|
+
const inner = parseOr(lexer);
|
|
7150
|
+
if (!inner.ok) return inner;
|
|
7151
|
+
const close = lexer.next();
|
|
7152
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7153
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7154
|
+
return ok(search(inner.value));
|
|
7155
|
+
}
|
|
7156
|
+
//#endregion
|
|
7157
|
+
//#region src/parse/meta/primary-parser.ts
|
|
7158
|
+
/**
|
|
7159
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7160
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7161
|
+
*
|
|
7162
|
+
* Primary parser — port of `bc-envelope-pattern-rust`
|
|
7163
|
+
* `parse/meta/primary_parser.rs`.
|
|
7164
|
+
*
|
|
7165
|
+
* Dispatches on the next token to the appropriate leaf/structure/meta
|
|
7166
|
+
* parser. When a `(` is encountered the open paren is consumed here and
|
|
7167
|
+
* `parse_group` handles the rest (paren'd expression + optional
|
|
7168
|
+
* quantifier suffix).
|
|
7169
|
+
*
|
|
7170
|
+
* @module envelope-pattern/parse/meta/primary-parser
|
|
7171
|
+
*/
|
|
7172
|
+
function parsePrimary(lexer) {
|
|
7173
|
+
const tokenResult = lexer.next();
|
|
7174
|
+
if (tokenResult === void 0) return err(unexpectedEndOfInput());
|
|
7175
|
+
const { token, span } = tokenResult;
|
|
7176
|
+
switch (token.type) {
|
|
7177
|
+
case "Search": return parseSearch(lexer);
|
|
7178
|
+
case "Node": return parseNode(lexer);
|
|
7179
|
+
case "Assertion": return parseAssertion(lexer);
|
|
7180
|
+
case "AssertionPred": return parseAssertionPred(lexer);
|
|
7181
|
+
case "AssertionObj": return parseAssertionObj(lexer);
|
|
7182
|
+
case "Digest": return parseDigest(lexer);
|
|
7183
|
+
case "Obj": return parseObject(lexer);
|
|
7184
|
+
case "Obscured": return parseObscured(lexer);
|
|
7185
|
+
case "Elided": return parseElided(lexer);
|
|
7186
|
+
case "Encrypted": return parseEncrypted(lexer);
|
|
7187
|
+
case "Compressed": return parseCompressed(lexer);
|
|
7188
|
+
case "Pred": return parsePredicate(lexer);
|
|
7189
|
+
case "Subject": return parseSubject(lexer);
|
|
7190
|
+
case "Wrapped": return parseWrapped(lexer);
|
|
7191
|
+
case "Unwrap": return parseUnwrap(lexer);
|
|
7192
|
+
case "Leaf": return ok(leaf());
|
|
7193
|
+
case "GroupName": return parseCapture(lexer, token.name);
|
|
7194
|
+
case "ParenOpen": return parseGroup(lexer);
|
|
7195
|
+
case "Cbor": return parseCbor(lexer);
|
|
7196
|
+
case "RepeatZeroOrMore": return ok(any());
|
|
7197
|
+
case "BoolKeyword": return ok(anyBool());
|
|
7198
|
+
case "BoolTrue": return ok(bool(true));
|
|
7199
|
+
case "BoolFalse": return ok(bool(false));
|
|
7200
|
+
case "NumberKeyword": return ok(anyNumber());
|
|
7201
|
+
case "TextKeyword": return ok(anyText());
|
|
7202
|
+
case "StringLiteral":
|
|
7203
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7204
|
+
return ok(text(token.value.value));
|
|
7205
|
+
case "UnsignedInteger":
|
|
7206
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7207
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7208
|
+
case "Integer":
|
|
7209
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7210
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7211
|
+
case "Float":
|
|
7212
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7213
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7214
|
+
case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
|
|
7215
|
+
case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
|
|
7216
|
+
case "GreaterThan": return parseComparisonNumber(lexer, ">");
|
|
7217
|
+
case "LessThan": return parseComparisonNumber(lexer, "<");
|
|
7218
|
+
case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
|
|
7219
|
+
case "Infinity": return ok(number(Infinity));
|
|
7220
|
+
case "NegativeInfinity": return ok(number(-Infinity));
|
|
7221
|
+
case "Regex":
|
|
7222
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7223
|
+
try {
|
|
7224
|
+
return ok(textRegex(new RegExp(token.value.value)));
|
|
7225
|
+
} catch {
|
|
7226
|
+
return err(invalidRegex(span));
|
|
7227
|
+
}
|
|
7228
|
+
case "BracketOpen": return parseArray(lexer);
|
|
7229
|
+
case "ByteString": return ok(anyByteString());
|
|
7230
|
+
case "HexPattern":
|
|
7231
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7232
|
+
return ok(byteString(token.value.value));
|
|
7233
|
+
case "HexBinaryRegex":
|
|
7234
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7235
|
+
try {
|
|
7236
|
+
return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
|
|
7237
|
+
} catch {
|
|
7238
|
+
return err(invalidRegex(span));
|
|
7239
|
+
}
|
|
7240
|
+
case "DateKeyword": return ok(anyDate());
|
|
7241
|
+
case "DatePattern":
|
|
7242
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7243
|
+
return parseDateContent(token.value.value, span);
|
|
7244
|
+
case "Tagged": return parseTag(lexer);
|
|
7245
|
+
case "Known": return ok(anyKnownValue());
|
|
7246
|
+
case "SingleQuotedPattern":
|
|
7247
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7248
|
+
return parseKnownValueContent(token.value.value);
|
|
7249
|
+
case "SingleQuotedRegex":
|
|
7250
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7251
|
+
try {
|
|
7252
|
+
return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
|
|
7253
|
+
} catch {
|
|
7254
|
+
return err(invalidRegex(span));
|
|
7255
|
+
}
|
|
7256
|
+
case "Null": return ok(nullPattern());
|
|
7257
|
+
case "Identifier": return err(unrecognizedToken(span));
|
|
7258
|
+
case "And":
|
|
7259
|
+
case "Or":
|
|
7260
|
+
case "Not":
|
|
7261
|
+
case "Traverse":
|
|
7262
|
+
case "RepeatZeroOrMoreLazy":
|
|
7263
|
+
case "RepeatZeroOrMorePossessive":
|
|
7264
|
+
case "RepeatOneOrMore":
|
|
7265
|
+
case "RepeatOneOrMoreLazy":
|
|
7266
|
+
case "RepeatOneOrMorePossessive":
|
|
7267
|
+
case "RepeatZeroOrOne":
|
|
7268
|
+
case "RepeatZeroOrOneLazy":
|
|
7269
|
+
case "RepeatZeroOrOnePossessive":
|
|
7270
|
+
case "ParenClose":
|
|
7271
|
+
case "BracketClose":
|
|
7272
|
+
case "Comma":
|
|
7273
|
+
case "Ellipsis":
|
|
7274
|
+
case "Range": return err(unexpectedToken(token, span));
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
//#endregion
|
|
7278
|
+
//#region src/parse/meta/and-parser.ts
|
|
7279
|
+
/**
|
|
7280
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7281
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7282
|
+
*
|
|
7283
|
+
* And parser — port of `bc-envelope-pattern-rust`
|
|
7284
|
+
* `parse/meta/and_parser.rs`.
|
|
7285
|
+
*
|
|
7286
|
+
* Mirrors Rust: `parse_and` calls `parse_primary` (NOT `parse_not`); `!`
|
|
7287
|
+
* is handled at a higher precedence level by `parse_not`.
|
|
7288
|
+
*
|
|
7289
|
+
* @module envelope-pattern/parse/meta/and-parser
|
|
7290
|
+
*/
|
|
7291
|
+
function parseAnd(lexer) {
|
|
7292
|
+
const patterns = [];
|
|
7293
|
+
const first = parsePrimary(lexer);
|
|
7294
|
+
if (!first.ok) return first;
|
|
7295
|
+
patterns.push(first.value);
|
|
7296
|
+
while (true) {
|
|
7297
|
+
if (lexer.peekToken()?.token.type !== "And") break;
|
|
7298
|
+
lexer.next();
|
|
7299
|
+
const nextExpr = parsePrimary(lexer);
|
|
7300
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7301
|
+
patterns.push(nextExpr.value);
|
|
7302
|
+
}
|
|
7303
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7304
|
+
return ok(and(patterns));
|
|
7305
|
+
}
|
|
7306
|
+
//#endregion
|
|
7307
|
+
//#region src/parse/meta/not-parser.ts
|
|
7308
|
+
/**
|
|
7309
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7310
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7311
|
+
*
|
|
7312
|
+
* Not parser — port of `bc-envelope-pattern-rust`
|
|
7313
|
+
* `parse/meta/not_parser.rs`.
|
|
7314
|
+
*
|
|
7315
|
+
* Mirrors Rust:
|
|
7316
|
+
* - On `!`, recurse into `parse_not` so chained negation parses as
|
|
7317
|
+
* `not(not(x))` rather than `not(group(x))`.
|
|
7318
|
+
* - Otherwise descend into `parse_and`.
|
|
7319
|
+
*
|
|
7320
|
+
* @module envelope-pattern/parse/meta/not-parser
|
|
7321
|
+
*/
|
|
7322
|
+
function parseNot(lexer) {
|
|
7323
|
+
if (lexer.peekToken()?.token.type === "Not") {
|
|
7324
|
+
lexer.next();
|
|
7325
|
+
const inner = parseNot(lexer);
|
|
7326
|
+
if (!inner.ok) return inner;
|
|
7327
|
+
return ok(notMatching(inner.value));
|
|
7328
|
+
}
|
|
7329
|
+
return parseAnd(lexer);
|
|
7330
|
+
}
|
|
7331
|
+
//#endregion
|
|
7332
|
+
//#region src/parse/meta/traverse-parser.ts
|
|
7333
|
+
/**
|
|
7334
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7335
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7336
|
+
*
|
|
7337
|
+
* Traverse parser — port of `bc-envelope-pattern-rust`
|
|
7338
|
+
* `parse/meta/traverse_parser.rs`.
|
|
7339
|
+
*
|
|
7340
|
+
* Note the precedence chain: `parse_or → parse_traverse → parse_not →
|
|
7341
|
+
* parse_and → parse_primary`. The earlier TS port had `parse_traverse`
|
|
7342
|
+
* call `parse_and` directly, which pushed `!` below `&` and
|
|
7343
|
+
* miscompiled `!a & b`.
|
|
7344
|
+
*
|
|
7345
|
+
* @module envelope-pattern/parse/meta/traverse-parser
|
|
7346
|
+
*/
|
|
7347
|
+
function parseTraverse(lexer) {
|
|
7348
|
+
const patterns = [];
|
|
7349
|
+
const first = parseNot(lexer);
|
|
7350
|
+
if (!first.ok) return first;
|
|
7351
|
+
patterns.push(first.value);
|
|
7352
|
+
while (true) {
|
|
7353
|
+
if (lexer.peekToken()?.token.type !== "Traverse") break;
|
|
7354
|
+
lexer.next();
|
|
7355
|
+
const nextExpr = parseNot(lexer);
|
|
7356
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7357
|
+
patterns.push(nextExpr.value);
|
|
7358
|
+
}
|
|
7359
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7360
|
+
return ok(traverse(patterns));
|
|
7361
|
+
}
|
|
7362
|
+
//#endregion
|
|
7363
|
+
//#region src/parse/meta/or-parser.ts
|
|
7364
|
+
/**
|
|
7365
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7366
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7367
|
+
*
|
|
7368
|
+
* Or parser — port of `bc-envelope-pattern-rust` `parse/meta/or_parser.rs`.
|
|
7369
|
+
*
|
|
7370
|
+
* @module envelope-pattern/parse/meta/or-parser
|
|
7371
|
+
*/
|
|
7372
|
+
function parseOr(lexer) {
|
|
7373
|
+
const patterns = [];
|
|
7374
|
+
const first = parseTraverse(lexer);
|
|
7375
|
+
if (!first.ok) return first;
|
|
7376
|
+
patterns.push(first.value);
|
|
7377
|
+
while (true) {
|
|
7378
|
+
if (lexer.peekToken()?.token.type !== "Or") break;
|
|
7379
|
+
lexer.next();
|
|
7380
|
+
const nextExpr = parseTraverse(lexer);
|
|
7381
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7382
|
+
patterns.push(nextExpr.value);
|
|
7383
|
+
}
|
|
7384
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7385
|
+
return ok(or(patterns));
|
|
7386
|
+
}
|
|
7387
|
+
//#endregion
|
|
7388
|
+
//#region src/parse/index.ts
|
|
7389
|
+
/**
|
|
7390
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7391
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7392
|
+
*
|
|
7393
|
+
*
|
|
7394
|
+
* @bcts/envelope-pattern - Parser entry point
|
|
7395
|
+
*
|
|
7396
|
+
* This is a 1:1 TypeScript port of bc-envelope-pattern-rust parse/mod.rs.
|
|
7397
|
+
*
|
|
7398
|
+
* Recursive-descent parser for the Gordian Envelope pattern syntax. The
|
|
7399
|
+
* parsing rules live under `parse/leaf/`, `parse/meta/`, and
|
|
7400
|
+
* `parse/structure/`, mirroring the Rust crate's module layout.
|
|
7401
|
+
*
|
|
7402
|
+
* @module envelope-pattern/parse
|
|
7403
|
+
*/
|
|
7404
|
+
/**
|
|
7405
|
+
* Parse a pattern expression string into a Pattern.
|
|
7406
|
+
*
|
|
7407
|
+
* Mirrors Rust `Pattern::parse`: tries envelope-pattern parsing first;
|
|
7408
|
+
* on failure falls back to dcbor-pattern parsing and converts the
|
|
7409
|
+
* result into an envelope pattern via the
|
|
7410
|
+
* `dcbor_integration::convert_dcbor_pattern_to_envelope_pattern` bridge.
|
|
7411
|
+
*/
|
|
7412
|
+
function parse(input) {
|
|
7413
|
+
const lexer = new Lexer(input);
|
|
7414
|
+
const result = parseOr(lexer);
|
|
7415
|
+
if (!result.ok) {
|
|
7416
|
+
const dcborResult = parse$1(input);
|
|
7417
|
+
if (dcborResult.ok) return convertDcborPatternToEnvelopePattern(dcborResult.value);
|
|
7418
|
+
return result;
|
|
7419
|
+
}
|
|
7420
|
+
const next = lexer.next();
|
|
7421
|
+
if (next !== void 0) return err(extraData(next.span));
|
|
7422
|
+
return result;
|
|
7423
|
+
}
|
|
7424
|
+
/**
|
|
7425
|
+
* Parse a pattern, allowing extra data after the pattern.
|
|
7426
|
+
*
|
|
7427
|
+
* Returns the parsed pattern and the byte offset at which parsing
|
|
7428
|
+
* stopped, mirroring `Pattern::parse_partial` in spirit.
|
|
7429
|
+
*/
|
|
7430
|
+
function parsePartial(input) {
|
|
7431
|
+
const lexer = new Lexer(input);
|
|
7432
|
+
const result = parseOr(lexer);
|
|
7433
|
+
if (!result.ok) return result;
|
|
7434
|
+
return ok([result.value, lexer.position]);
|
|
7435
|
+
}
|
|
6974
7436
|
//#endregion
|
|
6975
7437
|
//#region src/index.ts
|
|
6976
7438
|
/**
|
|
6977
7439
|
* Package version.
|
|
6978
7440
|
*/
|
|
6979
7441
|
const VERSION = "1.0.0-alpha.11";
|
|
6980
|
-
|
|
6981
7442
|
//#endregion
|
|
6982
|
-
export { AndPattern, AnyPattern, ArrayPattern, AssertionsPattern, BoolPattern, ByteStringPattern, CBORPattern, CapturePattern, DatePattern, DigestPattern, FormatPathsOptsBuilder, GroupPattern, Interval, KnownValuePattern, LeafStructurePattern, Lexer, MapPattern, MatcherDefaults, NodePattern, NotPattern, NullPattern, NumberPattern, ObjectPattern, ObscuredPattern, OrPattern, PredicatePattern, Quantifier, Reluctance, SearchPattern, SubjectPattern, TaggedPattern, TextPattern, TraversePattern, VERSION, WrappedPattern, and, any, anyArray, anyAssertion, anyBool, anyByteString, anyCbor, anyDate, anyKnownValue, anyMap, anyNode, anyNumber, anyObject, anyPredicate, anySubject, anyTag, anyText, assertionWithObject, assertionWithPredicate, axisChildren, bool, byteString, capture, cborPattern, cborValue, compile, compileAsAtomic, compressed, convertDcborPatternToEnvelopePattern, date, dateEarliest, dateLatest, dateRange, dateRegex, dcborPatternError, defaultFormatPathsOpts, defaultPathElementFormat, digest, digestPrefix, digestURFormat, dispatchCompile, dispatchIsComplex, dispatchPaths, dispatchPathsWithCaptures, dispatchPatternToString, elided, emptyInput, encrypted, envelopeSummary, envelopeURFormat, err, expectedCloseBracket, expectedCloseParen, expectedOpenBracket, expectedOpenParen, expectedPattern, extraData, formatError, formatPath, formatPathOpt, formatPaths, formatPathsOpt, formatPathsOpts, formatPathsWithCaptures, formatPathsWithCapturesOpt, group, invalidCaptureGroupName, invalidDateFormat, invalidHexString, invalidNumberFormat, invalidPattern, invalidRange, invalidRegex, invalidUr, isErr, isOk, knownValue, leaf, leafArray, leafBool, leafByteString, leafCbor, leafDate, leafKnownValue, leafMap, leafNull, leafNumber, leafPatternCompile, leafPatternIsComplex, leafPatternPaths, leafPatternPathsWithCaptures, leafPatternToString, leafTag, leafText, map, matchPattern, metaAnd, metaAny, metaCapture, metaGroup, metaNot, metaOr, metaPatternCollectCaptureNames, metaPatternCompile, metaPatternIsComplex, metaPatternPathsWithCaptures, metaPatternToString, metaSearch, metaTraverse, notMatching, nullPattern, number, numberGreaterThan, numberLessThan, numberRange, object, obscured, ok, or, parse, parsePartial, patternCollectCaptureNames, patternCompile, patternIsComplex, patternLeaf, patternMatches, patternMeta, patternPaths, patternPathsWithCaptures, patternStructure, patternToString, predicate, registerAndPatternFactory, registerAnyPatternFactory, registerArrayPatternFactory, registerAssertionsPatternFactory, registerBoolPatternFactory, registerByteStringPatternFactory, registerCBORPatternFactory, registerCapturePatternFactory, registerDatePatternFactory, registerDigestPatternFactory, registerGroupPatternFactory, registerKnownValuePatternFactory, registerLeafStructurePatternFactory, registerMapPatternFactory, registerNodePatternFactory, registerNotPatternFactory, registerNullPatternFactory, registerNumberPatternFactory, registerObjectPatternFactory, registerObscuredPatternFactory, registerOrPatternFactory, registerPatternDispatchFns, registerPatternMatchFn, registerPredicatePatternFactory, registerSearchPatternFactory, registerSubjectPatternFactory, registerTaggedPatternFactory, registerTextPatternFactory, registerTraversePatternFactory, registerVMPatternFunctions, registerWrappedPatternDispatch, registerWrappedPatternFactory, repeat, run, search, structureAssertions, structureDigest, structureLeaf, structureNode, structureObject, structureObscured, structurePatternCompile, structurePatternIsComplex, structurePatternPaths, structurePatternPathsWithCaptures, structurePatternToString, structurePredicate, structureSubject, structureWrapped, subject, summaryFormat, tagged, text, textRegex, traverse, unexpectedEndOfInput, unexpectedToken, unit, unknown, unmatchedBraces, unmatchedParentheses, unrecognizedToken, unterminatedRegex, unwrap, unwrapEnvelope, unwrapMatching, unwrapOr, wrapped };
|
|
7443
|
+
export { AndPattern, AnyPattern, ArrayPattern, AssertionsPattern, BoolPattern, ByteStringPattern, CBORPattern, CapturePattern, DatePattern, DigestPattern, FormatPathsOptsBuilder, GroupPattern, Interval, KnownValuePattern, LeafStructurePattern, Lexer, MapPattern, MatcherDefaults, NodePattern, NotPattern, NullPattern, NumberPattern, ObjectPattern, ObscuredPattern, OrPattern, PredicatePattern, Quantifier, Reluctance, SearchPattern, SubjectPattern, TaggedPattern, TextPattern, TraversePattern, VERSION, WrappedPattern, and, any, anyArray, anyAssertion, anyBool, anyByteString, anyCbor, anyDate, anyKnownValue, anyMap, anyNode, anyNumber, anyObject, anyPredicate, anySubject, anyTag, anyText, assertionWithObject, assertionWithPredicate, axisChildren, bool, byteString, capture, cborPattern, cborValue, compile, compileAsAtomic, compressed, convertDcborPatternToEnvelopePattern, date, dateEarliest, dateLatest, dateRange, dateRegex, dcborPatternError, defaultFormatPathsOpts, defaultPathElementFormat, digest, digestPrefix, digestURFormat, dispatchCompile, dispatchIsComplex, dispatchPaths, dispatchPathsWithCaptures, dispatchPatternToString, elided, emptyInput, encrypted, envelopeSummary, envelopeURFormat, err, expectedCloseBracket, expectedCloseParen, expectedOpenBracket, expectedOpenParen, expectedPattern, extraData, formatError, formatPath, formatPathOpt, formatPaths, formatPathsOpt, formatPathsOpts, formatPathsWithCaptures, formatPathsWithCapturesOpt, group, invalidCaptureGroupName, invalidDateFormat, invalidHexString, invalidNumberFormat, invalidPattern, invalidRange, invalidRegex, invalidUr, isErr, isOk, knownValue, leaf, leafArray, leafBool, leafByteString, leafCbor, leafDate, leafKnownValue, leafMap, leafNull, leafNumber, leafPatternCompile, leafPatternIsComplex, leafPatternPaths, leafPatternPathsWithCaptures, leafPatternToString, leafTag, leafText, map, matchPattern, metaAnd, metaAny, metaCapture, metaGroup, metaNot, metaOr, metaPatternCollectCaptureNames, metaPatternCompile, metaPatternIsComplex, metaPatternPathsWithCaptures, metaPatternToString, metaSearch, metaTraverse, notMatching, nullPattern, number, numberGreaterThan, numberLessThan, numberRange, object, obscured, ok, or, parse, parsePartial, patternCollectCaptureNames, patternCompile, patternIsComplex, patternLeaf, patternMatches, patternMeta, patternPaths, patternPathsWithCaptures, patternStructure, patternToString, predicate, registerAndPatternFactory, registerAnyPatternFactory, registerArrayPatternFactory, registerAssertionsPatternFactory, registerAssertionsPatternToStringDispatch, registerBoolPatternFactory, registerByteStringPatternFactory, registerCBORPatternFactory, registerCapturePatternFactory, registerDatePatternFactory, registerDigestPatternFactory, registerGroupPatternFactory, registerKnownValuePatternFactory, registerLeafStructurePatternFactory, registerMapPatternFactory, registerNodePatternFactory, registerNotPatternFactory, registerNullPatternFactory, registerNumberPatternFactory, registerObjectPatternFactory, registerObscuredPatternFactory, registerOrPatternFactory, registerPatternDispatchFns, registerPatternMatchFn, registerPredicatePatternFactory, registerSearchPatternFactory, registerSubjectPatternDispatch, registerSubjectPatternFactory, registerTaggedPatternFactory, registerTextPatternFactory, registerTraversePatternFactory, registerVMPatternFunctions, registerWrappedPatternAny, registerWrappedPatternDispatch, registerWrappedPatternFactory, repeat, run, search, structureAssertions, structureDigest, structureLeaf, structureNode, structureObject, structureObscured, structurePatternCompile, structurePatternIsComplex, structurePatternPaths, structurePatternPathsWithCaptures, structurePatternToString, structurePredicate, structureSubject, structureWrapped, subject, summaryFormat, tagged, text, textRegex, traverse, unexpectedEndOfInput, unexpectedToken, unit, unknown, unmatchedBraces, unmatchedParentheses, unrecognizedToken, unterminatedRegex, unwrap, unwrapEnvelope, unwrapMatching, unwrapOr, wrapped };
|
|
7444
|
+
|
|
6983
7445
|
//# sourceMappingURL=index.mjs.map
|