export type Player = { username: string; level: number; }; export type Result = { ok: true; value: T } | { ok: false; error: string }; export function playerFromUnknown(input: unknown): Result { if (input === undefined) { return { ok: false, error: "no input" }; } if (input === null) { return { ok: false, error: "no input" }; } if (typeof input === "string") { if (!/^[\d\w(:?\\\-)]+\-\d+$/.test(input)) { return { ok: false, error: "malformed player" }; } const splits = input.split("-"); let username = splits[0]; if (username.includes("\\-")) { username = username.replaceAll("\\-", "-"); } if (splits[1].startsWith("0") && splits[1].length >= 2) { return { ok: false, error: "malformed player" }; } const level = parseInt(splits[1]); return { ok: true, value: { username, level } }; } else if (typeof input === "object") { if (Object.keys(input).length < 2) { return { ok: false, error: "malformed player" }; } if (Object.keys(input).length > 2) { return { ok: false, error: "too much information" }; } if (!("username" in input && "level" in input)) { return { ok: false, error: "malformed player" }; } if (typeof input.username !== "string") { return { ok: false, error: "malformed player" }; } if (typeof input.level !== "number") { return { ok: false, error: "malformed player" }; } const { username, level } = input; return { ok: true, value: { username, level } }; } else { return { ok: false, error: "malformed player" }; } }