Skip to content

Commit

Permalink
trust-schema: printESM.Context
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Oct 29, 2024
1 parent 4ebc57f commit b255583
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 13 deletions.
6 changes: 5 additions & 1 deletion pkg/lvs/src/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ class LvsFilter implements P.VariablePattern.Filter, printESM.PrintableFilter {
this.func(name.at(0), args);
}

public printESM(indent: string): string {
public printESM(ctx: printESM.Context): string {
const { indent, imports } = ctx;
imports.get("./lvsuserfns.mjs").add("* as lvsUserFns");

const lines: string[] = [];
lines.push(`${indent}{`);
lines.push(`${indent} accept(name, vars) {`);
Expand All @@ -177,6 +180,7 @@ class LvsFilter implements P.VariablePattern.Filter, printESM.PrintableFilter {
if (typeof b === "string") {
lines.push(`${indent} vars.get(${JSON.stringify(b)})?.get(0),`);
} else {
imports.get("@ndn/packet").add("Component");
lines.push(`${indent} Component.from(${JSON.stringify(b.toString())}),`);
}
}
Expand Down
52 changes: 40 additions & 12 deletions pkg/trust-schema/src/schema/print.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { DefaultMap } from "mnemonist";

import { AlternatePattern, CertNamePattern, ConcatPattern, ConstPattern, OverlapPattern, type Pattern, VariablePattern } from "./pattern";
import type { TrustSchemaPolicy } from "./policy";

function printPattern(p: Pattern, indent = ""): string {
function printPattern(p: Pattern, ctx: printESM.Context): string {
const { indent } = ctx;
if (p instanceof ConstPattern) {
return `${indent}new P.ConstPattern(${JSON.stringify(p.name.toString())})`;
}
Expand All @@ -14,12 +17,12 @@ function printPattern(p: Pattern, indent = ""): string {
opts.push(`maxComps: ${p.maxComps}`);
}
if (p.inner) {
opts.push(`inner: ${printPattern(p.inner, indent).trimStart()}`);
opts.push(`inner: ${printPattern(p.inner, ctx).trimStart()}`);
}
if (p.filter) {
const filter = p.filter as Partial<printESM.PrintableFilter>;
if (typeof filter.printESM === "function") {
opts.push(`filter: ${filter.printESM(indent).trimStart()}`);
opts.push(`filter: ${filter.printESM(ctx).trimStart()}`);
} else {
opts.push(`filter: { accept(name, vars) { throw new Error(${
JSON.stringify(`cannot translate filter ${p.filter.constructor.name}`)}) } }`);
Expand All @@ -32,47 +35,72 @@ function printPattern(p: Pattern, indent = ""): string {
return `${indent}new P.CertNamePattern()`;
}
if (p instanceof ConcatPattern) {
return printSequence("ConcatPattern", p.parts, indent);
return printSequence("ConcatPattern", p.parts, ctx);
}
if (p instanceof AlternatePattern) {
return printSequence("AlternatePattern", p.choices, indent);
return printSequence("AlternatePattern", p.choices, ctx);
}
if (p instanceof OverlapPattern) {
return printSequence("OverlapPattern", p.branches, indent);
return printSequence("OverlapPattern", p.branches, ctx);
}
return `${indent}throw new Error(${
JSON.stringify(`cannot translate pattern ${p.constructor.name}`)})`;
}

function printSequence(typ: string, list: Pattern[], indent: string): string {
function printSequence(typ: string, list: Pattern[], ctx: printESM.Context): string {
const { indent } = ctx;
const inner = { ...ctx, indent: ` ${indent}` };
return `${indent}new P.${typ}([\n${
list.map((p) => printPattern(p, ` ${indent}`)).join(",\n")
list.map((p) => printPattern(p, inner)).join(",\n")
},\n${indent}])`;
}

/** Print policy as ECMAScript module. */
export function printESM(policy: TrustSchemaPolicy): string {
const ctx: printESM.Context = {
indent: "",
imports: new DefaultMap<string, Set<string>>(() => new Set<string>()),
};
ctx.imports.get("@ndn/trust-schema")
.add("TrustSchemaPolicy")
.add("pattern as P");

const lines: string[] = [];
lines.push(
"import { TrustSchemaPolicy, pattern as P } from \"@ndn/trust-schema\";",
"import { Name, Component } from \"@ndn/packet\";",
"",
"export const policy = new TrustSchemaPolicy();",
"",
);
for (const [id, p] of policy.listPatterns()) {
lines.push(`policy.addPattern(${JSON.stringify(id)}, ${printPattern(p)});`);
lines.push(`policy.addPattern(${JSON.stringify(id)}, ${printPattern(p, ctx)});`);
}
lines.push("");
for (const [packet, signer] of policy.listRules()) {
lines.push(`policy.addRule(${JSON.stringify(packet)}, ${JSON.stringify(signer)});`);
}
lines.push("");

const pkgs = Array.from(ctx.imports.keys());
pkgs.sort((a, b) => -a.localeCompare(b));
for (const pkg of pkgs) {
const tokens = Array.from(ctx.imports.get(pkg));
if (tokens.length === 1 && tokens[0]!.startsWith("* as ")) {
lines.unshift(`import ${tokens[0]} from ${JSON.stringify(pkg)};`);
} else {
tokens.sort((a, b) => a.localeCompare(b));
lines.unshift(`import { ${tokens.join(", ")} } from ${JSON.stringify(pkg)};`);
}
}
return lines.join("\n");
}

export namespace printESM {
export interface Context {
indent: string;
imports: DefaultMap<string, Set<string>>;
}

export interface PrintableFilter extends VariablePattern.Filter {
printESM: (indent: string) => string;
printESM: (ctx: Context) => string;
}
}

0 comments on commit b255583

Please sign in to comment.