cesr-ts 0.3.1 → 0.4.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/README.md +3 -3
- package/esm/src/annotate/annotator.js +4 -7
- package/esm/src/annotate/comments.js +1 -1
- package/esm/src/annotate/render.js +66 -75
- package/esm/src/core/bytes.js +47 -0
- package/esm/src/core/cbor.js +122 -0
- package/esm/src/core/errors.js +13 -0
- package/esm/src/core/parser-attachment-collector.js +1 -2
- package/esm/src/core/parser-engine.js +7 -7
- package/esm/src/core/parser-frame-parser.js +14 -20
- package/esm/src/index.js +59 -33
- package/esm/src/parser/attachment-parser.js +1 -1
- package/esm/src/parser/group-dispatch.js +27 -41
- package/esm/src/primitives/aggor.js +74 -31
- package/esm/src/primitives/bexter.js +60 -16
- package/esm/src/primitives/blinder.js +27 -20
- package/esm/src/primitives/cigar.js +25 -15
- package/esm/src/primitives/cipher.js +18 -0
- package/esm/src/primitives/codex.js +74 -0
- package/esm/src/primitives/compactor.js +1 -7
- package/esm/src/primitives/counter.js +203 -13
- package/esm/src/primitives/dater.js +31 -16
- package/esm/src/primitives/decimer.js +65 -0
- package/esm/src/primitives/decrypter.js +18 -0
- package/esm/src/primitives/diger.js +24 -18
- package/esm/src/primitives/encrypter.js +19 -0
- package/esm/src/primitives/ilker.js +24 -12
- package/esm/src/primitives/indexer.js +199 -7
- package/esm/src/primitives/labeler.js +74 -24
- package/esm/src/primitives/mapper.js +14 -35
- package/esm/src/primitives/matter.js +160 -6
- package/esm/src/primitives/mediar.js +27 -18
- package/esm/src/primitives/noncer.js +33 -15
- package/esm/src/primitives/number.js +28 -27
- package/esm/src/primitives/pather.js +30 -18
- package/esm/src/primitives/prefixer.js +23 -20
- package/esm/src/primitives/primitive.js +9 -0
- package/esm/src/primitives/registry.js +3 -3
- package/esm/src/primitives/saider.js +24 -18
- package/esm/src/primitives/salter.js +22 -0
- package/esm/src/primitives/sealer.js +27 -32
- package/esm/src/primitives/seqner.js +28 -19
- package/esm/src/primitives/siger.js +29 -0
- package/esm/src/primitives/signer.js +23 -0
- package/esm/src/primitives/structor.js +104 -0
- package/esm/src/primitives/tagger.js +44 -0
- package/esm/src/primitives/texter.js +24 -15
- package/esm/src/primitives/tholder.js +27 -24
- package/esm/src/primitives/traitor.js +23 -16
- package/esm/src/primitives/unknown.js +89 -0
- package/esm/src/primitives/verfer.js +25 -25
- package/esm/src/primitives/verser.js +54 -23
- package/esm/src/serder/serder.js +190 -10
- package/esm/src/serder/serdery.js +2 -2
- package/esm/src/tables/codex-utils.js +9 -0
- package/esm/src/tables/counter-codex.js +1 -1
- package/esm/src/tables/counter-groups.js +46 -0
- package/esm/src/tables/counter-version-registry.js +1 -1
- package/esm/src/tables/indexer.codex.generated.js +64 -0
- package/esm/src/tables/indexer.tables.generated.js +72 -0
- package/esm/src/tables/matter.codex.generated.js +399 -0
- package/esm/src/tables/matter.tables.generated.js +112 -0
- package/esm/src/tables/trait.codex.generated.js +10 -0
- package/esm/src/version.js +2 -2
- package/package.json +1 -1
- package/types/src/adapters/async-iterable.d.ts +1 -1
- package/types/src/adapters/async-iterable.d.ts.map +1 -1
- package/types/src/adapters/effection.d.ts +1 -1
- package/types/src/adapters/effection.d.ts.map +1 -1
- package/types/src/annotate/annotator.d.ts.map +1 -1
- package/types/src/annotate/comments.d.ts.map +1 -1
- package/types/src/annotate/render.d.ts.map +1 -1
- package/types/src/bench/parser-benchmark.d.ts.map +1 -1
- package/types/src/core/bytes.d.ts +22 -0
- package/types/src/core/bytes.d.ts.map +1 -1
- package/types/src/core/cbor.d.ts +30 -0
- package/types/src/core/cbor.d.ts.map +1 -0
- package/types/src/core/errors.d.ts +13 -0
- package/types/src/core/errors.d.ts.map +1 -1
- package/types/src/core/parser-attachment-collector.d.ts.map +1 -1
- package/types/src/core/parser-engine.d.ts +1 -1
- package/types/src/core/parser-engine.d.ts.map +1 -1
- package/types/src/core/parser-frame-parser.d.ts +1 -1
- package/types/src/core/parser-frame-parser.d.ts.map +1 -1
- package/types/src/core/types.d.ts +7 -36
- package/types/src/core/types.d.ts.map +1 -1
- package/types/src/index.d.ts +59 -33
- package/types/src/index.d.ts.map +1 -1
- package/types/src/parser/attachment-fallback-policy.d.ts.map +1 -1
- package/types/src/parser/attachment-parser.d.ts.map +1 -1
- package/types/src/parser/group-dispatch.d.ts +2 -2
- package/types/src/parser/group-dispatch.d.ts.map +1 -1
- package/types/src/primitives/aggor.d.ts +34 -8
- package/types/src/primitives/aggor.d.ts.map +1 -1
- package/types/src/primitives/bexter.d.ts +28 -6
- package/types/src/primitives/bexter.d.ts.map +1 -1
- package/types/src/primitives/blinder.d.ts +16 -8
- package/types/src/primitives/blinder.d.ts.map +1 -1
- package/types/src/primitives/cigar.d.ts +12 -7
- package/types/src/primitives/cigar.d.ts.map +1 -1
- package/types/src/primitives/cipher.d.ts +11 -0
- package/types/src/primitives/cipher.d.ts.map +1 -0
- package/types/src/primitives/codex.d.ts +54 -0
- package/types/src/primitives/codex.d.ts.map +1 -0
- package/types/src/primitives/compactor.d.ts.map +1 -1
- package/types/src/primitives/counter.d.ts +63 -2
- package/types/src/primitives/counter.d.ts.map +1 -1
- package/types/src/primitives/dater.d.ts +12 -7
- package/types/src/primitives/dater.d.ts.map +1 -1
- package/types/src/primitives/decimer.d.ts +23 -0
- package/types/src/primitives/decimer.d.ts.map +1 -0
- package/types/src/primitives/decrypter.d.ts +11 -0
- package/types/src/primitives/decrypter.d.ts.map +1 -0
- package/types/src/primitives/diger.d.ts +16 -7
- package/types/src/primitives/diger.d.ts.map +1 -1
- package/types/src/primitives/encrypter.d.ts +12 -0
- package/types/src/primitives/encrypter.d.ts.map +1 -0
- package/types/src/primitives/ilker.d.ts +13 -6
- package/types/src/primitives/ilker.d.ts.map +1 -1
- package/types/src/primitives/indexer.d.ts +52 -1
- package/types/src/primitives/indexer.d.ts.map +1 -1
- package/types/src/primitives/labeler.d.ts +28 -11
- package/types/src/primitives/labeler.d.ts.map +1 -1
- package/types/src/primitives/mapper.d.ts +4 -6
- package/types/src/primitives/mapper.d.ts.map +1 -1
- package/types/src/primitives/matter.d.ts +44 -1
- package/types/src/primitives/matter.d.ts.map +1 -1
- package/types/src/primitives/mediar.d.ts +16 -8
- package/types/src/primitives/mediar.d.ts.map +1 -1
- package/types/src/primitives/noncer.d.ts +20 -6
- package/types/src/primitives/noncer.d.ts.map +1 -1
- package/types/src/primitives/number.d.ts +12 -7
- package/types/src/primitives/number.d.ts.map +1 -1
- package/types/src/primitives/pather.d.ts +12 -6
- package/types/src/primitives/pather.d.ts.map +1 -1
- package/types/src/primitives/prefixer.d.ts +12 -6
- package/types/src/primitives/prefixer.d.ts.map +1 -1
- package/types/src/primitives/primitive.d.ts +25 -0
- package/types/src/primitives/primitive.d.ts.map +1 -0
- package/types/src/primitives/registry.d.ts.map +1 -1
- package/types/src/primitives/saider.d.ts +12 -7
- package/types/src/primitives/saider.d.ts.map +1 -1
- package/types/src/primitives/salter.d.ts +13 -0
- package/types/src/primitives/salter.d.ts.map +1 -0
- package/types/src/primitives/sealer.d.ts +16 -8
- package/types/src/primitives/sealer.d.ts.map +1 -1
- package/types/src/primitives/seqner.d.ts +12 -7
- package/types/src/primitives/seqner.d.ts.map +1 -1
- package/types/src/primitives/siger.d.ts +16 -0
- package/types/src/primitives/siger.d.ts.map +1 -0
- package/types/src/primitives/signer.d.ts +14 -0
- package/types/src/primitives/signer.d.ts.map +1 -0
- package/types/src/primitives/structor.d.ts +44 -0
- package/types/src/primitives/structor.d.ts.map +1 -0
- package/types/src/primitives/tagger.d.ts +17 -0
- package/types/src/primitives/tagger.d.ts.map +1 -0
- package/types/src/primitives/texter.d.ts +11 -6
- package/types/src/primitives/texter.d.ts.map +1 -1
- package/types/src/primitives/tholder.d.ts +11 -6
- package/types/src/primitives/tholder.d.ts.map +1 -1
- package/types/src/primitives/traitor.d.ts +13 -6
- package/types/src/primitives/traitor.d.ts.map +1 -1
- package/types/src/primitives/unknown.d.ts +31 -0
- package/types/src/primitives/unknown.d.ts.map +1 -0
- package/types/src/primitives/verfer.d.ts +12 -7
- package/types/src/primitives/verfer.d.ts.map +1 -1
- package/types/src/primitives/verser.d.ts +18 -8
- package/types/src/primitives/verser.d.ts.map +1 -1
- package/types/src/serder/serder.d.ts +69 -3
- package/types/src/serder/serder.d.ts.map +1 -1
- package/types/src/serder/serdery.d.ts.map +1 -1
- package/types/src/tables/codex-utils.d.ts +4 -0
- package/types/src/tables/codex-utils.d.ts.map +1 -0
- package/types/src/tables/counter-codex.d.ts.map +1 -1
- package/types/src/tables/counter-groups.d.ts +8 -0
- package/types/src/tables/counter-groups.d.ts.map +1 -0
- package/types/src/tables/indexer.codex.generated.d.ts +127 -0
- package/types/src/tables/indexer.codex.generated.d.ts.map +1 -0
- package/types/src/tables/indexer.tables.generated.d.ts +46 -0
- package/types/src/tables/indexer.tables.generated.d.ts.map +1 -0
- package/types/src/tables/matter.codex.generated.d.ts +797 -0
- package/types/src/tables/matter.codex.generated.d.ts.map +1 -0
- package/types/src/tables/matter.tables.generated.d.ts +112 -0
- package/types/src/tables/matter.tables.generated.d.ts.map +1 -1
- package/types/src/tables/table-types.d.ts +7 -0
- package/types/src/tables/table-types.d.ts.map +1 -1
- package/types/src/tables/trait.codex.generated.d.ts +19 -0
- package/types/src/tables/trait.codex.generated.d.ts.map +1 -0
- package/types/src/version.d.ts +2 -2
- package/esm/src/tables/indexer.tables.js +0 -30
- package/types/src/tables/indexer.tables.d.ts +0 -12
- package/types/src/tables/indexer.tables.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ const parser = createParser();
|
|
|
18
18
|
const out = parser.feed(new TextEncoder().encode("...CESR..."));
|
|
19
19
|
const last = parser.flush();
|
|
20
20
|
|
|
21
|
-
const text =
|
|
21
|
+
const text = "{\"v\":\"KERI10JSON00002e_\",\"t\":\"rpy\",\"d\":\"Eabc\"}";
|
|
22
22
|
const annotated = annotate(text, { domainHint: "txt", pretty: true });
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -61,5 +61,5 @@ tufa annotate --in mystream.cesr --pretty
|
|
|
61
61
|
|
|
62
62
|
## License
|
|
63
63
|
|
|
64
|
-
Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the
|
|
65
|
-
|
|
64
|
+
Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the top-level
|
|
65
|
+
`LICENSE` file in this repository.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { b } from "../core/bytes.js";
|
|
1
2
|
import { parseBytes } from "../core/parser-engine.js";
|
|
2
|
-
import { renderAnnotatedFrames, renderWrapperAnnotatedStream
|
|
3
|
+
import { renderAnnotatedFrames, renderWrapperAnnotatedStream } from "./render.js";
|
|
3
4
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
4
5
|
commentMode: "inline",
|
|
5
6
|
indent: 2,
|
|
@@ -26,17 +27,13 @@ function parsedFramesOrThrow(frames) {
|
|
|
26
27
|
}
|
|
27
28
|
export function annotateFrames(input, options) {
|
|
28
29
|
const opts = resolveOptions(options);
|
|
29
|
-
const bytes = typeof input === "string"
|
|
30
|
-
? new TextEncoder().encode(input)
|
|
31
|
-
: input;
|
|
30
|
+
const bytes = typeof input === "string" ? b(input) : input;
|
|
32
31
|
const frames = parsedFramesOrThrow(parseBytes(bytes));
|
|
33
32
|
return renderAnnotatedFrames(frames, opts);
|
|
34
33
|
}
|
|
35
34
|
export function annotate(input, options) {
|
|
36
35
|
const opts = resolveOptions(options);
|
|
37
|
-
const bytes = typeof input === "string"
|
|
38
|
-
? new TextEncoder().encode(input)
|
|
39
|
-
: input;
|
|
36
|
+
const bytes = typeof input === "string" ? b(input) : input;
|
|
40
37
|
const wrapperAnnotated = renderWrapperAnnotatedStream(bytes, opts);
|
|
41
38
|
if (wrapperAnnotated !== null) {
|
|
42
39
|
return wrapperAnnotated;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { resolveCounterCodeNameTable } from "../tables/counter-version-registry.js";
|
|
1
2
|
import { COUNTER_CODE_NAMES_V1, COUNTER_CODE_NAMES_V2, } from "../tables/counter.tables.generated.js";
|
|
2
3
|
import { MATTER_CODE_NAMES } from "../tables/matter.tables.generated.js";
|
|
3
|
-
import { resolveCounterCodeNameTable } from "../tables/counter-version-registry.js";
|
|
4
4
|
const NATIVE_FIELD_LABELS = Object.freeze({
|
|
5
5
|
v: "version string",
|
|
6
6
|
t: "ilk",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b64ToInt, intToB64 } from "../core/bytes.js";
|
|
2
2
|
import { DeserializeError, GroupSizeError, ShortageError, UnknownCodeError, } from "../core/errors.js";
|
|
3
|
+
import { parseBytes } from "../core/parser-engine.js";
|
|
3
4
|
import { sniff } from "../parser/cold-start.js";
|
|
4
|
-
import { parseCounter } from "../primitives/counter.js";
|
|
5
|
-
import { parseMatter } from "../primitives/matter.js";
|
|
6
|
-
import { parseIndexer } from "../primitives/indexer.js";
|
|
7
5
|
import { parseAttachmentDispatchCompat } from "../parser/group-dispatch.js";
|
|
6
|
+
import { Counter, parseCounter } from "../primitives/counter.js";
|
|
7
|
+
import { Indexer } from "../primitives/indexer.js";
|
|
8
|
+
import { Matter, parseMatter } from "../primitives/matter.js";
|
|
9
|
+
import { isCounterGroupLike, isPrimitiveTuple } from "../primitives/primitive.js";
|
|
10
|
+
import { UnknownPrimitive } from "../primitives/unknown.js";
|
|
8
11
|
import { counterCodeName, counterCodeNameForVersion, matterCodeName, nativeLabelName, } from "./comments.js";
|
|
9
|
-
import { b64ToInt, intToB64 } from "../core/bytes.js";
|
|
10
12
|
const TEXT_DECODER = new TextDecoder();
|
|
11
|
-
const TEXT_ENCODER = new TextEncoder();
|
|
12
13
|
const OPAQUE_TOKEN_COMMENT = "opaque token";
|
|
13
14
|
const OPAQUE_WRAPPER_PAYLOAD_COMMENT = "opaque wrapper payload";
|
|
14
15
|
const WRAPPER_GROUP_NAMES = new Set([
|
|
@@ -27,10 +28,10 @@ function toHex(bytes) {
|
|
|
27
28
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
28
29
|
}
|
|
29
30
|
function isRecoverableParseError(error) {
|
|
30
|
-
return error instanceof UnknownCodeError
|
|
31
|
-
error instanceof DeserializeError
|
|
32
|
-
error instanceof ShortageError
|
|
33
|
-
error instanceof GroupSizeError;
|
|
31
|
+
return error instanceof UnknownCodeError
|
|
32
|
+
|| error instanceof DeserializeError
|
|
33
|
+
|| error instanceof ShortageError
|
|
34
|
+
|| error instanceof GroupSizeError;
|
|
34
35
|
}
|
|
35
36
|
function spaces(count) {
|
|
36
37
|
return " ".repeat(Math.max(0, count));
|
|
@@ -58,51 +59,6 @@ function emitLine(lines, value, comment, indent, options) {
|
|
|
58
59
|
}
|
|
59
60
|
lines.push(`${pad}${value} # ${comment}`);
|
|
60
61
|
}
|
|
61
|
-
function describeToken(token, domain, version) {
|
|
62
|
-
const input = TEXT_ENCODER.encode(token);
|
|
63
|
-
try {
|
|
64
|
-
const counter = parseCounter(input, version, domain);
|
|
65
|
-
return {
|
|
66
|
-
comment: `${counterCodeNameForVersion(counter.code, version)} counter`,
|
|
67
|
-
size: domain === "bny" ? counter.fullSizeB2 : counter.fullSize,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
if (!isRecoverableParseError(error)) {
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
// Try indexer/matter below.
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const indexer = parseIndexer(input, domain);
|
|
78
|
-
return {
|
|
79
|
-
comment: `Indexer ${indexer.code}`,
|
|
80
|
-
size: domain === "bny" ? indexer.fullSizeB2 : indexer.fullSize,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
if (!isRecoverableParseError(error)) {
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
// Try matter below.
|
|
88
|
-
}
|
|
89
|
-
try {
|
|
90
|
-
const matter = parseMatter(input, domain);
|
|
91
|
-
return {
|
|
92
|
-
comment: matterCodeName(matter.code),
|
|
93
|
-
size: domain === "bny" ? matter.fullSizeB2 : matter.fullSize,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
if (!isRecoverableParseError(error)) {
|
|
98
|
-
throw error;
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
comment: OPAQUE_TOKEN_COMMENT,
|
|
102
|
-
size: token.length,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
62
|
function parseCounterCompat(input, version, domain) {
|
|
107
63
|
try {
|
|
108
64
|
return parseCounter(input, version, domain);
|
|
@@ -130,25 +86,35 @@ function decodeVersionCounter(counter) {
|
|
|
130
86
|
}
|
|
131
87
|
function renderGroupItems(lines, items, version, indent, options) {
|
|
132
88
|
for (const item of items) {
|
|
133
|
-
if (item
|
|
134
|
-
|
|
135
|
-
const comment = item.opaque
|
|
136
|
-
? OPAQUE_WRAPPER_PAYLOAD_COMMENT
|
|
137
|
-
: parsed.comment;
|
|
138
|
-
emitLine(lines, item.qb64, comment, indent, options);
|
|
89
|
+
if (isPrimitiveTuple(item)) {
|
|
90
|
+
renderGroupItems(lines, item, version, indent + options.indent, options);
|
|
139
91
|
continue;
|
|
140
92
|
}
|
|
141
|
-
if (item
|
|
142
|
-
emitLine(lines,
|
|
93
|
+
if (isCounterGroupLike(item)) {
|
|
94
|
+
emitLine(lines, item.qb64, `${item.name} nested group`, indent, options);
|
|
95
|
+
renderGroupItems(lines, [...item.items], version, indent + options.indent, options);
|
|
143
96
|
continue;
|
|
144
97
|
}
|
|
145
|
-
if (item
|
|
146
|
-
|
|
98
|
+
if (item instanceof UnknownPrimitive) {
|
|
99
|
+
const value = item.sourceDomain === "bny"
|
|
100
|
+
? `0x${toHex(item.qb2)}`
|
|
101
|
+
: item.qb64;
|
|
102
|
+
emitLine(lines, value, OPAQUE_WRAPPER_PAYLOAD_COMMENT, indent, options);
|
|
147
103
|
continue;
|
|
148
104
|
}
|
|
149
|
-
if (item
|
|
150
|
-
emitLine(lines,
|
|
105
|
+
if (item instanceof Counter) {
|
|
106
|
+
emitLine(lines, item.qb64, `${counterCodeNameForVersion(item.code, version)} counter`, indent, options);
|
|
107
|
+
continue;
|
|
151
108
|
}
|
|
109
|
+
if (item instanceof Indexer) {
|
|
110
|
+
emitLine(lines, item.qb64, `Indexer ${item.code}`, indent, options);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (item instanceof Matter) {
|
|
114
|
+
emitLine(lines, item.qb64, matterCodeName(item.code), indent, options);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
emitLine(lines, String(item), OPAQUE_TOKEN_COMMENT, indent, options);
|
|
152
118
|
}
|
|
153
119
|
}
|
|
154
120
|
function renderAttachmentGroupRaw(lines, raw, version, indent, options) {
|
|
@@ -212,18 +178,43 @@ function renderNativeBody(lines, frame, options, version) {
|
|
|
212
178
|
}
|
|
213
179
|
const counter = parseCounterCompat(raw, version, domain);
|
|
214
180
|
emitLine(lines, counter.qb64, `${counterCodeNameForVersion(counter.code, version)} count=${counter.count}`, 0, options);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
181
|
+
const unit = domain === "bny" ? 3 : 4;
|
|
182
|
+
const headerSize = domain === "bny" ? counter.fullSizeB2 : counter.fullSize;
|
|
183
|
+
const payloadSize = counter.count * unit;
|
|
184
|
+
const end = Math.min(raw.length, headerSize + payloadSize);
|
|
185
|
+
let offset = headerSize;
|
|
186
|
+
while (offset < end) {
|
|
187
|
+
const slice = raw.slice(offset, end);
|
|
188
|
+
try {
|
|
189
|
+
const nestedCounter = parseCounterCompat(slice, version, domain);
|
|
190
|
+
const nestedCounterSize = domain === "bny"
|
|
191
|
+
? nestedCounter.fullSizeB2
|
|
192
|
+
: nestedCounter.fullSize;
|
|
193
|
+
emitLine(lines, nestedCounter.qb64, `${counterCodeNameForVersion(nestedCounter.code, version)} counter`, options.indent, options);
|
|
194
|
+
offset += nestedCounterSize;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
if (!isRecoverableParseError(error)) {
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const matter = parseMatter(slice, domain);
|
|
203
|
+
const matterSize = domain === "bny" ? matter.fullSizeB2 : matter.fullSize;
|
|
204
|
+
const field = frame.body.native?.fields.find((candidate) => candidate.primitive.qb64 === matter.qb64);
|
|
205
|
+
const label = field ? nativeLabelName(field.label) : null;
|
|
206
|
+
const primitiveComment = matter instanceof Indexer
|
|
207
|
+
? `Indexer ${matter.code}`
|
|
208
|
+
: matterCodeName(matter.code);
|
|
209
|
+
const comment = label ? `${label} (${primitiveComment})` : primitiveComment;
|
|
210
|
+
emitLine(lines, matter.qb64, comment, options.indent, options);
|
|
211
|
+
offset += matterSize;
|
|
221
212
|
}
|
|
222
213
|
}
|
|
223
214
|
function renderMessageBody(lines, frame, options) {
|
|
224
215
|
const rawBody = TEXT_DECODER.decode(frame.body.raw);
|
|
225
|
-
const isOpaqueCesrBody = frame.body.kind === "CESR"
|
|
226
|
-
frame.body.ked === null;
|
|
216
|
+
const isOpaqueCesrBody = frame.body.kind === "CESR"
|
|
217
|
+
&& frame.body.ked === null;
|
|
227
218
|
if (isOpaqueCesrBody) {
|
|
228
219
|
emitLine(lines, rawBody, `OPAQUE CESR body (non-serder fallback, hex=${toHex(frame.body.raw)})`, 0, options);
|
|
229
220
|
return;
|
package/esm/src/core/bytes.js
CHANGED
|
@@ -56,6 +56,10 @@ export function decodeB64(text) {
|
|
|
56
56
|
}
|
|
57
57
|
return out;
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Symmetric ceiling function
|
|
61
|
+
* @param value
|
|
62
|
+
*/
|
|
59
63
|
export function sceil(value) {
|
|
60
64
|
return Math.ceil(value);
|
|
61
65
|
}
|
|
@@ -74,3 +78,46 @@ export function codeB2ToB64(bytes, sextets) {
|
|
|
74
78
|
export function nabSextets(bytes, sextets) {
|
|
75
79
|
return codeB64ToB2(codeB2ToB64(bytes, sextets));
|
|
76
80
|
}
|
|
81
|
+
/** UTF-8 string -> bytes helper. */
|
|
82
|
+
export const b = (t) => encoder.encode(t);
|
|
83
|
+
/** UTF-8 bytes -> string helper. */
|
|
84
|
+
export const t = (b) => decoder.decode(b);
|
|
85
|
+
/**
|
|
86
|
+
* Normalize lmdb-js key/value payloads to `Uint8Array`.
|
|
87
|
+
* Example: converts Node `Buffer`-like values from `getRange()`.
|
|
88
|
+
*/
|
|
89
|
+
export function toBytes(value) {
|
|
90
|
+
if (value instanceof Uint8Array) {
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
return new Uint8Array(value);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Format number as 32-char hex string, zero padded.
|
|
97
|
+
* @param num
|
|
98
|
+
*/
|
|
99
|
+
export const to32CharHex = (num) => {
|
|
100
|
+
return num
|
|
101
|
+
.toString(16)
|
|
102
|
+
.padStart(32, "0");
|
|
103
|
+
};
|
|
104
|
+
/** Constant-time-ish byte equality for small DB keys/values. */
|
|
105
|
+
export function bytesEqual(left, right) {
|
|
106
|
+
if (left.length !== right.length) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
for (let i = 0; i < left.length; i++) {
|
|
110
|
+
if (left[i] !== right[i]) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
/** Stable hex fingerprint used for set-membership dedupe of binary values. */
|
|
117
|
+
export function bytesHex(value) {
|
|
118
|
+
// deno-fmt-ignore
|
|
119
|
+
return Array.from(value)
|
|
120
|
+
.map((byte) => byte.toString(16)
|
|
121
|
+
.padStart(2, "0"))
|
|
122
|
+
.join("");
|
|
123
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Decoder } from "cbor-x/decode";
|
|
2
|
+
import { Encoder } from "cbor-x/encode";
|
|
3
|
+
/**
|
|
4
|
+
* Normalize encoder output to a plain `Uint8Array`.
|
|
5
|
+
*
|
|
6
|
+
* `cbor-x` may return subclasses or reused backing buffers depending on the
|
|
7
|
+
* runtime and code path. The shared KERI codec deliberately copies the result
|
|
8
|
+
* so callers see a stable, plain `Uint8Array` contract that is safe to compare,
|
|
9
|
+
* persist, and hand across package boundaries without inheriting library
|
|
10
|
+
* implementation details.
|
|
11
|
+
*/
|
|
12
|
+
function normalizeEncodedBytes(bytes) {
|
|
13
|
+
return new Uint8Array(bytes);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Reject JavaScript `Map` values anywhere in the payload graph.
|
|
17
|
+
*
|
|
18
|
+
* This is not a statement about CBOR in general. CBOR absolutely supports map
|
|
19
|
+
* values. The narrower rule here is about KERI/ACDC parity: KERIpy serializes
|
|
20
|
+
* the same semantic payloads through JSON, MGPK, and CBOR, and the CBOR paths
|
|
21
|
+
* we are mirroring are dict/list shaped rather than "generic CBOR" shaped.
|
|
22
|
+
*
|
|
23
|
+
* In TypeScript, allowing `Map` values would silently widen the contract past
|
|
24
|
+
* what the JSON and MGPK paths can represent and past what KERIpy currently
|
|
25
|
+
* exercises in the mirrored protocol/storage serializers. This guard fails
|
|
26
|
+
* early so parity drift becomes an explicit decision instead of an accidental
|
|
27
|
+
* convenience.
|
|
28
|
+
*
|
|
29
|
+
* The walk is cycle-safe because this function is defensive validation, not a
|
|
30
|
+
* serializer in its own right. Cycles would fail later in the encoder anyway,
|
|
31
|
+
* but we avoid infinite recursion here while still checking the reachable graph
|
|
32
|
+
* for `Map` instances.
|
|
33
|
+
*/
|
|
34
|
+
function assertNoMapValues(value, seen = new Set()) {
|
|
35
|
+
if (value === null || typeof value !== "object") {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Map) {
|
|
39
|
+
throw new TypeError("KERI/ACDC CBOR payloads must use JSON-compatible plain objects/arrays, not JavaScript Map.");
|
|
40
|
+
}
|
|
41
|
+
if (seen.has(value)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
seen.add(value);
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
for (const item of value) {
|
|
47
|
+
assertNoMapValues(item, seen);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for (const item of Object.values(value)) {
|
|
52
|
+
assertNoMapValues(item, seen);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Canonical KERI/ACDC CBOR encoder configuration.
|
|
57
|
+
*
|
|
58
|
+
* Two choices matter for parity:
|
|
59
|
+
* - `useRecords: false` disables `cbor-x` record extensions so plain objects
|
|
60
|
+
* stay plain maps on the wire, matching KERIpy's `cbor2` behavior.
|
|
61
|
+
* - `variableMapSize: true` forces preferred-size map headers, avoiding the
|
|
62
|
+
* default `map16` preallocation strategy that broke exact byte parity.
|
|
63
|
+
*
|
|
64
|
+
* We import `Encoder` from `cbor-x/encode` rather than the package root because
|
|
65
|
+
* the root Node entrypoint probes `process.env` during module evaluation. That
|
|
66
|
+
* widened Deno test permissions for no KERI value, so the shared codec avoids
|
|
67
|
+
* that entrypoint on purpose.
|
|
68
|
+
*/
|
|
69
|
+
const keriCborEncoder = new Encoder({
|
|
70
|
+
useRecords: false,
|
|
71
|
+
variableMapSize: true,
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* Canonical KERI/ACDC CBOR decoder configuration.
|
|
75
|
+
*
|
|
76
|
+
* `mapsAsObjects: true` keeps decoded values aligned with the JSON-compatible
|
|
77
|
+
* object/list contract enforced by `encodeKeriCbor()`. This prevents the decode
|
|
78
|
+
* side from reintroducing `Map`-typed semantics that the encode side forbids
|
|
79
|
+
* and keeps protocol/storage callers working with the same value shapes they
|
|
80
|
+
* would see from JSON or MGPK decoding.
|
|
81
|
+
*
|
|
82
|
+
* Like the encoder, this uses the `cbor-x/decode` subpath to avoid the package
|
|
83
|
+
* root's Node-oriented environment probe.
|
|
84
|
+
*/
|
|
85
|
+
const keriCborDecoder = new Decoder({
|
|
86
|
+
useRecords: false,
|
|
87
|
+
mapsAsObjects: true,
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Encode KERI/ACDC CBOR with the same preferred map-size choices as KERIpy's
|
|
91
|
+
* `cbor2.dumps`.
|
|
92
|
+
*
|
|
93
|
+
* This is a protocol/storage codec for KERI/ACDC payloads, not a generic CBOR
|
|
94
|
+
* helper. KERIpy's corresponding emitters serialize dict/list-shaped data
|
|
95
|
+
* through `cbor2.dumps`, for example:
|
|
96
|
+
* - `keri.core.coring.dumps`
|
|
97
|
+
* - `keri.core.serdering.Serder.dumps`
|
|
98
|
+
* - `keri.db.koming.Komer.__serializeCBOR`
|
|
99
|
+
*
|
|
100
|
+
* The same semantic payloads also serialize as JSON and MGPK in KERIpy, so the
|
|
101
|
+
* intended cross-format contract is JSON-compatible plain objects and arrays.
|
|
102
|
+
* The default `cbor-x` encoder intentionally uses fixed-width `map16` headers
|
|
103
|
+
* for plain JS objects so it can preallocate and patch in the size later. That
|
|
104
|
+
* is valid CBOR but not byte-identical to KERIpy. This helper enables
|
|
105
|
+
* `variableMapSize` so small maps use the same compact headers that `cbor2`
|
|
106
|
+
* emits and rejects `Map` values so we do not silently drift into a broader
|
|
107
|
+
* CBOR type contract than KERIpy currently uses.
|
|
108
|
+
*/
|
|
109
|
+
export function encodeKeriCbor(value) {
|
|
110
|
+
assertNoMapValues(value);
|
|
111
|
+
return normalizeEncodedBytes(keriCborEncoder.encode(value));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Decode KERI/ACDC CBOR into plain JS objects/arrays.
|
|
115
|
+
*
|
|
116
|
+
* This keeps the decoder aligned with the encoder policy surface and avoids
|
|
117
|
+
* record-extension or `Map`-typed decode behavior on KERI/ACDC protocol and
|
|
118
|
+
* storage paths.
|
|
119
|
+
*/
|
|
120
|
+
export function decodeKeriCbor(raw) {
|
|
121
|
+
return keriCborDecoder.decode(raw);
|
|
122
|
+
}
|
package/esm/src/core/errors.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base parser failure carrying optional offset/context for maintainer
|
|
3
|
+
* diagnostics.
|
|
4
|
+
*
|
|
5
|
+
* Subclasses identify which parser phase rejected the input so callers can
|
|
6
|
+
* decide whether to recover, retry, or fail hard.
|
|
7
|
+
*/
|
|
1
8
|
export class ParserError extends Error {
|
|
2
9
|
constructor(message, offset, context) {
|
|
3
10
|
super(message);
|
|
@@ -16,6 +23,7 @@ export class ParserError extends Error {
|
|
|
16
23
|
this.name = globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).name;
|
|
17
24
|
}
|
|
18
25
|
}
|
|
26
|
+
/** Input ended before the parser had enough bytes to complete the current unit. */
|
|
19
27
|
export class ShortageError extends ParserError {
|
|
20
28
|
constructor(needed, available, offset) {
|
|
21
29
|
super(`Need ${needed} bytes but only ${available} available`, offset);
|
|
@@ -33,14 +41,19 @@ export class ShortageError extends ParserError {
|
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
43
|
}
|
|
44
|
+
/** Parser encountered an invalid cold-start selector. */
|
|
36
45
|
export class ColdStartError extends ParserError {
|
|
37
46
|
}
|
|
47
|
+
/** Version framing or version-table selection failed. */
|
|
38
48
|
export class VersionError extends ParserError {
|
|
39
49
|
}
|
|
50
|
+
/** A CESR code selector was not recognized in the active codex. */
|
|
40
51
|
export class UnknownCodeError extends ParserError {
|
|
41
52
|
}
|
|
53
|
+
/** Group/count metadata could not describe a valid parse shape. */
|
|
42
54
|
export class GroupSizeError extends ParserError {
|
|
43
55
|
}
|
|
56
|
+
/** Qualified input could not be deserialized into a valid CESR payload. */
|
|
44
57
|
export class DeserializeError extends ParserError {
|
|
45
58
|
}
|
|
46
59
|
/** Failure while constructing syntax artifacts from token bytes. */
|
|
@@ -34,8 +34,7 @@ export class AttachmentCollector {
|
|
|
34
34
|
value: void 0
|
|
35
35
|
});
|
|
36
36
|
this.frameBoundaryPolicy = options.frameBoundaryPolicy;
|
|
37
|
-
this.attachmentVersionFallbackPolicy =
|
|
38
|
-
options.attachmentVersionFallbackPolicy;
|
|
37
|
+
this.attachmentVersionFallbackPolicy = options.attachmentVersionFallbackPolicy;
|
|
39
38
|
this.recoveryDiagnosticObserver = options.recoveryDiagnosticObserver;
|
|
40
39
|
this.isFrameBoundaryAhead = options.isFrameBoundaryAhead;
|
|
41
40
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createAttachmentVersionFallbackPolicy, } from "../parser/group-dispatch.js";
|
|
2
2
|
import { ParserError, ShortageError } from "./errors.js";
|
|
3
|
+
import { AttachmentCollector } from "./parser-attachment-collector.js";
|
|
3
4
|
import { DEFAULT_VERSION } from "./parser-constants.js";
|
|
4
|
-
import { ParserStreamState } from "./parser-stream-state.js";
|
|
5
5
|
import { DeferredFrameLifecycle } from "./parser-deferred-frames.js";
|
|
6
6
|
import { FrameParser } from "./parser-frame-parser.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { createFrameBoundaryPolicy } from "./parser-policy.js";
|
|
8
|
+
import { ParserStreamState } from "./parser-stream-state.js";
|
|
9
9
|
import { composeRecoveryDiagnosticObserver, } from "./recovery-diagnostics.js";
|
|
10
10
|
/**
|
|
11
11
|
* Streaming CESR parser for message-domain and CESR-native body-group streams.
|
|
@@ -60,16 +60,16 @@ export class CesrParser {
|
|
|
60
60
|
writable: true,
|
|
61
61
|
value: void 0
|
|
62
62
|
});
|
|
63
|
-
this.frameBoundaryPolicy = options.frameBoundaryPolicy
|
|
64
|
-
createFrameBoundaryPolicy(options.framed ?? false);
|
|
63
|
+
this.frameBoundaryPolicy = options.frameBoundaryPolicy
|
|
64
|
+
?? createFrameBoundaryPolicy(options.framed ?? false);
|
|
65
65
|
this.recoveryDiagnosticObserver = composeRecoveryDiagnosticObserver({
|
|
66
66
|
onRecoveryDiagnostic: options.onRecoveryDiagnostic,
|
|
67
67
|
onAttachmentVersionFallback: options.attachmentVersionFallbackPolicy
|
|
68
68
|
? undefined
|
|
69
69
|
: options.onAttachmentVersionFallback,
|
|
70
70
|
});
|
|
71
|
-
const attachmentVersionFallbackPolicy = options.attachmentVersionFallbackPolicy
|
|
72
|
-
createAttachmentVersionFallbackPolicy({
|
|
71
|
+
const attachmentVersionFallbackPolicy = options.attachmentVersionFallbackPolicy
|
|
72
|
+
?? createAttachmentVersionFallbackPolicy({
|
|
73
73
|
mode: options.attachmentDispatchMode,
|
|
74
74
|
});
|
|
75
75
|
this.stream = new ParserStreamState(DEFAULT_VERSION);
|
|
@@ -3,8 +3,8 @@ import { sniff } from "../parser/cold-start.js";
|
|
|
3
3
|
import { parseCounter } from "../primitives/counter.js";
|
|
4
4
|
import { parseIlker } from "../primitives/ilker.js";
|
|
5
5
|
import { isLabelerCode, parseLabeler } from "../primitives/labeler.js";
|
|
6
|
-
import { parseMatter } from "../primitives/matter.js";
|
|
7
6
|
import { interpretMapperBodySyntax, parseMapperBodySyntax, } from "../primitives/mapper.js";
|
|
7
|
+
import { parseMatter } from "../primitives/matter.js";
|
|
8
8
|
import { parseVerser } from "../primitives/verser.js";
|
|
9
9
|
import { reapSerder } from "../serder/serdery.js";
|
|
10
10
|
import { Kinds, Protocols } from "../tables/versions.js";
|
|
@@ -46,8 +46,7 @@ export class FrameParser {
|
|
|
46
46
|
value: void 0
|
|
47
47
|
});
|
|
48
48
|
this.frameBoundaryPolicy = options.frameBoundaryPolicy;
|
|
49
|
-
this.attachmentVersionFallbackPolicy =
|
|
50
|
-
options.attachmentVersionFallbackPolicy;
|
|
49
|
+
this.attachmentVersionFallbackPolicy = options.attachmentVersionFallbackPolicy;
|
|
51
50
|
this.onEnclosedFrames = options.onEnclosedFrames;
|
|
52
51
|
this.recoveryDiagnosticObserver = options.recoveryDiagnosticObserver;
|
|
53
52
|
}
|
|
@@ -432,9 +431,9 @@ export class FrameParser {
|
|
|
432
431
|
};
|
|
433
432
|
}
|
|
434
433
|
catch (error) {
|
|
435
|
-
if (error instanceof ShortageError
|
|
436
|
-
error instanceof UnknownCodeError
|
|
437
|
-
error instanceof DeserializeError) {
|
|
434
|
+
if (error instanceof ShortageError
|
|
435
|
+
|| error instanceof UnknownCodeError
|
|
436
|
+
|| error instanceof DeserializeError) {
|
|
438
437
|
throw new SyntaxParseError(`Native body syntax parse failed: ${error.message}`, error);
|
|
439
438
|
}
|
|
440
439
|
throw error;
|
|
@@ -499,8 +498,7 @@ export class FrameParser {
|
|
|
499
498
|
const size = tokenSize(ctr, cold);
|
|
500
499
|
entries.push({
|
|
501
500
|
kind: "value",
|
|
502
|
-
|
|
503
|
-
qb64: ctr.qb64,
|
|
501
|
+
primitive: ctr,
|
|
504
502
|
});
|
|
505
503
|
offset += size;
|
|
506
504
|
continue;
|
|
@@ -512,15 +510,13 @@ export class FrameParser {
|
|
|
512
510
|
entries.push({
|
|
513
511
|
kind: "label",
|
|
514
512
|
label: parseLabeler(at, cold).label,
|
|
515
|
-
|
|
516
|
-
qb64: token.qb64,
|
|
513
|
+
primitive: token,
|
|
517
514
|
});
|
|
518
515
|
continue;
|
|
519
516
|
}
|
|
520
517
|
entries.push({
|
|
521
518
|
kind: "value",
|
|
522
|
-
|
|
523
|
-
qb64: token.qb64,
|
|
519
|
+
primitive: token,
|
|
524
520
|
});
|
|
525
521
|
}
|
|
526
522
|
if (offset !== end) {
|
|
@@ -534,8 +530,7 @@ export class FrameParser {
|
|
|
534
530
|
try {
|
|
535
531
|
return interpretMapperBodySyntax(syntax.mapper).map((field) => ({
|
|
536
532
|
label: field.label,
|
|
537
|
-
|
|
538
|
-
qb64: field.qb64,
|
|
533
|
+
primitive: field.primitive,
|
|
539
534
|
}));
|
|
540
535
|
}
|
|
541
536
|
catch (error) {
|
|
@@ -554,8 +549,7 @@ export class FrameParser {
|
|
|
554
549
|
}
|
|
555
550
|
out.push({
|
|
556
551
|
label: pendingLabel,
|
|
557
|
-
|
|
558
|
-
qb64: entry.qb64,
|
|
552
|
+
primitive: entry.primitive,
|
|
559
553
|
});
|
|
560
554
|
pendingLabel = null;
|
|
561
555
|
}
|
|
@@ -591,8 +585,8 @@ export class FrameParser {
|
|
|
591
585
|
if (error instanceof ShortageError) {
|
|
592
586
|
throw error;
|
|
593
587
|
}
|
|
594
|
-
if (error instanceof UnknownCodeError
|
|
595
|
-
error instanceof DeserializeError) {
|
|
588
|
+
if (error instanceof UnknownCodeError
|
|
589
|
+
|| error instanceof DeserializeError) {
|
|
596
590
|
continue;
|
|
597
591
|
}
|
|
598
592
|
throw error;
|
|
@@ -622,8 +616,8 @@ export class FrameParser {
|
|
|
622
616
|
if (error instanceof ShortageError) {
|
|
623
617
|
throw error;
|
|
624
618
|
}
|
|
625
|
-
if (error instanceof UnknownCodeError
|
|
626
|
-
error instanceof DeserializeError) {
|
|
619
|
+
if (error instanceof UnknownCodeError
|
|
620
|
+
|| error instanceof DeserializeError) {
|
|
627
621
|
if (!firstError) {
|
|
628
622
|
firstError = error;
|
|
629
623
|
}
|