@bcts/envelope-pattern 1.0.0-alpha.16 → 1.0.0-alpha.17
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 +485 -485
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -29
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -29
- package/dist/index.d.mts.map +1 -1
- package/dist/index.iife.js +485 -485
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +504 -504
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/format.ts +9 -9
- package/src/parse/token.ts +55 -55
- package/src/pattern/leaf/array-pattern.ts +25 -25
- package/src/pattern/leaf/bool-pattern.ts +11 -11
- package/src/pattern/leaf/byte-string-pattern.ts +14 -14
- package/src/pattern/leaf/cbor-pattern.ts +29 -29
- package/src/pattern/leaf/date-pattern.ts +8 -8
- package/src/pattern/leaf/known-value-pattern.ts +17 -17
- package/src/pattern/leaf/map-pattern.ts +13 -13
- package/src/pattern/leaf/null-pattern.ts +7 -7
- package/src/pattern/leaf/number-pattern.ts +19 -19
- package/src/pattern/leaf/tagged-pattern.ts +20 -20
- package/src/pattern/leaf/text-pattern.ts +13 -13
- package/src/pattern/meta/and-pattern.ts +11 -11
- package/src/pattern/meta/capture-pattern.ts +14 -14
- package/src/pattern/meta/group-pattern.ts +13 -13
- package/src/pattern/meta/not-pattern.ts +7 -7
- package/src/pattern/meta/or-pattern.ts +15 -15
- package/src/pattern/meta/search-pattern.ts +15 -15
- package/src/pattern/meta/traverse-pattern.ts +15 -15
- package/src/pattern/structure/assertions-pattern.ts +28 -28
- package/src/pattern/structure/digest-pattern.ts +23 -23
- package/src/pattern/structure/node-pattern.ts +17 -17
- package/src/pattern/structure/object-pattern.ts +13 -13
- package/src/pattern/structure/obscured-pattern.ts +7 -7
- package/src/pattern/structure/predicate-pattern.ts +13 -13
- package/src/pattern/structure/subject-pattern.ts +15 -15
- package/src/pattern/structure/wrapped-pattern.ts +15 -15
|
@@ -25,10 +25,10 @@ export function registerOrPatternFactory(factory: (pattern: OrPattern) => Patter
|
|
|
25
25
|
* Corresponds to the Rust `OrPattern` struct in or_pattern.rs
|
|
26
26
|
*/
|
|
27
27
|
export class OrPattern implements Matcher {
|
|
28
|
-
readonly
|
|
28
|
+
private readonly _patterns: Pattern[];
|
|
29
29
|
|
|
30
30
|
private constructor(patterns: Pattern[]) {
|
|
31
|
-
this
|
|
31
|
+
this._patterns = patterns;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -42,11 +42,11 @@ export class OrPattern implements Matcher {
|
|
|
42
42
|
* Gets the patterns.
|
|
43
43
|
*/
|
|
44
44
|
patterns(): Pattern[] {
|
|
45
|
-
return this
|
|
45
|
+
return this._patterns;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
49
|
-
const anyMatch = this
|
|
49
|
+
const anyMatch = this._patterns.some((pattern) => matchPattern(pattern, haystack));
|
|
50
50
|
|
|
51
51
|
const paths = anyMatch ? [[haystack]] : [];
|
|
52
52
|
return [paths, new Map<string, Path[]>()];
|
|
@@ -61,7 +61,7 @@ export class OrPattern implements Matcher {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
compile(code: Instr[], literals: Pattern[], captures: string[]): void {
|
|
64
|
-
if (this
|
|
64
|
+
if (this._patterns.length === 0) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,7 +69,7 @@ export class OrPattern implements Matcher {
|
|
|
69
69
|
const splits: number[] = [];
|
|
70
70
|
|
|
71
71
|
// Generate splits for all but the last pattern
|
|
72
|
-
for (let i = 0; i < this
|
|
72
|
+
for (let i = 0; i < this._patterns.length - 1; i++) {
|
|
73
73
|
splits.push(code.length);
|
|
74
74
|
code.push({ type: "Split", a: 0, b: 0 }); // Placeholder
|
|
75
75
|
}
|
|
@@ -78,11 +78,11 @@ export class OrPattern implements Matcher {
|
|
|
78
78
|
const jumps: number[] = [];
|
|
79
79
|
|
|
80
80
|
// Now fill in the actual split targets
|
|
81
|
-
for (let i = 0; i < this
|
|
81
|
+
for (let i = 0; i < this._patterns.length; i++) {
|
|
82
82
|
const patternStart = code.length;
|
|
83
83
|
|
|
84
84
|
// Compile this pattern
|
|
85
|
-
const pattern = this
|
|
85
|
+
const pattern = this._patterns[i];
|
|
86
86
|
const matcher = pattern as unknown as Matcher;
|
|
87
87
|
matcher.compile(code, literals, captures);
|
|
88
88
|
|
|
@@ -92,7 +92,7 @@ export class OrPattern implements Matcher {
|
|
|
92
92
|
jumps.push(jumpPastAll);
|
|
93
93
|
|
|
94
94
|
// If there's a next pattern, update the split to point here
|
|
95
|
-
if (i < this
|
|
95
|
+
if (i < this._patterns.length - 1) {
|
|
96
96
|
const nextPattern = code.length;
|
|
97
97
|
code[splits[i]] = { type: "Split", a: patternStart, b: nextPattern };
|
|
98
98
|
}
|
|
@@ -109,12 +109,12 @@ export class OrPattern implements Matcher {
|
|
|
109
109
|
// The pattern is complex if it contains more than one pattern, or if
|
|
110
110
|
// the one pattern is complex itself.
|
|
111
111
|
return (
|
|
112
|
-
this
|
|
112
|
+
this._patterns.length > 1 || this._patterns.some((p) => (p as unknown as Matcher).isComplex())
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
toString(): string {
|
|
117
|
-
return this
|
|
117
|
+
return this._patterns
|
|
118
118
|
.map((p) => (p as unknown as { toString(): string }).toString())
|
|
119
119
|
.join(" | ");
|
|
120
120
|
}
|
|
@@ -123,11 +123,11 @@ export class OrPattern implements Matcher {
|
|
|
123
123
|
* Equality comparison.
|
|
124
124
|
*/
|
|
125
125
|
equals(other: OrPattern): boolean {
|
|
126
|
-
if (this
|
|
126
|
+
if (this._patterns.length !== other._patterns.length) {
|
|
127
127
|
return false;
|
|
128
128
|
}
|
|
129
|
-
for (let i = 0; i < this
|
|
130
|
-
if (this
|
|
129
|
+
for (let i = 0; i < this._patterns.length; i++) {
|
|
130
|
+
if (this._patterns[i] !== other._patterns[i]) {
|
|
131
131
|
return false;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -138,6 +138,6 @@ export class OrPattern implements Matcher {
|
|
|
138
138
|
* Hash code for use in Maps/Sets.
|
|
139
139
|
*/
|
|
140
140
|
hashCode(): number {
|
|
141
|
-
return this
|
|
141
|
+
return this._patterns.length;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -25,10 +25,10 @@ export function registerSearchPatternFactory(factory: (pattern: SearchPattern) =
|
|
|
25
25
|
* Corresponds to the Rust `SearchPattern` struct in search_pattern.rs
|
|
26
26
|
*/
|
|
27
27
|
export class SearchPattern implements Matcher {
|
|
28
|
-
readonly
|
|
28
|
+
private readonly _pattern: Pattern;
|
|
29
29
|
|
|
30
30
|
private constructor(pattern: Pattern) {
|
|
31
|
-
this
|
|
31
|
+
this._pattern = pattern;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -42,15 +42,15 @@ export class SearchPattern implements Matcher {
|
|
|
42
42
|
* Gets the inner pattern.
|
|
43
43
|
*/
|
|
44
44
|
pattern(): Pattern {
|
|
45
|
-
return this
|
|
45
|
+
return this._pattern;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
49
49
|
const resultPaths: Path[] = [];
|
|
50
|
-
const matcher = this
|
|
50
|
+
const matcher = this._pattern as unknown as Matcher;
|
|
51
51
|
|
|
52
52
|
// Walk the envelope tree
|
|
53
|
-
this
|
|
53
|
+
this._walkEnvelope(haystack, [], (currentEnvelope, pathToCurrent) => {
|
|
54
54
|
// Create the path to this node
|
|
55
55
|
const newPath: Envelope[] = [...pathToCurrent, currentEnvelope];
|
|
56
56
|
|
|
@@ -92,7 +92,7 @@ export class SearchPattern implements Matcher {
|
|
|
92
92
|
/**
|
|
93
93
|
* Walk the envelope tree recursively.
|
|
94
94
|
*/
|
|
95
|
-
|
|
95
|
+
private _walkEnvelope(
|
|
96
96
|
envelope: Envelope,
|
|
97
97
|
pathToCurrent: Envelope[],
|
|
98
98
|
visitor: (envelope: Envelope, path: Envelope[]) => void,
|
|
@@ -106,24 +106,24 @@ export class SearchPattern implements Matcher {
|
|
|
106
106
|
|
|
107
107
|
// Walk subject if it's different from this envelope
|
|
108
108
|
if (!subject.digest().equals(envelope.digest())) {
|
|
109
|
-
this
|
|
109
|
+
this._walkEnvelope(subject, newPath, visitor);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// Walk assertions
|
|
113
113
|
for (const assertion of envelope.assertions()) {
|
|
114
|
-
this
|
|
114
|
+
this._walkEnvelope(assertion, newPath, visitor);
|
|
115
115
|
|
|
116
116
|
// Walk predicate and object if available
|
|
117
117
|
const predicate = assertion.asPredicate?.();
|
|
118
118
|
if (predicate !== undefined) {
|
|
119
119
|
const assertionPath = [...newPath, assertion];
|
|
120
|
-
this
|
|
120
|
+
this._walkEnvelope(predicate, assertionPath, visitor);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
const object = assertion.asObject?.();
|
|
124
124
|
if (object !== undefined) {
|
|
125
125
|
const assertionPath = [...newPath, assertion];
|
|
126
|
-
this
|
|
126
|
+
this._walkEnvelope(object, assertionPath, visitor);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -131,7 +131,7 @@ export class SearchPattern implements Matcher {
|
|
|
131
131
|
if (subject.isWrapped()) {
|
|
132
132
|
const unwrapped = subject.tryUnwrap?.();
|
|
133
133
|
if (unwrapped !== undefined) {
|
|
134
|
-
this
|
|
134
|
+
this._walkEnvelope(unwrapped, newPath, visitor);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -146,11 +146,11 @@ export class SearchPattern implements Matcher {
|
|
|
146
146
|
|
|
147
147
|
compile(code: Instr[], literals: Pattern[], captures: string[]): void {
|
|
148
148
|
const idx = literals.length;
|
|
149
|
-
literals.push(this
|
|
149
|
+
literals.push(this._pattern);
|
|
150
150
|
|
|
151
151
|
// Collect capture names from inner pattern
|
|
152
152
|
const innerNames: string[] = [];
|
|
153
|
-
collectCaptureNames(this
|
|
153
|
+
collectCaptureNames(this._pattern, innerNames);
|
|
154
154
|
|
|
155
155
|
const captureMap: [string, number][] = [];
|
|
156
156
|
for (const name of innerNames) {
|
|
@@ -170,14 +170,14 @@ export class SearchPattern implements Matcher {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
toString(): string {
|
|
173
|
-
return `search(${(this
|
|
173
|
+
return `search(${(this._pattern as unknown as { toString(): string }).toString()})`;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* Equality comparison.
|
|
178
178
|
*/
|
|
179
179
|
equals(other: SearchPattern): boolean {
|
|
180
|
-
return this
|
|
180
|
+
return this._pattern === other._pattern;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
@@ -27,12 +27,12 @@ export function registerTraversePatternFactory(
|
|
|
27
27
|
* Corresponds to the Rust `TraversePattern` struct in traverse_pattern.rs
|
|
28
28
|
*/
|
|
29
29
|
export class TraversePattern implements Matcher {
|
|
30
|
-
readonly
|
|
31
|
-
readonly
|
|
30
|
+
private readonly _first: Pattern;
|
|
31
|
+
private readonly _rest: TraversePattern | undefined;
|
|
32
32
|
|
|
33
33
|
private constructor(first: Pattern, rest: TraversePattern | undefined) {
|
|
34
|
-
this
|
|
35
|
-
this
|
|
34
|
+
this._first = first;
|
|
35
|
+
this._rest = rest;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -53,19 +53,19 @@ export class TraversePattern implements Matcher {
|
|
|
53
53
|
* Gets all patterns in this traversal.
|
|
54
54
|
*/
|
|
55
55
|
patterns(): Pattern[] {
|
|
56
|
-
const result: Pattern[] = [this
|
|
57
|
-
if (this
|
|
58
|
-
result.push(...this
|
|
56
|
+
const result: Pattern[] = [this._first];
|
|
57
|
+
if (this._rest !== undefined) {
|
|
58
|
+
result.push(...this._rest.patterns());
|
|
59
59
|
}
|
|
60
60
|
return result;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
64
|
-
const firstMatcher = this
|
|
64
|
+
const firstMatcher = this._first as unknown as Matcher;
|
|
65
65
|
const headPaths = firstMatcher.paths(haystack);
|
|
66
66
|
|
|
67
67
|
// If there's no further traversal, return head paths
|
|
68
|
-
if (this
|
|
68
|
+
if (this._rest === undefined) {
|
|
69
69
|
return [headPaths, new Map<string, Path[]>()];
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -74,7 +74,7 @@ export class TraversePattern implements Matcher {
|
|
|
74
74
|
const lastEnv = path[path.length - 1];
|
|
75
75
|
if (lastEnv !== undefined) {
|
|
76
76
|
// Recursively match the rest of the traversal
|
|
77
|
-
const tailPaths = this
|
|
77
|
+
const tailPaths = this._rest.paths(lastEnv);
|
|
78
78
|
for (const tailPath of tailPaths) {
|
|
79
79
|
const combined = [...path, ...tailPath];
|
|
80
80
|
result.push(combined);
|
|
@@ -95,14 +95,14 @@ export class TraversePattern implements Matcher {
|
|
|
95
95
|
|
|
96
96
|
compile(code: Instr[], literals: Pattern[], captures: string[]): void {
|
|
97
97
|
// Compile the first pattern
|
|
98
|
-
const firstMatcher = this
|
|
98
|
+
const firstMatcher = this._first as unknown as Matcher;
|
|
99
99
|
firstMatcher.compile(code, literals, captures);
|
|
100
100
|
|
|
101
|
-
if (this
|
|
101
|
+
if (this._rest !== undefined) {
|
|
102
102
|
// Save the current path and switch to last envelope
|
|
103
103
|
code.push({ type: "ExtendTraversal" });
|
|
104
104
|
// Compile the rest of the traversal
|
|
105
|
-
this
|
|
105
|
+
this._rest.compile(code, literals, captures);
|
|
106
106
|
// Combine the paths correctly
|
|
107
107
|
code.push({ type: "CombineTraversal" });
|
|
108
108
|
}
|
|
@@ -110,8 +110,8 @@ export class TraversePattern implements Matcher {
|
|
|
110
110
|
|
|
111
111
|
isComplex(): boolean {
|
|
112
112
|
// A traversal is complex if `first` is complex, or it has more than one pattern
|
|
113
|
-
const firstMatcher = this
|
|
114
|
-
return firstMatcher.isComplex() || this
|
|
113
|
+
const firstMatcher = this._first as unknown as Matcher;
|
|
114
|
+
return firstMatcher.isComplex() || this._rest !== undefined;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
toString(): string {
|
|
@@ -42,10 +42,10 @@ export type AssertionsPatternType =
|
|
|
42
42
|
* Corresponds to the Rust `AssertionsPattern` enum in assertions_pattern.rs
|
|
43
43
|
*/
|
|
44
44
|
export class AssertionsPattern implements Matcher {
|
|
45
|
-
readonly
|
|
45
|
+
private readonly _pattern: AssertionsPatternType;
|
|
46
46
|
|
|
47
47
|
private constructor(pattern: AssertionsPatternType) {
|
|
48
|
-
this
|
|
48
|
+
this._pattern = pattern;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
@@ -83,18 +83,18 @@ export class AssertionsPattern implements Matcher {
|
|
|
83
83
|
* Gets the pattern type.
|
|
84
84
|
*/
|
|
85
85
|
get patternType(): AssertionsPatternType {
|
|
86
|
-
return this
|
|
86
|
+
return this._pattern;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* Gets the predicate pattern if this has one, undefined otherwise.
|
|
91
91
|
*/
|
|
92
92
|
predicatePattern(): Pattern | undefined {
|
|
93
|
-
if (this
|
|
94
|
-
return this
|
|
93
|
+
if (this._pattern.type === "WithPredicate") {
|
|
94
|
+
return this._pattern.pattern;
|
|
95
95
|
}
|
|
96
|
-
if (this
|
|
97
|
-
return this
|
|
96
|
+
if (this._pattern.type === "WithBoth") {
|
|
97
|
+
return this._pattern.predicatePattern;
|
|
98
98
|
}
|
|
99
99
|
return undefined;
|
|
100
100
|
}
|
|
@@ -103,11 +103,11 @@ export class AssertionsPattern implements Matcher {
|
|
|
103
103
|
* Gets the object pattern if this has one, undefined otherwise.
|
|
104
104
|
*/
|
|
105
105
|
objectPattern(): Pattern | undefined {
|
|
106
|
-
if (this
|
|
107
|
-
return this
|
|
106
|
+
if (this._pattern.type === "WithObject") {
|
|
107
|
+
return this._pattern.pattern;
|
|
108
108
|
}
|
|
109
|
-
if (this
|
|
110
|
-
return this
|
|
109
|
+
if (this._pattern.type === "WithBoth") {
|
|
110
|
+
return this._pattern.objectPattern;
|
|
111
111
|
}
|
|
112
112
|
return undefined;
|
|
113
113
|
}
|
|
@@ -116,14 +116,14 @@ export class AssertionsPattern implements Matcher {
|
|
|
116
116
|
const paths: Path[] = [];
|
|
117
117
|
|
|
118
118
|
for (const assertion of haystack.assertions()) {
|
|
119
|
-
switch (this
|
|
119
|
+
switch (this._pattern.type) {
|
|
120
120
|
case "Any":
|
|
121
121
|
paths.push([assertion]);
|
|
122
122
|
break;
|
|
123
123
|
case "WithPredicate": {
|
|
124
124
|
const predicate = assertion.asPredicate?.();
|
|
125
125
|
if (predicate !== undefined) {
|
|
126
|
-
const innerMatcher = this
|
|
126
|
+
const innerMatcher = this._pattern.pattern as unknown as Matcher;
|
|
127
127
|
if (innerMatcher.matches(predicate)) {
|
|
128
128
|
paths.push([assertion]);
|
|
129
129
|
}
|
|
@@ -133,7 +133,7 @@ export class AssertionsPattern implements Matcher {
|
|
|
133
133
|
case "WithObject": {
|
|
134
134
|
const object = assertion.asObject?.();
|
|
135
135
|
if (object !== undefined) {
|
|
136
|
-
const innerMatcher = this
|
|
136
|
+
const innerMatcher = this._pattern.pattern as unknown as Matcher;
|
|
137
137
|
if (innerMatcher.matches(object)) {
|
|
138
138
|
paths.push([assertion]);
|
|
139
139
|
}
|
|
@@ -144,8 +144,8 @@ export class AssertionsPattern implements Matcher {
|
|
|
144
144
|
const predicate = assertion.asPredicate?.();
|
|
145
145
|
const object = assertion.asObject?.();
|
|
146
146
|
if (predicate !== undefined && object !== undefined) {
|
|
147
|
-
const predMatcher = this
|
|
148
|
-
const objMatcher = this
|
|
147
|
+
const predMatcher = this._pattern.predicatePattern as unknown as Matcher;
|
|
148
|
+
const objMatcher = this._pattern.objectPattern as unknown as Matcher;
|
|
149
149
|
if (predMatcher.matches(predicate) && objMatcher.matches(object)) {
|
|
150
150
|
paths.push([assertion]);
|
|
151
151
|
}
|
|
@@ -180,15 +180,15 @@ export class AssertionsPattern implements Matcher {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
toString(): string {
|
|
183
|
-
switch (this
|
|
183
|
+
switch (this._pattern.type) {
|
|
184
184
|
case "Any":
|
|
185
185
|
return "assert";
|
|
186
186
|
case "WithPredicate":
|
|
187
|
-
return `assertpred(${(this
|
|
187
|
+
return `assertpred(${(this._pattern.pattern as unknown as { toString(): string }).toString()})`;
|
|
188
188
|
case "WithObject":
|
|
189
|
-
return `assertobj(${(this
|
|
189
|
+
return `assertobj(${(this._pattern.pattern as unknown as { toString(): string }).toString()})`;
|
|
190
190
|
case "WithBoth":
|
|
191
|
-
return `assert(${(this
|
|
191
|
+
return `assert(${(this._pattern.predicatePattern as unknown as { toString(): string }).toString()}, ${(this._pattern.objectPattern as unknown as { toString(): string }).toString()})`;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
@@ -196,31 +196,31 @@ export class AssertionsPattern implements Matcher {
|
|
|
196
196
|
* Equality comparison.
|
|
197
197
|
*/
|
|
198
198
|
equals(other: AssertionsPattern): boolean {
|
|
199
|
-
if (this
|
|
199
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
200
200
|
return false;
|
|
201
201
|
}
|
|
202
|
-
switch (this
|
|
202
|
+
switch (this._pattern.type) {
|
|
203
203
|
case "Any":
|
|
204
204
|
return true;
|
|
205
205
|
case "WithPredicate":
|
|
206
206
|
case "WithObject": {
|
|
207
207
|
const thisPattern = (
|
|
208
|
-
this
|
|
208
|
+
this._pattern as { type: "WithPredicate" | "WithObject"; pattern: Pattern }
|
|
209
209
|
).pattern;
|
|
210
210
|
const otherPattern = (
|
|
211
|
-
other
|
|
211
|
+
other._pattern as { type: "WithPredicate" | "WithObject"; pattern: Pattern }
|
|
212
212
|
).pattern;
|
|
213
213
|
return thisPattern === otherPattern;
|
|
214
214
|
}
|
|
215
215
|
case "WithBoth": {
|
|
216
|
-
const otherBoth = other
|
|
216
|
+
const otherBoth = other._pattern as {
|
|
217
217
|
type: "WithBoth";
|
|
218
218
|
predicatePattern: Pattern;
|
|
219
219
|
objectPattern: Pattern;
|
|
220
220
|
};
|
|
221
221
|
return (
|
|
222
|
-
this
|
|
223
|
-
this
|
|
222
|
+
this._pattern.predicatePattern === otherBoth.predicatePattern &&
|
|
223
|
+
this._pattern.objectPattern === otherBoth.objectPattern
|
|
224
224
|
);
|
|
225
225
|
}
|
|
226
226
|
}
|
|
@@ -230,7 +230,7 @@ export class AssertionsPattern implements Matcher {
|
|
|
230
230
|
* Hash code for use in Maps/Sets.
|
|
231
231
|
*/
|
|
232
232
|
hashCode(): number {
|
|
233
|
-
switch (this
|
|
233
|
+
switch (this._pattern.type) {
|
|
234
234
|
case "Any":
|
|
235
235
|
return 0;
|
|
236
236
|
case "WithPredicate":
|
|
@@ -49,10 +49,10 @@ export type DigestPatternType =
|
|
|
49
49
|
* Corresponds to the Rust `DigestPattern` enum in digest_pattern.rs
|
|
50
50
|
*/
|
|
51
51
|
export class DigestPattern implements Matcher {
|
|
52
|
-
readonly
|
|
52
|
+
private readonly _pattern: DigestPatternType;
|
|
53
53
|
|
|
54
54
|
private constructor(pattern: DigestPatternType) {
|
|
55
|
-
this
|
|
55
|
+
this._pattern = pattern;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -87,7 +87,7 @@ export class DigestPattern implements Matcher {
|
|
|
87
87
|
* Gets the pattern type.
|
|
88
88
|
*/
|
|
89
89
|
get patternType(): DigestPatternType {
|
|
90
|
-
return this
|
|
90
|
+
return this._pattern;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
pathsWithCaptures(haystack: Envelope): [Path[], Map<string, Path[]>] {
|
|
@@ -95,16 +95,16 @@ export class DigestPattern implements Matcher {
|
|
|
95
95
|
const digestData = digest.data();
|
|
96
96
|
let isHit = false;
|
|
97
97
|
|
|
98
|
-
switch (this
|
|
98
|
+
switch (this._pattern.type) {
|
|
99
99
|
case "Any":
|
|
100
100
|
// Any digest matches - every envelope has a digest
|
|
101
101
|
isHit = true;
|
|
102
102
|
break;
|
|
103
103
|
case "Digest":
|
|
104
|
-
isHit = digest.equals(this
|
|
104
|
+
isHit = digest.equals(this._pattern.digest);
|
|
105
105
|
break;
|
|
106
106
|
case "Prefix": {
|
|
107
|
-
const prefix = this
|
|
107
|
+
const prefix = this._pattern.prefix;
|
|
108
108
|
if (digestData.length >= prefix.length) {
|
|
109
109
|
isHit = true;
|
|
110
110
|
for (let i = 0; i < prefix.length; i++) {
|
|
@@ -118,7 +118,7 @@ export class DigestPattern implements Matcher {
|
|
|
118
118
|
}
|
|
119
119
|
case "BinaryRegex": {
|
|
120
120
|
const latin1 = bytesToLatin1(digestData);
|
|
121
|
-
isHit = this
|
|
121
|
+
isHit = this._pattern.regex.test(latin1);
|
|
122
122
|
break;
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -147,15 +147,15 @@ export class DigestPattern implements Matcher {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
toString(): string {
|
|
150
|
-
switch (this
|
|
150
|
+
switch (this._pattern.type) {
|
|
151
151
|
case "Any":
|
|
152
152
|
return "digest";
|
|
153
153
|
case "Digest":
|
|
154
|
-
return `digest(${this
|
|
154
|
+
return `digest(${this._pattern.digest.hex()})`;
|
|
155
155
|
case "Prefix":
|
|
156
|
-
return `digest(${bytesToHex(this
|
|
156
|
+
return `digest(${bytesToHex(this._pattern.prefix)})`;
|
|
157
157
|
case "BinaryRegex":
|
|
158
|
-
return `digest(/${this
|
|
158
|
+
return `digest(/${this._pattern.regex.source}/)`;
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -163,19 +163,19 @@ export class DigestPattern implements Matcher {
|
|
|
163
163
|
* Equality comparison.
|
|
164
164
|
*/
|
|
165
165
|
equals(other: DigestPattern): boolean {
|
|
166
|
-
if (this
|
|
166
|
+
if (this._pattern.type !== other._pattern.type) {
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
|
-
switch (this
|
|
169
|
+
switch (this._pattern.type) {
|
|
170
170
|
case "Any":
|
|
171
171
|
return true;
|
|
172
172
|
case "Digest":
|
|
173
|
-
return this
|
|
174
|
-
(other
|
|
173
|
+
return this._pattern.digest.equals(
|
|
174
|
+
(other._pattern as { type: "Digest"; digest: Digest }).digest,
|
|
175
175
|
);
|
|
176
176
|
case "Prefix": {
|
|
177
|
-
const thisPrefix = this
|
|
178
|
-
const otherPrefix = (other
|
|
177
|
+
const thisPrefix = this._pattern.prefix;
|
|
178
|
+
const otherPrefix = (other._pattern as { type: "Prefix"; prefix: Uint8Array }).prefix;
|
|
179
179
|
if (thisPrefix.length !== otherPrefix.length) return false;
|
|
180
180
|
for (let i = 0; i < thisPrefix.length; i++) {
|
|
181
181
|
if (thisPrefix[i] !== otherPrefix[i]) return false;
|
|
@@ -184,8 +184,8 @@ export class DigestPattern implements Matcher {
|
|
|
184
184
|
}
|
|
185
185
|
case "BinaryRegex":
|
|
186
186
|
return (
|
|
187
|
-
this
|
|
188
|
-
(other
|
|
187
|
+
this._pattern.regex.source ===
|
|
188
|
+
(other._pattern as { type: "BinaryRegex"; regex: RegExp }).regex.source
|
|
189
189
|
);
|
|
190
190
|
}
|
|
191
191
|
}
|
|
@@ -194,12 +194,12 @@ export class DigestPattern implements Matcher {
|
|
|
194
194
|
* Hash code for use in Maps/Sets.
|
|
195
195
|
*/
|
|
196
196
|
hashCode(): number {
|
|
197
|
-
switch (this
|
|
197
|
+
switch (this._pattern.type) {
|
|
198
198
|
case "Any":
|
|
199
199
|
return 0;
|
|
200
200
|
case "Digest": {
|
|
201
201
|
// Hash based on first few bytes of digest
|
|
202
|
-
const data = this
|
|
202
|
+
const data = this._pattern.digest.data().slice(0, 8);
|
|
203
203
|
let hash = 0;
|
|
204
204
|
for (const byte of data) {
|
|
205
205
|
hash = (hash * 31 + byte) | 0;
|
|
@@ -208,14 +208,14 @@ export class DigestPattern implements Matcher {
|
|
|
208
208
|
}
|
|
209
209
|
case "Prefix": {
|
|
210
210
|
let hash = 0;
|
|
211
|
-
for (const byte of this
|
|
211
|
+
for (const byte of this._pattern.prefix) {
|
|
212
212
|
hash = (hash * 31 + byte) | 0;
|
|
213
213
|
}
|
|
214
214
|
return hash;
|
|
215
215
|
}
|
|
216
216
|
case "BinaryRegex": {
|
|
217
217
|
let hash = 0;
|
|
218
|
-
for (const char of this
|
|
218
|
+
for (const char of this._pattern.regex.source) {
|
|
219
219
|
hash = (hash * 31 + char.charCodeAt(0)) | 0;
|
|
220
220
|
}
|
|
221
221
|
return hash;
|