Rework roughlyIs internal function

Now named missingKey, is much faster (approx 4x faster based on testing), and provides better error info when it fails (which property was missing from the provided object).
This commit is contained in:
omuretsu 2023-03-07 06:33:24 -05:00
parent e74dfe9b79
commit 0442f3d5e9

@ -551,7 +551,8 @@ function person(ctx: NetscriptContext, p: unknown): IPerson {
mults: undefined, mults: undefined,
city: undefined, city: undefined,
}; };
if (!roughlyIs(fakePerson, p)) throw makeRuntimeErrorMsg(ctx, `person should be a Person.`, "TYPE"); const error = missingKey(fakePerson, p);
if (error) throw makeRuntimeErrorMsg(ctx, `person should be a Person.\n${error}`, "TYPE");
return p as IPerson; return p as IPerson;
} }
@ -582,36 +583,36 @@ function server(ctx: NetscriptContext, s: unknown): Server {
requiredHackingSkill: undefined, requiredHackingSkill: undefined,
serverGrowth: undefined, serverGrowth: undefined,
}; };
if (!roughlyIs(fakeServer, s)) throw makeRuntimeErrorMsg(ctx, `server should be a Server.`, "TYPE"); const error = missingKey(fakeServer, s);
if (error) throw makeRuntimeErrorMsg(ctx, `server should be a hackable Server.\n${error}`, "TYPE");
return s as Server; return s as Server;
} }
function roughlyIs(expect: object, actual: unknown): boolean { function missingKey(expect: object, actual: unknown): string | false {
if (typeof actual !== "object" || actual == null) return false; if (typeof actual !== "object" || actual === null) {
return `Expected to be an object, was ${actual === null ? "null" : typeof actual}.`;
const expects = Object.keys(expect); }
const actuals = Object.keys(actual); for (const key in expect) {
for (const expect of expects) if (!(key in actual)) return `Property ${key} was expected but not present.`;
if (!actuals.includes(expect)) { }
return false; return false;
}
return true;
} }
function gang(ctx: NetscriptContext, g: unknown): FormulaGang { function gang(ctx: NetscriptContext, g: unknown): FormulaGang {
if (!roughlyIs({ respect: 0, territory: 0, wantedLevel: 0 }, g)) const error = missingKey({ respect: 0, territory: 0, wantedLevel: 0 }, g);
throw makeRuntimeErrorMsg(ctx, `gang should be a Gang.`, "TYPE"); if (error) throw makeRuntimeErrorMsg(ctx, `gang should be a Gang.\n${error}`, "TYPE");
return g as FormulaGang; return g as FormulaGang;
} }
function gangMember(ctx: NetscriptContext, m: unknown): GangMember { function gangMember(ctx: NetscriptContext, m: unknown): GangMember {
if (!roughlyIs(new GangMember(), m)) throw makeRuntimeErrorMsg(ctx, `member should be a GangMember.`, "TYPE"); const error = missingKey(new GangMember(), m);
if (error) throw makeRuntimeErrorMsg(ctx, `member should be a GangMember.\n${error}`, "TYPE");
return m as GangMember; return m as GangMember;
} }
function gangTask(ctx: NetscriptContext, t: unknown): GangMemberTask { function gangTask(ctx: NetscriptContext, t: unknown): GangMemberTask {
if (!roughlyIs(new GangMemberTask("", "", false, false, { hackWeight: 100 }), t)) const error = missingKey(new GangMemberTask("", "", false, false, { hackWeight: 100 }), t);
throw makeRuntimeErrorMsg(ctx, `task should be a GangMemberTask.`, "TYPE"); if (error) throw makeRuntimeErrorMsg(ctx, `task should be a GangMemberTask.\n${error}`, "TYPE");
return t as GangMemberTask; return t as GangMemberTask;
} }