cesr-ts 0.1.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/LICENSE +202 -0
- package/README.md +32 -0
- package/esm/_dnt.polyfills.js +127 -0
- package/esm/mod.js +2 -0
- package/esm/package.json +3 -0
- package/esm/src/adapters/async-iterable.js +17 -0
- package/esm/src/adapters/effection.js +9 -0
- package/esm/src/annotate/annotator.js +36 -0
- package/esm/src/annotate/cli-node.js +53 -0
- package/esm/src/annotate/cli.js +89 -0
- package/esm/src/annotate/comments.js +43 -0
- package/esm/src/annotate/denot.js +17 -0
- package/esm/src/annotate/render.js +246 -0
- package/esm/src/annotate/types.js +1 -0
- package/esm/src/core/bytes.js +70 -0
- package/esm/src/core/errors.js +45 -0
- package/esm/src/core/parser-engine.js +589 -0
- package/esm/src/core/types.js +1 -0
- package/esm/src/index.js +46 -0
- package/esm/src/parser/attachment-parser.js +4 -0
- package/esm/src/parser/cold-start.js +17 -0
- package/esm/src/parser/group-dispatch.js +420 -0
- package/esm/src/primitives/aggor.js +41 -0
- package/esm/src/primitives/bexter.js +20 -0
- package/esm/src/primitives/blinder.js +23 -0
- package/esm/src/primitives/cigar.js +18 -0
- package/esm/src/primitives/compactor.js +16 -0
- package/esm/src/primitives/counter.js +100 -0
- package/esm/src/primitives/dater.js +22 -0
- package/esm/src/primitives/diger.js +22 -0
- package/esm/src/primitives/ilker.js +15 -0
- package/esm/src/primitives/indexer.js +84 -0
- package/esm/src/primitives/labeler.js +31 -0
- package/esm/src/primitives/mapper.js +158 -0
- package/esm/src/primitives/matter.js +109 -0
- package/esm/src/primitives/mediar.js +21 -0
- package/esm/src/primitives/noncer.js +18 -0
- package/esm/src/primitives/number.js +31 -0
- package/esm/src/primitives/pather.js +23 -0
- package/esm/src/primitives/prefixer.js +23 -0
- package/esm/src/primitives/registry.js +17 -0
- package/esm/src/primitives/saider.js +22 -0
- package/esm/src/primitives/sealer.js +35 -0
- package/esm/src/primitives/seqner.js +23 -0
- package/esm/src/primitives/texter.js +20 -0
- package/esm/src/primitives/tholder.js +27 -0
- package/esm/src/primitives/traitor.js +20 -0
- package/esm/src/primitives/verfer.js +28 -0
- package/esm/src/primitives/verser.js +30 -0
- package/esm/src/router/router-stub.js +17 -0
- package/esm/src/serder/serder.js +22 -0
- package/esm/src/serder/serdery.js +12 -0
- package/esm/src/serder/smell.js +56 -0
- package/esm/src/tables/counter-codex.js +10 -0
- package/esm/src/tables/counter.tables.generated.js +178 -0
- package/esm/src/tables/indexer.tables.js +30 -0
- package/esm/src/tables/matter.tables.generated.js +238 -0
- package/esm/src/tables/table-types.js +1 -0
- package/esm/src/tables/versions.js +12 -0
- package/package.json +52 -0
- package/types/_dnt.polyfills.d.ts +101 -0
- package/types/_dnt.polyfills.d.ts.map +1 -0
- package/types/mod.d.ts +3 -0
- package/types/mod.d.ts.map +1 -0
- package/types/src/adapters/async-iterable.d.ts +4 -0
- package/types/src/adapters/async-iterable.d.ts.map +1 -0
- package/types/src/adapters/effection.d.ts +8 -0
- package/types/src/adapters/effection.d.ts.map +1 -0
- package/types/src/annotate/annotator.d.ts +4 -0
- package/types/src/annotate/annotator.d.ts.map +1 -0
- package/types/src/annotate/cli-node.d.ts +2 -0
- package/types/src/annotate/cli-node.d.ts.map +1 -0
- package/types/src/annotate/cli.d.ts +10 -0
- package/types/src/annotate/cli.d.ts.map +1 -0
- package/types/src/annotate/comments.d.ts +6 -0
- package/types/src/annotate/comments.d.ts.map +1 -0
- package/types/src/annotate/denot.d.ts +2 -0
- package/types/src/annotate/denot.d.ts.map +1 -0
- package/types/src/annotate/render.d.ts +5 -0
- package/types/src/annotate/render.d.ts.map +1 -0
- package/types/src/annotate/types.d.ts +15 -0
- package/types/src/annotate/types.d.ts.map +1 -0
- package/types/src/core/bytes.d.ts +12 -0
- package/types/src/core/bytes.d.ts.map +1 -0
- package/types/src/core/errors.d.ts +21 -0
- package/types/src/core/errors.d.ts.map +1 -0
- package/types/src/core/parser-engine.d.ts +58 -0
- package/types/src/core/parser-engine.d.ts.map +1 -0
- package/types/src/core/types.d.ts +52 -0
- package/types/src/core/types.d.ts.map +1 -0
- package/types/src/index.d.ts +47 -0
- package/types/src/index.d.ts.map +1 -0
- package/types/src/parser/attachment-parser.d.ts +8 -0
- package/types/src/parser/attachment-parser.d.ts.map +1 -0
- package/types/src/parser/cold-start.d.ts +3 -0
- package/types/src/parser/cold-start.d.ts.map +1 -0
- package/types/src/parser/group-dispatch.d.ts +29 -0
- package/types/src/parser/group-dispatch.d.ts.map +1 -0
- package/types/src/primitives/aggor.d.ts +13 -0
- package/types/src/primitives/aggor.d.ts.map +1 -0
- package/types/src/primitives/bexter.d.ts +10 -0
- package/types/src/primitives/bexter.d.ts.map +1 -0
- package/types/src/primitives/blinder.d.ts +12 -0
- package/types/src/primitives/blinder.d.ts.map +1 -0
- package/types/src/primitives/cigar.d.ts +11 -0
- package/types/src/primitives/cigar.d.ts.map +1 -0
- package/types/src/primitives/compactor.d.ts +5 -0
- package/types/src/primitives/compactor.d.ts.map +1 -0
- package/types/src/primitives/counter.d.ts +14 -0
- package/types/src/primitives/counter.d.ts.map +1 -0
- package/types/src/primitives/dater.d.ts +11 -0
- package/types/src/primitives/dater.d.ts.map +1 -0
- package/types/src/primitives/diger.d.ts +11 -0
- package/types/src/primitives/diger.d.ts.map +1 -0
- package/types/src/primitives/ilker.d.ts +10 -0
- package/types/src/primitives/ilker.d.ts.map +1 -0
- package/types/src/primitives/indexer.d.ts +12 -0
- package/types/src/primitives/indexer.d.ts.map +1 -0
- package/types/src/primitives/labeler.d.ts +15 -0
- package/types/src/primitives/labeler.d.ts.map +1 -0
- package/types/src/primitives/mapper.d.ts +28 -0
- package/types/src/primitives/mapper.d.ts.map +1 -0
- package/types/src/primitives/matter.d.ts +12 -0
- package/types/src/primitives/matter.d.ts.map +1 -0
- package/types/src/primitives/mediar.d.ts +12 -0
- package/types/src/primitives/mediar.d.ts.map +1 -0
- package/types/src/primitives/noncer.d.ts +10 -0
- package/types/src/primitives/noncer.d.ts.map +1 -0
- package/types/src/primitives/number.d.ts +11 -0
- package/types/src/primitives/number.d.ts.map +1 -0
- package/types/src/primitives/pather.d.ts +10 -0
- package/types/src/primitives/pather.d.ts.map +1 -0
- package/types/src/primitives/prefixer.d.ts +10 -0
- package/types/src/primitives/prefixer.d.ts.map +1 -0
- package/types/src/primitives/registry.d.ts +10 -0
- package/types/src/primitives/registry.d.ts.map +1 -0
- package/types/src/primitives/saider.d.ts +11 -0
- package/types/src/primitives/saider.d.ts.map +1 -0
- package/types/src/primitives/sealer.d.ts +12 -0
- package/types/src/primitives/sealer.d.ts.map +1 -0
- package/types/src/primitives/seqner.d.ts +11 -0
- package/types/src/primitives/seqner.d.ts.map +1 -0
- package/types/src/primitives/texter.d.ts +10 -0
- package/types/src/primitives/texter.d.ts.map +1 -0
- package/types/src/primitives/tholder.d.ts +10 -0
- package/types/src/primitives/tholder.d.ts.map +1 -0
- package/types/src/primitives/traitor.d.ts +10 -0
- package/types/src/primitives/traitor.d.ts.map +1 -0
- package/types/src/primitives/verfer.d.ts +11 -0
- package/types/src/primitives/verfer.d.ts.map +1 -0
- package/types/src/primitives/verser.d.ts +14 -0
- package/types/src/primitives/verser.d.ts.map +1 -0
- package/types/src/router/router-stub.d.ts +11 -0
- package/types/src/router/router-stub.d.ts.map +1 -0
- package/types/src/serder/serder.d.ts +4 -0
- package/types/src/serder/serder.d.ts.map +1 -0
- package/types/src/serder/serdery.d.ts +6 -0
- package/types/src/serder/serdery.d.ts.map +1 -0
- package/types/src/serder/smell.d.ts +7 -0
- package/types/src/serder/smell.d.ts.map +1 -0
- package/types/src/tables/counter-codex.d.ts +6 -0
- package/types/src/tables/counter-codex.d.ts.map +1 -0
- package/types/src/tables/counter.tables.generated.d.ts +92 -0
- package/types/src/tables/counter.tables.generated.d.ts.map +1 -0
- package/types/src/tables/indexer.tables.d.ts +12 -0
- package/types/src/tables/indexer.tables.d.ts.map +1 -0
- package/types/src/tables/matter.tables.generated.d.ts +116 -0
- package/types/src/tables/matter.tables.generated.d.ts.map +1 -0
- package/types/src/tables/table-types.d.ts +19 -0
- package/types/src/tables/table-types.d.ts.map +1 -0
- package/types/src/tables/versions.d.ts +16 -0
- package/types/src/tables/versions.d.ts.map +1 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { DeserializeError, GroupSizeError, ShortageError, UnknownCodeError, } from "../core/errors.js";
|
|
2
|
+
import { sniff } from "../parser/cold-start.js";
|
|
3
|
+
import { parseCounter } from "../primitives/counter.js";
|
|
4
|
+
import { parseMatter } from "../primitives/matter.js";
|
|
5
|
+
import { parseIndexer } from "../primitives/indexer.js";
|
|
6
|
+
import { parseAttachmentDispatchCompat } from "../parser/group-dispatch.js";
|
|
7
|
+
import { counterCodeNameForVersion, matterCodeName, nativeLabelName, } from "./comments.js";
|
|
8
|
+
const TEXT_DECODER = new TextDecoder();
|
|
9
|
+
const TEXT_ENCODER = new TextEncoder();
|
|
10
|
+
const OPAQUE_TOKEN_COMMENT = "opaque token";
|
|
11
|
+
const OPAQUE_WRAPPER_PAYLOAD_COMMENT = "opaque wrapper payload";
|
|
12
|
+
const WRAPPER_GROUP_NAMES = new Set([
|
|
13
|
+
"AttachmentGroup",
|
|
14
|
+
"BigAttachmentGroup",
|
|
15
|
+
"BodyWithAttachmentGroup",
|
|
16
|
+
"BigBodyWithAttachmentGroup",
|
|
17
|
+
]);
|
|
18
|
+
function toHex(bytes) {
|
|
19
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
20
|
+
}
|
|
21
|
+
function isRecoverableParseError(error) {
|
|
22
|
+
return error instanceof UnknownCodeError ||
|
|
23
|
+
error instanceof DeserializeError ||
|
|
24
|
+
error instanceof ShortageError ||
|
|
25
|
+
error instanceof GroupSizeError;
|
|
26
|
+
}
|
|
27
|
+
function spaces(count) {
|
|
28
|
+
return " ".repeat(Math.max(0, count));
|
|
29
|
+
}
|
|
30
|
+
function asDomain(raw) {
|
|
31
|
+
try {
|
|
32
|
+
const cold = sniff(raw);
|
|
33
|
+
if (cold === "txt" || cold === "bny" || cold === "msg")
|
|
34
|
+
return cold;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (!isRecoverableParseError(error)) {
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
// Fallback handled below.
|
|
41
|
+
}
|
|
42
|
+
return "msg";
|
|
43
|
+
}
|
|
44
|
+
function emitLine(lines, value, comment, indent, options) {
|
|
45
|
+
const pad = spaces(indent);
|
|
46
|
+
if (options.commentMode === "above") {
|
|
47
|
+
lines.push(`${pad}# ${comment}`);
|
|
48
|
+
lines.push(`${pad}${value}`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
lines.push(`${pad}${value} # ${comment}`);
|
|
52
|
+
}
|
|
53
|
+
function describeToken(token, domain, version) {
|
|
54
|
+
const input = TEXT_ENCODER.encode(token);
|
|
55
|
+
try {
|
|
56
|
+
const counter = parseCounter(input, version, domain);
|
|
57
|
+
return {
|
|
58
|
+
comment: `${counterCodeNameForVersion(counter.code, version)} counter`,
|
|
59
|
+
size: domain === "bny" ? counter.fullSizeB2 : counter.fullSize,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (!isRecoverableParseError(error)) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
// Try indexer/matter below.
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const indexer = parseIndexer(input, domain);
|
|
70
|
+
return {
|
|
71
|
+
comment: `Indexer ${indexer.code}`,
|
|
72
|
+
size: domain === "bny" ? indexer.fullSizeB2 : indexer.fullSize,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (!isRecoverableParseError(error)) {
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
// Try matter below.
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const matter = parseMatter(input, domain);
|
|
83
|
+
return {
|
|
84
|
+
comment: matterCodeName(matter.code),
|
|
85
|
+
size: domain === "bny" ? matter.fullSizeB2 : matter.fullSize,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (!isRecoverableParseError(error)) {
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
comment: OPAQUE_TOKEN_COMMENT,
|
|
94
|
+
size: token.length,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function parseCounterCompat(input, version, domain) {
|
|
99
|
+
try {
|
|
100
|
+
return parseCounter(input, version, domain);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (!isRecoverableParseError(error)) {
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
const alternate = version.major >= 2
|
|
107
|
+
? { major: 1, minor: 0 }
|
|
108
|
+
: { major: 2, minor: 0 };
|
|
109
|
+
return parseCounter(input, alternate, domain);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function renderGroupItems(lines, items, version, indent, options) {
|
|
113
|
+
for (const item of items) {
|
|
114
|
+
if (typeof item === "string") {
|
|
115
|
+
const parsed = describeToken(item, "txt", version);
|
|
116
|
+
emitLine(lines, item, parsed.comment, indent, options);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (item instanceof Uint8Array) {
|
|
120
|
+
emitLine(lines, `0x${toHex(item)}`, "raw qb2 quadlet fragment", indent, options);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(item)) {
|
|
124
|
+
renderGroupItems(lines, item, version, indent + options.indent, options);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (item && typeof item === "object") {
|
|
128
|
+
const nested = item;
|
|
129
|
+
if (typeof nested.code === "string" && typeof nested.name === "string") {
|
|
130
|
+
emitLine(lines, `${nested.code}`, `${nested.name} nested group`, indent, options);
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function renderAttachmentGroupRaw(lines, raw, version, indent, options) {
|
|
137
|
+
const domain = asDomain(raw);
|
|
138
|
+
if (domain !== "txt" && domain !== "bny") {
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
const parsed = parseAttachmentDispatchCompat(raw, version, domain);
|
|
142
|
+
const counter = parseCounterCompat(raw, version, domain);
|
|
143
|
+
emitLine(lines, counter.qb64, `${parsed.group.name} count=${counter.count}`, indent, options);
|
|
144
|
+
const headerSize = domain === "bny" ? counter.fullSizeB2 : counter.fullSize;
|
|
145
|
+
const payload = raw.slice(headerSize, parsed.consumed);
|
|
146
|
+
if (WRAPPER_GROUP_NAMES.has(parsed.group.name)) {
|
|
147
|
+
// Wrapper groups contain nested groups by convention, but real-world
|
|
148
|
+
// streams may include trailing opaque segments. Keep annotation resilient.
|
|
149
|
+
let offset = 0;
|
|
150
|
+
while (offset < payload.length) {
|
|
151
|
+
const slice = payload.slice(offset);
|
|
152
|
+
const sliceCold = asDomain(slice);
|
|
153
|
+
if (sliceCold === "msg") {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
if (sliceCold === "txt" && slice[0] !== "-".charCodeAt(0)) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
let consumed = 0;
|
|
160
|
+
try {
|
|
161
|
+
consumed = renderAttachmentGroupRaw(lines, slice, version, indent + options.indent, options);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (!isRecoverableParseError(error)) {
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
if (consumed <= 0)
|
|
170
|
+
break;
|
|
171
|
+
offset += consumed;
|
|
172
|
+
}
|
|
173
|
+
if (offset < payload.length) {
|
|
174
|
+
const remainder = payload.slice(offset);
|
|
175
|
+
const unit = domain === "bny" ? 3 : 4;
|
|
176
|
+
for (let i = 0; i < remainder.length; i += unit) {
|
|
177
|
+
const chunk = remainder.slice(i, Math.min(i + unit, remainder.length));
|
|
178
|
+
const rendered = domain === "bny"
|
|
179
|
+
? `0x${toHex(chunk)}`
|
|
180
|
+
: TEXT_DECODER.decode(chunk);
|
|
181
|
+
emitLine(lines, rendered, OPAQUE_WRAPPER_PAYLOAD_COMMENT, indent + options.indent, options);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return parsed.consumed;
|
|
185
|
+
}
|
|
186
|
+
renderGroupItems(lines, parsed.group.items, version, indent + options.indent, options);
|
|
187
|
+
return parsed.consumed;
|
|
188
|
+
}
|
|
189
|
+
function renderNativeBody(lines, frame, options, version) {
|
|
190
|
+
const raw = frame.serder.raw;
|
|
191
|
+
const domain = asDomain(raw);
|
|
192
|
+
if (domain !== "txt" && domain !== "bny") {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const counter = parseCounterCompat(raw, version, domain);
|
|
196
|
+
emitLine(lines, counter.qb64, `${counterCodeNameForVersion(counter.code, version)} count=${counter.count}`, 0, options);
|
|
197
|
+
for (const field of frame.serder.native?.fields ?? []) {
|
|
198
|
+
const label = nativeLabelName(field.label);
|
|
199
|
+
const comment = label
|
|
200
|
+
? `${label} (${matterCodeName(field.code)})`
|
|
201
|
+
: matterCodeName(field.code);
|
|
202
|
+
emitLine(lines, field.qb64, comment, options.indent, options);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function renderMessageBody(lines, frame, options) {
|
|
206
|
+
const rawBody = TEXT_DECODER.decode(frame.serder.raw);
|
|
207
|
+
let body = rawBody;
|
|
208
|
+
if (options.pretty && frame.serder.kind === "JSON") {
|
|
209
|
+
try {
|
|
210
|
+
body = JSON.stringify(JSON.parse(rawBody), null, 2);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (!(error instanceof SyntaxError)) {
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
body = rawBody;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const info = [
|
|
220
|
+
`SERDER`,
|
|
221
|
+
frame.serder.proto,
|
|
222
|
+
frame.serder.kind,
|
|
223
|
+
frame.serder.ilk ? `ilk=${frame.serder.ilk}` : null,
|
|
224
|
+
frame.serder.said ? `said=${frame.serder.said}` : null,
|
|
225
|
+
].filter(Boolean).join(" ");
|
|
226
|
+
emitLine(lines, body, info, 0, options);
|
|
227
|
+
}
|
|
228
|
+
function renderFrame(frame, index, options) {
|
|
229
|
+
const lines = [];
|
|
230
|
+
const version = frame.serder.gvrsn ?? frame.serder.pvrsn;
|
|
231
|
+
const domain = asDomain(frame.serder.raw);
|
|
232
|
+
if (domain === "txt" || domain === "bny") {
|
|
233
|
+
renderNativeBody(lines, frame, options, version);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
renderMessageBody(lines, frame, options);
|
|
237
|
+
}
|
|
238
|
+
for (const group of frame.attachments) {
|
|
239
|
+
renderAttachmentGroupRaw(lines, group.raw, version, 0, options);
|
|
240
|
+
}
|
|
241
|
+
return { index, frame, lines };
|
|
242
|
+
}
|
|
243
|
+
/** Render parsed CESR frames into line-oriented, human-annotated text blocks. */
|
|
244
|
+
export function renderAnnotatedFrames(frames, options) {
|
|
245
|
+
return frames.map((frame, index) => renderFrame(frame, index + 1, options));
|
|
246
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export const encoder = new TextEncoder();
|
|
2
|
+
export const decoder = new TextDecoder();
|
|
3
|
+
const B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4
|
+
export function concatBytes(...chunks) {
|
|
5
|
+
const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
6
|
+
const out = new Uint8Array(total);
|
|
7
|
+
let offset = 0;
|
|
8
|
+
for (const chunk of chunks) {
|
|
9
|
+
out.set(chunk, offset);
|
|
10
|
+
offset += chunk.length;
|
|
11
|
+
}
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
export function intToB64(value, length = 1) {
|
|
15
|
+
if (value < 0) {
|
|
16
|
+
throw new Error(`value must be >= 0, got ${value}`);
|
|
17
|
+
}
|
|
18
|
+
let v = value;
|
|
19
|
+
let out = "";
|
|
20
|
+
do {
|
|
21
|
+
out = B64_ALPHABET[v & 63] + out;
|
|
22
|
+
v = Math.floor(v / 64);
|
|
23
|
+
} while (v > 0);
|
|
24
|
+
if (out.length > length) {
|
|
25
|
+
throw new Error(`value ${value} too large for base64 length ${length}`);
|
|
26
|
+
}
|
|
27
|
+
return out.padStart(length, "A");
|
|
28
|
+
}
|
|
29
|
+
export function b64ToInt(text) {
|
|
30
|
+
let out = 0;
|
|
31
|
+
for (const ch of text) {
|
|
32
|
+
const idx = B64_ALPHABET.indexOf(ch);
|
|
33
|
+
if (idx < 0) {
|
|
34
|
+
throw new Error(`Invalid base64 char ${ch}`);
|
|
35
|
+
}
|
|
36
|
+
out = out * 64 + idx;
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
export function encodeB64(data) {
|
|
41
|
+
const str = btoa(String.fromCharCode(...data));
|
|
42
|
+
return str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
43
|
+
}
|
|
44
|
+
export function decodeB64(text) {
|
|
45
|
+
const padded = text + "===".slice((text.length + 3) % 4);
|
|
46
|
+
const raw = atob(padded.replace(/-/g, "+").replace(/_/g, "/"));
|
|
47
|
+
const out = new Uint8Array(raw.length);
|
|
48
|
+
for (let i = 0; i < raw.length; i++) {
|
|
49
|
+
out[i] = raw.charCodeAt(i);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
export function sceil(value) {
|
|
54
|
+
return Math.ceil(value);
|
|
55
|
+
}
|
|
56
|
+
export function codeB64ToB2(text) {
|
|
57
|
+
const n = sceil((text.length * 3) / 4);
|
|
58
|
+
const full = text + "A".repeat((4 - (text.length % 4)) % 4);
|
|
59
|
+
return decodeB64(full).slice(0, n);
|
|
60
|
+
}
|
|
61
|
+
export function codeB2ToB64(bytes, sextets) {
|
|
62
|
+
const n = sceil((sextets * 3) / 4);
|
|
63
|
+
if (n > bytes.length) {
|
|
64
|
+
throw new Error(`Not enough bytes to convert ${sextets} sextets`);
|
|
65
|
+
}
|
|
66
|
+
return encodeB64(bytes.slice(0, n)).slice(0, sextets);
|
|
67
|
+
}
|
|
68
|
+
export function nabSextets(bytes, sextets) {
|
|
69
|
+
return codeB64ToB2(codeB2ToB64(bytes, sextets));
|
|
70
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class ParserError extends Error {
|
|
2
|
+
constructor(message, offset, context) {
|
|
3
|
+
super(message);
|
|
4
|
+
Object.defineProperty(this, "offset", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true,
|
|
8
|
+
value: offset
|
|
9
|
+
});
|
|
10
|
+
Object.defineProperty(this, "context", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: context
|
|
15
|
+
});
|
|
16
|
+
this.name = globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).name;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class ShortageError extends ParserError {
|
|
20
|
+
constructor(needed, available, offset) {
|
|
21
|
+
super(`Need ${needed} bytes but only ${available} available`, offset);
|
|
22
|
+
Object.defineProperty(this, "needed", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: needed
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "available", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: available
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class ColdStartError extends ParserError {
|
|
37
|
+
}
|
|
38
|
+
export class VersionError extends ParserError {
|
|
39
|
+
}
|
|
40
|
+
export class UnknownCodeError extends ParserError {
|
|
41
|
+
}
|
|
42
|
+
export class GroupSizeError extends ParserError {
|
|
43
|
+
}
|
|
44
|
+
export class DeserializeError extends ParserError {
|
|
45
|
+
}
|