Skip to content

Commit

Permalink
packet: Name.compare static function
Browse files Browse the repository at this point in the history
  • Loading branch information
yoursunny committed Nov 6, 2024
1 parent 1ea5a59 commit 443104c
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/pkg/*/lib/
/pkg/*/README.md.ts
/pkg/*/test-fixture/tsconfig.json
/pkg/*/tests/tsconfig.json
/pkg/*/tsconfig.json
/pnpm-debug.log
/pnpm-lock.yaml
Expand Down
17 changes: 10 additions & 7 deletions mk/make-pkg-tsconfig.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ for (const filename of ["src/mod.ts", "src/main.ts"]) {

await fs.writeFile("tsconfig.json", JSON.stringify(tsconfig, undefined, 2));

const tsconfigTestFixture = {
/** @type {typeof tsconfig} */
const tsconfigTest = {
extends: "../../../mk/tsconfig-base.json",
compilerOptions: {
rootDir: "..",
Expand All @@ -55,10 +56,12 @@ const tsconfigTestFixture = {
],
};

let hasTestFixture = false;
try {
hasTestFixture = (await fs.stat("test-fixture")).isDirectory();
} catch {}
if (hasTestFixture) {
await fs.writeFile("test-fixture/tsconfig.json", JSON.stringify(tsconfigTestFixture, undefined, 2));
for (const dir of ["test-fixture", "tests"]) {
let found = false;
try {
found = (await fs.stat(dir)).isDirectory();
} catch {}
if (found) {
await fs.writeFile(path.join(dir, "tsconfig.json"), JSON.stringify(tsconfigTest, undefined, 2));
}
}
4 changes: 2 additions & 2 deletions pkg/keychain/test-fixture/key-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function execute(keyChain: KeyChain, enabled: Enable = {}): Promise
const keys1 = gen.map(([pvt]) => pvt.name).map(String);

const keyNames2 = await keyChain.listKeys();
keyNames2.sort((a, b) => a.compare(b));
keyNames2.sort(Name.compare);
const keys2 = (await Promise.all(keyNames2.map((n) => keyChain.getKey(n, "signer"))))
.map((pvt) => pvt.name.toString());

Expand All @@ -59,7 +59,7 @@ export async function execute(keyChain: KeyChain, enabled: Enable = {}): Promise
.map((u) => keyChain.deleteKey(new Name(u))),
);
const keyNames3 = await keyChain.listKeys();
keyNames3.sort((a, b) => a.compare(b));
keyNames3.sort(Name.compare);
const keys3 = (await Promise.all(keyNames3.map((n) => keyChain.getKey(n, "verifier"))))
.map((pub) => pub.name.toString());

Expand Down
10 changes: 7 additions & 3 deletions pkg/packet/src/name/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ export class Component {

/** Compare this component with other. */
public compare(other: ComponentLike): Component.CompareResult {
other = Component.from(other);
return 2 * Math.sign(this.type - other.type || this.length - other.length ||
bufferCompare<Uint8Array>(this.value, other.value));
return Component.compare(this, Component.from(other));
}

/** Determine if this component equals other. */
Expand All @@ -199,4 +197,10 @@ export namespace Component {
/** lhs is greater than rhs */
GT = 2,
}

/** Compare two components. */
export function compare(lhs: Component, rhs: Component): CompareResult {
return 2 * Math.sign(lhs.type - rhs.type || lhs.length - rhs.length ||
bufferCompare<Uint8Array>(lhs.value, rhs.value));
}
}
66 changes: 36 additions & 30 deletions pkg/packet/src/name/name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ export class Name {
public append(...args: unknown[]) {
let suffix: readonly ComponentLike[];
if (args.length === 2 &&
typeof (args[0] as NamingConvention<any>).create === "function") {
suffix = [(args[0] as NamingConvention<any>).create(args[1])];
typeof (args[0] as NamingConvention<unknown>).create === "function") {
suffix = [(args[0] as NamingConvention<unknown>).create(args[1])];
} else {
suffix = args as readonly ComponentLike[];
}
Expand All @@ -157,27 +157,12 @@ export class Name {

/** Return a copy of Name with i-th component replaced with `comp`. */
public replaceAt(i: number, comp: ComponentLike): Name {
const comps: ComponentLike[] = [...this.comps];
comps.splice(i, 1, comp);
return new Name(comps);
return new Name((this.comps as readonly ComponentLike[]).toSpliced(i, 1, comp));
}

/** Compare with other name. */
public compare(other: NameLike): Name.CompareResult {
other = Name.from(other);
const commonSize = Math.min(this.length, other.length);
const cmp = this.comparePrefix(other, commonSize);
if (cmp !== Name.CompareResult.EQUAL) {
return cmp;
}

if (this.length > commonSize) {
return Name.CompareResult.RPREFIX;
}
if (other.length > commonSize) {
return Name.CompareResult.LPREFIX;
}
return Name.CompareResult.EQUAL;
return Name.compare(this, Name.from(other));
}

/** Determine if this name equals other. */
Expand All @@ -186,23 +171,16 @@ export class Name {
if (this.hex_ !== undefined && other.hex_ !== undefined) {
return this.hex_ === other.hex_;
}
return this.length === other.length && this.comparePrefix(other, this.length) === Name.CompareResult.EQUAL;
return this.length === other.length && comparePrefix(this, other, this.length) === Name.CompareResult.EQUAL;
}

/** Determine if this name is a prefix of other. */
public isPrefixOf(other: NameLike): boolean {
other = Name.from(other);
return this.length <= other.length && this.comparePrefix(other, this.length) === Name.CompareResult.EQUAL;
}

private comparePrefix(other: Name, n: number): Name.CompareResult {
for (let i = 0; i < n; ++i) {
const cmp = this.comps[i]!.compare(other.comps[i]!);
if (cmp !== Component.CompareResult.EQUAL) {
return cmp as unknown as Name.CompareResult;
}
if (this.hex_ !== undefined && other.hex_ !== undefined) {
return other.hex_.startsWith(this.hex_);
}
return Name.CompareResult.EQUAL;
return this.length <= other.length && comparePrefix(this, other, this.length) === Name.CompareResult.EQUAL;
}

public encodeTo(encoder: Encoder) {
Expand Down Expand Up @@ -233,4 +211,32 @@ export namespace Name {
/** rhs is less than, but not a prefix of lhs */
GT = 2,
}

/** Compare two names. */
export function compare(lhs: Name, rhs: Name): CompareResult {
const commonSize = Math.min(lhs.length, rhs.length);
const cmp = comparePrefix(lhs, rhs, commonSize);
if (cmp !== CompareResult.EQUAL) {
return cmp;
}

if (lhs.length > commonSize) {
return CompareResult.RPREFIX;
}
if (rhs.length > commonSize) {
return CompareResult.LPREFIX;
}
return CompareResult.EQUAL;
}
}

/** Compare first n components between two names. */
function comparePrefix(lhs: Name, rhs: Name, n: number): Name.CompareResult {
for (let i = 0; i < n; ++i) {
const cmp = lhs.comps[i]!.compare(rhs.comps[i]!);
if (cmp !== Component.CompareResult.EQUAL) {
return cmp as unknown as Name.CompareResult;
}
}
return Name.CompareResult.EQUAL;
}
4 changes: 1 addition & 3 deletions pkg/trust-schema/tests/schema/pattern.t.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ function match(p: P.Pattern, name: NameLike): P.Vars[] {
}

function build(p: P.Pattern, vars: P.VarsLike): Name[] {
const list = Array.from(p.build(vars));
list.sort((a, b) => a.compare(b));
return list;
return Array.from(p.build(vars)).toSorted(Name.compare);
}

test("const variable concat", () => {
Expand Down

0 comments on commit 443104c

Please sign in to comment.