cesr-ts 0.3.0 → 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 +6 -1
- 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
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { b64ToInt, codeB2ToB64, codeB64ToB2, decodeB64, nabSextets, sceil, } from "../core/bytes.js";
|
|
2
|
-
import { DeserializeError, ShortageError, UnknownCodeError
|
|
3
|
-
import { INDEXER_HARDS, INDEXER_SIZES } from "../tables/indexer.tables.js";
|
|
1
|
+
import { b, b64ToInt, codeB2ToB64, codeB64ToB2, concatBytes, decodeB64, encodeB64, intToB64, nabSextets, sceil, } from "../core/bytes.js";
|
|
2
|
+
import { DeserializeError, ShortageError, UnknownCodeError } from "../core/errors.js";
|
|
3
|
+
import { INDEXER_HARDS, INDEXER_SIZES } from "../tables/indexer.tables.generated.js";
|
|
4
4
|
const INDEXER_BARDS = new Map([...INDEXER_HARDS.entries()].map(([code, hs]) => [
|
|
5
5
|
String.fromCharCode(codeB64ToB2(code)[0]),
|
|
6
6
|
hs,
|
|
7
7
|
]));
|
|
8
|
+
function isIndexerData(value) {
|
|
9
|
+
return typeof value === "object" && value !== null
|
|
10
|
+
&& "code" in value && "raw" in value && "qb64" in value
|
|
11
|
+
&& "fullSize" in value && "fullSizeB2" in value && "index" in value;
|
|
12
|
+
}
|
|
8
13
|
function parseIndexerCodeFromText(txt) {
|
|
9
14
|
const hs = INDEXER_HARDS.get(txt[0]);
|
|
10
15
|
if (!hs) {
|
|
@@ -16,7 +21,19 @@ function parseIndexerCodeFromText(txt) {
|
|
|
16
21
|
}
|
|
17
22
|
return { code };
|
|
18
23
|
}
|
|
19
|
-
|
|
24
|
+
function parseIndexFields(code, qb64) {
|
|
25
|
+
const sizage = INDEXER_SIZES.get(code);
|
|
26
|
+
if (!sizage) {
|
|
27
|
+
throw new UnknownCodeError(`Unknown indexer code ${code}`);
|
|
28
|
+
}
|
|
29
|
+
const cs = sizage.hs + sizage.ss;
|
|
30
|
+
const soft = qb64.slice(sizage.hs, cs);
|
|
31
|
+
const ms = sizage.ss - sizage.os;
|
|
32
|
+
const index = ms > 0 ? b64ToInt(soft.slice(0, ms)) : 0;
|
|
33
|
+
const ondex = sizage.os > 0 ? b64ToInt(soft.slice(ms, sizage.ss)) : undefined;
|
|
34
|
+
return { index, ondex };
|
|
35
|
+
}
|
|
36
|
+
function parseIndexerFromTextData(input) {
|
|
20
37
|
const txt = String.fromCharCode(...input);
|
|
21
38
|
if (txt.length === 0) {
|
|
22
39
|
throw new DeserializeError("Empty indexer input");
|
|
@@ -29,16 +46,20 @@ export function parseIndexerFromText(input) {
|
|
|
29
46
|
if (txt.length < fullSize) {
|
|
30
47
|
throw new ShortageError(fullSize, txt.length);
|
|
31
48
|
}
|
|
32
|
-
const
|
|
49
|
+
const qb64 = txt.slice(0, fullSize);
|
|
50
|
+
const raw = decodeB64(qb64.slice(cs)).slice(sizage.ls);
|
|
51
|
+
const { index, ondex } = parseIndexFields(code, qb64);
|
|
33
52
|
return {
|
|
34
53
|
code,
|
|
35
54
|
raw,
|
|
36
|
-
qb64
|
|
55
|
+
qb64,
|
|
37
56
|
fullSize,
|
|
38
57
|
fullSizeB2: sceil((fullSize * 3) / 4),
|
|
58
|
+
index,
|
|
59
|
+
ondex,
|
|
39
60
|
};
|
|
40
61
|
}
|
|
41
|
-
|
|
62
|
+
function parseIndexerFromBinaryData(input) {
|
|
42
63
|
if (input.length === 0) {
|
|
43
64
|
throw new ShortageError(1, 0);
|
|
44
65
|
}
|
|
@@ -71,14 +92,185 @@ export function parseIndexerFromBinary(input) {
|
|
|
71
92
|
const qb2 = input.slice(0, bfs);
|
|
72
93
|
const qb64 = codeB2ToB64(qb2, fs);
|
|
73
94
|
const raw = decodeB64(qb64.slice(cs)).slice(sizage.ls);
|
|
95
|
+
const { index, ondex } = parseIndexFields(hard, qb64);
|
|
74
96
|
return {
|
|
75
97
|
code: hard,
|
|
76
98
|
raw,
|
|
77
99
|
qb64,
|
|
78
100
|
fullSize: fs,
|
|
79
101
|
fullSizeB2: bfs,
|
|
102
|
+
index,
|
|
103
|
+
ondex,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function encodeIndexerFromRaw(code, raw, index, ondex) {
|
|
107
|
+
const sizage = INDEXER_SIZES.get(code);
|
|
108
|
+
if (!sizage) {
|
|
109
|
+
throw new UnknownCodeError(`Unknown indexer code ${code}`);
|
|
110
|
+
}
|
|
111
|
+
const ms = sizage.ss - sizage.os;
|
|
112
|
+
if (ms < 0) {
|
|
113
|
+
throw new DeserializeError(`Invalid indexer sizage for ${code}`);
|
|
114
|
+
}
|
|
115
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
116
|
+
throw new DeserializeError(`Invalid index ${index} for ${code}`);
|
|
117
|
+
}
|
|
118
|
+
const ondexValue = sizage.os > 0 ? (ondex ?? index) : undefined;
|
|
119
|
+
if (sizage.os > 0 && (ondexValue === undefined || ondexValue < 0)) {
|
|
120
|
+
throw new DeserializeError(`Invalid ondex ${ondexValue} for ${code}`);
|
|
121
|
+
}
|
|
122
|
+
const cs = sizage.hs + sizage.ss;
|
|
123
|
+
const ps = cs % 4;
|
|
124
|
+
const paw = concatBytes(new Uint8Array(ps + sizage.ls), raw);
|
|
125
|
+
const body = encodeB64(paw).slice(ps);
|
|
126
|
+
const soft = `${intToB64(index, ms)}${sizage.os > 0 ? intToB64(ondexValue ?? 0, sizage.os) : ""}`;
|
|
127
|
+
const qb64 = `${code}${soft}${body}`;
|
|
128
|
+
const fullSize = qb64.length;
|
|
129
|
+
if (sizage.fs !== null && fullSize !== sizage.fs) {
|
|
130
|
+
throw new DeserializeError(`Encoded indexer size mismatch for ${code}: expected=${sizage.fs} got=${fullSize}`);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
code,
|
|
134
|
+
raw: raw.slice(),
|
|
135
|
+
qb64,
|
|
136
|
+
fullSize,
|
|
137
|
+
fullSizeB2: sceil((fullSize * 3) / 4),
|
|
138
|
+
index,
|
|
139
|
+
ondex: ondexValue,
|
|
80
140
|
};
|
|
81
141
|
}
|
|
142
|
+
function parseIndexerInit(init) {
|
|
143
|
+
if (init.raw && init.code) {
|
|
144
|
+
return encodeIndexerFromRaw(init.code, init.raw, init.index ?? 0, init.ondex);
|
|
145
|
+
}
|
|
146
|
+
if (init.qb64b) {
|
|
147
|
+
return parseIndexerFromTextData(init.qb64b);
|
|
148
|
+
}
|
|
149
|
+
if (init.qb64) {
|
|
150
|
+
return parseIndexerFromTextData(b(init.qb64));
|
|
151
|
+
}
|
|
152
|
+
if (init.qb2) {
|
|
153
|
+
return parseIndexerFromBinaryData(init.qb2);
|
|
154
|
+
}
|
|
155
|
+
throw new DeserializeError("Indexer requires (raw + code) or qb64/qb64b/qb2 initialization");
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Base indexed CESR primitive.
|
|
159
|
+
*
|
|
160
|
+
* KERIpy substance: `Indexer` extends matter semantics with index/ondex fields
|
|
161
|
+
* used by indexed signatures and other attachment-indexed material families.
|
|
162
|
+
*/
|
|
163
|
+
export class Indexer {
|
|
164
|
+
constructor(init) {
|
|
165
|
+
Object.defineProperty(this, "_code", {
|
|
166
|
+
enumerable: true,
|
|
167
|
+
configurable: true,
|
|
168
|
+
writable: true,
|
|
169
|
+
value: void 0
|
|
170
|
+
});
|
|
171
|
+
Object.defineProperty(this, "_raw", {
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
writable: true,
|
|
175
|
+
value: void 0
|
|
176
|
+
});
|
|
177
|
+
Object.defineProperty(this, "_qb64", {
|
|
178
|
+
enumerable: true,
|
|
179
|
+
configurable: true,
|
|
180
|
+
writable: true,
|
|
181
|
+
value: void 0
|
|
182
|
+
});
|
|
183
|
+
Object.defineProperty(this, "_fullSize", {
|
|
184
|
+
enumerable: true,
|
|
185
|
+
configurable: true,
|
|
186
|
+
writable: true,
|
|
187
|
+
value: void 0
|
|
188
|
+
});
|
|
189
|
+
Object.defineProperty(this, "_fullSizeB2", {
|
|
190
|
+
enumerable: true,
|
|
191
|
+
configurable: true,
|
|
192
|
+
writable: true,
|
|
193
|
+
value: void 0
|
|
194
|
+
});
|
|
195
|
+
Object.defineProperty(this, "_index", {
|
|
196
|
+
enumerable: true,
|
|
197
|
+
configurable: true,
|
|
198
|
+
writable: true,
|
|
199
|
+
value: void 0
|
|
200
|
+
});
|
|
201
|
+
Object.defineProperty(this, "_ondex", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
configurable: true,
|
|
204
|
+
writable: true,
|
|
205
|
+
value: void 0
|
|
206
|
+
});
|
|
207
|
+
const data = init instanceof Indexer
|
|
208
|
+
? init.toIndexerData()
|
|
209
|
+
: isIndexerData(init)
|
|
210
|
+
? init
|
|
211
|
+
: parseIndexerInit(init);
|
|
212
|
+
this._code = data.code;
|
|
213
|
+
this._raw = data.raw.slice();
|
|
214
|
+
this._qb64 = data.qb64;
|
|
215
|
+
this._fullSize = data.fullSize;
|
|
216
|
+
this._fullSizeB2 = data.fullSizeB2;
|
|
217
|
+
this._index = data.index;
|
|
218
|
+
this._ondex = data.ondex;
|
|
219
|
+
}
|
|
220
|
+
toIndexerData() {
|
|
221
|
+
return {
|
|
222
|
+
code: this._code,
|
|
223
|
+
raw: this._raw.slice(),
|
|
224
|
+
qb64: this._qb64,
|
|
225
|
+
fullSize: this._fullSize,
|
|
226
|
+
fullSizeB2: this._fullSizeB2,
|
|
227
|
+
index: this._index,
|
|
228
|
+
ondex: this._ondex,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
get code() {
|
|
232
|
+
return this._code;
|
|
233
|
+
}
|
|
234
|
+
get raw() {
|
|
235
|
+
return this._raw;
|
|
236
|
+
}
|
|
237
|
+
get qb64() {
|
|
238
|
+
return this._qb64;
|
|
239
|
+
}
|
|
240
|
+
get qb64b() {
|
|
241
|
+
return b(this._qb64);
|
|
242
|
+
}
|
|
243
|
+
get qb2() {
|
|
244
|
+
return codeB64ToB2(this._qb64);
|
|
245
|
+
}
|
|
246
|
+
get fullSize() {
|
|
247
|
+
return this._fullSize;
|
|
248
|
+
}
|
|
249
|
+
get fullSizeB2() {
|
|
250
|
+
return this._fullSizeB2;
|
|
251
|
+
}
|
|
252
|
+
get index() {
|
|
253
|
+
return this._index;
|
|
254
|
+
}
|
|
255
|
+
get ondex() {
|
|
256
|
+
return this._ondex;
|
|
257
|
+
}
|
|
258
|
+
equals(other) {
|
|
259
|
+
return this._qb64 === other.qb64;
|
|
260
|
+
}
|
|
261
|
+
toString() {
|
|
262
|
+
return this._qb64;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** Parse indexer material from text-domain CESR bytes. */
|
|
266
|
+
export function parseIndexerFromText(input) {
|
|
267
|
+
return new Indexer(parseIndexerFromTextData(input));
|
|
268
|
+
}
|
|
269
|
+
/** Parse indexer material from binary-domain CESR bytes. */
|
|
270
|
+
export function parseIndexerFromBinary(input) {
|
|
271
|
+
return new Indexer(parseIndexerFromBinaryData(input));
|
|
272
|
+
}
|
|
273
|
+
/** Parse indexer using caller-provided cold-start domain hint (`txt` or `bny`). */
|
|
82
274
|
export function parseIndexer(input, cold) {
|
|
83
275
|
return cold === "bny"
|
|
84
276
|
? parseIndexerFromBinary(input)
|
|
@@ -1,31 +1,81 @@
|
|
|
1
1
|
import { UnknownCodeError } from "../core/errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Bexter } from "./bexter.js";
|
|
3
|
+
import { BEXTER_CODES, isAttLabel, LABELER_CODES, TAG_CODES } from "./codex.js";
|
|
4
|
+
import { Matter, parseMatter } from "./matter.js";
|
|
5
|
+
import { Tagger } from "./tagger.js";
|
|
3
6
|
const TEXT_DECODER = new TextDecoder();
|
|
4
|
-
|
|
7
|
+
/** True when code belongs to KERIpy `LabelCodex` accepted by native map labels. */
|
|
5
8
|
export function isLabelerCode(code) {
|
|
6
9
|
return LABELER_CODES.has(code);
|
|
7
10
|
}
|
|
8
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Decode a label/text token according to LabelCodex encoding rules.
|
|
13
|
+
*
|
|
14
|
+
* Tag/Bext encodings require specialized decoding logic; all other label forms
|
|
15
|
+
* project directly from raw bytes.
|
|
16
|
+
*/
|
|
17
|
+
function decodeLabelText(matter) {
|
|
18
|
+
if (TAG_CODES.has(matter.code)) {
|
|
19
|
+
return new Tagger(matter).tag;
|
|
20
|
+
}
|
|
21
|
+
if (BEXTER_CODES.has(matter.code)) {
|
|
22
|
+
const bext = Bexter.derawify(matter.raw, matter.code);
|
|
23
|
+
return bext.startsWith("-") && isAttLabel(bext.slice(1))
|
|
24
|
+
? bext.slice(1)
|
|
25
|
+
: bext;
|
|
26
|
+
}
|
|
27
|
+
return TEXT_DECODER.decode(matter.raw);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Label/text primitive used for native map keys and textual field values.
|
|
31
|
+
*
|
|
32
|
+
* KERIpy semantics: `Labeler` accepts Tag/Bext/Bytes families (plus compact
|
|
33
|
+
* label codes) and provides both strict attribute-label projection (`label`)
|
|
34
|
+
* and generic text projection (`text`).
|
|
35
|
+
*/
|
|
36
|
+
export class Labeler extends Matter {
|
|
37
|
+
constructor(init) {
|
|
38
|
+
const matter = init instanceof Matter ? init : new Matter(init);
|
|
39
|
+
super(matter);
|
|
40
|
+
if (!isLabelerCode(this.code)) {
|
|
41
|
+
throw new UnknownCodeError(`Expected labeler code, got ${this.code}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Canonical qb64 token for emit/roundtrip paths. */
|
|
45
|
+
get token() {
|
|
46
|
+
return this.qb64;
|
|
47
|
+
}
|
|
48
|
+
/** Attribute-safe label projection used for map key semantics. */
|
|
49
|
+
get label() {
|
|
50
|
+
const label = decodeLabelText(this);
|
|
51
|
+
if (!isAttLabel(label)) {
|
|
52
|
+
throw new UnknownCodeError(`Invalid label text: ${label}`);
|
|
53
|
+
}
|
|
54
|
+
return label;
|
|
55
|
+
}
|
|
56
|
+
/** Raw text projection without attribute-name validation. */
|
|
57
|
+
get text() {
|
|
58
|
+
return decodeLabelText(this);
|
|
59
|
+
}
|
|
60
|
+
/** Numeric projection helper used for compact fixed-width label values. */
|
|
61
|
+
get index() {
|
|
62
|
+
let index = 0;
|
|
63
|
+
for (const b of this.raw) {
|
|
64
|
+
index = (index << 8) | b;
|
|
65
|
+
}
|
|
66
|
+
return index;
|
|
67
|
+
}
|
|
68
|
+
/** Raw decoded bytes backing the label/text token. */
|
|
69
|
+
get bytes() {
|
|
70
|
+
return this.raw;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse and hydrate a `Labeler` from txt/qb2 bytes.
|
|
75
|
+
*
|
|
76
|
+
* Boundary contract: parsing is syntactic; semantic label validity is enforced
|
|
77
|
+
* when `label` accessor is read.
|
|
78
|
+
*/
|
|
9
79
|
export function parseLabeler(input, cold) {
|
|
10
|
-
|
|
11
|
-
const matter = parseMatter(input, cold);
|
|
12
|
-
if (!isLabelerCode(matter.code)) {
|
|
13
|
-
throw new UnknownCodeError(`Expected labeler code (V/W), got ${matter.code}`);
|
|
14
|
-
}
|
|
15
|
-
let index = 0;
|
|
16
|
-
for (const b of matter.raw) {
|
|
17
|
-
index = (index << 8) | b;
|
|
18
|
-
}
|
|
19
|
-
const text = TEXT_DECODER.decode(matter.raw).replace(/\u0000/g, "");
|
|
20
|
-
const label = text.length > 0 ? text : matter.qb64.slice(matter.code.length);
|
|
21
|
-
return {
|
|
22
|
-
code: matter.code,
|
|
23
|
-
qb64: matter.qb64,
|
|
24
|
-
fullSize: matter.fullSize,
|
|
25
|
-
fullSizeB2: matter.fullSizeB2,
|
|
26
|
-
token: matter.qb64,
|
|
27
|
-
label,
|
|
28
|
-
index,
|
|
29
|
-
bytes: matter.raw,
|
|
30
|
-
};
|
|
80
|
+
return new Labeler(parseMatter(input, cold));
|
|
31
81
|
}
|
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import { encodeB64 } from "../core/bytes.js";
|
|
2
1
|
import { DeserializeError, SemanticInterpretationError, ShortageError, SyntaxParseError, UnknownCodeError, } from "../core/errors.js";
|
|
3
2
|
import { parseAttachmentDispatch } from "../parser/group-dispatch.js";
|
|
4
|
-
import {
|
|
3
|
+
import { AGGOR_LIST_CODES, AGGOR_MAP_CODES } from "../tables/counter-groups.js";
|
|
5
4
|
import { parseCounter } from "./counter.js";
|
|
6
5
|
import { parseLabeler } from "./labeler.js";
|
|
7
6
|
import { parseMatter } from "./matter.js";
|
|
8
|
-
const MAP_GROUP_CODES = new Set([
|
|
9
|
-
CtrDexV2.MapBodyGroup,
|
|
10
|
-
CtrDexV2.BigMapBodyGroup,
|
|
11
|
-
CtrDexV2.GenericMapGroup,
|
|
12
|
-
CtrDexV2.BigGenericMapGroup,
|
|
13
|
-
]);
|
|
14
|
-
const LIST_GROUP_CODES = new Set([
|
|
15
|
-
CtrDexV2.GenericGroup,
|
|
16
|
-
CtrDexV2.BigGenericGroup,
|
|
17
|
-
CtrDexV2.GenericListGroup,
|
|
18
|
-
CtrDexV2.BigGenericListGroup,
|
|
19
|
-
]);
|
|
20
7
|
function tokenSize(token, domain) {
|
|
21
8
|
return domain === "bny" ? token.fullSizeB2 : token.fullSize;
|
|
22
9
|
}
|
|
23
10
|
function isMapGroupCode(code) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
function asQb64(raw, domain) {
|
|
27
|
-
return domain === "txt" ? String.fromCharCode(...raw) : encodeB64(raw);
|
|
11
|
+
return AGGOR_MAP_CODES.has(code);
|
|
28
12
|
}
|
|
29
13
|
function parseCounterProbe(input, version, domain) {
|
|
30
14
|
/**
|
|
@@ -46,8 +30,8 @@ function parseCounterProbe(input, version, domain) {
|
|
|
46
30
|
if (error instanceof ShortageError) {
|
|
47
31
|
throw error;
|
|
48
32
|
}
|
|
49
|
-
if (error instanceof UnknownCodeError
|
|
50
|
-
error instanceof DeserializeError) {
|
|
33
|
+
if (error instanceof UnknownCodeError
|
|
34
|
+
|| error instanceof DeserializeError) {
|
|
51
35
|
continue;
|
|
52
36
|
}
|
|
53
37
|
throw error;
|
|
@@ -64,8 +48,8 @@ function parseLabelProbe(input, domain) {
|
|
|
64
48
|
if (error instanceof ShortageError) {
|
|
65
49
|
throw error;
|
|
66
50
|
}
|
|
67
|
-
if (error instanceof UnknownCodeError
|
|
68
|
-
error instanceof DeserializeError) {
|
|
51
|
+
if (error instanceof UnknownCodeError
|
|
52
|
+
|| error instanceof DeserializeError) {
|
|
69
53
|
return null;
|
|
70
54
|
}
|
|
71
55
|
throw error;
|
|
@@ -81,11 +65,9 @@ function parseMapperValueSyntax(input, version, domain) {
|
|
|
81
65
|
const counter = parseCounterProbe(input, version, domain);
|
|
82
66
|
if (counter) {
|
|
83
67
|
const dispatch = parseAttachmentDispatch(input, version, domain);
|
|
84
|
-
const raw = input.slice(0, dispatch.consumed);
|
|
85
68
|
const value = {
|
|
86
69
|
kind: "value",
|
|
87
|
-
|
|
88
|
-
qb64: asQb64(raw, domain),
|
|
70
|
+
primitive: dispatch.group,
|
|
89
71
|
isCounter: true,
|
|
90
72
|
consumed: dispatch.consumed,
|
|
91
73
|
};
|
|
@@ -97,8 +79,7 @@ function parseMapperValueSyntax(input, version, domain) {
|
|
|
97
79
|
const matter = parseMatter(input, domain);
|
|
98
80
|
return {
|
|
99
81
|
kind: "value",
|
|
100
|
-
|
|
101
|
-
qb64: matter.qb64,
|
|
82
|
+
primitive: matter,
|
|
102
83
|
isCounter: false,
|
|
103
84
|
consumed: tokenSize(matter, domain),
|
|
104
85
|
};
|
|
@@ -119,8 +100,7 @@ function parseMapPayloadSyntax(input, version, domain, start, end) {
|
|
|
119
100
|
const consumed = tokenSize(maybeLabel, domain);
|
|
120
101
|
entries.push({
|
|
121
102
|
kind: "label",
|
|
122
|
-
|
|
123
|
-
qb64: maybeLabel.token,
|
|
103
|
+
primitive: parseMatter(at, domain),
|
|
124
104
|
label: maybeLabel.label,
|
|
125
105
|
consumed,
|
|
126
106
|
});
|
|
@@ -147,8 +127,7 @@ export function interpretMapperBodySyntax(syntax) {
|
|
|
147
127
|
}
|
|
148
128
|
fields.push({
|
|
149
129
|
label: pendingLabel,
|
|
150
|
-
|
|
151
|
-
qb64: entry.qb64,
|
|
130
|
+
primitive: entry.primitive,
|
|
152
131
|
isCounter: entry.isCounter,
|
|
153
132
|
children: entry.children
|
|
154
133
|
? interpretMapperBodySyntax(entry.children)
|
|
@@ -190,9 +169,9 @@ export function parseMapperBodySyntax(input, version, domain) {
|
|
|
190
169
|
};
|
|
191
170
|
}
|
|
192
171
|
catch (error) {
|
|
193
|
-
if (error instanceof ShortageError
|
|
194
|
-
error instanceof UnknownCodeError
|
|
195
|
-
error instanceof DeserializeError) {
|
|
172
|
+
if (error instanceof ShortageError
|
|
173
|
+
|| error instanceof UnknownCodeError
|
|
174
|
+
|| error instanceof DeserializeError) {
|
|
196
175
|
throw new SyntaxParseError(`Map-body syntax parse failed: ${error.message}`, error);
|
|
197
176
|
}
|
|
198
177
|
throw error;
|
|
@@ -235,5 +214,5 @@ export function parseMapperBody(input, version, domain) {
|
|
|
235
214
|
}
|
|
236
215
|
/** True for counter codes that represent map/list-native aggregate primitives. */
|
|
237
216
|
export function isMapperCounterCode(code) {
|
|
238
|
-
return
|
|
217
|
+
return AGGOR_MAP_CODES.has(code) || AGGOR_LIST_CODES.has(code);
|
|
239
218
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { b64ToInt, codeB2ToB64, codeB64ToB2, decodeB64, nabSextets, sceil, } from "../core/bytes.js";
|
|
2
|
-
import { DeserializeError, ShortageError, UnknownCodeError
|
|
3
|
-
import { MATTER_HARDS, MATTER_SIZES
|
|
1
|
+
import { b, b64ToInt, codeB2ToB64, codeB64ToB2, concatBytes, decodeB64, encodeB64, intToB64, nabSextets, sceil, } from "../core/bytes.js";
|
|
2
|
+
import { DeserializeError, ShortageError, UnknownCodeError } from "../core/errors.js";
|
|
3
|
+
import { MATTER_HARDS, MATTER_SIZES } from "../tables/matter.tables.generated.js";
|
|
4
4
|
const MATTER_BARDS = new Map([...MATTER_HARDS.entries()].map(([code, hs]) => [
|
|
5
5
|
String.fromCharCode(codeB64ToB2(code)[0]),
|
|
6
6
|
hs,
|
|
7
7
|
]));
|
|
8
|
+
function isMatterData(value) {
|
|
9
|
+
return typeof value === "object"
|
|
10
|
+
&& value !== null
|
|
11
|
+
&& "code" in value
|
|
12
|
+
&& "raw" in value
|
|
13
|
+
&& "qb64" in value
|
|
14
|
+
&& "fullSize" in value
|
|
15
|
+
&& "fullSizeB2" in value;
|
|
16
|
+
}
|
|
8
17
|
function parseMatterCodeFromText(txt) {
|
|
9
18
|
const hs = MATTER_HARDS.get(txt[0]);
|
|
10
19
|
if (!hs) {
|
|
@@ -23,7 +32,7 @@ function parseMatterCodeFromText(txt) {
|
|
|
23
32
|
}
|
|
24
33
|
return { code, hs: sizage.hs };
|
|
25
34
|
}
|
|
26
|
-
|
|
35
|
+
function parseMatterFromTextData(input) {
|
|
27
36
|
const txt = String.fromCharCode(...input);
|
|
28
37
|
if (txt.length === 0) {
|
|
29
38
|
throw new ShortageError(1, 0);
|
|
@@ -48,7 +57,7 @@ export function parseMatterFromText(input) {
|
|
|
48
57
|
fullSizeB2: sceil((fullSize * 3) / 4),
|
|
49
58
|
};
|
|
50
59
|
}
|
|
51
|
-
|
|
60
|
+
function parseMatterFromBinaryData(input) {
|
|
52
61
|
if (input.length === 0) {
|
|
53
62
|
throw new ShortageError(1, 0);
|
|
54
63
|
}
|
|
@@ -93,7 +102,8 @@ export function parseMatterFromBinary(input) {
|
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
104
|
const qb64 = codeB2ToB64(qb2, fs);
|
|
96
|
-
const
|
|
105
|
+
const paw = decodeB64("A".repeat(ps) + qb64.slice(cs));
|
|
106
|
+
const raw = paw.slice(ps + sizage.ls);
|
|
97
107
|
return {
|
|
98
108
|
code: hard,
|
|
99
109
|
raw,
|
|
@@ -102,6 +112,150 @@ export function parseMatterFromBinary(input) {
|
|
|
102
112
|
fullSizeB2: bfs,
|
|
103
113
|
};
|
|
104
114
|
}
|
|
115
|
+
function encodeMatterFromRaw(code, raw) {
|
|
116
|
+
const sizage = MATTER_SIZES.get(code);
|
|
117
|
+
if (!sizage) {
|
|
118
|
+
throw new UnknownCodeError(`Unknown matter code ${code}`);
|
|
119
|
+
}
|
|
120
|
+
const cs = sizage.hs + sizage.ss;
|
|
121
|
+
const ps = cs % 4;
|
|
122
|
+
const paw = concatBytes(new Uint8Array(ps + sizage.ls), raw);
|
|
123
|
+
const body = encodeB64(paw).slice(ps);
|
|
124
|
+
let soft = "";
|
|
125
|
+
if (sizage.ss > 0) {
|
|
126
|
+
const softLen = sizage.ss - sizage.xs;
|
|
127
|
+
if (softLen < 0) {
|
|
128
|
+
throw new DeserializeError(`Invalid sizage soft width for code ${code}`);
|
|
129
|
+
}
|
|
130
|
+
const count = sizage.fs === null ? body.length / 4 : (sizage.fs - cs) / 4;
|
|
131
|
+
if (!Number.isInteger(count) || count < 0) {
|
|
132
|
+
throw new DeserializeError(`Invalid computed count for code ${code}`);
|
|
133
|
+
}
|
|
134
|
+
soft = "_".repeat(sizage.xs) + intToB64(count, softLen);
|
|
135
|
+
}
|
|
136
|
+
const qb64 = `${code}${soft}${body}`;
|
|
137
|
+
const fullSize = qb64.length;
|
|
138
|
+
if (sizage.fs !== null && fullSize !== sizage.fs) {
|
|
139
|
+
throw new DeserializeError(`Encoded size mismatch for ${code}: expected=${sizage.fs} got=${fullSize}`);
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
code,
|
|
143
|
+
raw: raw.slice(),
|
|
144
|
+
qb64,
|
|
145
|
+
fullSize,
|
|
146
|
+
fullSizeB2: sceil((fullSize * 3) / 4),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function parseMatterInit(init) {
|
|
150
|
+
if (init.raw && init.code) {
|
|
151
|
+
return encodeMatterFromRaw(init.code, init.raw);
|
|
152
|
+
}
|
|
153
|
+
if (init.qb64b) {
|
|
154
|
+
return parseMatterFromTextData(init.qb64b);
|
|
155
|
+
}
|
|
156
|
+
if (init.qb64) {
|
|
157
|
+
return parseMatterFromTextData(b(init.qb64));
|
|
158
|
+
}
|
|
159
|
+
if (init.qb2) {
|
|
160
|
+
return parseMatterFromBinaryData(init.qb2);
|
|
161
|
+
}
|
|
162
|
+
throw new DeserializeError("Matter requires (raw + code) or qb64/qb64b/qb2 initialization");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Base CESR primitive carrying qualified matter material.
|
|
166
|
+
*
|
|
167
|
+
* KERIpy substance: `Matter` is the foundational primitive abstraction that
|
|
168
|
+
* handles exfil/infil between raw bytes and qualified CESR encodings.
|
|
169
|
+
*/
|
|
170
|
+
export class Matter {
|
|
171
|
+
constructor(init) {
|
|
172
|
+
Object.defineProperty(this, "_code", {
|
|
173
|
+
enumerable: true,
|
|
174
|
+
configurable: true,
|
|
175
|
+
writable: true,
|
|
176
|
+
value: void 0
|
|
177
|
+
});
|
|
178
|
+
Object.defineProperty(this, "_raw", {
|
|
179
|
+
enumerable: true,
|
|
180
|
+
configurable: true,
|
|
181
|
+
writable: true,
|
|
182
|
+
value: void 0
|
|
183
|
+
});
|
|
184
|
+
Object.defineProperty(this, "_qb64", {
|
|
185
|
+
enumerable: true,
|
|
186
|
+
configurable: true,
|
|
187
|
+
writable: true,
|
|
188
|
+
value: void 0
|
|
189
|
+
});
|
|
190
|
+
Object.defineProperty(this, "_fullSize", {
|
|
191
|
+
enumerable: true,
|
|
192
|
+
configurable: true,
|
|
193
|
+
writable: true,
|
|
194
|
+
value: void 0
|
|
195
|
+
});
|
|
196
|
+
Object.defineProperty(this, "_fullSizeB2", {
|
|
197
|
+
enumerable: true,
|
|
198
|
+
configurable: true,
|
|
199
|
+
writable: true,
|
|
200
|
+
value: void 0
|
|
201
|
+
});
|
|
202
|
+
const data = init instanceof Matter
|
|
203
|
+
? init.toMatterData()
|
|
204
|
+
: isMatterData(init)
|
|
205
|
+
? init
|
|
206
|
+
: parseMatterInit(init);
|
|
207
|
+
this._code = data.code;
|
|
208
|
+
this._raw = data.raw.slice();
|
|
209
|
+
this._qb64 = data.qb64;
|
|
210
|
+
this._fullSize = data.fullSize;
|
|
211
|
+
this._fullSizeB2 = data.fullSizeB2;
|
|
212
|
+
}
|
|
213
|
+
toMatterData() {
|
|
214
|
+
return {
|
|
215
|
+
code: this._code,
|
|
216
|
+
raw: this._raw.slice(),
|
|
217
|
+
qb64: this._qb64,
|
|
218
|
+
fullSize: this._fullSize,
|
|
219
|
+
fullSizeB2: this._fullSizeB2,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
get code() {
|
|
223
|
+
return this._code;
|
|
224
|
+
}
|
|
225
|
+
get raw() {
|
|
226
|
+
return this._raw;
|
|
227
|
+
}
|
|
228
|
+
get qb64() {
|
|
229
|
+
return this._qb64;
|
|
230
|
+
}
|
|
231
|
+
get qb64b() {
|
|
232
|
+
return b(this._qb64);
|
|
233
|
+
}
|
|
234
|
+
get qb2() {
|
|
235
|
+
return codeB64ToB2(this._qb64);
|
|
236
|
+
}
|
|
237
|
+
get fullSize() {
|
|
238
|
+
return this._fullSize;
|
|
239
|
+
}
|
|
240
|
+
get fullSizeB2() {
|
|
241
|
+
return this._fullSizeB2;
|
|
242
|
+
}
|
|
243
|
+
equals(other) {
|
|
244
|
+
return this._qb64 === other.qb64;
|
|
245
|
+
}
|
|
246
|
+
toString() {
|
|
247
|
+
return this._qb64;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/** Parse matter from text-domain CESR bytes. */
|
|
251
|
+
export function parseMatterFromText(input) {
|
|
252
|
+
return new Matter(parseMatterFromTextData(input));
|
|
253
|
+
}
|
|
254
|
+
/** Parse matter from binary-domain CESR bytes. */
|
|
255
|
+
export function parseMatterFromBinary(input) {
|
|
256
|
+
return new Matter(parseMatterFromBinaryData(input));
|
|
257
|
+
}
|
|
258
|
+
/** Parse matter using caller-provided cold-start domain hint (`txt` or `bny`). */
|
|
105
259
|
export function parseMatter(input, cold) {
|
|
106
260
|
return cold === "bny"
|
|
107
261
|
? parseMatterFromBinary(input)
|