@bcts/envelope-pattern 1.0.0-alpha.23 → 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 +1302 -766
- 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 +1299 -763
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +1299 -766
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -6
- package/src/format.ts +19 -31
- package/src/parse/index.ts +16 -1009
- 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.iife.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_values,
|
|
1
|
+
var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_values, _bcts_dcbor, _bcts_envelope, _bcts_dcbor_parse) {
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
//#region src/error.ts
|
|
4
4
|
/**
|
|
@@ -302,6 +302,14 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
302
302
|
/**
|
|
303
303
|
* Gets a summary of an envelope for display.
|
|
304
304
|
*
|
|
305
|
+
* Mirrors Rust `envelope_summary` in `format.rs`: defers to
|
|
306
|
+
* `Envelope::format_flat()` for nodes / wrapped / assertions and to
|
|
307
|
+
* `cbor.envelope_summary(usize::MAX, ...)` for raw CBOR leaves. The
|
|
308
|
+
* obscured cases (`elided` / `encrypted` / `compressed`) emit just the
|
|
309
|
+
* keyword. KnownValue envelopes look up the canonical name via
|
|
310
|
+
* `KnownValue.name()`, matching the Rust call to
|
|
311
|
+
* `KnownValuesStore::known_value_for_raw_value(value, …)`.
|
|
312
|
+
*
|
|
305
313
|
* @param env - The envelope to summarize
|
|
306
314
|
* @returns A string summary of the envelope
|
|
307
315
|
*/
|
|
@@ -310,25 +318,17 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
310
318
|
const c = env.case();
|
|
311
319
|
let summary;
|
|
312
320
|
switch (c.type) {
|
|
313
|
-
case "node":
|
|
314
|
-
|
|
315
|
-
const assertions = env.assertions();
|
|
316
|
-
if (assertions.length > 0) summary = `NODE ${subjectSummary} [ ${assertions.map((a) => {
|
|
317
|
-
const ac = a.case();
|
|
318
|
-
if (ac.type === "assertion") return `${ac.assertion.predicate().summary(Number.MAX_SAFE_INTEGER)}: ${ac.assertion.object().summary(Number.MAX_SAFE_INTEGER)}`;
|
|
319
|
-
return a.summary(Number.MAX_SAFE_INTEGER);
|
|
320
|
-
}).join(", ")} ]`;
|
|
321
|
-
else summary = `NODE ${subjectSummary}`;
|
|
321
|
+
case "node":
|
|
322
|
+
summary = `NODE ${env.formatFlat()}`;
|
|
322
323
|
break;
|
|
323
|
-
}
|
|
324
324
|
case "leaf":
|
|
325
325
|
summary = `LEAF ${env.summary(Number.MAX_SAFE_INTEGER)}`;
|
|
326
326
|
break;
|
|
327
327
|
case "wrapped":
|
|
328
|
-
summary = `WRAPPED ${env.
|
|
328
|
+
summary = `WRAPPED ${env.formatFlat()}`;
|
|
329
329
|
break;
|
|
330
330
|
case "assertion":
|
|
331
|
-
summary = `ASSERTION ${
|
|
331
|
+
summary = `ASSERTION ${env.formatFlat()}`;
|
|
332
332
|
break;
|
|
333
333
|
case "elided":
|
|
334
334
|
summary = "ELIDED";
|
|
@@ -374,8 +374,8 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
374
374
|
if (element === void 0) return "";
|
|
375
375
|
switch (opts.elementFormat.type) {
|
|
376
376
|
case "Summary": return truncateWithEllipsis(envelopeSummary(element), opts.elementFormat.maxLength);
|
|
377
|
-
case "EnvelopeUR": return element.
|
|
378
|
-
case "DigestUR": return element.digest().
|
|
377
|
+
case "EnvelopeUR": return element.urString();
|
|
378
|
+
case "DigestUR": return element.digest().urString();
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
switch (opts.elementFormat.type) {
|
|
@@ -390,8 +390,8 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
390
390
|
}
|
|
391
391
|
return lines.join("\n");
|
|
392
392
|
}
|
|
393
|
-
case "EnvelopeUR": return path.map((element) => element.
|
|
394
|
-
case "DigestUR": return path.map((element) => element.digest().
|
|
393
|
+
case "EnvelopeUR": return path.map((element) => element.urString()).join(" ");
|
|
394
|
+
case "DigestUR": return path.map((element) => element.digest().urString()).join(" ");
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
397
|
/**
|
|
@@ -1233,25 +1233,16 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1233
1233
|
};
|
|
1234
1234
|
//#endregion
|
|
1235
1235
|
//#region src/pattern/leaf/array-pattern.ts
|
|
1236
|
-
/**
|
|
1237
|
-
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
1238
|
-
* Copyright © 2025-2026 Parity Technologies
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
* @bcts/envelope-pattern - Array pattern matching
|
|
1242
|
-
*
|
|
1243
|
-
* This is a 1:1 TypeScript port of bc-envelope-pattern-rust array_pattern.rs
|
|
1244
|
-
*
|
|
1245
|
-
* @module envelope-pattern/pattern/leaf/array-pattern
|
|
1246
|
-
*/
|
|
1247
1236
|
let createLeafArrayPattern;
|
|
1248
1237
|
function registerArrayPatternFactory(factory) {
|
|
1249
1238
|
createLeafArrayPattern = factory;
|
|
1250
1239
|
}
|
|
1251
1240
|
/**
|
|
1252
|
-
* Pattern for matching
|
|
1241
|
+
* Pattern for matching arrays.
|
|
1253
1242
|
*
|
|
1254
|
-
*
|
|
1243
|
+
* Mirrors Rust `ArrayPattern(dcbor_pattern::ArrayPattern)` from
|
|
1244
|
+
* `bc-envelope-pattern-rust/src/pattern/leaf/array_pattern.rs`. All
|
|
1245
|
+
* matching, display, and equality is delegated to dcbor-pattern.
|
|
1255
1246
|
*/
|
|
1256
1247
|
var ArrayPattern = class ArrayPattern {
|
|
1257
1248
|
_pattern;
|
|
@@ -1262,93 +1253,54 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1262
1253
|
* Creates a new ArrayPattern that matches any array.
|
|
1263
1254
|
*/
|
|
1264
1255
|
static any() {
|
|
1265
|
-
return new ArrayPattern(
|
|
1256
|
+
return new ArrayPattern((0, _bcts_dcbor_pattern.arrayPatternAny)());
|
|
1266
1257
|
}
|
|
1267
1258
|
/**
|
|
1268
1259
|
* Creates a new ArrayPattern that matches arrays with a specific length.
|
|
1269
1260
|
*/
|
|
1270
1261
|
static count(count) {
|
|
1271
|
-
return new ArrayPattern(
|
|
1272
|
-
type: "Interval",
|
|
1273
|
-
interval: _bcts_dcbor_pattern.Interval.exactly(count)
|
|
1274
|
-
});
|
|
1262
|
+
return new ArrayPattern((0, _bcts_dcbor_pattern.arrayPatternWithLength)(count));
|
|
1275
1263
|
}
|
|
1276
1264
|
/**
|
|
1277
1265
|
* Creates a new ArrayPattern that matches arrays within a length range.
|
|
1278
1266
|
*/
|
|
1279
1267
|
static interval(min, max) {
|
|
1280
|
-
return new ArrayPattern(
|
|
1281
|
-
type: "Interval",
|
|
1282
|
-
interval: max !== void 0 ? _bcts_dcbor_pattern.Interval.from(min, max) : _bcts_dcbor_pattern.Interval.atLeast(min)
|
|
1283
|
-
});
|
|
1268
|
+
return new ArrayPattern((0, _bcts_dcbor_pattern.arrayPatternWithLengthRange)(min, max));
|
|
1284
1269
|
}
|
|
1285
1270
|
/**
|
|
1286
|
-
* Creates a new ArrayPattern from a
|
|
1271
|
+
* Creates a new ArrayPattern from a length Interval.
|
|
1287
1272
|
*/
|
|
1288
|
-
static
|
|
1289
|
-
return new ArrayPattern(
|
|
1290
|
-
type: "DCBORPattern",
|
|
1291
|
-
pattern: dcborPattern
|
|
1292
|
-
});
|
|
1273
|
+
static fromInterval(interval) {
|
|
1274
|
+
return new ArrayPattern((0, _bcts_dcbor_pattern.arrayPatternWithLengthInterval)(interval));
|
|
1293
1275
|
}
|
|
1294
1276
|
/**
|
|
1295
|
-
* Creates a new ArrayPattern
|
|
1277
|
+
* Creates a new ArrayPattern from a top-level dcbor-pattern.
|
|
1278
|
+
*
|
|
1279
|
+
* Mirrors Rust `ArrayPattern::from_dcbor_pattern`, which constructs an
|
|
1280
|
+
* `ArrayPattern::Elements`-style dcbor array pattern.
|
|
1296
1281
|
*/
|
|
1297
|
-
static
|
|
1298
|
-
return new ArrayPattern(
|
|
1299
|
-
type: "WithPatterns",
|
|
1300
|
-
patterns
|
|
1301
|
-
});
|
|
1282
|
+
static fromDcborPattern(pattern) {
|
|
1283
|
+
return new ArrayPattern((0, _bcts_dcbor_pattern.arrayPatternWithElements)(pattern));
|
|
1302
1284
|
}
|
|
1303
1285
|
/**
|
|
1304
|
-
*
|
|
1286
|
+
* Creates a new ArrayPattern from an existing dcbor-pattern ArrayPattern.
|
|
1287
|
+
*
|
|
1288
|
+
* Mirrors Rust `ArrayPattern::from_dcbor_array_pattern`.
|
|
1305
1289
|
*/
|
|
1306
|
-
|
|
1290
|
+
static fromDcborArrayPattern(arrayPattern) {
|
|
1291
|
+
return new ArrayPattern(arrayPattern);
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Returns the underlying dcbor-pattern ArrayPattern.
|
|
1295
|
+
*/
|
|
1296
|
+
inner() {
|
|
1307
1297
|
return this._pattern;
|
|
1308
1298
|
}
|
|
1309
1299
|
pathsWithCaptures(haystack) {
|
|
1310
1300
|
const cbor = haystack.subject().asLeaf();
|
|
1311
1301
|
if (cbor === void 0) return [[], /* @__PURE__ */ new Map()];
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
switch (this._pattern.type) {
|
|
1315
|
-
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1316
|
-
case "Interval": {
|
|
1317
|
-
const length = array.length;
|
|
1318
|
-
if (this._pattern.interval.contains(length)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1319
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1320
|
-
}
|
|
1321
|
-
case "DCBORPattern": {
|
|
1322
|
-
const { paths: dcborPaths, captures: dcborCaptures } = (0, _bcts_dcbor_pattern.patternPathsWithCaptures)(this._pattern.pattern, cbor);
|
|
1323
|
-
if (dcborPaths.length > 0) {
|
|
1324
|
-
const envelopePaths = dcborPaths.map((dcborPath) => {
|
|
1325
|
-
const envPath = [haystack];
|
|
1326
|
-
for (let i = 1; i < dcborPath.length; i++) {
|
|
1327
|
-
const elem = dcborPath[i];
|
|
1328
|
-
if (elem !== void 0) envPath.push(_bcts_envelope.Envelope.newLeaf(elem));
|
|
1329
|
-
}
|
|
1330
|
-
return envPath;
|
|
1331
|
-
});
|
|
1332
|
-
const envelopeCaptures = /* @__PURE__ */ new Map();
|
|
1333
|
-
for (const [name, capturePaths] of dcborCaptures) {
|
|
1334
|
-
const envCapturePaths = capturePaths.map((dcborPath) => {
|
|
1335
|
-
const envPath = [haystack];
|
|
1336
|
-
for (let i = 1; i < dcborPath.length; i++) {
|
|
1337
|
-
const elem = dcborPath[i];
|
|
1338
|
-
if (elem !== void 0) envPath.push(_bcts_envelope.Envelope.newLeaf(elem));
|
|
1339
|
-
}
|
|
1340
|
-
return envPath;
|
|
1341
|
-
});
|
|
1342
|
-
envelopeCaptures.set(name, envCapturePaths);
|
|
1343
|
-
}
|
|
1344
|
-
return [envelopePaths, envelopeCaptures];
|
|
1345
|
-
}
|
|
1346
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1347
|
-
}
|
|
1348
|
-
case "WithPatterns":
|
|
1349
|
-
if (array.length === this._pattern.patterns.length) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1350
|
-
return [[], /* @__PURE__ */ new Map()];
|
|
1351
|
-
}
|
|
1302
|
+
if ((0, _bcts_dcbor_pattern.arrayPatternMatches)(this._pattern, cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1303
|
+
return [[], /* @__PURE__ */ new Map()];
|
|
1352
1304
|
}
|
|
1353
1305
|
paths(haystack) {
|
|
1354
1306
|
return this.pathsWithCaptures(haystack)[0];
|
|
@@ -1364,54 +1316,31 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1364
1316
|
return false;
|
|
1365
1317
|
}
|
|
1366
1318
|
toString() {
|
|
1367
|
-
|
|
1368
|
-
case "Any": return "[*]";
|
|
1369
|
-
case "Interval": return `[{${this._pattern.interval.toString()}}]`;
|
|
1370
|
-
case "DCBORPattern": return (0, _bcts_dcbor_pattern.patternDisplay)(this._pattern.pattern);
|
|
1371
|
-
case "WithPatterns": return `[${this._pattern.patterns.map(String).join(", ")}]`;
|
|
1372
|
-
}
|
|
1319
|
+
return (0, _bcts_dcbor_pattern.arrayPatternDisplay)(this._pattern, _bcts_dcbor_pattern.patternDisplay);
|
|
1373
1320
|
}
|
|
1374
1321
|
/**
|
|
1375
|
-
* Equality comparison.
|
|
1322
|
+
* Equality comparison. Delegates to dcbor-pattern's structural equality
|
|
1323
|
+
* with a display-string fallback for pattern-equality (mirrors Rust's
|
|
1324
|
+
* `Hash` impl that hashes the display, since dcbor `ArrayPattern`
|
|
1325
|
+
* itself does not derive `Hash`).
|
|
1376
1326
|
*/
|
|
1377
1327
|
equals(other) {
|
|
1378
|
-
|
|
1379
|
-
switch (this._pattern.type) {
|
|
1380
|
-
case "Any": return true;
|
|
1381
|
-
case "Interval": return this._pattern.interval.equals(other._pattern.interval);
|
|
1382
|
-
case "DCBORPattern": return (0, _bcts_dcbor_pattern.patternDisplay)(this._pattern.pattern) === (0, _bcts_dcbor_pattern.patternDisplay)(other._pattern.pattern);
|
|
1383
|
-
case "WithPatterns": {
|
|
1384
|
-
const otherPatterns = other._pattern.patterns;
|
|
1385
|
-
if (this._pattern.patterns.length !== otherPatterns.length) return false;
|
|
1386
|
-
for (let i = 0; i < this._pattern.patterns.length; i++) if (this._pattern.patterns[i] !== otherPatterns[i]) return false;
|
|
1387
|
-
return true;
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1328
|
+
return (0, _bcts_dcbor_pattern.arrayPatternEquals)(this._pattern, other._pattern, (a, b) => (0, _bcts_dcbor_pattern.patternDisplay)(a) === (0, _bcts_dcbor_pattern.patternDisplay)(b));
|
|
1390
1329
|
}
|
|
1391
1330
|
/**
|
|
1392
|
-
* Hash code for use in Maps/Sets.
|
|
1331
|
+
* Hash code for use in Maps/Sets. Mirrors Rust's
|
|
1332
|
+
* "hash the string representation" approach.
|
|
1393
1333
|
*/
|
|
1394
1334
|
hashCode() {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1335
|
+
let hash = 0;
|
|
1336
|
+
const str = this.toString();
|
|
1337
|
+
for (let i = 0; i < str.length; i++) {
|
|
1338
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
1339
|
+
hash = hash & hash;
|
|
1400
1340
|
}
|
|
1341
|
+
return hash;
|
|
1401
1342
|
}
|
|
1402
1343
|
};
|
|
1403
|
-
/**
|
|
1404
|
-
* Simple string hash function for hashCode implementations.
|
|
1405
|
-
*/
|
|
1406
|
-
function simpleStringHash$3(str) {
|
|
1407
|
-
let hash = 0;
|
|
1408
|
-
for (let i = 0; i < str.length; i++) {
|
|
1409
|
-
const char = str.charCodeAt(i);
|
|
1410
|
-
hash = (hash << 5) - hash + char;
|
|
1411
|
-
hash = hash & hash;
|
|
1412
|
-
}
|
|
1413
|
-
return hash;
|
|
1414
|
-
}
|
|
1415
1344
|
//#endregion
|
|
1416
1345
|
//#region src/pattern/leaf/map-pattern.ts
|
|
1417
1346
|
let createLeafMapPattern;
|
|
@@ -1444,6 +1373,19 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1444
1373
|
});
|
|
1445
1374
|
}
|
|
1446
1375
|
/**
|
|
1376
|
+
* Creates a new MapPattern from a length Interval.
|
|
1377
|
+
*
|
|
1378
|
+
* Mirrors Rust `MapPattern::from_interval`. Used by the
|
|
1379
|
+
* dcbor-pattern → envelope-pattern bridge to preserve `{{n,m}}`
|
|
1380
|
+
* length info.
|
|
1381
|
+
*/
|
|
1382
|
+
static fromInterval(interval) {
|
|
1383
|
+
return new MapPattern({
|
|
1384
|
+
type: "Interval",
|
|
1385
|
+
interval
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1447
1389
|
* Gets the pattern type.
|
|
1448
1390
|
*/
|
|
1449
1391
|
get pattern() {
|
|
@@ -1478,8 +1420,8 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1478
1420
|
}
|
|
1479
1421
|
toString() {
|
|
1480
1422
|
switch (this._pattern.type) {
|
|
1481
|
-
case "Any": return "
|
|
1482
|
-
case "Interval": return `{
|
|
1423
|
+
case "Any": return "map";
|
|
1424
|
+
case "Interval": return `{${this._pattern.interval.toString()}}`;
|
|
1483
1425
|
}
|
|
1484
1426
|
}
|
|
1485
1427
|
/**
|
|
@@ -1732,7 +1674,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1732
1674
|
return false;
|
|
1733
1675
|
}
|
|
1734
1676
|
toString() {
|
|
1735
|
-
return (0, _bcts_dcbor_pattern.taggedPatternDisplay)(this._inner, _bcts_dcbor_pattern.patternDisplay);
|
|
1677
|
+
return (0, _bcts_dcbor_pattern.taggedPatternDisplay)(this._inner, _bcts_dcbor_pattern.patternDisplay).replace(", ", ", ");
|
|
1736
1678
|
}
|
|
1737
1679
|
/**
|
|
1738
1680
|
* Equality comparison.
|
|
@@ -1858,10 +1800,18 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1858
1800
|
}
|
|
1859
1801
|
/**
|
|
1860
1802
|
* Convert a single dcbor path to an envelope path.
|
|
1803
|
+
*
|
|
1804
|
+
* Uses canonical CBOR-byte equality (`cborEquals`) for the "skip the
|
|
1805
|
+
* dcbor root if it duplicates our base envelope" check, mirroring
|
|
1806
|
+
* Rust's `dcbor_path.first().map(|first| first == &base_cbor)`. The
|
|
1807
|
+
* earlier port compared diagnostic strings, which collapses values
|
|
1808
|
+
* that share a textual representation but differ structurally
|
|
1809
|
+
* (e.g. NaN payloads).
|
|
1861
1810
|
*/
|
|
1862
1811
|
_convertDcborPathToEnvelopePath(dcborPath, baseEnvelope, baseCbor) {
|
|
1863
1812
|
const envelopePath = [baseEnvelope];
|
|
1864
|
-
const
|
|
1813
|
+
const first = dcborPath[0];
|
|
1814
|
+
const elementsToAdd = first !== void 0 && (0, _bcts_dcbor.cborEquals)(first, baseCbor) ? dcborPath.slice(1) : dcborPath;
|
|
1865
1815
|
for (const cborElement of elementsToAdd) envelopePath.push(_bcts_envelope.Envelope.newLeaf(cborElement));
|
|
1866
1816
|
return envelopePath;
|
|
1867
1817
|
}
|
|
@@ -1888,7 +1838,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1888
1838
|
switch (this._pattern.type) {
|
|
1889
1839
|
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1890
1840
|
case "Value":
|
|
1891
|
-
if (
|
|
1841
|
+
if ((0, _bcts_dcbor.cborEquals)(knownValueCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1892
1842
|
return [[], /* @__PURE__ */ new Map()];
|
|
1893
1843
|
case "Pattern": {
|
|
1894
1844
|
const { paths: dcborPaths, captures: dcborCaptures } = (0, _bcts_dcbor_pattern.patternPathsWithCaptures)(this._pattern.pattern, knownValueCbor);
|
|
@@ -1912,7 +1862,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1912
1862
|
switch (this._pattern.type) {
|
|
1913
1863
|
case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1914
1864
|
case "Value":
|
|
1915
|
-
if (
|
|
1865
|
+
if ((0, _bcts_dcbor.cborEquals)(leafCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
|
|
1916
1866
|
return [[], /* @__PURE__ */ new Map()];
|
|
1917
1867
|
case "Pattern": {
|
|
1918
1868
|
const { paths: dcborPaths, captures: dcborCaptures } = (0, _bcts_dcbor_pattern.patternPathsWithCaptures)(this._pattern.pattern, leafCbor);
|
|
@@ -1920,7 +1870,8 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1920
1870
|
const basePath = [haystack];
|
|
1921
1871
|
return [dcborPaths.map((dcborPath) => {
|
|
1922
1872
|
const extendedPath = [...basePath];
|
|
1923
|
-
const
|
|
1873
|
+
const first = dcborPath[0];
|
|
1874
|
+
const elementsToAdd = first !== void 0 && (0, _bcts_dcbor.cborEquals)(first, leafCbor) ? dcborPath.slice(1) : dcborPath;
|
|
1924
1875
|
for (const cborElement of elementsToAdd) extendedPath.push(_bcts_envelope.Envelope.newLeaf(cborElement));
|
|
1925
1876
|
return extendedPath;
|
|
1926
1877
|
}), this._convertDcborCapturesToEnvelopeCaptures(dcborCaptures, haystack, leafCbor)];
|
|
@@ -1955,13 +1906,16 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1955
1906
|
}
|
|
1956
1907
|
}
|
|
1957
1908
|
/**
|
|
1958
|
-
* Equality comparison.
|
|
1909
|
+
* Equality comparison. `Value` variants compare by canonical CBOR
|
|
1910
|
+
* byte sequence (mirrors Rust `==` on `CBOR`); `Pattern` variants fall
|
|
1911
|
+
* back to display-string compare since `DCBORPattern` doesn't expose
|
|
1912
|
+
* structural equality outside the crate.
|
|
1959
1913
|
*/
|
|
1960
1914
|
equals(other) {
|
|
1961
1915
|
if (this._pattern.type !== other._pattern.type) return false;
|
|
1962
1916
|
switch (this._pattern.type) {
|
|
1963
1917
|
case "Any": return true;
|
|
1964
|
-
case "Value": return this._pattern.cbor
|
|
1918
|
+
case "Value": return (0, _bcts_dcbor.cborEquals)(this._pattern.cbor, other._pattern.cbor);
|
|
1965
1919
|
case "Pattern": return (0, _bcts_dcbor_pattern.patternDisplay)(this._pattern.pattern) === (0, _bcts_dcbor_pattern.patternDisplay)(other._pattern.pattern);
|
|
1966
1920
|
}
|
|
1967
1921
|
}
|
|
@@ -1971,7 +1925,12 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
1971
1925
|
hashCode() {
|
|
1972
1926
|
switch (this._pattern.type) {
|
|
1973
1927
|
case "Any": return 0;
|
|
1974
|
-
case "Value":
|
|
1928
|
+
case "Value": {
|
|
1929
|
+
const bytes = (0, _bcts_dcbor.cborData)(this._pattern.cbor);
|
|
1930
|
+
let hash = 0;
|
|
1931
|
+
for (const byte of bytes) hash = hash * 31 + byte | 0;
|
|
1932
|
+
return hash;
|
|
1933
|
+
}
|
|
1975
1934
|
case "Pattern": return simpleStringHash((0, _bcts_dcbor_pattern.patternDisplay)(this._pattern.pattern));
|
|
1976
1935
|
}
|
|
1977
1936
|
}
|
|
@@ -2240,7 +2199,13 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2240
2199
|
return 0;
|
|
2241
2200
|
}
|
|
2242
2201
|
};
|
|
2202
|
+
let dispatchPatternCompile$1;
|
|
2203
|
+
let dispatchPatternToString$3;
|
|
2243
2204
|
function registerSubjectPatternFactory(factory) {}
|
|
2205
|
+
function registerSubjectPatternDispatch(dispatch) {
|
|
2206
|
+
dispatchPatternCompile$1 = dispatch.compile;
|
|
2207
|
+
dispatchPatternToString$3 = dispatch.toString;
|
|
2208
|
+
}
|
|
2244
2209
|
/**
|
|
2245
2210
|
* Pattern for matching subjects in envelopes.
|
|
2246
2211
|
*
|
|
@@ -2304,9 +2269,10 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2304
2269
|
code.push({ type: "NavigateSubject" });
|
|
2305
2270
|
break;
|
|
2306
2271
|
case "Pattern":
|
|
2272
|
+
if (dispatchPatternCompile$1 === void 0) throw new Error("SubjectPattern.compile requires the top-level Pattern compile dispatch; not registered");
|
|
2307
2273
|
code.push({ type: "NavigateSubject" });
|
|
2308
2274
|
code.push({ type: "ExtendTraversal" });
|
|
2309
|
-
this._pattern.pattern
|
|
2275
|
+
dispatchPatternCompile$1(this._pattern.pattern, code, literals, captures);
|
|
2310
2276
|
code.push({ type: "CombineTraversal" });
|
|
2311
2277
|
break;
|
|
2312
2278
|
}
|
|
@@ -2317,7 +2283,10 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2317
2283
|
toString() {
|
|
2318
2284
|
switch (this._pattern.type) {
|
|
2319
2285
|
case "Any": return "subj";
|
|
2320
|
-
case "Pattern":
|
|
2286
|
+
case "Pattern": {
|
|
2287
|
+
const fmt = dispatchPatternToString$3;
|
|
2288
|
+
return `subj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2289
|
+
}
|
|
2321
2290
|
}
|
|
2322
2291
|
}
|
|
2323
2292
|
/**
|
|
@@ -2414,7 +2383,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2414
2383
|
toString() {
|
|
2415
2384
|
switch (this._pattern.type) {
|
|
2416
2385
|
case "Any": return "pred";
|
|
2417
|
-
case "Pattern": return `pred(${this._pattern.pattern
|
|
2386
|
+
case "Pattern": return `pred(${dispatchPatternToString(this._pattern.pattern)})`;
|
|
2418
2387
|
}
|
|
2419
2388
|
}
|
|
2420
2389
|
/**
|
|
@@ -2511,7 +2480,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2511
2480
|
toString() {
|
|
2512
2481
|
switch (this._pattern.type) {
|
|
2513
2482
|
case "Any": return "obj";
|
|
2514
|
-
case "Pattern": return `obj(${this._pattern.pattern
|
|
2483
|
+
case "Pattern": return `obj(${dispatchPatternToString(this._pattern.pattern)})`;
|
|
2515
2484
|
}
|
|
2516
2485
|
}
|
|
2517
2486
|
/**
|
|
@@ -2532,9 +2501,13 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2532
2501
|
//#endregion
|
|
2533
2502
|
//#region src/pattern/structure/assertions-pattern.ts
|
|
2534
2503
|
let createStructureAssertionsPattern;
|
|
2504
|
+
let dispatchPatternToString$2;
|
|
2535
2505
|
function registerAssertionsPatternFactory(factory) {
|
|
2536
2506
|
createStructureAssertionsPattern = factory;
|
|
2537
2507
|
}
|
|
2508
|
+
function registerAssertionsPatternToStringDispatch(fn) {
|
|
2509
|
+
dispatchPatternToString$2 = fn;
|
|
2510
|
+
}
|
|
2538
2511
|
/**
|
|
2539
2512
|
* Pattern for matching assertions in envelopes.
|
|
2540
2513
|
*
|
|
@@ -2572,17 +2545,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2572
2545
|
});
|
|
2573
2546
|
}
|
|
2574
2547
|
/**
|
|
2575
|
-
* Creates a new AssertionsPattern that matches assertions with both
|
|
2576
|
-
* predicate and object patterns.
|
|
2577
|
-
*/
|
|
2578
|
-
static withBoth(predicatePattern, objectPattern) {
|
|
2579
|
-
return new AssertionsPattern({
|
|
2580
|
-
type: "WithBoth",
|
|
2581
|
-
predicatePattern,
|
|
2582
|
-
objectPattern
|
|
2583
|
-
});
|
|
2584
|
-
}
|
|
2585
|
-
/**
|
|
2586
2548
|
* Gets the pattern type.
|
|
2587
2549
|
*/
|
|
2588
2550
|
get patternType() {
|
|
@@ -2593,14 +2555,12 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2593
2555
|
*/
|
|
2594
2556
|
predicatePattern() {
|
|
2595
2557
|
if (this._pattern.type === "WithPredicate") return this._pattern.pattern;
|
|
2596
|
-
if (this._pattern.type === "WithBoth") return this._pattern.predicatePattern;
|
|
2597
2558
|
}
|
|
2598
2559
|
/**
|
|
2599
2560
|
* Gets the object pattern if this has one, undefined otherwise.
|
|
2600
2561
|
*/
|
|
2601
2562
|
objectPattern() {
|
|
2602
2563
|
if (this._pattern.type === "WithObject") return this._pattern.pattern;
|
|
2603
|
-
if (this._pattern.type === "WithBoth") return this._pattern.objectPattern;
|
|
2604
2564
|
}
|
|
2605
2565
|
pathsWithCaptures(haystack) {
|
|
2606
2566
|
const paths = [];
|
|
@@ -2622,14 +2582,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2622
2582
|
}
|
|
2623
2583
|
break;
|
|
2624
2584
|
}
|
|
2625
|
-
case "WithBoth": {
|
|
2626
|
-
const predicate = assertion.asPredicate?.();
|
|
2627
|
-
const object = assertion.asObject?.();
|
|
2628
|
-
if (predicate !== void 0 && object !== void 0) {
|
|
2629
|
-
if (matchPattern(this._pattern.predicatePattern, predicate) && matchPattern(this._pattern.objectPattern, object)) paths.push([assertion]);
|
|
2630
|
-
}
|
|
2631
|
-
break;
|
|
2632
|
-
}
|
|
2633
2585
|
}
|
|
2634
2586
|
return [paths, /* @__PURE__ */ new Map()];
|
|
2635
2587
|
}
|
|
@@ -2652,11 +2604,11 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2652
2604
|
return false;
|
|
2653
2605
|
}
|
|
2654
2606
|
toString() {
|
|
2607
|
+
const fmt = dispatchPatternToString$2;
|
|
2655
2608
|
switch (this._pattern.type) {
|
|
2656
2609
|
case "Any": return "assert";
|
|
2657
|
-
case "WithPredicate": return `assertpred(${this._pattern.pattern
|
|
2658
|
-
case "WithObject": return `assertobj(${this._pattern.pattern
|
|
2659
|
-
case "WithBoth": return `assert(${this._pattern.predicatePattern.toString()}, ${this._pattern.objectPattern.toString()})`;
|
|
2610
|
+
case "WithPredicate": return `assertpred(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2611
|
+
case "WithObject": return `assertobj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
|
|
2660
2612
|
}
|
|
2661
2613
|
}
|
|
2662
2614
|
/**
|
|
@@ -2668,10 +2620,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2668
2620
|
case "Any": return true;
|
|
2669
2621
|
case "WithPredicate":
|
|
2670
2622
|
case "WithObject": return this._pattern.pattern === other._pattern.pattern;
|
|
2671
|
-
case "WithBoth": {
|
|
2672
|
-
const otherBoth = other._pattern;
|
|
2673
|
-
return this._pattern.predicatePattern === otherBoth.predicatePattern && this._pattern.objectPattern === otherBoth.objectPattern;
|
|
2674
|
-
}
|
|
2675
2623
|
}
|
|
2676
2624
|
}
|
|
2677
2625
|
/**
|
|
@@ -2682,7 +2630,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2682
2630
|
case "Any": return 0;
|
|
2683
2631
|
case "WithPredicate": return 1;
|
|
2684
2632
|
case "WithObject": return 2;
|
|
2685
|
-
case "WithBoth": return 3;
|
|
2686
2633
|
}
|
|
2687
2634
|
}
|
|
2688
2635
|
};
|
|
@@ -2711,12 +2658,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2711
2658
|
this._pattern = pattern;
|
|
2712
2659
|
}
|
|
2713
2660
|
/**
|
|
2714
|
-
* Creates a new DigestPattern that matches any digest.
|
|
2715
|
-
*/
|
|
2716
|
-
static any() {
|
|
2717
|
-
return new DigestPattern({ type: "Any" });
|
|
2718
|
-
}
|
|
2719
|
-
/**
|
|
2720
2661
|
* Creates a new DigestPattern that matches the exact digest.
|
|
2721
2662
|
*/
|
|
2722
2663
|
static digest(digest) {
|
|
@@ -2754,9 +2695,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2754
2695
|
const digestData = digest.data();
|
|
2755
2696
|
let isHit = false;
|
|
2756
2697
|
switch (this._pattern.type) {
|
|
2757
|
-
case "Any":
|
|
2758
|
-
isHit = true;
|
|
2759
|
-
break;
|
|
2760
2698
|
case "Digest":
|
|
2761
2699
|
isHit = digest.equals(this._pattern.digest);
|
|
2762
2700
|
break;
|
|
@@ -2794,7 +2732,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2794
2732
|
}
|
|
2795
2733
|
toString() {
|
|
2796
2734
|
switch (this._pattern.type) {
|
|
2797
|
-
case "Any": return "digest";
|
|
2798
2735
|
case "Digest": return `digest(${this._pattern.digest.hex()})`;
|
|
2799
2736
|
case "Prefix": return `digest(${(0, _bcts_dcbor.bytesToHex)(this._pattern.prefix)})`;
|
|
2800
2737
|
case "BinaryRegex": return `digest(/${this._pattern.regex.source}/)`;
|
|
@@ -2802,17 +2739,26 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2802
2739
|
}
|
|
2803
2740
|
/**
|
|
2804
2741
|
* Equality comparison.
|
|
2742
|
+
*
|
|
2743
|
+
* `Prefix` comparison is case-insensitive on the *hex representation* to
|
|
2744
|
+
* mirror Rust's `eq_ignore_ascii_case` (which compares the underlying
|
|
2745
|
+
* `Vec<u8>` of hex bytes byte-for-byte modulo ASCII case). For raw byte
|
|
2746
|
+
* prefixes that happen to be ASCII, this is an ordinary byte compare.
|
|
2805
2747
|
*/
|
|
2806
2748
|
equals(other) {
|
|
2807
2749
|
if (this._pattern.type !== other._pattern.type) return false;
|
|
2808
2750
|
switch (this._pattern.type) {
|
|
2809
|
-
case "Any": return true;
|
|
2810
2751
|
case "Digest": return this._pattern.digest.equals(other._pattern.digest);
|
|
2811
2752
|
case "Prefix": {
|
|
2812
2753
|
const thisPrefix = this._pattern.prefix;
|
|
2813
2754
|
const otherPrefix = other._pattern.prefix;
|
|
2814
2755
|
if (thisPrefix.length !== otherPrefix.length) return false;
|
|
2815
|
-
for (let i = 0; i < thisPrefix.length; i++)
|
|
2756
|
+
for (let i = 0; i < thisPrefix.length; i++) {
|
|
2757
|
+
const a = thisPrefix[i];
|
|
2758
|
+
const b = otherPrefix[i];
|
|
2759
|
+
if (a === b) continue;
|
|
2760
|
+
if ((a >= 65 && a <= 90 ? a + 32 : a) !== (b >= 65 && b <= 90 ? b + 32 : b)) return false;
|
|
2761
|
+
}
|
|
2816
2762
|
return true;
|
|
2817
2763
|
}
|
|
2818
2764
|
case "BinaryRegex": return this._pattern.regex.source === other._pattern.regex.source;
|
|
@@ -2823,7 +2769,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2823
2769
|
*/
|
|
2824
2770
|
hashCode() {
|
|
2825
2771
|
switch (this._pattern.type) {
|
|
2826
|
-
case "Any": return 0;
|
|
2827
2772
|
case "Digest": {
|
|
2828
2773
|
const data = this._pattern.digest.data().slice(0, 8);
|
|
2829
2774
|
let hash = 0;
|
|
@@ -2832,7 +2777,10 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2832
2777
|
}
|
|
2833
2778
|
case "Prefix": {
|
|
2834
2779
|
let hash = 0;
|
|
2835
|
-
for (const byte of this._pattern.prefix)
|
|
2780
|
+
for (const byte of this._pattern.prefix) {
|
|
2781
|
+
const folded = byte >= 65 && byte <= 90 ? byte + 32 : byte;
|
|
2782
|
+
hash = hash * 31 + folded | 0;
|
|
2783
|
+
}
|
|
2836
2784
|
return hash;
|
|
2837
2785
|
}
|
|
2838
2786
|
case "BinaryRegex": {
|
|
@@ -2884,28 +2832,19 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2884
2832
|
});
|
|
2885
2833
|
}
|
|
2886
2834
|
/**
|
|
2887
|
-
* Creates a new NodePattern with a subject pattern constraint.
|
|
2888
|
-
*/
|
|
2889
|
-
static withSubject(subjectPattern) {
|
|
2890
|
-
return new NodePattern({
|
|
2891
|
-
type: "WithSubject",
|
|
2892
|
-
subjectPattern
|
|
2893
|
-
});
|
|
2894
|
-
}
|
|
2895
|
-
/**
|
|
2896
2835
|
* Gets the pattern type.
|
|
2897
2836
|
*/
|
|
2898
2837
|
get patternType() {
|
|
2899
2838
|
return this._pattern;
|
|
2900
2839
|
}
|
|
2901
2840
|
/**
|
|
2902
|
-
*
|
|
2841
|
+
* Returns the subject pattern, if any. Rust's `NodePattern` does not carry
|
|
2842
|
+
* subject patterns, so this always returns `undefined`.
|
|
2903
2843
|
*/
|
|
2904
|
-
subjectPattern() {
|
|
2905
|
-
return this._pattern.type === "WithSubject" ? this._pattern.subjectPattern : void 0;
|
|
2906
|
-
}
|
|
2844
|
+
subjectPattern() {}
|
|
2907
2845
|
/**
|
|
2908
|
-
*
|
|
2846
|
+
* Returns the assertion patterns. Rust's `NodePattern` does not carry
|
|
2847
|
+
* assertion sub-patterns, so this always returns an empty array.
|
|
2909
2848
|
*/
|
|
2910
2849
|
assertionPatterns() {
|
|
2911
2850
|
return [];
|
|
@@ -2920,9 +2859,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2920
2859
|
case "AssertionsInterval":
|
|
2921
2860
|
isHit = this._pattern.interval.contains(haystack.assertions().length);
|
|
2922
2861
|
break;
|
|
2923
|
-
case "WithSubject":
|
|
2924
|
-
isHit = true;
|
|
2925
|
-
break;
|
|
2926
2862
|
}
|
|
2927
2863
|
return [isHit ? [[haystack]] : [], /* @__PURE__ */ new Map()];
|
|
2928
2864
|
}
|
|
@@ -2943,7 +2879,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2943
2879
|
switch (this._pattern.type) {
|
|
2944
2880
|
case "Any": return "node";
|
|
2945
2881
|
case "AssertionsInterval": return `node(${this._pattern.interval.toString()})`;
|
|
2946
|
-
case "WithSubject": return `node(${this._pattern.subjectPattern.toString()})`;
|
|
2947
2882
|
}
|
|
2948
2883
|
}
|
|
2949
2884
|
/**
|
|
@@ -2954,7 +2889,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2954
2889
|
switch (this._pattern.type) {
|
|
2955
2890
|
case "Any": return true;
|
|
2956
2891
|
case "AssertionsInterval": return this._pattern.interval.equals(other._pattern.interval);
|
|
2957
|
-
case "WithSubject": return this._pattern.subjectPattern === other._pattern.subjectPattern;
|
|
2958
2892
|
}
|
|
2959
2893
|
}
|
|
2960
2894
|
/**
|
|
@@ -2964,7 +2898,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
2964
2898
|
switch (this._pattern.type) {
|
|
2965
2899
|
case "Any": return 0;
|
|
2966
2900
|
case "AssertionsInterval": return this._pattern.interval.min() * 31 + (this._pattern.interval.max() ?? 0);
|
|
2967
|
-
case "WithSubject": return 1;
|
|
2968
2901
|
}
|
|
2969
2902
|
}
|
|
2970
2903
|
};
|
|
@@ -3074,12 +3007,16 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
3074
3007
|
//#endregion
|
|
3075
3008
|
//#region src/pattern/structure/wrapped-pattern.ts
|
|
3076
3009
|
let createStructureWrappedPattern;
|
|
3010
|
+
let createAnyPattern;
|
|
3077
3011
|
let dispatchPatternPathsWithCaptures;
|
|
3078
3012
|
let dispatchPatternCompile;
|
|
3079
3013
|
let dispatchPatternToString$1;
|
|
3080
3014
|
function registerWrappedPatternFactory(factory) {
|
|
3081
3015
|
createStructureWrappedPattern = factory;
|
|
3082
3016
|
}
|
|
3017
|
+
function registerWrappedPatternAny(factory) {
|
|
3018
|
+
createAnyPattern = factory;
|
|
3019
|
+
}
|
|
3083
3020
|
function registerWrappedPatternDispatch(dispatch) {
|
|
3084
3021
|
dispatchPatternPathsWithCaptures = dispatch.pathsWithCaptures;
|
|
3085
3022
|
dispatchPatternCompile = dispatch.compile;
|
|
@@ -3113,10 +3050,15 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
3113
3050
|
}
|
|
3114
3051
|
/**
|
|
3115
3052
|
* Creates a new WrappedPattern that matches any wrapped envelope and descends into it.
|
|
3116
|
-
*
|
|
3053
|
+
*
|
|
3054
|
+
* Mirrors Rust `WrappedPattern::unwrap()` which delegates to
|
|
3055
|
+
* `Self::unwrap_matching(Pattern::any())`. The `any` factory is wired in
|
|
3056
|
+
* during module-load registration to break the circular import on the
|
|
3057
|
+
* top-level `Pattern` type.
|
|
3117
3058
|
*/
|
|
3118
3059
|
static unwrap() {
|
|
3119
|
-
|
|
3060
|
+
if (createAnyPattern === void 0) throw new Error("WrappedPattern.unwrap() requires Pattern.any factory; not registered");
|
|
3061
|
+
return WrappedPattern.unwrapMatching(createAnyPattern());
|
|
3120
3062
|
}
|
|
3121
3063
|
/**
|
|
3122
3064
|
* Gets the pattern type.
|
|
@@ -3192,9 +3134,9 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
3192
3134
|
switch (this._pattern.type) {
|
|
3193
3135
|
case "Any": return "wrapped";
|
|
3194
3136
|
case "Unwrap": {
|
|
3195
|
-
const
|
|
3196
|
-
if (
|
|
3197
|
-
return `unwrap(${
|
|
3137
|
+
const inner = this._pattern.pattern;
|
|
3138
|
+
if (inner.type === "Meta" && inner.pattern.type === "Any") return "unwrap";
|
|
3139
|
+
return `unwrap(${dispatchPatternToString$1 !== void 0 ? dispatchPatternToString$1(inner) : "?"})`;
|
|
3198
3140
|
}
|
|
3199
3141
|
}
|
|
3200
3142
|
}
|
|
@@ -3418,10 +3360,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
3418
3360
|
case "Wrapped":
|
|
3419
3361
|
if (envCase.type === "node") {
|
|
3420
3362
|
const subject = envCase.subject;
|
|
3421
|
-
if (subject.isWrapped())
|
|
3422
|
-
const unwrapped = subject.unwrap();
|
|
3423
|
-
if (unwrapped !== void 0) return [[unwrapped, "Content"]];
|
|
3424
|
-
}
|
|
3363
|
+
if (subject.isWrapped()) return [[subject.tryUnwrap(), "Content"]];
|
|
3425
3364
|
} else if (envCase.type === "wrapped") return [[envCase.envelope, "Content"]];
|
|
3426
3365
|
return [];
|
|
3427
3366
|
}
|
|
@@ -4419,30 +4358,20 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
4419
4358
|
return [uniquePaths, /* @__PURE__ */ new Map()];
|
|
4420
4359
|
}
|
|
4421
4360
|
/**
|
|
4422
|
-
* Walk the envelope tree
|
|
4361
|
+
* Walk the envelope tree using the canonical `Envelope.walk` traversal.
|
|
4362
|
+
*
|
|
4363
|
+
* Mirrors Rust `bc_envelope::Envelope::walk(false, vec![], visitor)`
|
|
4364
|
+
* which is what `SearchPattern::paths_with_captures` uses. The earlier
|
|
4365
|
+
* port hand-rolled a recursion that double-recursed assertions and
|
|
4366
|
+
* stepped through wrapped subjects manually, producing a different
|
|
4367
|
+
* path order (and extra duplicates that the digest-set deduplication
|
|
4368
|
+
* would partially mask).
|
|
4423
4369
|
*/
|
|
4424
4370
|
_walkEnvelope(envelope, pathToCurrent, visitor) {
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
for (const assertion of envelope.assertions()) {
|
|
4430
|
-
this._walkEnvelope(assertion, newPath, visitor);
|
|
4431
|
-
const predicate = assertion.asPredicate?.();
|
|
4432
|
-
if (predicate !== void 0) {
|
|
4433
|
-
const assertionPath = [...newPath, assertion];
|
|
4434
|
-
this._walkEnvelope(predicate, assertionPath, visitor);
|
|
4435
|
-
}
|
|
4436
|
-
const object = assertion.asObject?.();
|
|
4437
|
-
if (object !== void 0) {
|
|
4438
|
-
const assertionPath = [...newPath, assertion];
|
|
4439
|
-
this._walkEnvelope(object, assertionPath, visitor);
|
|
4440
|
-
}
|
|
4441
|
-
}
|
|
4442
|
-
if (subject.isWrapped()) {
|
|
4443
|
-
const unwrapped = subject.tryUnwrap?.();
|
|
4444
|
-
if (unwrapped !== void 0) this._walkEnvelope(unwrapped, newPath, visitor);
|
|
4445
|
-
}
|
|
4371
|
+
envelope.walk(false, pathToCurrent, (current, _level, _edge, state) => {
|
|
4372
|
+
visitor(current, state);
|
|
4373
|
+
return [[...state, current], false];
|
|
4374
|
+
});
|
|
4446
4375
|
}
|
|
4447
4376
|
paths(haystack) {
|
|
4448
4377
|
return this.pathsWithCaptures(haystack)[0];
|
|
@@ -4571,7 +4500,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
4571
4500
|
return _patternIsComplex(this._first) || this._rest !== void 0;
|
|
4572
4501
|
}
|
|
4573
4502
|
toString() {
|
|
4574
|
-
return this.patterns().map((p) => p
|
|
4503
|
+
return this.patterns().map((p) => dispatchPatternToString(p)).join(" -> ");
|
|
4575
4504
|
}
|
|
4576
4505
|
/**
|
|
4577
4506
|
* Equality comparison.
|
|
@@ -4920,17 +4849,44 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
4920
4849
|
*/
|
|
4921
4850
|
function convertStructurePatternToEnvelopePattern(structurePattern) {
|
|
4922
4851
|
switch (structurePattern.type) {
|
|
4923
|
-
case "Array":
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4852
|
+
case "Array": {
|
|
4853
|
+
const inner = structurePattern.pattern;
|
|
4854
|
+
let arrayPattern;
|
|
4855
|
+
switch (inner.variant) {
|
|
4856
|
+
case "Any":
|
|
4857
|
+
arrayPattern = ArrayPattern.any();
|
|
4858
|
+
break;
|
|
4859
|
+
case "Length":
|
|
4860
|
+
arrayPattern = ArrayPattern.fromInterval(inner.length);
|
|
4861
|
+
break;
|
|
4862
|
+
case "Elements":
|
|
4863
|
+
arrayPattern = ArrayPattern.fromDcborArrayPattern(inner);
|
|
4864
|
+
break;
|
|
4865
|
+
}
|
|
4866
|
+
return ok({
|
|
4867
|
+
type: "Leaf",
|
|
4868
|
+
pattern: leafArray(arrayPattern)
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4871
|
+
case "Map": {
|
|
4872
|
+
const inner = structurePattern.pattern;
|
|
4873
|
+
let mapPattern;
|
|
4874
|
+
switch (inner.variant) {
|
|
4875
|
+
case "Any":
|
|
4876
|
+
mapPattern = MapPattern.any();
|
|
4877
|
+
break;
|
|
4878
|
+
case "Length":
|
|
4879
|
+
mapPattern = MapPattern.fromInterval(inner.length);
|
|
4880
|
+
break;
|
|
4881
|
+
case "Constraints":
|
|
4882
|
+
mapPattern = MapPattern.any();
|
|
4883
|
+
break;
|
|
4884
|
+
}
|
|
4885
|
+
return ok({
|
|
4886
|
+
type: "Leaf",
|
|
4887
|
+
pattern: leafMap(mapPattern)
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4934
4890
|
case "Tagged": return ok({
|
|
4935
4891
|
type: "Leaf",
|
|
4936
4892
|
pattern: leafTag(TaggedPattern.fromDcborPattern(structurePattern.pattern))
|
|
@@ -4988,6 +4944,169 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
4988
4944
|
}
|
|
4989
4945
|
}
|
|
4990
4946
|
//#endregion
|
|
4947
|
+
//#region src/parse/utils.ts
|
|
4948
|
+
let createCborPattern;
|
|
4949
|
+
let createCborPatternFromDcbor;
|
|
4950
|
+
let createAnyArray;
|
|
4951
|
+
let createArrayWithCount;
|
|
4952
|
+
let createArrayWithRange;
|
|
4953
|
+
let createArrayFromDcborPattern;
|
|
4954
|
+
/**
|
|
4955
|
+
* Register pattern factory functions.
|
|
4956
|
+
* This is called by the pattern module to avoid circular dependencies.
|
|
4957
|
+
*/
|
|
4958
|
+
function registerPatternFactories(factories) {
|
|
4959
|
+
createCborPattern = factories.cborPattern;
|
|
4960
|
+
createCborPatternFromDcbor = factories.cborPatternFromDcbor;
|
|
4961
|
+
createAnyArray = factories.anyArray;
|
|
4962
|
+
createArrayWithCount = factories.arrayWithCount;
|
|
4963
|
+
createArrayWithRange = factories.arrayWithRange;
|
|
4964
|
+
createArrayFromDcborPattern = factories.arrayFromDcborPattern;
|
|
4965
|
+
}
|
|
4966
|
+
/**
|
|
4967
|
+
* Skips whitespace in the source string.
|
|
4968
|
+
*
|
|
4969
|
+
* @param src - The source string
|
|
4970
|
+
* @param pos - The current position (modified in place)
|
|
4971
|
+
*/
|
|
4972
|
+
function skipWs$1(src, pos) {
|
|
4973
|
+
while (pos.value < src.length) {
|
|
4974
|
+
const ch = src[pos.value];
|
|
4975
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos.value++;
|
|
4976
|
+
else break;
|
|
4977
|
+
}
|
|
4978
|
+
}
|
|
4979
|
+
/**
|
|
4980
|
+
* Parses a CBOR value or dcbor-pattern expression.
|
|
4981
|
+
*
|
|
4982
|
+
* @param src - The source string
|
|
4983
|
+
* @returns The parsed pattern and consumed character count, or an error
|
|
4984
|
+
*/
|
|
4985
|
+
function parseCborInner(src) {
|
|
4986
|
+
if (createCborPattern === void 0 || createCborPatternFromDcbor === void 0) return err(unknown());
|
|
4987
|
+
const pos = { value: 0 };
|
|
4988
|
+
skipWs$1(src, pos);
|
|
4989
|
+
if (src[pos.value] === "/") {
|
|
4990
|
+
pos.value++;
|
|
4991
|
+
const start = pos.value;
|
|
4992
|
+
let escape = false;
|
|
4993
|
+
while (pos.value < src.length) {
|
|
4994
|
+
const b = src[pos.value];
|
|
4995
|
+
pos.value++;
|
|
4996
|
+
if (escape) {
|
|
4997
|
+
escape = false;
|
|
4998
|
+
continue;
|
|
4999
|
+
}
|
|
5000
|
+
if (b === "\\") {
|
|
5001
|
+
escape = true;
|
|
5002
|
+
continue;
|
|
5003
|
+
}
|
|
5004
|
+
if (b === "/") {
|
|
5005
|
+
const parseResult = (0, _bcts_dcbor_pattern.parse)(src.slice(start, pos.value - 1));
|
|
5006
|
+
if (!parseResult.ok) return err(invalidPattern({
|
|
5007
|
+
start,
|
|
5008
|
+
end: pos.value - 1
|
|
5009
|
+
}));
|
|
5010
|
+
skipWs$1(src, pos);
|
|
5011
|
+
return ok([createCborPatternFromDcbor(parseResult.value), pos.value]);
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
return err(unterminatedRegex({
|
|
5015
|
+
start: start - 1,
|
|
5016
|
+
end: pos.value
|
|
5017
|
+
}));
|
|
5018
|
+
}
|
|
5019
|
+
if (src.slice(pos.value, pos.value + 3) === "ur:") {
|
|
5020
|
+
const parseResult = (0, _bcts_dcbor_parse.parseDcborItemPartial)(src.slice(pos.value));
|
|
5021
|
+
if (!parseResult.ok) return err(unknown());
|
|
5022
|
+
const [cborValue, consumed] = parseResult.value;
|
|
5023
|
+
return ok([createCborPattern(cborValue), pos.value + consumed]);
|
|
5024
|
+
}
|
|
5025
|
+
const parseResult = (0, _bcts_dcbor_parse.parseDcborItemPartial)(src.slice(pos.value));
|
|
5026
|
+
if (!parseResult.ok) return err(unknown());
|
|
5027
|
+
const [cborValue, consumed] = parseResult.value;
|
|
5028
|
+
return ok([createCborPattern(cborValue), pos.value + consumed]);
|
|
5029
|
+
}
|
|
5030
|
+
/**
|
|
5031
|
+
* Parses an array pattern inner content.
|
|
5032
|
+
*
|
|
5033
|
+
* @param src - The source string (content between [ and ])
|
|
5034
|
+
* @returns The parsed pattern and consumed character count, or an error
|
|
5035
|
+
*/
|
|
5036
|
+
function parseArrayInner(src) {
|
|
5037
|
+
if (createAnyArray === void 0 || createArrayWithCount === void 0 || createArrayWithRange === void 0 || createArrayFromDcborPattern === void 0) return err(unknown());
|
|
5038
|
+
const pos = { value: 0 };
|
|
5039
|
+
skipWs$1(src, pos);
|
|
5040
|
+
if (src[pos.value] === "*") {
|
|
5041
|
+
pos.value++;
|
|
5042
|
+
skipWs$1(src, pos);
|
|
5043
|
+
return ok([createAnyArray(), pos.value]);
|
|
5044
|
+
}
|
|
5045
|
+
if (src[pos.value] === "{") {
|
|
5046
|
+
pos.value++;
|
|
5047
|
+
skipWs$1(src, pos);
|
|
5048
|
+
const startPos = pos.value;
|
|
5049
|
+
while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
|
|
5050
|
+
if (startPos === pos.value) return err(invalidRange({
|
|
5051
|
+
start: pos.value,
|
|
5052
|
+
end: pos.value
|
|
5053
|
+
}));
|
|
5054
|
+
const firstNum = parseInt(src.slice(startPos, pos.value), 10);
|
|
5055
|
+
if (Number.isNaN(firstNum)) return err(invalidNumberFormat({
|
|
5056
|
+
start: startPos,
|
|
5057
|
+
end: pos.value
|
|
5058
|
+
}));
|
|
5059
|
+
skipWs$1(src, pos);
|
|
5060
|
+
if (pos.value >= src.length) return err(unexpectedEndOfInput());
|
|
5061
|
+
const ch = src[pos.value];
|
|
5062
|
+
if (ch === "}") {
|
|
5063
|
+
pos.value++;
|
|
5064
|
+
skipWs$1(src, pos);
|
|
5065
|
+
return ok([createArrayWithCount(firstNum), pos.value]);
|
|
5066
|
+
}
|
|
5067
|
+
if (ch === ",") {
|
|
5068
|
+
pos.value++;
|
|
5069
|
+
skipWs$1(src, pos);
|
|
5070
|
+
if (pos.value >= src.length) return err(unexpectedEndOfInput());
|
|
5071
|
+
const nextCh = src[pos.value];
|
|
5072
|
+
if (nextCh === "}") {
|
|
5073
|
+
pos.value++;
|
|
5074
|
+
skipWs$1(src, pos);
|
|
5075
|
+
return ok([createArrayWithRange(firstNum, void 0), pos.value]);
|
|
5076
|
+
}
|
|
5077
|
+
if (nextCh !== void 0 && /\d/.test(nextCh)) {
|
|
5078
|
+
const secondStart = pos.value;
|
|
5079
|
+
while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
|
|
5080
|
+
const secondNum = parseInt(src.slice(secondStart, pos.value), 10);
|
|
5081
|
+
if (Number.isNaN(secondNum)) return err(invalidNumberFormat({
|
|
5082
|
+
start: secondStart,
|
|
5083
|
+
end: pos.value
|
|
5084
|
+
}));
|
|
5085
|
+
skipWs$1(src, pos);
|
|
5086
|
+
if (pos.value >= src.length || src[pos.value] !== "}") return err(unexpectedEndOfInput());
|
|
5087
|
+
pos.value++;
|
|
5088
|
+
skipWs$1(src, pos);
|
|
5089
|
+
return ok([createArrayWithRange(firstNum, secondNum), pos.value]);
|
|
5090
|
+
}
|
|
5091
|
+
return err(invalidRange({
|
|
5092
|
+
start: pos.value,
|
|
5093
|
+
end: pos.value
|
|
5094
|
+
}));
|
|
5095
|
+
}
|
|
5096
|
+
return err(invalidRange({
|
|
5097
|
+
start: pos.value,
|
|
5098
|
+
end: pos.value
|
|
5099
|
+
}));
|
|
5100
|
+
}
|
|
5101
|
+
const parseResult = (0, _bcts_dcbor_pattern.parse)(`[${src.slice(pos.value)}]`);
|
|
5102
|
+
if (!parseResult.ok) return err(invalidPattern({
|
|
5103
|
+
start: pos.value,
|
|
5104
|
+
end: src.length
|
|
5105
|
+
}));
|
|
5106
|
+
const consumed = src.length - pos.value;
|
|
5107
|
+
return ok([createArrayFromDcborPattern(parseResult.value), consumed]);
|
|
5108
|
+
}
|
|
5109
|
+
//#endregion
|
|
4991
5110
|
//#region src/pattern/index.ts
|
|
4992
5111
|
/**
|
|
4993
5112
|
* Creates a Leaf pattern.
|
|
@@ -5502,6 +5621,12 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
5502
5621
|
compile: patternCompile,
|
|
5503
5622
|
toString: patternToString
|
|
5504
5623
|
});
|
|
5624
|
+
registerWrappedPatternAny(any);
|
|
5625
|
+
registerAssertionsPatternToStringDispatch(patternToString);
|
|
5626
|
+
registerSubjectPatternDispatch({
|
|
5627
|
+
compile: patternCompile,
|
|
5628
|
+
toString: patternToString
|
|
5629
|
+
});
|
|
5505
5630
|
registerAnyPatternFactory((p) => patternMeta(metaAny(p)));
|
|
5506
5631
|
registerAndPatternFactory((p) => patternMeta(metaAnd(p)));
|
|
5507
5632
|
registerOrPatternFactory((p) => patternMeta(metaOr(p)));
|
|
@@ -5513,6 +5638,14 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
5513
5638
|
}
|
|
5514
5639
|
registerAllFactories();
|
|
5515
5640
|
registerVMPatternFunctions(patternPathsWithCaptures, patternMatches, patternPaths);
|
|
5641
|
+
registerPatternFactories({
|
|
5642
|
+
cborPattern: (value) => cborValue(value),
|
|
5643
|
+
cborPatternFromDcbor: (pattern) => cborPattern(pattern),
|
|
5644
|
+
anyArray,
|
|
5645
|
+
arrayWithCount: (count) => patternLeaf(leafArray(ArrayPattern.count(count))),
|
|
5646
|
+
arrayWithRange: (min, max) => patternLeaf(leafArray(ArrayPattern.interval(min, max))),
|
|
5647
|
+
arrayFromDcborPattern: (pattern) => patternLeaf(leafArray(ArrayPattern.fromDcborPattern(pattern)))
|
|
5648
|
+
});
|
|
5516
5649
|
registerPatternMatchFn(patternMatches);
|
|
5517
5650
|
registerPatternDispatchFns({
|
|
5518
5651
|
pathsWithCaptures: patternPathsWithCaptures,
|
|
@@ -6266,305 +6399,198 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
6266
6399
|
}
|
|
6267
6400
|
};
|
|
6268
6401
|
//#endregion
|
|
6269
|
-
//#region src/parse/
|
|
6402
|
+
//#region src/parse/leaf/array-parser.ts
|
|
6270
6403
|
/**
|
|
6271
6404
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6272
6405
|
* Copyright © 2025-2026 Parity Technologies
|
|
6273
6406
|
*
|
|
6407
|
+
* Array parser — port of `bc-envelope-pattern-rust`
|
|
6408
|
+
* `parse/leaf/array_parser.rs`.
|
|
6274
6409
|
*
|
|
6275
|
-
*
|
|
6276
|
-
*
|
|
6277
|
-
*
|
|
6278
|
-
*
|
|
6410
|
+
* Mirrors Rust's flow exactly: after the `[` token has been consumed,
|
|
6411
|
+
* delegate to `utils::parseArrayInner` (which handles `*`, `{n}`, `{n,m}`,
|
|
6412
|
+
* `{n,}` directly and otherwise wraps the body in `[...]` and re-parses
|
|
6413
|
+
* via dcbor-pattern), then expect a closing `]`.
|
|
6279
6414
|
*
|
|
6280
|
-
* @module envelope-pattern/parse
|
|
6281
|
-
*/
|
|
6282
|
-
/**
|
|
6283
|
-
* Parse a pattern expression string into a Pattern.
|
|
6415
|
+
* @module envelope-pattern/parse/leaf/array-parser
|
|
6284
6416
|
*/
|
|
6285
|
-
function
|
|
6286
|
-
const
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
if (next !== void 0) return err(extraData(next.span));
|
|
6295
|
-
return result;
|
|
6417
|
+
function parseArray(lexer) {
|
|
6418
|
+
const inner = parseArrayInner(lexer.remainder());
|
|
6419
|
+
if (!inner.ok) return inner;
|
|
6420
|
+
const [pattern, consumed] = inner.value;
|
|
6421
|
+
lexer.bump(consumed);
|
|
6422
|
+
const close = lexer.next();
|
|
6423
|
+
if (close === void 0) return err(expectedCloseBracket(lexer.span()));
|
|
6424
|
+
if (close.token.type !== "BracketClose") return err(unexpectedToken(close.token, close.span));
|
|
6425
|
+
return ok(pattern);
|
|
6296
6426
|
}
|
|
6427
|
+
//#endregion
|
|
6428
|
+
//#region src/parse/leaf/cbor-parser.ts
|
|
6297
6429
|
/**
|
|
6298
|
-
*
|
|
6430
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6431
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6432
|
+
*
|
|
6433
|
+
* CBOR pattern parser — port of `bc-envelope-pattern-rust`
|
|
6434
|
+
* `parse/leaf/cbor_parser.rs`.
|
|
6435
|
+
*
|
|
6436
|
+
* Mirrors Rust's flow: lookahead for `(`. If absent, return `any_cbor()`.
|
|
6437
|
+
* Otherwise consume the `(`, delegate to `parseCborInner` (handles
|
|
6438
|
+
* `/regex/`, `ur:…`, and CBOR diagnostic notation), and expect a closing
|
|
6439
|
+
* `)`.
|
|
6440
|
+
*
|
|
6441
|
+
* @module envelope-pattern/parse/leaf/cbor-parser
|
|
6299
6442
|
*/
|
|
6300
|
-
function
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6443
|
+
function parseCbor(lexer) {
|
|
6444
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyCbor());
|
|
6445
|
+
lexer.next();
|
|
6446
|
+
const innerResult = parseCborInner(lexer.remainder());
|
|
6447
|
+
if (!innerResult.ok) return innerResult;
|
|
6448
|
+
const [pattern, consumed] = innerResult.value;
|
|
6449
|
+
lexer.bump(consumed);
|
|
6450
|
+
const close = lexer.next();
|
|
6451
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6452
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6453
|
+
return ok(pattern);
|
|
6305
6454
|
}
|
|
6455
|
+
//#endregion
|
|
6456
|
+
//#region src/parse/leaf/date-parser.ts
|
|
6306
6457
|
/**
|
|
6307
|
-
*
|
|
6458
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6459
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6460
|
+
*
|
|
6461
|
+
* Date content parser — port of `bc-envelope-pattern-rust`
|
|
6462
|
+
* `parse/leaf/date_parser.rs`.
|
|
6463
|
+
*
|
|
6464
|
+
* Mirrors Rust's `Date::from_string`, which accepts a strict ISO-8601
|
|
6465
|
+
* subset, by deferring to dcbor's `CborDate.fromString`. Falls back to JS
|
|
6466
|
+
* `Date.parse` only as a defensive shim — that branch is unreachable for
|
|
6467
|
+
* conformant inputs.
|
|
6468
|
+
*
|
|
6469
|
+
* @module envelope-pattern/parse/leaf/date-parser
|
|
6308
6470
|
*/
|
|
6309
|
-
function convertDcborPatternToEnvelopePattern$1(_dcborPattern) {
|
|
6310
|
-
return ok(any());
|
|
6311
|
-
}
|
|
6312
6471
|
/**
|
|
6313
|
-
* Parse
|
|
6472
|
+
* Parse a date pattern of one of the forms accepted by Rust:
|
|
6473
|
+
*
|
|
6474
|
+
* - `/regex/` (regex match against ISO-8601 string)
|
|
6475
|
+
* - `start...end` (inclusive range)
|
|
6476
|
+
* - `start...` (earliest)
|
|
6477
|
+
* - `...end` (latest)
|
|
6478
|
+
* - `iso-8601` (exact)
|
|
6479
|
+
*
|
|
6480
|
+
* Mirrors `parse_date_content` in Rust; uses `CborDate.fromString` so the
|
|
6481
|
+
* accepted formats match Rust's `bc_envelope::prelude::Date::from_string`
|
|
6482
|
+
* exactly rather than the looser JS `Date.parse`.
|
|
6314
6483
|
*/
|
|
6315
|
-
function
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
const nextExpr = parseTraverse(lexer);
|
|
6324
|
-
if (!nextExpr.ok) return nextExpr;
|
|
6325
|
-
patterns.push(nextExpr.value);
|
|
6484
|
+
function parseDateContent(content, span) {
|
|
6485
|
+
if (content.startsWith("/") && content.endsWith("/") && content.length >= 2) {
|
|
6486
|
+
const regexStr = content.slice(1, -1);
|
|
6487
|
+
try {
|
|
6488
|
+
return ok(dateRegex(new RegExp(regexStr)));
|
|
6489
|
+
} catch {
|
|
6490
|
+
return err(invalidRegex(span));
|
|
6491
|
+
}
|
|
6326
6492
|
}
|
|
6327
|
-
|
|
6328
|
-
|
|
6493
|
+
const ellipsisIdx = content.indexOf("...");
|
|
6494
|
+
if (ellipsisIdx !== -1) {
|
|
6495
|
+
const left = content.slice(0, ellipsisIdx);
|
|
6496
|
+
const right = content.slice(ellipsisIdx + 3);
|
|
6497
|
+
if (left.length === 0 && right.length > 0) {
|
|
6498
|
+
const parsed = parseIsoDateStrict(right);
|
|
6499
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6500
|
+
return ok(dateLatest(parsed));
|
|
6501
|
+
}
|
|
6502
|
+
if (left.length > 0 && right.length === 0) {
|
|
6503
|
+
const parsed = parseIsoDateStrict(left);
|
|
6504
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6505
|
+
return ok(dateEarliest(parsed));
|
|
6506
|
+
}
|
|
6507
|
+
if (left.length > 0 && right.length > 0) {
|
|
6508
|
+
const start = parseIsoDateStrict(left);
|
|
6509
|
+
const end = parseIsoDateStrict(right);
|
|
6510
|
+
if (start === void 0 || end === void 0) return err(invalidDateFormat(span));
|
|
6511
|
+
return ok(dateRange(start, end));
|
|
6512
|
+
}
|
|
6513
|
+
return err(invalidDateFormat(span));
|
|
6514
|
+
}
|
|
6515
|
+
const parsed = parseIsoDateStrict(content);
|
|
6516
|
+
if (parsed === void 0) return err(invalidDateFormat(span));
|
|
6517
|
+
return ok(date(parsed));
|
|
6329
6518
|
}
|
|
6519
|
+
function parseIsoDateStrict(value) {
|
|
6520
|
+
try {
|
|
6521
|
+
return _bcts_dcbor.CborDate.fromString(value);
|
|
6522
|
+
} catch {
|
|
6523
|
+
return;
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
//#endregion
|
|
6527
|
+
//#region src/parse/leaf/known-value-parser.ts
|
|
6330
6528
|
/**
|
|
6331
|
-
*
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
return ok(traverse(patterns));
|
|
6347
|
-
}
|
|
6348
|
-
/**
|
|
6349
|
-
* Parse an And expression: expr (& expr)*
|
|
6529
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6530
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6531
|
+
*
|
|
6532
|
+
* Helpers for parsing the body of a `'…'` (single-quoted) known-value
|
|
6533
|
+
* literal. Mirrors the inline body of Rust's `Token::SingleQuotedPattern`
|
|
6534
|
+
* branch in `parse_primary`:
|
|
6535
|
+
*
|
|
6536
|
+
* - If the contents are a valid `u64`, build `Pattern::known_value(...)`.
|
|
6537
|
+
* - Otherwise, build `Pattern::known_value_named(...)`.
|
|
6538
|
+
*
|
|
6539
|
+
* The earlier port duck-typed a fake `KnownValue`; this version uses the
|
|
6540
|
+
* real `KnownValue` constructor so all subsequent KnownValue methods work
|
|
6541
|
+
* (e.g., `taggedCbor()`, `name()`, etc.).
|
|
6542
|
+
*
|
|
6543
|
+
* @module envelope-pattern/parse/leaf/known-value-parser
|
|
6350
6544
|
*/
|
|
6351
|
-
function parseAnd(lexer) {
|
|
6352
|
-
const patterns = [];
|
|
6353
|
-
const first = parseNot(lexer);
|
|
6354
|
-
if (!first.ok) return first;
|
|
6355
|
-
patterns.push(first.value);
|
|
6356
|
-
while (true) {
|
|
6357
|
-
if (lexer.peekToken()?.token.type !== "And") break;
|
|
6358
|
-
lexer.next();
|
|
6359
|
-
const nextExpr = parseNot(lexer);
|
|
6360
|
-
if (!nextExpr.ok) return nextExpr;
|
|
6361
|
-
patterns.push(nextExpr.value);
|
|
6362
|
-
}
|
|
6363
|
-
if (patterns.length === 1) return ok(patterns[0]);
|
|
6364
|
-
return ok(and(patterns));
|
|
6365
|
-
}
|
|
6366
6545
|
/**
|
|
6367
|
-
*
|
|
6546
|
+
* Maximum value of a Rust `u64`. Used to reject literals that would
|
|
6547
|
+
* silently wrap or lose precision when constructing a `KnownValue`.
|
|
6368
6548
|
*/
|
|
6369
|
-
|
|
6370
|
-
if (lexer.peekToken()?.token.type === "Not") {
|
|
6371
|
-
lexer.next();
|
|
6372
|
-
const inner = parseGroup(lexer);
|
|
6373
|
-
if (!inner.ok) return inner;
|
|
6374
|
-
return ok(notMatching(inner.value));
|
|
6375
|
-
}
|
|
6376
|
-
return parseGroup(lexer);
|
|
6377
|
-
}
|
|
6549
|
+
const U64_MAX = 18446744073709551615n;
|
|
6378
6550
|
/**
|
|
6379
|
-
* Parse a
|
|
6551
|
+
* Parse the inner contents of a `'…'` known-value pattern token.
|
|
6552
|
+
*
|
|
6553
|
+
* Mirrors the Rust dispatch
|
|
6554
|
+
* ```ignore
|
|
6555
|
+
* if let Ok(value) = content.parse::<u64>() {
|
|
6556
|
+
* Pattern::known_value(KnownValue::new(value))
|
|
6557
|
+
* } else {
|
|
6558
|
+
* Pattern::known_value_named(content)
|
|
6559
|
+
* }
|
|
6560
|
+
* ```
|
|
6561
|
+
* but uses BigInt parsing to preserve full `u64` range — the previous
|
|
6562
|
+
* `parseInt(...)` path silently truncated above `2^53-1`.
|
|
6380
6563
|
*/
|
|
6381
|
-
function
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
const next = lexer.peekToken();
|
|
6385
|
-
if (next === void 0) return primary;
|
|
6386
|
-
const tokenType = next.token.type;
|
|
6387
|
-
let quantifier;
|
|
6388
|
-
if (tokenType === "RepeatZeroOrMore") {
|
|
6389
|
-
lexer.next();
|
|
6390
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
6391
|
-
} else if (tokenType === "RepeatZeroOrMoreLazy") {
|
|
6392
|
-
lexer.next();
|
|
6393
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
6394
|
-
} else if (tokenType === "RepeatZeroOrMorePossessive") {
|
|
6395
|
-
lexer.next();
|
|
6396
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
6397
|
-
} else if (tokenType === "RepeatOneOrMore") {
|
|
6398
|
-
lexer.next();
|
|
6399
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
6400
|
-
} else if (tokenType === "RepeatOneOrMoreLazy") {
|
|
6401
|
-
lexer.next();
|
|
6402
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
6403
|
-
} else if (tokenType === "RepeatOneOrMorePossessive") {
|
|
6404
|
-
lexer.next();
|
|
6405
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
6406
|
-
} else if (tokenType === "RepeatZeroOrOne") {
|
|
6407
|
-
lexer.next();
|
|
6408
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
6409
|
-
} else if (tokenType === "RepeatZeroOrOneLazy") {
|
|
6410
|
-
lexer.next();
|
|
6411
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
6412
|
-
} else if (tokenType === "RepeatZeroOrOnePossessive") {
|
|
6413
|
-
lexer.next();
|
|
6414
|
-
quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
6415
|
-
} else if (tokenType === "Range") {
|
|
6416
|
-
lexer.next();
|
|
6417
|
-
if (!next.token.value.ok) return err(next.token.value.error);
|
|
6418
|
-
quantifier = next.token.value.value;
|
|
6419
|
-
} else return primary;
|
|
6420
|
-
return ok(repeat(primary.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
|
|
6564
|
+
function parseKnownValueContent(content) {
|
|
6565
|
+
if (isU64Literal(content)) return ok(knownValue(new _bcts_known_values.KnownValue(BigInt(content))));
|
|
6566
|
+
return ok(patternLeaf(leafKnownValue(KnownValuePattern.named(content))));
|
|
6421
6567
|
}
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
case "AssertionPred": return parseAssertionPred(lexer);
|
|
6434
|
-
case "AssertionObj": return parseAssertionObj(lexer);
|
|
6435
|
-
case "Digest": return parseDigest(lexer);
|
|
6436
|
-
case "Obj": return parseObject(lexer);
|
|
6437
|
-
case "Obscured": return ok(obscured());
|
|
6438
|
-
case "Elided": return ok(elided());
|
|
6439
|
-
case "Encrypted": return ok(encrypted());
|
|
6440
|
-
case "Compressed": return ok(compressed());
|
|
6441
|
-
case "Pred": return parsePredicate(lexer);
|
|
6442
|
-
case "Subject": return parseSubject(lexer);
|
|
6443
|
-
case "Wrapped": return ok(wrapped());
|
|
6444
|
-
case "Unwrap": return parseUnwrap(lexer);
|
|
6445
|
-
case "Leaf": return ok(leaf());
|
|
6446
|
-
case "GroupName": return parseCapture(lexer, token.name);
|
|
6447
|
-
case "ParenOpen": return parseParenGroup(lexer);
|
|
6448
|
-
case "Cbor": return parseCbor(lexer);
|
|
6449
|
-
case "RepeatZeroOrMore": return ok(any());
|
|
6450
|
-
case "BoolKeyword": return ok(anyBool());
|
|
6451
|
-
case "BoolTrue": return ok(bool(true));
|
|
6452
|
-
case "BoolFalse": return ok(bool(false));
|
|
6453
|
-
case "NumberKeyword": return ok(anyNumber());
|
|
6454
|
-
case "TextKeyword": return ok(anyText());
|
|
6455
|
-
case "StringLiteral":
|
|
6456
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6457
|
-
return ok(text(token.value.value));
|
|
6458
|
-
case "UnsignedInteger":
|
|
6459
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6460
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6461
|
-
case "Integer":
|
|
6462
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6463
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6464
|
-
case "Float":
|
|
6465
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6466
|
-
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
6467
|
-
case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
|
|
6468
|
-
case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
|
|
6469
|
-
case "GreaterThan": return parseComparisonNumber(lexer, ">");
|
|
6470
|
-
case "LessThan": return parseComparisonNumber(lexer, "<");
|
|
6471
|
-
case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
|
|
6472
|
-
case "Infinity": return ok(number(Infinity));
|
|
6473
|
-
case "NegativeInfinity": return ok(number(-Infinity));
|
|
6474
|
-
case "Regex":
|
|
6475
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6476
|
-
try {
|
|
6477
|
-
return ok(textRegex(new RegExp(token.value.value)));
|
|
6478
|
-
} catch {
|
|
6479
|
-
return err(invalidRegex(span));
|
|
6480
|
-
}
|
|
6481
|
-
case "BracketOpen": return parseArray(lexer);
|
|
6482
|
-
case "ByteString": return ok(anyByteString());
|
|
6483
|
-
case "HexPattern":
|
|
6484
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6485
|
-
return ok(byteString(token.value.value));
|
|
6486
|
-
case "HexBinaryRegex":
|
|
6487
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6488
|
-
try {
|
|
6489
|
-
return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
|
|
6490
|
-
} catch {
|
|
6491
|
-
return err(invalidRegex(span));
|
|
6492
|
-
}
|
|
6493
|
-
case "DateKeyword": return ok(anyDate());
|
|
6494
|
-
case "DatePattern":
|
|
6495
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6496
|
-
return parseDateContent(token.value.value, span);
|
|
6497
|
-
case "Tagged": return parseTag(lexer);
|
|
6498
|
-
case "Known": return ok(anyKnownValue());
|
|
6499
|
-
case "SingleQuotedPattern":
|
|
6500
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6501
|
-
return parseKnownValueContent(token.value.value);
|
|
6502
|
-
case "SingleQuotedRegex":
|
|
6503
|
-
if (!token.value.ok) return err(token.value.error);
|
|
6504
|
-
try {
|
|
6505
|
-
return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
|
|
6506
|
-
} catch {
|
|
6507
|
-
return err(invalidRegex(span));
|
|
6508
|
-
}
|
|
6509
|
-
case "Null": return ok(nullPattern());
|
|
6510
|
-
case "And":
|
|
6511
|
-
case "Or":
|
|
6512
|
-
case "Not":
|
|
6513
|
-
case "Traverse":
|
|
6514
|
-
case "RepeatZeroOrMoreLazy":
|
|
6515
|
-
case "RepeatZeroOrMorePossessive":
|
|
6516
|
-
case "RepeatOneOrMore":
|
|
6517
|
-
case "RepeatOneOrMoreLazy":
|
|
6518
|
-
case "RepeatOneOrMorePossessive":
|
|
6519
|
-
case "RepeatZeroOrOne":
|
|
6520
|
-
case "RepeatZeroOrOneLazy":
|
|
6521
|
-
case "RepeatZeroOrOnePossessive":
|
|
6522
|
-
case "ParenClose":
|
|
6523
|
-
case "BracketClose":
|
|
6524
|
-
case "Comma":
|
|
6525
|
-
case "Ellipsis":
|
|
6526
|
-
case "Range":
|
|
6527
|
-
case "Identifier": return err(unexpectedToken(token, span));
|
|
6568
|
+
function isU64Literal(content) {
|
|
6569
|
+
if (content.length === 0) return false;
|
|
6570
|
+
for (let i = 0; i < content.length; i++) {
|
|
6571
|
+
const c = content.charCodeAt(i);
|
|
6572
|
+
if (c < 48 || c > 57) return false;
|
|
6573
|
+
}
|
|
6574
|
+
try {
|
|
6575
|
+
const value = BigInt(content);
|
|
6576
|
+
return value >= 0n && value <= U64_MAX;
|
|
6577
|
+
} catch {
|
|
6578
|
+
return false;
|
|
6528
6579
|
}
|
|
6529
6580
|
}
|
|
6581
|
+
//#endregion
|
|
6582
|
+
//#region src/parse/leaf/number-parser.ts
|
|
6530
6583
|
/**
|
|
6531
|
-
*
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
type: "ExpectedCloseParen",
|
|
6538
|
-
span: lexer.span()
|
|
6539
|
-
});
|
|
6540
|
-
return ok(group(inner.value));
|
|
6541
|
-
}
|
|
6542
|
-
/**
|
|
6543
|
-
* Parse a capture group: @name pattern
|
|
6544
|
-
*/
|
|
6545
|
-
function parseCapture(lexer, name) {
|
|
6546
|
-
const inner = parseGroup(lexer);
|
|
6547
|
-
if (!inner.ok) return inner;
|
|
6548
|
-
return ok(capture(name, inner.value));
|
|
6549
|
-
}
|
|
6550
|
-
/**
|
|
6551
|
-
* Parse a search pattern: search(pattern)
|
|
6584
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6585
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6586
|
+
*
|
|
6587
|
+
* Number parsers — port of `bc-envelope-pattern-rust` `parse/leaf/number_parser.rs`.
|
|
6588
|
+
*
|
|
6589
|
+
* @module envelope-pattern/parse/leaf/number-parser
|
|
6552
6590
|
*/
|
|
6553
|
-
function parseSearch(lexer) {
|
|
6554
|
-
if (lexer.next()?.token.type !== "ParenOpen") return err({
|
|
6555
|
-
type: "ExpectedOpenParen",
|
|
6556
|
-
span: lexer.span()
|
|
6557
|
-
});
|
|
6558
|
-
const inner = parseOr(lexer);
|
|
6559
|
-
if (!inner.ok) return inner;
|
|
6560
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6561
|
-
type: "ExpectedCloseParen",
|
|
6562
|
-
span: lexer.span()
|
|
6563
|
-
});
|
|
6564
|
-
return ok(search(inner.value));
|
|
6565
|
-
}
|
|
6566
6591
|
/**
|
|
6567
|
-
*
|
|
6592
|
+
* Parses an optional `...end` suffix following an already-consumed number,
|
|
6593
|
+
* mirroring Rust `parse_number_range_or_comparison`.
|
|
6568
6594
|
*/
|
|
6569
6595
|
function parseNumberRangeOrComparison(lexer, firstValue) {
|
|
6570
6596
|
const next = lexer.peekToken();
|
|
@@ -6574,10 +6600,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
6574
6600
|
const endToken = lexer.next();
|
|
6575
6601
|
if (endToken === void 0) return err(unexpectedEndOfInput());
|
|
6576
6602
|
let endValue;
|
|
6577
|
-
if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer") {
|
|
6578
|
-
if (!endToken.token.value.ok) return err(endToken.token.value.error);
|
|
6579
|
-
endValue = endToken.token.value.value;
|
|
6580
|
-
} else if (endToken.token.type === "Float") {
|
|
6603
|
+
if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer" || endToken.token.type === "Float") {
|
|
6581
6604
|
if (!endToken.token.value.ok) return err(endToken.token.value.error);
|
|
6582
6605
|
endValue = endToken.token.value.value;
|
|
6583
6606
|
} else return err(unexpectedToken(endToken.token, endToken.span));
|
|
@@ -6586,16 +6609,14 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
6586
6609
|
return ok(number(firstValue));
|
|
6587
6610
|
}
|
|
6588
6611
|
/**
|
|
6589
|
-
*
|
|
6612
|
+
* Parses a number following a comparison operator, mirroring Rust
|
|
6613
|
+
* `parse_comparison_number`.
|
|
6590
6614
|
*/
|
|
6591
6615
|
function parseComparisonNumber(lexer, op) {
|
|
6592
6616
|
const numToken = lexer.next();
|
|
6593
6617
|
if (numToken === void 0) return err(unexpectedEndOfInput());
|
|
6594
6618
|
let value;
|
|
6595
|
-
if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer") {
|
|
6596
|
-
if (!numToken.token.value.ok) return err(numToken.token.value.error);
|
|
6597
|
-
value = numToken.token.value.value;
|
|
6598
|
-
} else if (numToken.token.type === "Float") {
|
|
6619
|
+
if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer" || numToken.token.type === "Float") {
|
|
6599
6620
|
if (!numToken.token.value.ok) return err(numToken.token.value.error);
|
|
6600
6621
|
value = numToken.token.value.value;
|
|
6601
6622
|
} else return err(unexpectedToken(numToken.token, numToken.span));
|
|
@@ -6604,300 +6625,812 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
6604
6625
|
case "<=": return ok(patternLeaf(leafNumber(NumberPattern.lessThanOrEqual(value))));
|
|
6605
6626
|
case ">": return ok(numberGreaterThan(value));
|
|
6606
6627
|
case "<": return ok(numberLessThan(value));
|
|
6607
|
-
default: return ok(number(value));
|
|
6608
6628
|
}
|
|
6609
6629
|
}
|
|
6630
|
+
//#endregion
|
|
6631
|
+
//#region src/parse/leaf/tag-parser.ts
|
|
6610
6632
|
/**
|
|
6611
|
-
*
|
|
6633
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6634
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6635
|
+
*
|
|
6636
|
+
* Tag parser — port of `bc-envelope-pattern-rust`
|
|
6637
|
+
* `parse/leaf/tag_parser.rs`.
|
|
6638
|
+
*
|
|
6639
|
+
* Mirrors the Rust dispatch exactly: lookahead for `(`; if absent, return
|
|
6640
|
+
* the bare `any_tag()`. Otherwise build a synthetic dcbor-pattern
|
|
6641
|
+
* expression `tagged(<inner>)`, parse it via `@bcts/dcbor-pattern`, and
|
|
6642
|
+
* extract the resulting `TaggedPattern` to wrap as an envelope-pattern
|
|
6643
|
+
* leaf. This keeps the **full** tag selector (number, name, regex)
|
|
6644
|
+
* intact — the previous port discarded the tag value entirely.
|
|
6645
|
+
*
|
|
6646
|
+
* @module envelope-pattern/parse/leaf/tag-parser
|
|
6612
6647
|
*/
|
|
6613
|
-
function parseArray(lexer) {
|
|
6614
|
-
const first = lexer.peekToken();
|
|
6615
|
-
if (first === void 0) return err(unexpectedEndOfInput());
|
|
6616
|
-
if (first.token.type === "BracketClose") {
|
|
6617
|
-
lexer.next();
|
|
6618
|
-
return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
|
|
6619
|
-
}
|
|
6620
|
-
if (first.token.type === "RepeatZeroOrMore") {
|
|
6621
|
-
lexer.next();
|
|
6622
|
-
if (lexer.next()?.token.type !== "BracketClose") return err({
|
|
6623
|
-
type: "ExpectedCloseBracket",
|
|
6624
|
-
span: lexer.span()
|
|
6625
|
-
});
|
|
6626
|
-
return ok(anyArray());
|
|
6627
|
-
}
|
|
6628
|
-
const patterns = [];
|
|
6629
|
-
while (true) {
|
|
6630
|
-
const next = lexer.peekToken();
|
|
6631
|
-
if (next === void 0) return err(unexpectedEndOfInput());
|
|
6632
|
-
if (next.token.type === "BracketClose") {
|
|
6633
|
-
lexer.next();
|
|
6634
|
-
break;
|
|
6635
|
-
}
|
|
6636
|
-
const pattern = parseOr(lexer);
|
|
6637
|
-
if (!pattern.ok) return pattern;
|
|
6638
|
-
patterns.push(pattern.value);
|
|
6639
|
-
const afterPattern = lexer.peekToken();
|
|
6640
|
-
if (afterPattern === void 0) return err(unexpectedEndOfInput());
|
|
6641
|
-
if (afterPattern.token.type === "Comma") lexer.next();
|
|
6642
|
-
else if (afterPattern.token.type !== "BracketClose") return err(unexpectedToken(afterPattern.token, afterPattern.span));
|
|
6643
|
-
}
|
|
6644
|
-
if (patterns.length === 0) return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
|
|
6645
|
-
return ok(patternLeaf(leafArray(ArrayPattern.withPatterns(patterns))));
|
|
6646
|
-
}
|
|
6647
6648
|
/**
|
|
6648
|
-
* Parse
|
|
6649
|
+
* Parse `tagged` and `tagged(...)` patterns.
|
|
6649
6650
|
*/
|
|
6650
6651
|
function parseTag(lexer) {
|
|
6651
|
-
if (lexer.
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
if (
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
if (content.startsWith("/") && content.endsWith("/")) {
|
|
6667
|
-
const regexStr = content.slice(1, -1);
|
|
6668
|
-
try {
|
|
6669
|
-
return ok(dateRegex(new RegExp(regexStr)));
|
|
6670
|
-
} catch {
|
|
6671
|
-
return err(invalidRegex(span));
|
|
6652
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyTag());
|
|
6653
|
+
lexer.next();
|
|
6654
|
+
const remainder = lexer.remainder();
|
|
6655
|
+
const closeIdx = findMatchingCloseParen(remainder);
|
|
6656
|
+
if (closeIdx === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6657
|
+
const innerContent = remainder.slice(0, closeIdx);
|
|
6658
|
+
const dcborResult = (0, _bcts_dcbor_pattern.parse)(`tagged(${innerContent})`);
|
|
6659
|
+
if (dcborResult.ok) {
|
|
6660
|
+
const dcborPattern = dcborResult.value;
|
|
6661
|
+
if (dcborPattern.kind === "Structure" && dcborPattern.pattern.type === "Tagged") {
|
|
6662
|
+
lexer.bump(closeIdx);
|
|
6663
|
+
const close = lexer.next();
|
|
6664
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6665
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6666
|
+
return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborPattern.pattern.pattern))));
|
|
6672
6667
|
}
|
|
6673
6668
|
}
|
|
6674
|
-
const
|
|
6675
|
-
if (
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
if (left.length > 0 && right.length > 0) {
|
|
6695
|
-
const parsedStart = Date.parse(left);
|
|
6696
|
-
const parsedEnd = Date.parse(right);
|
|
6697
|
-
if (isNaN(parsedStart) || isNaN(parsedEnd)) return err({
|
|
6698
|
-
type: "InvalidDateFormat",
|
|
6699
|
-
span
|
|
6700
|
-
});
|
|
6701
|
-
return ok(dateRange(_bcts_dcbor.CborDate.fromDatetime(new Date(parsedStart)), _bcts_dcbor.CborDate.fromDatetime(new Date(parsedEnd))));
|
|
6669
|
+
const fallback = parseTagInner(innerContent);
|
|
6670
|
+
if (!fallback.ok) return fallback;
|
|
6671
|
+
lexer.bump(closeIdx);
|
|
6672
|
+
const close = lexer.next();
|
|
6673
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6674
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6675
|
+
return ok(fallback.value);
|
|
6676
|
+
}
|
|
6677
|
+
/**
|
|
6678
|
+
* Locate the index of the closing `)` matching the `(` that has already
|
|
6679
|
+
* been consumed by `parseTag`. Mirrors Rust `find_matching_paren`.
|
|
6680
|
+
*/
|
|
6681
|
+
function findMatchingCloseParen(src) {
|
|
6682
|
+
let depth = 0;
|
|
6683
|
+
for (let i = 0; i < src.length; i++) {
|
|
6684
|
+
const ch = src.charCodeAt(i);
|
|
6685
|
+
if (ch === 40) depth += 1;
|
|
6686
|
+
else if (ch === 41) {
|
|
6687
|
+
if (depth === 0) return i;
|
|
6688
|
+
depth -= 1;
|
|
6702
6689
|
}
|
|
6703
|
-
return err({
|
|
6704
|
-
type: "InvalidDateFormat",
|
|
6705
|
-
span
|
|
6706
|
-
});
|
|
6707
6690
|
}
|
|
6708
|
-
const parsed = Date.parse(content);
|
|
6709
|
-
if (isNaN(parsed)) return err({
|
|
6710
|
-
type: "InvalidDateFormat",
|
|
6711
|
-
span
|
|
6712
|
-
});
|
|
6713
|
-
return ok(date(_bcts_dcbor.CborDate.fromDatetime(new Date(parsed))));
|
|
6714
6691
|
}
|
|
6715
6692
|
/**
|
|
6716
|
-
*
|
|
6693
|
+
* Fallback for `tagged(N)` and `tagged(name)` when the full delegation
|
|
6694
|
+
* to dcbor-pattern fails. Mirrors Rust `parse_tag_inner`.
|
|
6717
6695
|
*/
|
|
6718
|
-
function
|
|
6719
|
-
const
|
|
6720
|
-
if (
|
|
6721
|
-
|
|
6696
|
+
function parseTagInner(src) {
|
|
6697
|
+
const trimmed = src.trim();
|
|
6698
|
+
if (trimmed.length === 0) return err(unexpectedEndOfInput());
|
|
6699
|
+
if (trimmed.startsWith("/")) return err(unexpectedEndOfInput());
|
|
6700
|
+
if (/^\d+$/.test(trimmed)) try {
|
|
6701
|
+
const dcborResult = (0, _bcts_dcbor_pattern.parse)(`tagged(${trimmed})`);
|
|
6702
|
+
if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
|
|
6703
|
+
} catch {}
|
|
6704
|
+
const dcborResult = (0, _bcts_dcbor_pattern.parse)(`tagged(${trimmed})`);
|
|
6705
|
+
if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
|
|
6706
|
+
return err(unexpectedEndOfInput());
|
|
6722
6707
|
}
|
|
6708
|
+
//#endregion
|
|
6709
|
+
//#region src/parse/structure/assertion-parser.ts
|
|
6723
6710
|
/**
|
|
6724
|
-
*
|
|
6711
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6712
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6713
|
+
*
|
|
6714
|
+
* Assertion parser — port of `bc-envelope-pattern-rust`
|
|
6715
|
+
* `parse/structure/assertion_parser.rs`.
|
|
6716
|
+
*
|
|
6717
|
+
* Note: Rust's `parse_assertion` ignores its lexer entirely and always
|
|
6718
|
+
* returns `Pattern::any_assertion()`. There is intentionally **no**
|
|
6719
|
+
* `assert(pred, obj)` syntax — predicate/object filters are written via
|
|
6720
|
+
* the dedicated `assertpred(...)` / `assertobj(...)` keywords.
|
|
6725
6721
|
*
|
|
6726
|
-
*
|
|
6727
|
-
* then CBOR diagnostic notation via parseDcborItemPartial, then falls
|
|
6728
|
-
* back to parseOr for envelope pattern expressions.
|
|
6722
|
+
* @module envelope-pattern/parse/structure/assertion-parser
|
|
6729
6723
|
*/
|
|
6730
|
-
function
|
|
6731
|
-
|
|
6732
|
-
lexer.next();
|
|
6733
|
-
if (lexer.peek() === "/") {
|
|
6734
|
-
const regexTokenResult = lexer.next();
|
|
6735
|
-
if (regexTokenResult?.token.type === "Regex") {
|
|
6736
|
-
const regexToken = regexTokenResult.token;
|
|
6737
|
-
if (!regexToken.value.ok) return err(regexToken.value.error);
|
|
6738
|
-
const keyword = regexToken.value.value;
|
|
6739
|
-
const dcborResult = (0, _bcts_dcbor_pattern.parse)(keyword);
|
|
6740
|
-
if (!dcborResult.ok) return err(unexpectedToken(regexToken, regexTokenResult.span));
|
|
6741
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6742
|
-
type: "ExpectedCloseParen",
|
|
6743
|
-
span: lexer.span()
|
|
6744
|
-
});
|
|
6745
|
-
return ok(cborPattern(dcborResult.value));
|
|
6746
|
-
}
|
|
6747
|
-
}
|
|
6748
|
-
const cborResult = (0, _bcts_dcbor_parse.parseDcborItemPartial)(lexer.remainder());
|
|
6749
|
-
if (cborResult.ok) {
|
|
6750
|
-
const [cborData, consumed] = cborResult.value;
|
|
6751
|
-
lexer.bump(consumed);
|
|
6752
|
-
while (lexer.peek() === " " || lexer.peek() === " " || lexer.peek() === "\n") lexer.bump(1);
|
|
6753
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6754
|
-
type: "ExpectedCloseParen",
|
|
6755
|
-
span: lexer.span()
|
|
6756
|
-
});
|
|
6757
|
-
return ok(cborValue(cborData));
|
|
6758
|
-
}
|
|
6759
|
-
const inner = parseOr(lexer);
|
|
6760
|
-
if (!inner.ok) return inner;
|
|
6761
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6762
|
-
type: "ExpectedCloseParen",
|
|
6763
|
-
span: lexer.span()
|
|
6764
|
-
});
|
|
6765
|
-
return inner;
|
|
6724
|
+
function parseAssertion(_lexer) {
|
|
6725
|
+
return ok(anyAssertion());
|
|
6766
6726
|
}
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6727
|
+
//#endregion
|
|
6728
|
+
//#region src/parse/structure/assertion-obj-parser.ts
|
|
6729
|
+
/**
|
|
6730
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6731
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6732
|
+
*
|
|
6733
|
+
* Assertion-object parser — port of
|
|
6734
|
+
* `bc-envelope-pattern-rust/src/parse/structure/assertion_obj_parser.rs`.
|
|
6735
|
+
*
|
|
6736
|
+
* Requires `assertobj(<pattern>)`. The bare `assertobj` keyword is a
|
|
6737
|
+
* syntax error in Rust; we now mirror that behaviour.
|
|
6738
|
+
*
|
|
6739
|
+
* @module envelope-pattern/parse/structure/assertion-obj-parser
|
|
6740
|
+
*/
|
|
6741
|
+
function parseAssertionObj(lexer) {
|
|
6742
|
+
const open = lexer.next();
|
|
6743
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6744
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6782
6745
|
const inner = parseOr(lexer);
|
|
6783
6746
|
if (!inner.ok) return inner;
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
return ok(patternStructure(structureNode(NodePattern.withSubject(inner.value))));
|
|
6789
|
-
}
|
|
6790
|
-
function parseAssertion(lexer) {
|
|
6791
|
-
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyAssertion());
|
|
6792
|
-
lexer.next();
|
|
6793
|
-
const pred = parseOr(lexer);
|
|
6794
|
-
if (!pred.ok) return pred;
|
|
6795
|
-
const comma = lexer.next();
|
|
6796
|
-
if (comma?.token.type !== "Comma") return err(unexpectedToken(comma?.token ?? { type: "Null" }, comma?.span ?? lexer.span()));
|
|
6797
|
-
const obj = parseOr(lexer);
|
|
6798
|
-
if (!obj.ok) return obj;
|
|
6799
|
-
if (lexer.next()?.token.type !== "ParenClose") return err({
|
|
6800
|
-
type: "ExpectedCloseParen",
|
|
6801
|
-
span: lexer.span()
|
|
6802
|
-
});
|
|
6803
|
-
return ok(patternStructure(structureAssertions(AssertionsPattern.withBoth(pred.value, obj.value))));
|
|
6747
|
+
const close = lexer.next();
|
|
6748
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6749
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6750
|
+
return ok(assertionWithObject(inner.value));
|
|
6804
6751
|
}
|
|
6752
|
+
//#endregion
|
|
6753
|
+
//#region src/parse/structure/assertion-pred-parser.ts
|
|
6754
|
+
/**
|
|
6755
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6756
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6757
|
+
*
|
|
6758
|
+
* Assertion-predicate parser — port of
|
|
6759
|
+
* `bc-envelope-pattern-rust/src/parse/structure/assertion_pred_parser.rs`.
|
|
6760
|
+
*
|
|
6761
|
+
* Requires `assertpred(<pattern>)`. The bare `assertpred` keyword is a
|
|
6762
|
+
* syntax error in Rust (it errors on `UnexpectedEndOfInput` /
|
|
6763
|
+
* `UnexpectedToken`); we now mirror that behaviour.
|
|
6764
|
+
*
|
|
6765
|
+
* @module envelope-pattern/parse/structure/assertion-pred-parser
|
|
6766
|
+
*/
|
|
6805
6767
|
function parseAssertionPred(lexer) {
|
|
6806
|
-
|
|
6807
|
-
|
|
6768
|
+
const open = lexer.next();
|
|
6769
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6770
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6808
6771
|
const inner = parseOr(lexer);
|
|
6809
6772
|
if (!inner.ok) return inner;
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
});
|
|
6773
|
+
const close = lexer.next();
|
|
6774
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6775
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6814
6776
|
return ok(assertionWithPredicate(inner.value));
|
|
6815
6777
|
}
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6778
|
+
//#endregion
|
|
6779
|
+
//#region src/parse/structure/compressed-parser.ts
|
|
6780
|
+
/**
|
|
6781
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6782
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6783
|
+
*
|
|
6784
|
+
* Compressed parser — port of `bc-envelope-pattern-rust`
|
|
6785
|
+
* `parse/structure/compressed_parser.rs`.
|
|
6786
|
+
*
|
|
6787
|
+
* @module envelope-pattern/parse/structure/compressed-parser
|
|
6788
|
+
*/
|
|
6789
|
+
function parseCompressed(_lexer) {
|
|
6790
|
+
return ok(compressed());
|
|
6826
6791
|
}
|
|
6792
|
+
//#endregion
|
|
6793
|
+
//#region src/parse/structure/digest-parser.ts
|
|
6794
|
+
/**
|
|
6795
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6796
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6797
|
+
*
|
|
6798
|
+
* Digest parser — port of `bc-envelope-pattern-rust`
|
|
6799
|
+
* `parse/structure/digest_parser.rs`.
|
|
6800
|
+
*
|
|
6801
|
+
* Mirrors Rust exactly:
|
|
6802
|
+
*
|
|
6803
|
+
* - Requires `digest(...)` — bare `digest` is an `UnexpectedEndOfInput`
|
|
6804
|
+
* error (the previous TS port silently returned `digest(any)`).
|
|
6805
|
+
* - Inside the parens, accepts either a UR string (`ur:digest/...`,
|
|
6806
|
+
* parsed via `Digest.fromURString`) or a hex byte prefix.
|
|
6807
|
+
* - Hex prefixes must have even length and not exceed `Digest.DIGEST_SIZE`
|
|
6808
|
+
* bytes; otherwise the parser surfaces `InvalidHexString`.
|
|
6809
|
+
*
|
|
6810
|
+
* @module envelope-pattern/parse/structure/digest-parser
|
|
6811
|
+
*/
|
|
6812
|
+
const DIGEST_SIZE = _bcts_envelope.Digest.DIGEST_SIZE;
|
|
6827
6813
|
function parseDigest(lexer) {
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
if (
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6814
|
+
const open = lexer.next();
|
|
6815
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
6816
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
6817
|
+
const innerResult = parseDigestInner(lexer.remainder(), lexer.position);
|
|
6818
|
+
if (!innerResult.ok) return innerResult;
|
|
6819
|
+
const [pattern, consumed] = innerResult.value;
|
|
6820
|
+
lexer.bump(consumed);
|
|
6821
|
+
const close = lexer.next();
|
|
6822
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6823
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6824
|
+
return ok(pattern);
|
|
6825
|
+
}
|
|
6826
|
+
function parseDigestInner(src, basePos) {
|
|
6827
|
+
let pos = 0;
|
|
6828
|
+
pos = skipWs(src, pos);
|
|
6829
|
+
if (src.startsWith("ur:", pos)) {
|
|
6830
|
+
const start = pos;
|
|
6831
|
+
while (pos < src.length && src[pos] !== ")") pos += 1;
|
|
6832
|
+
const ur = src.slice(start, pos).trimEnd();
|
|
6833
|
+
let parsed;
|
|
6834
|
+
try {
|
|
6835
|
+
parsed = _bcts_envelope.Digest.fromURString(ur);
|
|
6836
|
+
} catch {
|
|
6837
|
+
return err(invalidUr(ur, {
|
|
6838
|
+
start: basePos + start,
|
|
6839
|
+
end: basePos + pos
|
|
6840
|
+
}));
|
|
6841
|
+
}
|
|
6842
|
+
pos = skipWs(src, pos);
|
|
6843
|
+
return ok([digest(parsed), pos]);
|
|
6844
|
+
}
|
|
6845
|
+
const start = pos;
|
|
6846
|
+
while (pos < src.length && isAsciiHexDigit(src.charCodeAt(pos))) pos += 1;
|
|
6847
|
+
if (pos === start) return err(invalidHexString({
|
|
6848
|
+
start: basePos + pos,
|
|
6849
|
+
end: basePos + pos
|
|
6850
|
+
}));
|
|
6851
|
+
const hexStr = src.slice(start, pos);
|
|
6852
|
+
if (hexStr.length % 2 !== 0) return err(invalidHexString({
|
|
6853
|
+
start: basePos + pos,
|
|
6854
|
+
end: basePos + pos
|
|
6855
|
+
}));
|
|
6856
|
+
const bytes = decodeHex(hexStr);
|
|
6857
|
+
if (bytes === void 0) return err(invalidHexString({
|
|
6858
|
+
start: basePos + pos,
|
|
6859
|
+
end: basePos + pos
|
|
6860
|
+
}));
|
|
6861
|
+
if (bytes.length > DIGEST_SIZE) return err(invalidHexString({
|
|
6862
|
+
start: basePos + pos,
|
|
6863
|
+
end: basePos + pos
|
|
6864
|
+
}));
|
|
6865
|
+
pos = skipWs(src, pos);
|
|
6866
|
+
return ok([digestPrefix(bytes), pos]);
|
|
6867
|
+
}
|
|
6868
|
+
function skipWs(src, pos) {
|
|
6869
|
+
while (pos < src.length) {
|
|
6870
|
+
const ch = src[pos];
|
|
6871
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos += 1;
|
|
6872
|
+
else break;
|
|
6839
6873
|
}
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
return ok(digestPrefix(bytes));
|
|
6874
|
+
return pos;
|
|
6875
|
+
}
|
|
6876
|
+
function isAsciiHexDigit(c) {
|
|
6877
|
+
return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
|
|
6878
|
+
}
|
|
6879
|
+
function decodeHex(hex) {
|
|
6880
|
+
if (hex.length % 2 !== 0) return void 0;
|
|
6881
|
+
const out = new Uint8Array(hex.length / 2);
|
|
6882
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
6883
|
+
const value = Number.parseInt(hex.slice(i, i + 2), 16);
|
|
6884
|
+
if (Number.isNaN(value)) return void 0;
|
|
6885
|
+
out[i / 2] = value;
|
|
6853
6886
|
}
|
|
6854
|
-
return
|
|
6887
|
+
return out;
|
|
6888
|
+
}
|
|
6889
|
+
//#endregion
|
|
6890
|
+
//#region src/parse/structure/elided-parser.ts
|
|
6891
|
+
/**
|
|
6892
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6893
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6894
|
+
*
|
|
6895
|
+
* Elided parser — port of `bc-envelope-pattern-rust`
|
|
6896
|
+
* `parse/structure/elided_parser.rs`.
|
|
6897
|
+
*
|
|
6898
|
+
* @module envelope-pattern/parse/structure/elided-parser
|
|
6899
|
+
*/
|
|
6900
|
+
function parseElided(_lexer) {
|
|
6901
|
+
return ok(elided());
|
|
6855
6902
|
}
|
|
6903
|
+
//#endregion
|
|
6904
|
+
//#region src/parse/structure/encrypted-parser.ts
|
|
6905
|
+
/**
|
|
6906
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6907
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6908
|
+
*
|
|
6909
|
+
* Encrypted parser — port of `bc-envelope-pattern-rust`
|
|
6910
|
+
* `parse/structure/encrypted_parser.rs`.
|
|
6911
|
+
*
|
|
6912
|
+
* @module envelope-pattern/parse/structure/encrypted-parser
|
|
6913
|
+
*/
|
|
6914
|
+
function parseEncrypted(_lexer) {
|
|
6915
|
+
return ok(encrypted());
|
|
6916
|
+
}
|
|
6917
|
+
//#endregion
|
|
6918
|
+
//#region src/parse/structure/node-parser.ts
|
|
6919
|
+
/**
|
|
6920
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6921
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6922
|
+
*
|
|
6923
|
+
* Node parser — port of `bc-envelope-pattern-rust`
|
|
6924
|
+
* `parse/structure/node_parser.rs`.
|
|
6925
|
+
*
|
|
6926
|
+
* Mirrors Rust:
|
|
6927
|
+
* - Bare `node` → `any_node()`.
|
|
6928
|
+
* - `node({n})` / `node({n,m})` / `node({n,})` → `node_with_assertions_range`.
|
|
6929
|
+
* - Anything else inside the parens (e.g. `node(text)`) is a syntax error
|
|
6930
|
+
* in Rust; the previous TS port silently produced an always-matching
|
|
6931
|
+
* `WithSubject` node, which we have removed.
|
|
6932
|
+
*
|
|
6933
|
+
* @module envelope-pattern/parse/structure/node-parser
|
|
6934
|
+
*/
|
|
6935
|
+
function parseNode(lexer) {
|
|
6936
|
+
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyNode());
|
|
6937
|
+
lexer.next();
|
|
6938
|
+
const inner = lexer.next();
|
|
6939
|
+
if (inner === void 0) return err(unexpectedEndOfInput());
|
|
6940
|
+
if (inner.token.type !== "Range") return err(unexpectedToken(inner.token, inner.span));
|
|
6941
|
+
if (!inner.token.value.ok) return err(inner.token.value.error);
|
|
6942
|
+
const interval = inner.token.value.value.interval();
|
|
6943
|
+
const close = lexer.next();
|
|
6944
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6945
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6946
|
+
return ok(patternStructure(structureNode(NodePattern.fromInterval(interval))));
|
|
6947
|
+
}
|
|
6948
|
+
//#endregion
|
|
6949
|
+
//#region src/parse/structure/object-parser.ts
|
|
6950
|
+
/**
|
|
6951
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6952
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6953
|
+
*
|
|
6954
|
+
* Object parser — port of `bc-envelope-pattern-rust`
|
|
6955
|
+
* `parse/structure/object_parser.rs`.
|
|
6956
|
+
*
|
|
6957
|
+
* @module envelope-pattern/parse/structure/object-parser
|
|
6958
|
+
*/
|
|
6856
6959
|
function parseObject(lexer) {
|
|
6857
6960
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyObject());
|
|
6858
6961
|
lexer.next();
|
|
6859
6962
|
const inner = parseOr(lexer);
|
|
6860
6963
|
if (!inner.ok) return inner;
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
});
|
|
6964
|
+
const close = lexer.next();
|
|
6965
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
6966
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6865
6967
|
return ok(object(inner.value));
|
|
6866
6968
|
}
|
|
6969
|
+
//#endregion
|
|
6970
|
+
//#region src/parse/structure/obscured-parser.ts
|
|
6971
|
+
/**
|
|
6972
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6973
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6974
|
+
*
|
|
6975
|
+
* Obscured parser — port of `bc-envelope-pattern-rust`
|
|
6976
|
+
* `parse/structure/obscured_parser.rs`.
|
|
6977
|
+
*
|
|
6978
|
+
* @module envelope-pattern/parse/structure/obscured-parser
|
|
6979
|
+
*/
|
|
6980
|
+
function parseObscured(_lexer) {
|
|
6981
|
+
return ok(obscured());
|
|
6982
|
+
}
|
|
6983
|
+
//#endregion
|
|
6984
|
+
//#region src/parse/structure/predicate-parser.ts
|
|
6985
|
+
/**
|
|
6986
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
6987
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
6988
|
+
*
|
|
6989
|
+
* Predicate parser — port of `bc-envelope-pattern-rust`
|
|
6990
|
+
* `parse/structure/predicate_parser.rs`.
|
|
6991
|
+
*
|
|
6992
|
+
* @module envelope-pattern/parse/structure/predicate-parser
|
|
6993
|
+
*/
|
|
6867
6994
|
function parsePredicate(lexer) {
|
|
6868
6995
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyPredicate());
|
|
6869
6996
|
lexer.next();
|
|
6870
6997
|
const inner = parseOr(lexer);
|
|
6871
6998
|
if (!inner.ok) return inner;
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
});
|
|
6999
|
+
const close = lexer.next();
|
|
7000
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7001
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6876
7002
|
return ok(predicate(inner.value));
|
|
6877
7003
|
}
|
|
7004
|
+
//#endregion
|
|
7005
|
+
//#region src/parse/structure/subject-parser.ts
|
|
7006
|
+
/**
|
|
7007
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7008
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7009
|
+
*
|
|
7010
|
+
* Subject parser — port of `bc-envelope-pattern-rust`
|
|
7011
|
+
* `parse/structure/subject_parser.rs`.
|
|
7012
|
+
*
|
|
7013
|
+
* @module envelope-pattern/parse/structure/subject-parser
|
|
7014
|
+
*/
|
|
6878
7015
|
function parseSubject(lexer) {
|
|
6879
7016
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anySubject());
|
|
6880
7017
|
lexer.next();
|
|
6881
7018
|
const inner = parseOr(lexer);
|
|
6882
7019
|
if (!inner.ok) return inner;
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
});
|
|
7020
|
+
const close = lexer.next();
|
|
7021
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7022
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6887
7023
|
return ok(subject(inner.value));
|
|
6888
7024
|
}
|
|
7025
|
+
//#endregion
|
|
7026
|
+
//#region src/parse/structure/wrapped-parser.ts
|
|
7027
|
+
/**
|
|
7028
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7029
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7030
|
+
*
|
|
7031
|
+
* Wrapped/unwrap parser — port of `bc-envelope-pattern-rust`
|
|
7032
|
+
* `parse/structure/wrapped_parser.rs`.
|
|
7033
|
+
*
|
|
7034
|
+
* @module envelope-pattern/parse/structure/wrapped-parser
|
|
7035
|
+
*/
|
|
7036
|
+
function parseWrapped(_lexer) {
|
|
7037
|
+
return ok(wrapped());
|
|
7038
|
+
}
|
|
6889
7039
|
function parseUnwrap(lexer) {
|
|
6890
7040
|
if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(unwrapEnvelope());
|
|
6891
7041
|
lexer.next();
|
|
6892
7042
|
const inner = parseOr(lexer);
|
|
6893
7043
|
if (!inner.ok) return inner;
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
});
|
|
7044
|
+
const close = lexer.next();
|
|
7045
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7046
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
6898
7047
|
return ok(unwrapMatching(inner.value));
|
|
6899
7048
|
}
|
|
6900
7049
|
//#endregion
|
|
7050
|
+
//#region src/parse/meta/capture-parser.ts
|
|
7051
|
+
/**
|
|
7052
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7053
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7054
|
+
*
|
|
7055
|
+
* Capture parser — port of `bc-envelope-pattern-rust`
|
|
7056
|
+
* `parse/meta/capture_parser.rs`.
|
|
7057
|
+
*
|
|
7058
|
+
* The `@name(...)` form requires explicit parentheses. Mirrors Rust
|
|
7059
|
+
* exactly:
|
|
7060
|
+
* ```ignore
|
|
7061
|
+
* @name ( expr )
|
|
7062
|
+
* ```
|
|
7063
|
+
* The previous TS port called `parse_group` (primary + quantifier), which
|
|
7064
|
+
* wrapped the inner expression in a redundant `GroupPattern` and accepted
|
|
7065
|
+
* the bare `@name p` form that Rust rejects.
|
|
7066
|
+
*
|
|
7067
|
+
* @module envelope-pattern/parse/meta/capture-parser
|
|
7068
|
+
*/
|
|
7069
|
+
function parseCapture(lexer, name) {
|
|
7070
|
+
const open = lexer.next();
|
|
7071
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
7072
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
7073
|
+
const inner = parseOr(lexer);
|
|
7074
|
+
if (!inner.ok) return inner;
|
|
7075
|
+
const close = lexer.next();
|
|
7076
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7077
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7078
|
+
return ok(capture(name, inner.value));
|
|
7079
|
+
}
|
|
7080
|
+
//#endregion
|
|
7081
|
+
//#region src/parse/meta/group-parser.ts
|
|
7082
|
+
/**
|
|
7083
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7084
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7085
|
+
*
|
|
7086
|
+
* Group parser — port of `bc-envelope-pattern-rust`
|
|
7087
|
+
* `parse/meta/group_parser.rs`.
|
|
7088
|
+
*
|
|
7089
|
+
* Called from `parse_primary` after the opening `(` has been consumed.
|
|
7090
|
+
*
|
|
7091
|
+
* Mirrors Rust exactly:
|
|
7092
|
+
*
|
|
7093
|
+
* - Parse the inner expression with `parse_or`.
|
|
7094
|
+
* - Expect `)`. If missing, surface `ExpectedCloseParen`.
|
|
7095
|
+
* - Lookahead **once** for a quantifier suffix. If present, consume it
|
|
7096
|
+
* and wrap as `Pattern::repeat(inner, …)`. Otherwise return the inner
|
|
7097
|
+
* expression unchanged.
|
|
7098
|
+
*
|
|
7099
|
+
* The previous TS port wrapped every parenthesised expression in a
|
|
7100
|
+
* dedicated `GroupPattern` and applied quantifiers to bare primaries —
|
|
7101
|
+
* both broke `format(parse(s)) === s` round-tripping.
|
|
7102
|
+
*
|
|
7103
|
+
* @module envelope-pattern/parse/meta/group-parser
|
|
7104
|
+
*/
|
|
7105
|
+
function parseGroup(lexer) {
|
|
7106
|
+
const inner = parseOr(lexer);
|
|
7107
|
+
if (!inner.ok) return inner;
|
|
7108
|
+
const close = lexer.next();
|
|
7109
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7110
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7111
|
+
const next = lexer.peekToken();
|
|
7112
|
+
if (next === void 0) return inner;
|
|
7113
|
+
let quantifier;
|
|
7114
|
+
const tokenType = next.token.type;
|
|
7115
|
+
if (tokenType === "RepeatZeroOrMore") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
7116
|
+
else if (tokenType === "RepeatZeroOrMoreLazy") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
7117
|
+
else if (tokenType === "RepeatZeroOrMorePossessive") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrMore(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
7118
|
+
else if (tokenType === "RepeatOneOrMore") quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
7119
|
+
else if (tokenType === "RepeatOneOrMoreLazy") quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
7120
|
+
else if (tokenType === "RepeatOneOrMorePossessive") quantifier = _bcts_dcbor_pattern.Quantifier.oneOrMore(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
7121
|
+
else if (tokenType === "RepeatZeroOrOne") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Greedy);
|
|
7122
|
+
else if (tokenType === "RepeatZeroOrOneLazy") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Lazy);
|
|
7123
|
+
else if (tokenType === "RepeatZeroOrOnePossessive") quantifier = _bcts_dcbor_pattern.Quantifier.zeroOrOne(_bcts_dcbor_pattern.Reluctance.Possessive);
|
|
7124
|
+
else if (tokenType === "Range") {
|
|
7125
|
+
if (!next.token.value.ok) return err(next.token.value.error);
|
|
7126
|
+
quantifier = next.token.value.value;
|
|
7127
|
+
} else return inner;
|
|
7128
|
+
lexer.next();
|
|
7129
|
+
return ok(repeat(inner.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
|
|
7130
|
+
}
|
|
7131
|
+
//#endregion
|
|
7132
|
+
//#region src/parse/meta/search-parser.ts
|
|
7133
|
+
/**
|
|
7134
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7135
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7136
|
+
*
|
|
7137
|
+
* Search parser — port of `bc-envelope-pattern-rust`
|
|
7138
|
+
* `parse/meta/search_parser.rs`.
|
|
7139
|
+
*
|
|
7140
|
+
* @module envelope-pattern/parse/meta/search-parser
|
|
7141
|
+
*/
|
|
7142
|
+
function parseSearch(lexer) {
|
|
7143
|
+
const open = lexer.next();
|
|
7144
|
+
if (open === void 0) return err(unexpectedEndOfInput());
|
|
7145
|
+
if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
|
|
7146
|
+
const inner = parseOr(lexer);
|
|
7147
|
+
if (!inner.ok) return inner;
|
|
7148
|
+
const close = lexer.next();
|
|
7149
|
+
if (close === void 0) return err(expectedCloseParen(lexer.span()));
|
|
7150
|
+
if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
|
|
7151
|
+
return ok(search(inner.value));
|
|
7152
|
+
}
|
|
7153
|
+
//#endregion
|
|
7154
|
+
//#region src/parse/meta/primary-parser.ts
|
|
7155
|
+
/**
|
|
7156
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7157
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7158
|
+
*
|
|
7159
|
+
* Primary parser — port of `bc-envelope-pattern-rust`
|
|
7160
|
+
* `parse/meta/primary_parser.rs`.
|
|
7161
|
+
*
|
|
7162
|
+
* Dispatches on the next token to the appropriate leaf/structure/meta
|
|
7163
|
+
* parser. When a `(` is encountered the open paren is consumed here and
|
|
7164
|
+
* `parse_group` handles the rest (paren'd expression + optional
|
|
7165
|
+
* quantifier suffix).
|
|
7166
|
+
*
|
|
7167
|
+
* @module envelope-pattern/parse/meta/primary-parser
|
|
7168
|
+
*/
|
|
7169
|
+
function parsePrimary(lexer) {
|
|
7170
|
+
const tokenResult = lexer.next();
|
|
7171
|
+
if (tokenResult === void 0) return err(unexpectedEndOfInput());
|
|
7172
|
+
const { token, span } = tokenResult;
|
|
7173
|
+
switch (token.type) {
|
|
7174
|
+
case "Search": return parseSearch(lexer);
|
|
7175
|
+
case "Node": return parseNode(lexer);
|
|
7176
|
+
case "Assertion": return parseAssertion(lexer);
|
|
7177
|
+
case "AssertionPred": return parseAssertionPred(lexer);
|
|
7178
|
+
case "AssertionObj": return parseAssertionObj(lexer);
|
|
7179
|
+
case "Digest": return parseDigest(lexer);
|
|
7180
|
+
case "Obj": return parseObject(lexer);
|
|
7181
|
+
case "Obscured": return parseObscured(lexer);
|
|
7182
|
+
case "Elided": return parseElided(lexer);
|
|
7183
|
+
case "Encrypted": return parseEncrypted(lexer);
|
|
7184
|
+
case "Compressed": return parseCompressed(lexer);
|
|
7185
|
+
case "Pred": return parsePredicate(lexer);
|
|
7186
|
+
case "Subject": return parseSubject(lexer);
|
|
7187
|
+
case "Wrapped": return parseWrapped(lexer);
|
|
7188
|
+
case "Unwrap": return parseUnwrap(lexer);
|
|
7189
|
+
case "Leaf": return ok(leaf());
|
|
7190
|
+
case "GroupName": return parseCapture(lexer, token.name);
|
|
7191
|
+
case "ParenOpen": return parseGroup(lexer);
|
|
7192
|
+
case "Cbor": return parseCbor(lexer);
|
|
7193
|
+
case "RepeatZeroOrMore": return ok(any());
|
|
7194
|
+
case "BoolKeyword": return ok(anyBool());
|
|
7195
|
+
case "BoolTrue": return ok(bool(true));
|
|
7196
|
+
case "BoolFalse": return ok(bool(false));
|
|
7197
|
+
case "NumberKeyword": return ok(anyNumber());
|
|
7198
|
+
case "TextKeyword": return ok(anyText());
|
|
7199
|
+
case "StringLiteral":
|
|
7200
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7201
|
+
return ok(text(token.value.value));
|
|
7202
|
+
case "UnsignedInteger":
|
|
7203
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7204
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7205
|
+
case "Integer":
|
|
7206
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7207
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7208
|
+
case "Float":
|
|
7209
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7210
|
+
return parseNumberRangeOrComparison(lexer, token.value.value);
|
|
7211
|
+
case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
|
|
7212
|
+
case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
|
|
7213
|
+
case "GreaterThan": return parseComparisonNumber(lexer, ">");
|
|
7214
|
+
case "LessThan": return parseComparisonNumber(lexer, "<");
|
|
7215
|
+
case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
|
|
7216
|
+
case "Infinity": return ok(number(Infinity));
|
|
7217
|
+
case "NegativeInfinity": return ok(number(-Infinity));
|
|
7218
|
+
case "Regex":
|
|
7219
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7220
|
+
try {
|
|
7221
|
+
return ok(textRegex(new RegExp(token.value.value)));
|
|
7222
|
+
} catch {
|
|
7223
|
+
return err(invalidRegex(span));
|
|
7224
|
+
}
|
|
7225
|
+
case "BracketOpen": return parseArray(lexer);
|
|
7226
|
+
case "ByteString": return ok(anyByteString());
|
|
7227
|
+
case "HexPattern":
|
|
7228
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7229
|
+
return ok(byteString(token.value.value));
|
|
7230
|
+
case "HexBinaryRegex":
|
|
7231
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7232
|
+
try {
|
|
7233
|
+
return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
|
|
7234
|
+
} catch {
|
|
7235
|
+
return err(invalidRegex(span));
|
|
7236
|
+
}
|
|
7237
|
+
case "DateKeyword": return ok(anyDate());
|
|
7238
|
+
case "DatePattern":
|
|
7239
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7240
|
+
return parseDateContent(token.value.value, span);
|
|
7241
|
+
case "Tagged": return parseTag(lexer);
|
|
7242
|
+
case "Known": return ok(anyKnownValue());
|
|
7243
|
+
case "SingleQuotedPattern":
|
|
7244
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7245
|
+
return parseKnownValueContent(token.value.value);
|
|
7246
|
+
case "SingleQuotedRegex":
|
|
7247
|
+
if (!token.value.ok) return err(token.value.error);
|
|
7248
|
+
try {
|
|
7249
|
+
return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
|
|
7250
|
+
} catch {
|
|
7251
|
+
return err(invalidRegex(span));
|
|
7252
|
+
}
|
|
7253
|
+
case "Null": return ok(nullPattern());
|
|
7254
|
+
case "Identifier": return err(unrecognizedToken(span));
|
|
7255
|
+
case "And":
|
|
7256
|
+
case "Or":
|
|
7257
|
+
case "Not":
|
|
7258
|
+
case "Traverse":
|
|
7259
|
+
case "RepeatZeroOrMoreLazy":
|
|
7260
|
+
case "RepeatZeroOrMorePossessive":
|
|
7261
|
+
case "RepeatOneOrMore":
|
|
7262
|
+
case "RepeatOneOrMoreLazy":
|
|
7263
|
+
case "RepeatOneOrMorePossessive":
|
|
7264
|
+
case "RepeatZeroOrOne":
|
|
7265
|
+
case "RepeatZeroOrOneLazy":
|
|
7266
|
+
case "RepeatZeroOrOnePossessive":
|
|
7267
|
+
case "ParenClose":
|
|
7268
|
+
case "BracketClose":
|
|
7269
|
+
case "Comma":
|
|
7270
|
+
case "Ellipsis":
|
|
7271
|
+
case "Range": return err(unexpectedToken(token, span));
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
//#endregion
|
|
7275
|
+
//#region src/parse/meta/and-parser.ts
|
|
7276
|
+
/**
|
|
7277
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7278
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7279
|
+
*
|
|
7280
|
+
* And parser — port of `bc-envelope-pattern-rust`
|
|
7281
|
+
* `parse/meta/and_parser.rs`.
|
|
7282
|
+
*
|
|
7283
|
+
* Mirrors Rust: `parse_and` calls `parse_primary` (NOT `parse_not`); `!`
|
|
7284
|
+
* is handled at a higher precedence level by `parse_not`.
|
|
7285
|
+
*
|
|
7286
|
+
* @module envelope-pattern/parse/meta/and-parser
|
|
7287
|
+
*/
|
|
7288
|
+
function parseAnd(lexer) {
|
|
7289
|
+
const patterns = [];
|
|
7290
|
+
const first = parsePrimary(lexer);
|
|
7291
|
+
if (!first.ok) return first;
|
|
7292
|
+
patterns.push(first.value);
|
|
7293
|
+
while (true) {
|
|
7294
|
+
if (lexer.peekToken()?.token.type !== "And") break;
|
|
7295
|
+
lexer.next();
|
|
7296
|
+
const nextExpr = parsePrimary(lexer);
|
|
7297
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7298
|
+
patterns.push(nextExpr.value);
|
|
7299
|
+
}
|
|
7300
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7301
|
+
return ok(and(patterns));
|
|
7302
|
+
}
|
|
7303
|
+
//#endregion
|
|
7304
|
+
//#region src/parse/meta/not-parser.ts
|
|
7305
|
+
/**
|
|
7306
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7307
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7308
|
+
*
|
|
7309
|
+
* Not parser — port of `bc-envelope-pattern-rust`
|
|
7310
|
+
* `parse/meta/not_parser.rs`.
|
|
7311
|
+
*
|
|
7312
|
+
* Mirrors Rust:
|
|
7313
|
+
* - On `!`, recurse into `parse_not` so chained negation parses as
|
|
7314
|
+
* `not(not(x))` rather than `not(group(x))`.
|
|
7315
|
+
* - Otherwise descend into `parse_and`.
|
|
7316
|
+
*
|
|
7317
|
+
* @module envelope-pattern/parse/meta/not-parser
|
|
7318
|
+
*/
|
|
7319
|
+
function parseNot(lexer) {
|
|
7320
|
+
if (lexer.peekToken()?.token.type === "Not") {
|
|
7321
|
+
lexer.next();
|
|
7322
|
+
const inner = parseNot(lexer);
|
|
7323
|
+
if (!inner.ok) return inner;
|
|
7324
|
+
return ok(notMatching(inner.value));
|
|
7325
|
+
}
|
|
7326
|
+
return parseAnd(lexer);
|
|
7327
|
+
}
|
|
7328
|
+
//#endregion
|
|
7329
|
+
//#region src/parse/meta/traverse-parser.ts
|
|
7330
|
+
/**
|
|
7331
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7332
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7333
|
+
*
|
|
7334
|
+
* Traverse parser — port of `bc-envelope-pattern-rust`
|
|
7335
|
+
* `parse/meta/traverse_parser.rs`.
|
|
7336
|
+
*
|
|
7337
|
+
* Note the precedence chain: `parse_or → parse_traverse → parse_not →
|
|
7338
|
+
* parse_and → parse_primary`. The earlier TS port had `parse_traverse`
|
|
7339
|
+
* call `parse_and` directly, which pushed `!` below `&` and
|
|
7340
|
+
* miscompiled `!a & b`.
|
|
7341
|
+
*
|
|
7342
|
+
* @module envelope-pattern/parse/meta/traverse-parser
|
|
7343
|
+
*/
|
|
7344
|
+
function parseTraverse(lexer) {
|
|
7345
|
+
const patterns = [];
|
|
7346
|
+
const first = parseNot(lexer);
|
|
7347
|
+
if (!first.ok) return first;
|
|
7348
|
+
patterns.push(first.value);
|
|
7349
|
+
while (true) {
|
|
7350
|
+
if (lexer.peekToken()?.token.type !== "Traverse") break;
|
|
7351
|
+
lexer.next();
|
|
7352
|
+
const nextExpr = parseNot(lexer);
|
|
7353
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7354
|
+
patterns.push(nextExpr.value);
|
|
7355
|
+
}
|
|
7356
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7357
|
+
return ok(traverse(patterns));
|
|
7358
|
+
}
|
|
7359
|
+
//#endregion
|
|
7360
|
+
//#region src/parse/meta/or-parser.ts
|
|
7361
|
+
/**
|
|
7362
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7363
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7364
|
+
*
|
|
7365
|
+
* Or parser — port of `bc-envelope-pattern-rust` `parse/meta/or_parser.rs`.
|
|
7366
|
+
*
|
|
7367
|
+
* @module envelope-pattern/parse/meta/or-parser
|
|
7368
|
+
*/
|
|
7369
|
+
function parseOr(lexer) {
|
|
7370
|
+
const patterns = [];
|
|
7371
|
+
const first = parseTraverse(lexer);
|
|
7372
|
+
if (!first.ok) return first;
|
|
7373
|
+
patterns.push(first.value);
|
|
7374
|
+
while (true) {
|
|
7375
|
+
if (lexer.peekToken()?.token.type !== "Or") break;
|
|
7376
|
+
lexer.next();
|
|
7377
|
+
const nextExpr = parseTraverse(lexer);
|
|
7378
|
+
if (!nextExpr.ok) return nextExpr;
|
|
7379
|
+
patterns.push(nextExpr.value);
|
|
7380
|
+
}
|
|
7381
|
+
if (patterns.length === 1) return ok(patterns[0]);
|
|
7382
|
+
return ok(or(patterns));
|
|
7383
|
+
}
|
|
7384
|
+
//#endregion
|
|
7385
|
+
//#region src/parse/index.ts
|
|
7386
|
+
/**
|
|
7387
|
+
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
7388
|
+
* Copyright © 2025-2026 Parity Technologies
|
|
7389
|
+
*
|
|
7390
|
+
*
|
|
7391
|
+
* @bcts/envelope-pattern - Parser entry point
|
|
7392
|
+
*
|
|
7393
|
+
* This is a 1:1 TypeScript port of bc-envelope-pattern-rust parse/mod.rs.
|
|
7394
|
+
*
|
|
7395
|
+
* Recursive-descent parser for the Gordian Envelope pattern syntax. The
|
|
7396
|
+
* parsing rules live under `parse/leaf/`, `parse/meta/`, and
|
|
7397
|
+
* `parse/structure/`, mirroring the Rust crate's module layout.
|
|
7398
|
+
*
|
|
7399
|
+
* @module envelope-pattern/parse
|
|
7400
|
+
*/
|
|
7401
|
+
/**
|
|
7402
|
+
* Parse a pattern expression string into a Pattern.
|
|
7403
|
+
*
|
|
7404
|
+
* Mirrors Rust `Pattern::parse`: tries envelope-pattern parsing first;
|
|
7405
|
+
* on failure falls back to dcbor-pattern parsing and converts the
|
|
7406
|
+
* result into an envelope pattern via the
|
|
7407
|
+
* `dcbor_integration::convert_dcbor_pattern_to_envelope_pattern` bridge.
|
|
7408
|
+
*/
|
|
7409
|
+
function parse(input) {
|
|
7410
|
+
const lexer = new Lexer(input);
|
|
7411
|
+
const result = parseOr(lexer);
|
|
7412
|
+
if (!result.ok) {
|
|
7413
|
+
const dcborResult = (0, _bcts_dcbor_pattern.parse)(input);
|
|
7414
|
+
if (dcborResult.ok) return convertDcborPatternToEnvelopePattern(dcborResult.value);
|
|
7415
|
+
return result;
|
|
7416
|
+
}
|
|
7417
|
+
const next = lexer.next();
|
|
7418
|
+
if (next !== void 0) return err(extraData(next.span));
|
|
7419
|
+
return result;
|
|
7420
|
+
}
|
|
7421
|
+
/**
|
|
7422
|
+
* Parse a pattern, allowing extra data after the pattern.
|
|
7423
|
+
*
|
|
7424
|
+
* Returns the parsed pattern and the byte offset at which parsing
|
|
7425
|
+
* stopped, mirroring `Pattern::parse_partial` in spirit.
|
|
7426
|
+
*/
|
|
7427
|
+
function parsePartial(input) {
|
|
7428
|
+
const lexer = new Lexer(input);
|
|
7429
|
+
const result = parseOr(lexer);
|
|
7430
|
+
if (!result.ok) return result;
|
|
7431
|
+
return ok([result.value, lexer.position]);
|
|
7432
|
+
}
|
|
7433
|
+
//#endregion
|
|
6901
7434
|
//#region src/index.ts
|
|
6902
7435
|
/**
|
|
6903
7436
|
* Package version.
|
|
@@ -7090,6 +7623,7 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
7090
7623
|
exports.registerAnyPatternFactory = registerAnyPatternFactory;
|
|
7091
7624
|
exports.registerArrayPatternFactory = registerArrayPatternFactory;
|
|
7092
7625
|
exports.registerAssertionsPatternFactory = registerAssertionsPatternFactory;
|
|
7626
|
+
exports.registerAssertionsPatternToStringDispatch = registerAssertionsPatternToStringDispatch;
|
|
7093
7627
|
exports.registerBoolPatternFactory = registerBoolPatternFactory;
|
|
7094
7628
|
exports.registerByteStringPatternFactory = registerByteStringPatternFactory;
|
|
7095
7629
|
exports.registerCBORPatternFactory = registerCBORPatternFactory;
|
|
@@ -7111,11 +7645,13 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
7111
7645
|
exports.registerPatternMatchFn = registerPatternMatchFn;
|
|
7112
7646
|
exports.registerPredicatePatternFactory = registerPredicatePatternFactory;
|
|
7113
7647
|
exports.registerSearchPatternFactory = registerSearchPatternFactory;
|
|
7648
|
+
exports.registerSubjectPatternDispatch = registerSubjectPatternDispatch;
|
|
7114
7649
|
exports.registerSubjectPatternFactory = registerSubjectPatternFactory;
|
|
7115
7650
|
exports.registerTaggedPatternFactory = registerTaggedPatternFactory;
|
|
7116
7651
|
exports.registerTextPatternFactory = registerTextPatternFactory;
|
|
7117
7652
|
exports.registerTraversePatternFactory = registerTraversePatternFactory;
|
|
7118
7653
|
exports.registerVMPatternFunctions = registerVMPatternFunctions;
|
|
7654
|
+
exports.registerWrappedPatternAny = registerWrappedPatternAny;
|
|
7119
7655
|
exports.registerWrappedPatternDispatch = registerWrappedPatternDispatch;
|
|
7120
7656
|
exports.registerWrappedPatternFactory = registerWrappedPatternFactory;
|
|
7121
7657
|
exports.repeat = repeat;
|
|
@@ -7155,6 +7691,6 @@ var bctsEnvelopePattern = (function(exports, _bcts_dcbor_pattern, _bcts_known_va
|
|
|
7155
7691
|
exports.unwrapOr = unwrapOr;
|
|
7156
7692
|
exports.wrapped = wrapped;
|
|
7157
7693
|
return exports;
|
|
7158
|
-
})({}, bctsDcborPattern, bctsKnownValues,
|
|
7694
|
+
})({}, bctsDcborPattern, bctsKnownValues, bctsDcbor, bctsEnvelope, bctsDcborParse);
|
|
7159
7695
|
|
|
7160
7696
|
//# sourceMappingURL=index.iife.js.map
|