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