cesr
Version:
[](https://www.npmjs.com/package/cesr) [](https://github.com/lenkan/cesr-js/blob/main/LICENSE)
191 lines (190 loc) • 8.23 kB
JavaScript
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Parser_instances, _Parser_buffer, _Parser_stack, _Parser_version, _Parser_readJSON, _Parser_read;
import { CountCode_10 } from "./codes.js";
import { decodeUtf8, encodeUtf8 } from "./encoding-utf8.js";
import { encoding } from "./encoding.js";
function concat(a, b) {
if (a.length === 0) {
return b;
}
if (b.length === 0) {
return a;
}
const merged = new Uint8Array(a.length + b.length);
merged.set(a);
merged.set(b, a.length);
return merged;
}
function isContextComplete(context) {
if (context.version === 1) {
switch (context.code) {
case CountCode_10.ControllerIdxSigs:
case CountCode_10.WitnessIdxSigs:
return context.frames === context.count;
case CountCode_10.SealSourceCouples:
case CountCode_10.FirstSeenReplayCouples:
case CountCode_10.NonTransReceiptCouples:
return context.frames === context.count * 2;
case CountCode_10.SealSourceTriples:
return context.frames === context.count * 3;
case CountCode_10.TransReceiptQuadruples:
return context.frames === context.count * 4;
case CountCode_10.TransIdxSigGroups:
// |pre|snu|dig|group of controller sigs
// So, we assume that this group is finished for simplicity, higher level code
// needs to verify the signatures anyway
return context.frames === context.count * 3;
case CountCode_10.TransLastIdxSigGroups:
// |pre|group of controller sigs
// So, we assume that this group is finished for simplicity, higher level code
// needs to verify the signatures anyway
return context.frames === context.count;
case CountCode_10.AttachmentGroup:
case CountCode_10.BigAttachmentGroup:
return context.quadlets === context.count;
default:
throw new Error(`Cannot determine if group ${context.code} is finished`);
}
}
return context.quadlets === context.count;
}
class Parser {
constructor(options = {}) {
_Parser_instances.add(this);
_Parser_buffer.set(this, void 0);
_Parser_stack.set(this, []);
_Parser_version.set(this, void 0);
__classPrivateFieldSet(this, _Parser_buffer, new Uint8Array(0), "f");
__classPrivateFieldSet(this, _Parser_version, options.version ?? 1, "f");
}
*parse(source) {
__classPrivateFieldSet(this, _Parser_buffer, concat(__classPrivateFieldGet(this, _Parser_buffer, "f"), source), "f");
while (__classPrivateFieldGet(this, _Parser_buffer, "f").length > 0) {
const frame = __classPrivateFieldGet(this, _Parser_instances, "m", _Parser_read).call(this);
if (!frame) {
return null;
}
yield frame;
}
}
get finished() {
return __classPrivateFieldGet(this, _Parser_buffer, "f").length === 0 && __classPrivateFieldGet(this, _Parser_stack, "f").length === 0;
}
}
_Parser_buffer = new WeakMap(), _Parser_stack = new WeakMap(), _Parser_version = new WeakMap(), _Parser_instances = new WeakSet(), _Parser_readJSON = function _Parser_readJSON() {
if (__classPrivateFieldGet(this, _Parser_buffer, "f").length < 25) {
return null;
}
const version = encoding.decodeVersionString(__classPrivateFieldGet(this, _Parser_buffer, "f").slice(0, 24));
if (__classPrivateFieldGet(this, _Parser_buffer, "f").length < version.size) {
return null;
}
const frame = __classPrivateFieldGet(this, _Parser_buffer, "f").slice(0, version.size);
__classPrivateFieldSet(this, _Parser_buffer, __classPrivateFieldGet(this, _Parser_buffer, "f").slice(version.size), "f");
return {
type: "message",
version: version,
text: decodeUtf8(frame),
};
}, _Parser_read = function _Parser_read() {
const start = __classPrivateFieldGet(this, _Parser_buffer, "f")[0] >> 5;
switch (start) {
case 0b011:
return __classPrivateFieldGet(this, _Parser_instances, "m", _Parser_readJSON).call(this);
}
const context = __classPrivateFieldGet(this, _Parser_stack, "f")[__classPrivateFieldGet(this, _Parser_stack, "f").length - 1] ?? undefined;
const result = encoding.decodeStream(__classPrivateFieldGet(this, _Parser_buffer, "f"), context);
__classPrivateFieldSet(this, _Parser_buffer, __classPrivateFieldGet(this, _Parser_buffer, "f").slice(result.n), "f");
if (!result.frame) {
return null;
}
for (const ctx of __classPrivateFieldGet(this, _Parser_stack, "f")) {
ctx.quadlets += result.n / 4;
ctx.frames += 1;
}
while (__classPrivateFieldGet(this, _Parser_stack, "f").length > 0) {
const ctx = __classPrivateFieldGet(this, _Parser_stack, "f")[__classPrivateFieldGet(this, _Parser_stack, "f").length - 1];
if (isContextComplete(ctx)) {
__classPrivateFieldGet(this, _Parser_stack, "f").pop();
}
else {
break;
}
}
if (result.frame.code.startsWith("-")) {
if (result.frame.code === CountCode_10.KERIACDCGenusVersion) {
const genus = encoding.decodeGenus(result.frame.text);
__classPrivateFieldSet(this, _Parser_version, genus.major, "f");
}
else {
__classPrivateFieldGet(this, _Parser_stack, "f").push({
code: result.frame.code,
version: __classPrivateFieldGet(this, _Parser_version, "f"),
count: result.frame.count ?? 0,
quadlets: 0,
frames: 0,
});
}
}
return {
type: "cesr",
code: result.frame.code,
text: result.frame.text,
count: result.frame.count,
raw: result.frame.raw,
};
};
/**
* Parses CESR frames from an incoming stream of bytes.
*
* @param input Incoming stream of bytes
* @returns An iterable of CESR frames
*/
export function* parseSync(input, options = {}) {
if (typeof input === "string") {
input = encodeUtf8(input);
}
const parser = new Parser(options);
for (const frame of parser.parse(input)) {
yield frame;
}
if (!parser.finished) {
throw new Error("Unexpected end of stream");
}
}
/**
* Parses CESR frames from an incoming stream of bytes.
*
* @param input Incoming stream of bytes
* @returns An async iterable of CESR frames
*/
export async function* parse(input, options) {
const parser = new Parser(options);
for await (const chunk of resolveInput(input)) {
for (const frame of parser.parse(chunk)) {
yield frame;
}
}
if (!parser.finished) {
throw new Error("Unexpected end of stream");
}
}
function resolveInput(input) {
if (typeof input === "string") {
return ReadableStream.from([encodeUtf8(input)]);
}
if (input instanceof Uint8Array) {
return ReadableStream.from([input]);
}
return input;
}